Merge "Revert "SurfaceFlinger: setGeometryAppliesWithResize crop latching fixes."" into oc-dev am: cbcefae07a
am: 92a3cc4761
Change-Id: I1e88987fdaacebec61a15f8234839e89f4b79799
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
index 880bc75..10dda56 100644
--- a/cmds/bugreportz/Android.mk
+++ b/cmds/bugreportz/Android.mk
@@ -25,6 +25,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := bugreportz_test
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_MODULE_TAGS := tests
LOCAL_CFLAGS := -Werror -Wall
diff --git a/cmds/bugreportz/AndroidTest.xml b/cmds/bugreportz/AndroidTest.xml
new file mode 100644
index 0000000..38b6276
--- /dev/null
+++ b/cmds/bugreportz/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for bugreportz_test">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="bugreportz_test->/data/local/tmp/bugreportz_test" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="bugreportz_test" />
+ </test>
+</configuration>
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 18a4078..a1b6a51 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -138,7 +138,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := dumpstate_test_fixture
-
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_MODULE_TAGS := tests
LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
diff --git a/cmds/dumpstate/AndroidTest.xml b/cmds/dumpstate/AndroidTest.xml
new file mode 100644
index 0000000..f189489
--- /dev/null
+++ b/cmds/dumpstate/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for dumpstate_test_fixture">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="dumpstate_test_fixture->/data/local/tmp/dumpstate_test_fixture" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="dumpstate_test_fixture" />
+ </test>
+</configuration>
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index a0d987d..6e89f3a 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1782,6 +1782,16 @@
return ok();
}
+// Copy the contents of a system profile over the data profile.
+binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
+ int32_t packageUid, const std::string& packageName, bool* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+ *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName);
+ return ok();
+}
+
// TODO: Consider returning error codes.
binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
bool* _aidl_return) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 200fc77..a94223c 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -91,6 +91,8 @@
binder::Status mergeProfiles(int32_t uid, const std::string& packageName, bool* _aidl_return);
binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
const std::string& codePaths, bool* _aidl_return);
+ binder::Status copySystemProfile(const std::string& systemProfile,
+ int32_t uid, const std::string& packageName, bool* _aidl_return);
binder::Status clearAppProfiles(const std::string& packageName);
binder::Status destroyAppProfiles(const std::string& packageName);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 6b99c1d..efcae4f 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -57,6 +57,8 @@
boolean mergeProfiles(int uid, @utf8InCpp String packageName);
boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
+ boolean copySystemProfile(@utf8InCpp String systemProfile, int uid,
+ @utf8InCpp String packageName);
void clearAppProfiles(@utf8InCpp String packageName);
void destroyAppProfiles(@utf8InCpp String packageName);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 3bbe3a1..5a78d78 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -847,6 +847,66 @@
return true;
}
+bool copy_system_profile(const std::string& system_profile,
+ uid_t packageUid, const std::string& data_profile_location) {
+ unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
+ unique_fd out_fd(open_reference_profile(packageUid,
+ data_profile_location,
+ /*read_write*/ true,
+ /*secondary*/ false));
+ if (in_fd.get() < 0) {
+ PLOG(WARNING) << "Could not open profile " << system_profile;
+ return false;
+ }
+ if (out_fd.get() < 0) {
+ PLOG(WARNING) << "Could not open profile " << data_profile_location;
+ return false;
+ }
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ /* child -- drop privileges before continuing */
+ drop_capabilities(packageUid);
+
+ if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
+ if (errno != EWOULDBLOCK) {
+ PLOG(WARNING) << "Error locking profile " << data_profile_location;
+ }
+ // This implies that the app owning this profile is running
+ // (and has acquired the lock).
+ //
+ // The app never acquires the lock for the reference profiles of primary apks.
+ // Only dex2oat from installd will do that. Since installd is single threaded
+ // we should not see this case. Nevertheless be prepared for it.
+ PLOG(WARNING) << "Failed to flock " << data_profile_location;
+ return false;
+ }
+
+ bool truncated = ftruncate(out_fd.get(), 0) == 0;
+ if (!truncated) {
+ PLOG(WARNING) << "Could not truncate " << data_profile_location;
+ }
+
+ // Copy over data.
+ static constexpr size_t kBufferSize = 4 * 1024;
+ char buffer[kBufferSize];
+ while (true) {
+ ssize_t bytes = read(in_fd.get(), buffer, kBufferSize);
+ if (bytes == 0) {
+ break;
+ }
+ write(out_fd.get(), buffer, bytes);
+ }
+ if (flock(out_fd.get(), LOCK_UN) != 0) {
+ PLOG(WARNING) << "Error unlocking profile " << data_profile_location;
+ }
+ exit(0);
+ }
+ /* parent */
+ int return_code = wait_child(pid);
+ return return_code == 0;
+}
+
static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
// A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
if (EndsWith(oat_path, ".dex")) {
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index cb8aaeb..d171ee5 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -50,6 +50,10 @@
bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
+bool copy_system_profile(const std::string& system_profile,
+ uid_t packageUid,
+ const std::string& data_profile_location);
+
bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path);
bool reconcile_secondary_dex_file(const std::string& dex_path,
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 39d92a7..d3d396f 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -46,7 +46,6 @@
cflags: [
"-DVENDORSERVICEMANAGER=1",
],
- shared_libs: ["libcutils"],
- static_libs: ["libselinux"],
+ shared_libs: ["libcutils", "libselinux_vendor"],
init_rc: ["vndservicemanager.rc"],
}
diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp
new file mode 100644
index 0000000..d4c037a
--- /dev/null
+++ b/cmds/surfacereplayer/Android.bp
@@ -0,0 +1,4 @@
+subdirs = [
+ "proto",
+ "replayer",
+]
\ No newline at end of file
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
new file mode 100644
index 0000000..dda80bb
--- /dev/null
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -0,0 +1,10 @@
+cc_library_static {
+ name: "libtrace_proto",
+ srcs: [
+ "src/trace.proto",
+ ],
+ proto: {
+ type: "lite",
+ export_proto_headers: true,
+ },
+}
diff --git a/cmds/surfacereplayer/proto/Android.mk b/cmds/surfacereplayer/proto/Android.mk
deleted file mode 100644
index 3cf1148..0000000
--- a/cmds/surfacereplayer/proto/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-proto-files-under, src)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-
-LOCAL_MODULE := libtrace_proto
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
new file mode 100644
index 0000000..5caceec
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -0,0 +1,66 @@
+cc_library_shared {
+ name: "libsurfacereplayer",
+ clang: true,
+ srcs: [
+ "BufferQueueScheduler.cpp",
+ "Event.cpp",
+ "Replayer.cpp",
+ ],
+ cppflags: [
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-format",
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-float-conversion",
+ "-Wno-disabled-macro-expansion",
+ "-Wno-float-equal",
+ "-Wno-sign-conversion",
+ "-Wno-padded",
+ "-std=c++14",
+ ],
+ static_libs: [
+ "libtrace_proto",
+ ],
+ shared_libs: [
+ "libEGL",
+ "libGLESv2",
+ "libbinder",
+ "liblog",
+ "libcutils",
+ "libgui",
+ "libui",
+ "libutils",
+ "libprotobuf-cpp-lite",
+ "libbase",
+ "libnativewindow",
+ ],
+ export_include_dirs: [
+ ".",
+ ],
+}
+
+cc_binary {
+ name: "surfacereplayer",
+ clang: true,
+ srcs: [
+ "Main.cpp",
+ ],
+ shared_libs: [
+ "libprotobuf-cpp-lite",
+ "libsurfacereplayer",
+ "libutils",
+ "libgui",
+ ],
+ static_libs: [
+ "libtrace_proto",
+ ],
+ cppflags: [
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-float-conversion",
+ "-Wno-disabled-macro-expansion",
+ "-Wno-float-equal",
+ "-std=c++14",
+ ],
+}
diff --git a/cmds/surfacereplayer/replayer/Android.mk b/cmds/surfacereplayer/replayer/Android.mk
deleted file mode 100644
index 1dd926c..0000000
--- a/cmds/surfacereplayer/replayer/Android.mk
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_TARGET_DIR := $(TARGET_OUT_DATA)/local/tmp
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(call first-makefiles-under, /frameworks/native/cmds/surfacereplayer/proto)
-
-include $(CLEAR_VARS)
-
-LOCAL_CPPFLAGS := -Weverything -Werror
-LOCAL_CPPFLAGS := -Wno-unused-parameter
-LOCAL_CPPFLAGS := -Wno-format
-
-LOCAL_MODULE := libsurfacereplayer
-
-LOCAL_SRC_FILES := \
- BufferQueueScheduler.cpp \
- Event.cpp \
- Replayer.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- libEGL \
- libGLESv2 \
- libbinder \
- liblog \
- libcutils \
- libgui \
- libui \
- libutils \
- libprotobuf-cpp-lite \
- libbase \
- libnativewindow \
-
-LOCAL_STATIC_LIBRARIES := \
- libtrace_proto \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/..
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := surfacereplayer
-
-LOCAL_SRC_FILES := \
- Main.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- libprotobuf-cpp-lite \
- libsurfacereplayer \
- libutils \
- libgui \
-
-LOCAL_STATIC_LIBRARIES := \
- libtrace_proto \
-
-LOCAL_CPPFLAGS := -Weverything -Werror
-LOCAL_CPPFLAGS := -Wno-unused-parameter
-
-LOCAL_MODULE_PATH := $(LOCAL_TARGET_DIR)
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/surfacereplayer/replayer/Main.cpp b/cmds/surfacereplayer/replayer/Main.cpp
index dd1dd7d..7090bdb 100644
--- a/cmds/surfacereplayer/replayer/Main.cpp
+++ b/cmds/surfacereplayer/replayer/Main.cpp
@@ -24,7 +24,7 @@
* 5. Exit successfully or print error statement
*/
-#include <replayer/Replayer.h>
+#include <Replayer.h>
#include <csignal>
#include <iostream>
diff --git a/data/etc/android.hardware.radio.xml b/data/etc/android.hardware.radio.xml
new file mode 100644
index 0000000..f718c47
--- /dev/null
+++ b/data/etc/android.hardware.radio.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard set of features for a broadcast radio. -->
+<permissions>
+ <feature name="android.hardware.radio" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.euicc.xml b/data/etc/android.hardware.telephony.euicc.xml
new file mode 100644
index 0000000..167ed6a
--- /dev/null
+++ b/data/etc/android.hardware.telephony.euicc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices with an eUICC. -->
+<permissions>
+ <feature name="android.hardware.telephony.euicc" />
+</permissions>
diff --git a/data/etc/android.hardware.wifi.passpoint.xml b/data/etc/android.hardware.wifi.passpoint.xml
new file mode 100644
index 0000000..4698bb3
--- /dev/null
+++ b/data/etc/android.hardware.wifi.passpoint.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device includes WiFi Passpoint. -->
+<permissions>
+ <feature name="android.hardware.wifi.passpoint" />
+</permissions>
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 8b1d106..c8c6e99 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -27,7 +27,7 @@
#include <utils/Mutex.h>
#include <utils/RefBase.h>
-struct ANativeWindow_Buffer;
+#include <system/window.h>
namespace android {
diff --git a/include/media/hardware/HDCPAPI.h b/include/media/hardware/HDCPAPI.h
index 30cd5fd..7797bb2 100644
--- a/include/media/hardware/HDCPAPI.h
+++ b/include/media/hardware/HDCPAPI.h
@@ -15,11 +15,10 @@
*/
#ifndef HDCP_API_H_
-
#define HDCP_API_H_
#include <utils/Errors.h>
-#include <system/window.h>
+#include <cutils/native_handle.h>
namespace android {
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index cecf715..6c1ba3d 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -20,13 +20,15 @@
#include <media/hardware/OMXPluginBase.h>
#include <media/hardware/MetadataBufferType.h>
-#include <system/window.h>
+#include <cutils/native_handle.h>
#include <utils/RefBase.h>
#include "VideoAPI.h"
#include <OMX_Component.h>
+struct ANativeWindowBuffer;
+
namespace android {
// This structure is used to enable Android native buffer use for either
diff --git a/include/ui/ANativeObjectBase.h b/include/ui/ANativeObjectBase.h
index 640e34b..e9d5d8d 100644
--- a/include/ui/ANativeObjectBase.h
+++ b/include/ui/ANativeObjectBase.h
@@ -19,26 +19,8 @@
#include <sys/types.h>
-#include <system/window.h>
+#include <nativebase/nativebase.h>
-// ---------------------------------------------------------------------------
-
-/* FIXME: this is legacy for pixmaps */
-typedef struct egl_native_pixmap_t
-{
- int32_t version; /* must be 32 */
- int32_t width;
- int32_t height;
- int32_t stride;
- uint8_t* data;
- uint8_t format;
- uint8_t rfu[3];
- union {
- uint32_t compressedFormat;
- int32_t vstride;
- };
- int32_t reserved;
-} egl_native_pixmap_t;
/*****************************************************************************/
@@ -52,7 +34,8 @@
* This helper class turns a ANativeXXX object type into a C++
* reference-counted object; with proper type conversions.
*/
-template <typename NATIVE_TYPE, typename TYPE, typename REF>
+template <typename NATIVE_TYPE, typename TYPE, typename REF,
+ typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
public:
@@ -65,7 +48,7 @@
}
protected:
- typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE;
+ typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF, NATIVE_BASE> BASE;
ANativeObjectBase() : NATIVE_TYPE(), REF() {
NATIVE_TYPE::common.incRef = incRef;
NATIVE_TYPE::common.decRef = decRef;
@@ -76,17 +59,17 @@
static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
return static_cast<TYPE const *>(self);
}
- static inline TYPE* getSelf(android_native_base_t* base) {
+ static inline TYPE* getSelf(NATIVE_BASE* base) {
return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
}
- static inline TYPE const * getSelf(android_native_base_t const* base) {
+ static inline TYPE const * getSelf(NATIVE_BASE const* base) {
return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
}
- static void incRef(android_native_base_t* base) {
+ static void incRef(NATIVE_BASE* base) {
ANativeObjectBase* self = getSelf(base);
self->incStrong(self);
}
- static void decRef(android_native_base_t* base) {
+ static void decRef(NATIVE_BASE* base) {
ANativeObjectBase* self = getSelf(base);
self->decStrong(self);
}
diff --git a/include/ui/DebugUtils.h b/include/ui/DebugUtils.h
index 8483808..30f4a59 100644
--- a/include/ui/DebugUtils.h
+++ b/include/ui/DebugUtils.h
@@ -17,6 +17,7 @@
#pragma once
#include <system/graphics.h>
+#include <ui/PixelFormat.h>
#include <string>
@@ -25,3 +26,4 @@
std::string decodeRange(android_dataspace dataspace);
std::string dataspaceDetails(android_dataspace dataspace);
std::string decodeColorMode(android_color_mode colormode);
+std::string decodePixelFormat(android::PixelFormat format);
diff --git a/include/ui/Gralloc2.h b/include/ui/Gralloc2.h
index f826b92..e7b8ca9 100644
--- a/include/ui/Gralloc2.h
+++ b/include/ui/Gralloc2.h
@@ -21,7 +21,6 @@
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <system/window.h>
#include <utils/StrongPointer.h>
namespace android {
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 4b82cff..9a5aa69 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -28,9 +28,9 @@
#include <utils/Flattenable.h>
#include <utils/RefBase.h>
-#include <hardware/gralloc.h>
+#include <nativebase/nativebase.h>
-struct ANativeWindowBuffer;
+#include <hardware/gralloc.h>
namespace android {
@@ -41,7 +41,7 @@
// ===========================================================================
class GraphicBuffer
- : public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,
+ : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
public Flattenable<GraphicBuffer>
{
friend class Flattenable<GraphicBuffer>;
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index fe99de1..14a865e 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -25,8 +25,6 @@
#include <cutils/native_handle.h>
-#include <system/window.h>
-
#include <ui/PixelFormat.h>
#include <utils/Errors.h>
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 0d25176..a20154f 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -23,5 +23,6 @@
cc_library_static {
name: "libarect",
host_supported: true,
+ vendor_available: true,
export_include_dirs: ["include"],
}
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
new file mode 100644
index 0000000..f2686d5
--- /dev/null
+++ b/libs/graphicsenv/Android.bp
@@ -0,0 +1,28 @@
+// 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.
+
+cc_library_shared {
+ name: "libgraphicsenv",
+
+ srcs: [
+ "GraphicsEnv.cpp",
+ ],
+
+ shared_libs: [
+ "libnativeloader",
+ "liblog",
+ ],
+
+ export_include_dirs: ["include"],
+}
diff --git a/libs/ui/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
similarity index 98%
rename from libs/ui/GraphicsEnv.cpp
rename to libs/graphicsenv/GraphicsEnv.cpp
index 8182c07..39b5829 100644
--- a/libs/ui/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -16,7 +16,7 @@
//#define LOG_NDEBUG 1
#define LOG_TAG "GraphicsEnv"
-#include <ui/GraphicsEnv.h>
+#include <graphicsenv/GraphicsEnv.h>
#include <mutex>
diff --git a/include/ui/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
similarity index 100%
rename from include/ui/GraphicsEnv.h
rename to libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 5a12740..c0ae3d7 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -117,9 +117,14 @@
"android.hardware.configstore-utils",
],
+ header_libs: [
+ "libnativebase_headers",
+ ],
+
export_shared_lib_headers: [
"libbinder",
"libui",
+ "libnativewindow",
"android.hidl.token@1.0-utils",
"android.hardware.graphics.bufferqueue@1.0",
],
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 5e5de44..be754c2 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -36,6 +36,8 @@
#include <binder/PermissionCache.h>
#include <private/android_filesystem_config.h>
+#include <system/window.h>
+
namespace android {
BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index cfb25e0..bb703da 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -38,6 +38,8 @@
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
+#include <system/window.h>
+
namespace android {
static String8 getUniqueName() {
@@ -110,54 +112,60 @@
void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
Mutex::Autolock lock(mMutex);
- String8 fifo;
+ outResult->appendFormat("%s- BufferQueue ", prefix.string());
+ outResult->appendFormat("mMaxAcquiredBufferCount=%d mMaxDequeuedBufferCount=%d\n",
+ mMaxAcquiredBufferCount, mMaxDequeuedBufferCount);
+ outResult->appendFormat("%s mDequeueBufferCannotBlock=%d mAsyncMode=%d\n", prefix.string(),
+ mDequeueBufferCannotBlock, mAsyncMode);
+ outResult->appendFormat("%s default-size=[%dx%d] default-format=%d ", prefix.string(),
+ mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
+ outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
+ mFrameCounter);
+
+ outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
Fifo::const_iterator current(mQueue.begin());
while (current != mQueue.end()) {
- fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
- "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
- current->mSlot, current->mGraphicBuffer.get(),
- current->mCrop.left, current->mCrop.top, current->mCrop.right,
- current->mCrop.bottom, current->mTransform, current->mTimestamp,
- BufferItem::scalingModeName(current->mScalingMode));
+ double timestamp = current->mTimestamp / 1e9;
+ outResult->appendFormat("%s %02d:%p ", prefix.string(), current->mSlot,
+ current->mGraphicBuffer.get());
+ outResult->appendFormat("crop=[%d,%d,%d,%d] ", current->mCrop.left, current->mCrop.top,
+ current->mCrop.right, current->mCrop.bottom);
+ outResult->appendFormat("xform=0x%02x time=%.4f scale=%s\n", current->mTransform, timestamp,
+ BufferItem::scalingModeName(current->mScalingMode));
++current;
}
- outResult->appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
- "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
- "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
- "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix.string(),
- mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
- mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
- mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
- fifo.string());
-
+ outResult->appendFormat("%sSlots:\n", prefix.string());
for (int s : mActiveBuffers) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
// A dequeued buffer might be null if it's still being allocated
if (buffer.get()) {
- outResult->appendFormat("%s%s[%02d:%p] state=%-8s, %p "
- "[%4ux%4u:%4u,%3X]\n", prefix.string(),
- (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
- buffer.get(), mSlots[s].mBufferState.string(),
- buffer->handle, buffer->width, buffer->height,
- buffer->stride, buffer->format);
+ outResult->appendFormat("%s %s[%02d:%p] ", prefix.string(),
+ (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
+ buffer.get());
+ outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
+ buffer->handle, mSlots[s].mFrameNumber);
+ outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
+ buffer->stride, buffer->format);
} else {
- outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
- buffer.get(), mSlots[s].mBufferState.string());
+ outResult->appendFormat("%s [%02d:%p] ", prefix.string(), s, buffer.get());
+ outResult->appendFormat("state=%-8s frame=%" PRIu64 "\n",
+ mSlots[s].mBufferState.string(), mSlots[s].mFrameNumber);
}
}
for (int s : mFreeBuffers) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
- outResult->appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
- prefix.string(), s, buffer.get(), mSlots[s].mBufferState.string(),
- buffer->handle, buffer->width, buffer->height, buffer->stride,
- buffer->format);
+ outResult->appendFormat("%s [%02d:%p] ", prefix.string(), s, buffer.get());
+ outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
+ buffer->handle, mSlots[s].mFrameNumber);
+ outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
+ buffer->stride, buffer->format);
}
for (int s : mFreeSlots) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
- outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
- buffer.get(), mSlots[s].mBufferState.string());
+ outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s, buffer.get(),
+ mSlots[s].mBufferState.string());
}
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 6a5593c..b76e2c6 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -39,6 +39,8 @@
#include <utils/Log.h>
#include <utils/Trace.h>
+#include <system/window.h>
+
namespace android {
static constexpr uint32_t BQ_LAYER_COUNT = 1;
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index bafe947..52c9067 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -31,6 +31,8 @@
#include <utils/Trace.h>
+#include <system/window.h>
+
namespace android {
status_t StreamSplitter::createSplitter(
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 60c1277..4220aaf 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -32,6 +32,8 @@
#include <utils/String8.h>
#include <utils/threads.h>
+#include <system/window.h>
+
#include <gtest/gtest.h>
#include <thread>
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index aa071f6..bcfc91c 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -29,6 +29,8 @@
#include <gui/BufferQueue.h>
#include <gui/IProducerListener.h>
+#include <system/window.h>
+
#include <vector>
#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 80e30da..e2f4948 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -24,6 +24,8 @@
#include <gui/StreamSplitter.h>
#include <private/gui/ComposerService.h>
+#include <system/window.h>
+
#include <gtest/gtest.h>
namespace android {
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 3ef8b4a..693bace 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -15,6 +15,7 @@
cc_library_static {
name: "libmath",
host_supported: true,
+ vendor_available: true,
export_include_dirs: ["include"],
}
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
new file mode 100644
index 0000000..7375a2b
--- /dev/null
+++ b/libs/nativebase/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+cc_library_headers {
+ name: "libnativebase_headers",
+ vendor_available: true,
+ host_supported: true,
+ export_include_dirs: ["include"],
+
+ target: {
+ linux_bionic: {
+ enabled: true,
+ },
+ windows: {
+ enabled: true,
+ },
+ }
+}
diff --git a/libs/nativebase/MODULE_LICENSE_APACHE2 b/libs/nativebase/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/nativebase/MODULE_LICENSE_APACHE2
diff --git a/libs/nativebase/NOTICE b/libs/nativebase/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/libs/nativebase/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/libs/nativebase/include/nativebase/nativebase.h b/libs/nativebase/include/nativebase/nativebase.h
new file mode 100644
index 0000000..90afb3f
--- /dev/null
+++ b/libs/nativebase/include/nativebase/nativebase.h
@@ -0,0 +1,106 @@
+/*
+ * 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 <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <system/graphics-base.h>
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+#ifdef __cplusplus
+#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
+#else
+#define ANDROID_NATIVE_UNSIGNED_CAST(x) ((unsigned int)(x))
+#endif
+
+#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
+ ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
+ (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
+ (ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | \
+ (ANDROID_NATIVE_UNSIGNED_CAST(d)))
+
+#define ANDROID_NATIVE_BUFFER_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
+
+
+typedef struct android_native_base_t
+{
+ /* a magic value defined by the actual EGL native type */
+ int magic;
+
+ /* the sizeof() of the actual EGL native type */
+ int version;
+
+ void* reserved[4];
+
+ /* reference-counting interface */
+ void (*incRef)(struct android_native_base_t* base);
+ void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+typedef struct android_native_rect_t
+{
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+} android_native_rect_t;
+
+typedef struct ANativeWindowBuffer
+{
+#ifdef __cplusplus
+ ANativeWindowBuffer() {
+ common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+ common.version = sizeof(ANativeWindowBuffer);
+ memset(common.reserved, 0, sizeof(common.reserved));
+ }
+
+ // Implement the methods that sp<ANativeWindowBuffer> expects so that it
+ // can be used to automatically refcount ANativeWindowBuffer's.
+ void incStrong(const void* /*id*/) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* /*id*/) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
+#endif
+
+ struct android_native_base_t common;
+
+ int width;
+ int height;
+ int stride;
+ int format;
+ int usage;
+ uintptr_t layerCount;
+
+ void* reserved[1];
+
+ const native_handle_t* handle;
+
+ void* reserved_proc[8];
+} ANativeWindowBuffer_t;
+
+typedef struct ANativeWindowBuffer ANativeWindowBuffer;
+
+// Old typedef for backwards compatibility.
+typedef ANativeWindowBuffer_t android_native_buffer_t;
+
+__END_DECLS
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index f64bab1..9224df6 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -16,8 +16,6 @@
#define LOG_TAG "ANativeWindow"
-#include <android/native_window.h>
-
#include <grallocusage/GrallocUsageConversion.h>
// from nativewindow/includes/system/window.h
// (not to be confused with the compatibility-only window.h from system/core/includes)
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index d759acb..e61fbd6 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -57,10 +57,25 @@
"libgrallocusage",
],
+ header_libs: [
+ "libnativebase_headers",
+ ],
+
// headers we include in our public headers
export_static_lib_headers: [
"libarect",
],
+
+ export_header_lib_headers: [
+ "libnativebase_headers",
+ ],
+}
+
+llndk_library {
+ name: "libnativewindow",
+ symbol_file: "libnativewindow.map.txt",
+ unversioned: true,
+ export_include_dirs: ["include"],
}
subdirs = ["tests"]
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 45110c4..6429c52 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -60,25 +60,6 @@
// ---------------------------------------------------------------------------
-typedef const native_handle_t* buffer_handle_t;
-
-// ---------------------------------------------------------------------------
-
-typedef struct android_native_rect_t
-{
- int32_t left;
- int32_t top;
- int32_t right;
- int32_t bottom;
-} android_native_rect_t;
-
-// ---------------------------------------------------------------------------
-
-// Old typedef for backwards compatibility.
-typedef ANativeWindowBuffer_t android_native_buffer_t;
-
-// ---------------------------------------------------------------------------
-
/* attributes queriable with query() */
enum {
NATIVE_WINDOW_WIDTH = 0,
@@ -549,7 +530,6 @@
/* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
* android_native_window_t is deprecated.
*/
-typedef struct ANativeWindow ANativeWindow;
typedef struct ANativeWindow android_native_window_t __deprecated;
/*
diff --git a/libs/nativewindow/include/vndk/window.h b/libs/nativewindow/include/vndk/window.h
index 95618c4..a7b340a 100644
--- a/libs/nativewindow/include/vndk/window.h
+++ b/libs/nativewindow/include/vndk/window.h
@@ -17,88 +17,14 @@
#ifndef ANDROID_VNDK_NATIVEWINDOW_ANATIVEWINDOW_H
#define ANDROID_VNDK_NATIVEWINDOW_ANATIVEWINDOW_H
-#include <stdint.h>
-#include <stdbool.h>
-#include <sys/cdefs.h>
-#include <system/graphics-base.h>
-#include <cutils/native_handle.h>
+#include <nativebase/nativebase.h>
// vndk is a superset of the NDK
#include <android/native_window.h>
+
__BEGIN_DECLS
-/*****************************************************************************/
-
-#ifdef __cplusplus
-#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
-#else
-#define ANDROID_NATIVE_UNSIGNED_CAST(x) ((unsigned int)(x))
-#endif
-
-#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
- ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
- (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
- (ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | \
- (ANDROID_NATIVE_UNSIGNED_CAST(d)))
-
-#define ANDROID_NATIVE_BUFFER_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
-
-
-/*****************************************************************************/
-
-typedef struct android_native_base_t
-{
- /* a magic value defined by the actual EGL native type */
- int magic;
-
- /* the sizeof() of the actual EGL native type */
- int version;
-
- void* reserved[4];
-
- /* reference-counting interface */
- void (*incRef)(struct android_native_base_t* base);
- void (*decRef)(struct android_native_base_t* base);
-} android_native_base_t;
-
-typedef struct ANativeWindowBuffer
-{
-#ifdef __cplusplus
- ANativeWindowBuffer() {
- common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
- common.version = sizeof(ANativeWindowBuffer);
- memset(common.reserved, 0, sizeof(common.reserved));
- }
-
- // Implement the methods that sp<ANativeWindowBuffer> expects so that it
- // can be used to automatically refcount ANativeWindowBuffer's.
- void incStrong(const void* /*id*/) const {
- common.incRef(const_cast<android_native_base_t*>(&common));
- }
- void decStrong(const void* /*id*/) const {
- common.decRef(const_cast<android_native_base_t*>(&common));
- }
-#endif
-
- struct android_native_base_t common;
-
- int width;
- int height;
- int stride;
- int format;
- int usage;
- uintptr_t layerCount;
-
- void* reserved[1];
-
- const native_handle_t* handle;
-
- void* reserved_proc[8];
-} ANativeWindowBuffer_t;
-
-typedef struct ANativeWindowBuffer ANativeWindowBuffer;
-
/*
* Convert this ANativeWindowBuffer into a AHardwareBuffer
*/
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index b1d1a72..58045be 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -4,22 +4,40 @@
AHardwareBuffer_allocate;
AHardwareBuffer_describe;
AHardwareBuffer_fromHardwareBuffer;
+ AHardwareBuffer_getNativeHandle; # vndk
AHardwareBuffer_lock;
AHardwareBuffer_recvHandleFromUnixSocket;
AHardwareBuffer_release;
AHardwareBuffer_sendHandleToUnixSocket;
AHardwareBuffer_toHardwareBuffer;
AHardwareBuffer_unlock;
+ ANativeWindowBuffer_getHardwareBuffer; # vndk
+ ANativeWindow_OemStorageGet; # vndk
+ ANativeWindow_OemStorageSet; # vndk
ANativeWindow_acquire;
+ ANativeWindow_cancelBuffer; # vndk
+ ANativeWindow_dequeueBuffer; # vndk
ANativeWindow_fromSurface;
ANativeWindow_fromSurfaceTexture;
ANativeWindow_getFormat;
ANativeWindow_getHeight;
ANativeWindow_getWidth;
ANativeWindow_lock;
+ ANativeWindow_query; # vndk
+ ANativeWindow_queryf; # vndk
+ ANativeWindow_queueBuffer; # vndk
ANativeWindow_release;
+ ANativeWindow_setAutoRefresh; # vndk
+ ANativeWindow_setBufferCount; # vndk
+ ANativeWindow_setBufferDataSpace; # vndk
+ ANativeWindow_setBuffersDimensions; # vndk
+ ANativeWindow_setBuffersFormat; # vndk
ANativeWindow_setBuffersGeometry;
+ ANativeWindow_setBuffersTimestamp; # vndk
ANativeWindow_setBuffersTransform;
+ ANativeWindow_setSharedBufferMode; # vndk
+ ANativeWindow_setSwapInterval; # vndk
+ ANativeWindow_setUsage; # vndk
ANativeWindow_unlockAndPost;
local:
*;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 5ccf178..fb553e2 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -14,6 +14,7 @@
cc_library_shared {
name: "libui",
+ vendor_available: true,
clang: true,
cppflags: [
@@ -53,7 +54,6 @@
"GraphicBuffer.cpp",
"GraphicBufferAllocator.cpp",
"GraphicBufferMapper.cpp",
- "GraphicsEnv.cpp",
"HdrCapabilities.cpp",
"PixelFormat.cpp",
"Rect.cpp",
@@ -61,13 +61,16 @@
"UiConfig.cpp",
],
+ include_dirs: [
+ "frameworks/native/include",
+ ],
+
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.configstore@1.0",
- "android.hardware.configstore-utils",
+ "android.hardware.configstore-utils",
"libbase",
- "libnativeloader",
"libcutils",
"libhardware",
"libhidlbase",
@@ -83,10 +86,18 @@
"libmath",
],
+ header_libs: [
+ "libnativebase_headers",
+ ],
+
export_static_lib_headers: [
"libarect",
"libmath",
],
+
+ export_header_lib_headers: [
+ "libnativebase_headers",
+ ],
}
subdirs = ["tests"]
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 882bd7c..94b68e7 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -15,6 +15,7 @@
*/
#include <ui/DebugUtils.h>
+#include <ui/PixelFormat.h>
#include <android-base/stringprintf.h>
#include <string>
@@ -145,6 +146,9 @@
}
std::string dataspaceDetails(android_dataspace dataspace) {
+ if (dataspace == 0) {
+ return "Default (0)";
+ }
return android::base::StringPrintf("%s %s %s", decodeStandard(dataspace).c_str(),
decodeTransfer(dataspace).c_str(),
decodeRange(dataspace).c_str());
@@ -185,3 +189,36 @@
return android::base::StringPrintf("Unknown color mode %d", colorMode);
}
+
+// Converts a PixelFormat to a human-readable string. Max 11 chars.
+// (Could use a table of prefab String8 objects.)
+std::string decodePixelFormat(android::PixelFormat format) {
+ switch (format) {
+ case android::PIXEL_FORMAT_UNKNOWN:
+ return std::string("Unknown/None");
+ case android::PIXEL_FORMAT_CUSTOM:
+ return std::string("Custom");
+ case android::PIXEL_FORMAT_TRANSLUCENT:
+ return std::string("Translucent");
+ case android::PIXEL_FORMAT_TRANSPARENT:
+ return std::string("Transparent");
+ case android::PIXEL_FORMAT_OPAQUE:
+ return std::string("Opaque");
+ case android::PIXEL_FORMAT_RGBA_8888:
+ return std::string("RGBA_8888");
+ case android::PIXEL_FORMAT_RGBX_8888:
+ return std::string("RGBx_8888");
+ case android::PIXEL_FORMAT_RGBA_FP16:
+ return std::string("RGBA_FP16");
+ case android::PIXEL_FORMAT_RGBA_1010102:
+ return std::string("RGBA_1010102");
+ case android::PIXEL_FORMAT_RGB_888:
+ return std::string("RGB_888");
+ case android::PIXEL_FORMAT_RGB_565:
+ return std::string("RGB_565");
+ case android::PIXEL_FORMAT_BGRA_8888:
+ return std::string("BGRA_8888");
+ default:
+ return android::base::StringPrintf("Unknown %#08x", format);
+ }
+}
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 452bad0..da0ea24 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -34,6 +34,11 @@
"liblog",
"libui",
"libutils",
+ "libnativewindow"
+]
+
+HeaderLibraries = [
+ "libnativebase_headers",
]
cc_library {
@@ -45,7 +50,11 @@
export_include_dirs: localIncludeFiles,
static_libs: staticLibraries,
shared_libs: sharedLibraries,
+ header_libs: HeaderLibraries,
name: "libbufferhub",
+ export_header_lib_headers: [
+ "libnativebase_headers",
+ ],
}
cc_test {
diff --git a/libs/vr/libbufferhub/include/private/dvr/native_buffer.h b/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
index b4ef2f5..a54579f 100644
--- a/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
@@ -4,9 +4,9 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <log/log.h>
-#include <system/window.h>
#include <ui/ANativeObjectBase.h>
#include <utils/RefBase.h>
+#include <nativebase/nativebase.h>
#include <private/dvr/buffer_hub_client.h>
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index a587f95..0b3b2f0 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -21,10 +21,6 @@
"include",
]
-headerLibraries = [
- "libdvr_headers",
-]
-
staticLibraries = [
"libbufferhub",
"libdvrcommon",
@@ -42,6 +38,11 @@
"libgui",
]
+headerLibraries = [
+ "libdvr_headers",
+ "libnativebase_headers",
+]
+
cc_library {
name: "libbufferhubqueue",
cflags: [
@@ -51,9 +52,9 @@
srcs: sourceFiles,
export_include_dirs: includeFiles,
export_static_lib_headers: staticLibraries,
- header_libs: headerLibraries,
static_libs: staticLibraries,
shared_libs: sharedLibraries,
+ header_libs: headerLibraries,
}
subdirs = ["tests"]
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 012a4e7..1978f41 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -23,34 +23,61 @@
using android::pdx::ErrorStatus;
using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
using android::pdx::Status;
namespace android {
namespace dvr {
+namespace {
+
+// Polls an fd for the given events.
+Status<int> PollEvents(int fd, short events) {
+ const int kTimeoutMs = 0;
+ pollfd pfd{fd, events, 0};
+ const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
+ if (count < 0) {
+ return ErrorStatus(errno);
+ } else if (count == 0) {
+ return ErrorStatus(ETIMEDOUT);
+ } else {
+ return {pfd.revents};
+ }
+}
+
+// Polls a buffer for the given events, taking care to do the proper
+// translation.
+Status<int> PollEvents(const std::shared_ptr<BufferHubBuffer>& buffer,
+ short events) {
+ auto poll_status = PollEvents(buffer->event_fd(), events);
+ if (!poll_status)
+ return poll_status;
+
+ return buffer->GetEventMask(poll_status.get());
+}
+
+std::pair<int32_t, int32_t> Unstuff(uint64_t value) {
+ return {static_cast<int32_t>(value >> 32),
+ static_cast<int32_t>(value & ((1ull << 32) - 1))};
+}
+
+uint64_t Stuff(int32_t a, int32_t b) {
+ const uint32_t ua = static_cast<uint32_t>(a);
+ const uint32_t ub = static_cast<uint32_t>(b);
+ return (static_cast<uint64_t>(ua) << 32) | static_cast<uint64_t>(ub);
+}
+
+} // anonymous namespace
+
BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle)
: Client{pdx::default_transport::ClientChannel::Create(
- std::move(channel_handle))},
- meta_size_(0),
- buffers_(BufferHubQueue::kMaxQueueCapacity),
- epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
- available_buffers_(BufferHubQueue::kMaxQueueCapacity),
- fences_(BufferHubQueue::kMaxQueueCapacity),
- capacity_(0),
- id_(-1) {
+ std::move(channel_handle))} {
Initialize();
}
BufferHubQueue::BufferHubQueue(const std::string& endpoint_path)
- : Client{pdx::default_transport::ClientChannelFactory::Create(
- endpoint_path)},
- meta_size_(0),
- buffers_(BufferHubQueue::kMaxQueueCapacity),
- epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
- available_buffers_(BufferHubQueue::kMaxQueueCapacity),
- fences_(BufferHubQueue::kMaxQueueCapacity),
- capacity_(0),
- id_(-1) {
+ : Client{
+ pdx::default_transport::ClientChannelFactory::Create(endpoint_path)} {
Initialize();
}
@@ -62,9 +89,9 @@
return;
}
- epoll_event event = {.events = EPOLLIN | EPOLLET,
- .data = {.u64 = static_cast<uint64_t>(
- BufferHubQueue::kEpollQueueEventIndex)}};
+ epoll_event event = {
+ .events = EPOLLIN | EPOLLET,
+ .data = {.u64 = Stuff(-1, BufferHubQueue::kEpollQueueEventIndex)}};
ret = epoll_fd_.Control(EPOLL_CTL_ADD, event_fd(), &event);
if (ret < 0) {
ALOGE("BufferHubQueue::Initialize: Failed to add event fd to epoll set: %s",
@@ -87,7 +114,6 @@
void BufferHubQueue::SetupQueue(size_t meta_size_bytes, int id) {
meta_size_ = meta_size_bytes;
id_ = id;
- meta_buffer_tmp_.reset(meta_size_ > 0 ? new uint8_t[meta_size_] : nullptr);
}
std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
@@ -152,19 +178,24 @@
// one for each buffer, in the queue and one extra event for the queue
// client itself.
for (int i = 0; i < num_events; i++) {
- int64_t index = static_cast<int64_t>(events[i].data.u64);
+ int32_t event_fd;
+ int32_t index;
+ std::tie(event_fd, index) = Unstuff(events[i].data.u64);
ALOGD_IF(TRACE,
- "BufferHubQueue::WaitForBuffers: event %d: index=%" PRId64, i,
- index);
+ "BufferHubQueue::WaitForBuffers: event %d: event_fd=%d index=%d",
+ i, event_fd, index);
if (is_buffer_event_index(index)) {
- HandleBufferEvent(static_cast<size_t>(index), events[i].events);
+ HandleBufferEvent(static_cast<size_t>(index), event_fd,
+ events[i].events);
} else if (is_queue_event_index(index)) {
HandleQueueEvent(events[i].events);
} else {
- ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
- index);
+ ALOGW(
+ "BufferHubQueue::WaitForBuffers: Unknown event type event_fd=%d "
+ "index=%d",
+ event_fd, index);
}
}
} while (count() == 0 && capacity() > 0 && !hung_up());
@@ -172,52 +203,72 @@
return count() != 0;
}
-void BufferHubQueue::HandleBufferEvent(size_t slot, int poll_events) {
- auto buffer = buffers_[slot];
- if (!buffer) {
+Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd,
+ int poll_events) {
+ if (!buffers_[slot]) {
ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot);
- return;
+ return ErrorStatus(ENOENT);
}
- auto status = buffer->GetEventMask(poll_events);
+ auto status = buffers_[slot]->GetEventMask(poll_events);
if (!status) {
ALOGW("BufferHubQueue::HandleBufferEvent: Failed to get event mask: %s",
status.GetErrorMessage().c_str());
- return;
+ return status.error_status();
}
const int events = status.get();
if (events & EPOLLIN) {
- const int ret = OnBufferReady(buffer, &fences_[slot]);
- if (ret == 0 || ret == -EALREADY || ret == -EBUSY) {
+ auto entry_status = OnBufferReady(buffers_[slot], slot);
+ if (entry_status.ok() || entry_status.error() == EALREADY) {
// Only enqueue the buffer if it moves to or is already in the state
- // requested in OnBufferReady(). If the buffer is busy this means that the
- // buffer moved from released to posted when a new consumer was created
- // before the ProducerQueue had a chance to regain it. This is a valid
- // transition that we have to handle because edge triggered poll events
- // latch the ready state even if it is later de-asserted -- don't enqueue
- // or print an error log in this case.
- if (ret != -EBUSY)
- Enqueue(buffer, slot);
+ // requested in OnBufferReady().
+ return Enqueue(entry_status.take());
+ } else if (entry_status.error() == EBUSY) {
+ // If the buffer is busy this means that the buffer moved from released to
+ // posted when a new consumer was created before the ProducerQueue had a
+ // chance to regain it. This is a valid transition that we have to handle
+ // because edge triggered poll events latch the ready state even if it is
+ // later de-asserted -- don't enqueue or print an error log in this case.
} else {
ALOGE(
"BufferHubQueue::HandleBufferEvent: Failed to set buffer ready, "
"queue_id=%d buffer_id=%d: %s",
- id(), buffer->id(), strerror(-ret));
+ id(), buffers_[slot]->id(), entry_status.GetErrorMessage().c_str());
}
} else if (events & EPOLLHUP) {
- // This might be caused by producer replacing an existing buffer slot, or
- // when BufferHubQueue is shutting down. For the first case, currently the
- // epoll FD is cleaned up when the replacement consumer client is imported,
- // we shouldn't detach again if |epollhub_pending_[slot]| is set.
+ // Check to see if the current buffer in the slot hung up. This is a bit of
+ // paranoia to deal with the epoll set getting out of sync with the buffer
+ // slots.
+ auto poll_status = PollEvents(buffers_[slot], POLLIN);
+ if (!poll_status && poll_status.error() != ETIMEDOUT) {
+ ALOGE("BufferHubQueue::HandleBufferEvent: Failed to poll buffer: %s",
+ poll_status.GetErrorMessage().c_str());
+ return poll_status.error_status();
+ }
+
+ const bool hangup_pending = status.ok() && (poll_status.get() & EPOLLHUP);
+
ALOGW(
- "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP at slot: %zu, "
- "buffer event fd: %d, EPOLLHUP pending: %d",
- slot, buffer->event_fd(), int{epollhup_pending_[slot]});
- if (epollhup_pending_[slot]) {
- epollhup_pending_[slot] = false;
+ "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP event: slot=%zu "
+ "event_fd=%d buffer_id=%d hangup_pending=%d poll_status=%x",
+ slot, buffers_[slot]->event_fd(), buffers_[slot]->id(), hangup_pending,
+ poll_status.get());
+
+ if (hangup_pending) {
+ return DetachBuffer(slot);
} else {
- DetachBuffer(slot);
+ // Clean up the bookkeeping for the event fd. This is a bit of paranoia to
+ // deal with the epoll set getting out of sync with the buffer slots.
+ // Hitting this path should be very unusual.
+ const int ret = epoll_fd_.Control(EPOLL_CTL_DEL, event_fd, nullptr);
+ if (ret < 0) {
+ ALOGE(
+ "BufferHubQueue::HandleBufferEvent: Failed to remove fd=%d from "
+ "epoll set: %s",
+ event_fd, strerror(-ret));
+ return ErrorStatus(-ret);
+ }
}
} else {
ALOGW(
@@ -225,14 +276,16 @@
"events=%d",
slot, events);
}
+
+ return {};
}
-void BufferHubQueue::HandleQueueEvent(int poll_event) {
+Status<void> BufferHubQueue::HandleQueueEvent(int poll_event) {
auto status = GetEventMask(poll_event);
if (!status) {
ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s",
status.GetErrorMessage().c_str());
- return;
+ return status.error_status();
}
const int events = status.get();
@@ -250,111 +303,97 @@
} else {
ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%x", events);
}
+
+ return {};
}
-int BufferHubQueue::AddBuffer(const std::shared_ptr<BufferHubBuffer>& buf,
- size_t slot) {
+Status<void> BufferHubQueue::AddBuffer(
+ const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+ ALOGD_IF(TRACE, "BufferHubQueue::AddBuffer: buffer_id=%d slot=%zu",
+ buffer->id(), slot);
+
if (is_full()) {
- // TODO(jwcai) Move the check into Producer's AllocateBuffer and consumer's
- // import buffer.
ALOGE("BufferHubQueue::AddBuffer queue is at maximum capacity: %zu",
capacity_);
- return -E2BIG;
+ return ErrorStatus(E2BIG);
}
- if (buffers_[slot] != nullptr) {
- // Replace the buffer if the slot is preoccupied. This could happen when the
+ if (buffers_[slot]) {
+ // Replace the buffer if the slot is occupied. This could happen when the
// producer side replaced the slot with a newly allocated buffer. Detach the
// buffer before setting up with the new one.
- DetachBuffer(slot);
- epollhup_pending_[slot] = true;
+ auto detach_status = DetachBuffer(slot);
+ if (!detach_status)
+ return detach_status.error_status();
}
- epoll_event event = {.events = EPOLLIN | EPOLLET, .data = {.u64 = slot}};
- const int ret = epoll_fd_.Control(EPOLL_CTL_ADD, buf->event_fd(), &event);
+ epoll_event event = {.events = EPOLLIN | EPOLLET,
+ .data = {.u64 = Stuff(buffer->event_fd(), slot)}};
+ const int ret = epoll_fd_.Control(EPOLL_CTL_ADD, buffer->event_fd(), &event);
if (ret < 0) {
ALOGE("BufferHubQueue::AddBuffer: Failed to add buffer to epoll set: %s",
strerror(-ret));
- return ret;
+ return ErrorStatus(-ret);
}
- buffers_[slot] = buf;
+ buffers_[slot] = buffer;
capacity_++;
- return 0;
+ return {};
}
-int BufferHubQueue::DetachBuffer(size_t slot) {
- auto& buf = buffers_[slot];
- if (buf == nullptr) {
- ALOGE("BufferHubQueue::DetachBuffer: Invalid slot: %zu", slot);
- return -EINVAL;
+Status<void> BufferHubQueue::DetachBuffer(size_t slot) {
+ ALOGD_IF(TRACE, "BufferHubQueue::DetachBuffer: slot=%zu", slot);
+
+ if (buffers_[slot]) {
+ const int ret =
+ epoll_fd_.Control(EPOLL_CTL_DEL, buffers_[slot]->event_fd(), nullptr);
+ if (ret < 0) {
+ ALOGE(
+ "BufferHubQueue::DetachBuffer: Failed to detach buffer from epoll "
+ "set: "
+ "%s",
+ strerror(-ret));
+ return ErrorStatus(-ret);
+ }
+
+ buffers_[slot] = nullptr;
+ capacity_--;
}
- const int ret = epoll_fd_.Control(EPOLL_CTL_DEL, buf->event_fd(), nullptr);
- if (ret < 0) {
- ALOGE(
- "BufferHubQueue::DetachBuffer: Failed to detach buffer from epoll set: "
- "%s",
- strerror(-ret));
- return ret;
- }
-
- buffers_[slot] = nullptr;
- capacity_--;
- return 0;
+ return {};
}
-void BufferHubQueue::Enqueue(const std::shared_ptr<BufferHubBuffer>& buf,
- size_t slot) {
- if (count() == capacity_) {
+Status<void> BufferHubQueue::Enqueue(Entry entry) {
+ if (!is_full()) {
+ available_buffers_.Append(std::move(entry));
+ return {};
+ } else {
ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
- return;
+ return ErrorStatus(E2BIG);
}
-
- // Set slot buffer back to vector.
- // TODO(jwcai) Here have to dynamically allocate BufferInfo::metadata due to
- // the limitation of the RingBuffer we are using. Would be better to refactor
- // that.
- BufferInfo buffer_info(slot, meta_size_);
- buffer_info.buffer = buf;
- // Swap metadata loaded during onBufferReady into vector.
- std::swap(buffer_info.metadata, meta_buffer_tmp_);
-
- available_buffers_.Append(std::move(buffer_info));
}
Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(
int timeout, size_t* slot, void* meta, LocalHandle* fence) {
- ALOGD_IF(TRACE, "Dequeue: count=%zu, timeout=%d", count(), timeout);
+ ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(),
+ timeout);
if (!WaitForBuffers(timeout))
return ErrorStatus(ETIMEDOUT);
- std::shared_ptr<BufferHubBuffer> buf;
- BufferInfo& buffer_info = available_buffers_.Front();
+ auto& entry = available_buffers_.Front();
- *fence = std::move(fences_[buffer_info.slot]);
-
- // Report current pos as the output slot.
- std::swap(buffer_info.slot, *slot);
- // Swap buffer from vector to be returned later.
- std::swap(buffer_info.buffer, buf);
- // Swap metadata from vector into tmp so that we can write out to |meta|.
- std::swap(buffer_info.metadata, meta_buffer_tmp_);
-
- available_buffers_.PopFront();
-
- if (!buf) {
- ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
- return ErrorStatus(ENOBUFS);
- }
-
- if (meta) {
- std::copy(meta_buffer_tmp_.get(), meta_buffer_tmp_.get() + meta_size_,
+ std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer);
+ *slot = entry.slot;
+ *fence = std::move(entry.fence);
+ if (meta && entry.metadata) {
+ std::copy(entry.metadata.get(), entry.metadata.get() + meta_size_,
reinterpret_cast<uint8_t*>(meta));
}
- return {std::move(buf)};
+ available_buffers_.PopFront();
+
+ return {std::move(buffer)};
}
ProducerQueue::ProducerQueue(size_t meta_size)
@@ -388,28 +427,29 @@
SetupQueue(status.get().meta_size_bytes, status.get().id);
}
-int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage, size_t* out_slot) {
+Status<void> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t layer_count,
+ uint32_t format, uint64_t usage,
+ size_t* out_slot) {
if (out_slot == nullptr) {
ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
- return -EINVAL;
+ return ErrorStatus(EINVAL);
}
if (is_full()) {
ALOGE("ProducerQueue::AllocateBuffer queue is at maximum capacity: %zu",
capacity());
- return -E2BIG;
+ return ErrorStatus(E2BIG);
}
- const size_t kBufferCount = 1U;
+ const size_t kBufferCount = 1u;
Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
width, height, layer_count, format, usage, kBufferCount);
if (!status) {
ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
status.GetErrorMessage().c_str());
- return -status.error();
+ return status.error_status();
}
auto buffer_handle_slots = status.take();
@@ -429,27 +469,26 @@
buffer_slot);
}
-int ProducerQueue::AddBuffer(const std::shared_ptr<BufferProducer>& buf,
- size_t slot) {
+Status<void> ProducerQueue::AddBuffer(
+ const std::shared_ptr<BufferProducer>& buffer, size_t slot) {
ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
- id(), buf->id(), slot);
+ id(), buffer->id(), slot);
// For producer buffer, we need to enqueue the newly added buffer
// immediately. Producer queue starts with all buffers in available state.
- const int ret = BufferHubQueue::AddBuffer(buf, slot);
- if (ret < 0)
- return ret;
+ auto status = BufferHubQueue::AddBuffer(buffer, slot);
+ if (!status)
+ return status;
- Enqueue(buf, slot);
- return 0;
+ return Enqueue(buffer, slot);
}
-int ProducerQueue::DetachBuffer(size_t slot) {
+Status<void> ProducerQueue::DetachBuffer(size_t slot) {
auto status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
if (!status) {
ALOGE("ProducerQueue::DetachBuffer: Failed to detach producer buffer: %s",
status.GetErrorMessage().c_str());
- return -status.error();
+ return status.error_status();
}
return BufferHubQueue::DetachBuffer(slot);
@@ -471,12 +510,22 @@
return {std::static_pointer_cast<BufferProducer>(buffer_status.take())};
}
-int ProducerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
- LocalHandle* release_fence) {
- ALOGD_IF(TRACE, "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
- id(), buf->id());
- auto buffer = std::static_pointer_cast<BufferProducer>(buf);
- return buffer->Gain(release_fence);
+Status<BufferHubQueue::Entry> ProducerQueue::OnBufferReady(
+ const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+ ALOGD_IF(TRACE,
+ "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d slot=%zu",
+ id(), buffer->id(), slot);
+
+ // Avoid taking a transient reference, buffer is valid for the duration of
+ // this method call.
+ auto* producer_buffer = static_cast<BufferProducer*>(buffer.get());
+ LocalHandle release_fence;
+
+ const int ret = producer_buffer->Gain(&release_fence);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {{buffer, nullptr, std::move(release_fence), slot}};
}
ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import)
@@ -503,12 +552,12 @@
if (!status) {
ALOGE("ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
status.GetErrorMessage().c_str());
- return ErrorStatus(status.error());
+ return status.error_status();
}
int ret;
- int last_error = 0;
- int imported_buffers = 0;
+ Status<void> last_error;
+ size_t imported_buffers_count = 0;
auto buffer_handle_slots = status.take();
for (auto& buffer_handle_slot : buffer_handle_slots) {
@@ -530,53 +579,52 @@
"ConsumerQueue::ImportBuffers: Failed to set ignored state on "
"imported buffer buffer_id=%d: %s",
buffer_consumer->id(), strerror(-ret));
- last_error = ret;
+ last_error = ErrorStatus(-ret);
}
}
- ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
- if (ret < 0) {
+ auto add_status =
+ AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+ if (!add_status) {
ALOGE("ConsumerQueue::ImportBuffers: Failed to add buffer: %s",
- strerror(-ret));
- last_error = ret;
- continue;
+ add_status.GetErrorMessage().c_str());
+ last_error = add_status;
} else {
- imported_buffers++;
+ imported_buffers_count++;
}
}
- if (imported_buffers > 0)
- return {imported_buffers};
+ if (imported_buffers_count > 0)
+ return {imported_buffers_count};
else
- return ErrorStatus(-last_error);
+ return last_error.error_status();
}
-int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
- size_t slot) {
+Status<void> ConsumerQueue::AddBuffer(
+ const std::shared_ptr<BufferConsumer>& buffer, size_t slot) {
ALOGD_IF(TRACE, "ConsumerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
- id(), buf->id(), slot);
- const int ret = BufferHubQueue::AddBuffer(buf, slot);
- if (ret < 0)
- return ret;
+ id(), buffer->id(), slot);
+ auto status = BufferHubQueue::AddBuffer(buffer, slot);
+ if (!status)
+ return status;
// Check to see if the buffer is already signaled. This is necessary to catch
// cases where buffers are already available; epoll edge triggered mode does
// not fire until and edge transition when adding new buffers to the epoll
- // set.
- const int kTimeoutMs = 0;
- pollfd pfd{buf->event_fd(), POLLIN, 0};
- const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
- if (count < 0) {
- const int error = errno;
+ // set. Note that we only poll the fd events because HandleBufferEvent() takes
+ // care of checking the translated buffer events.
+ auto poll_status = PollEvents(buffer->event_fd(), POLLIN);
+ if (!poll_status && poll_status.error() != ETIMEDOUT) {
ALOGE("ConsumerQueue::AddBuffer: Failed to poll consumer buffer: %s",
- strerror(errno));
- return -error;
+ poll_status.GetErrorMessage().c_str());
+ return poll_status.error_status();
}
- if (count == 1)
- HandleBufferEvent(slot, pfd.revents);
-
- return 0;
+ // Update accounting if the buffer is available.
+ if (poll_status)
+ return HandleBufferEvent(slot, buffer->event_fd(), poll_status.get());
+ else
+ return {};
}
Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
@@ -606,15 +654,30 @@
return {std::static_pointer_cast<BufferConsumer>(buffer_status.take())};
}
-int ConsumerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
- LocalHandle* acquire_fence) {
- ALOGD_IF(TRACE, "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
- id(), buf->id());
- auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
- return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
+Status<BufferHubQueue::Entry> ConsumerQueue::OnBufferReady(
+ const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+ ALOGD_IF(TRACE,
+ "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d slot=%zu",
+ id(), buffer->id(), slot);
+
+ // Avoid taking a transient reference, buffer is valid for the duration of
+ // this method call.
+ auto* consumer_buffer = static_cast<BufferConsumer*>(buffer.get());
+ std::unique_ptr<uint8_t[]> metadata(meta_size_ ? new uint8_t[meta_size_]
+ : nullptr);
+ LocalHandle acquire_fence;
+
+ const int ret =
+ consumer_buffer->Acquire(&acquire_fence, metadata.get(), meta_size_);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {{buffer, std::move(metadata), std::move(acquire_fence), slot}};
}
Status<void> ConsumerQueue::OnBufferAllocated() {
+ ALOGD_IF(TRACE, "ConsumerQueue::OnBufferAllocated: queue_id=%d", id());
+
auto status = ImportBuffers();
if (!status) {
ALOGE("ConsumerQueue::OnBufferAllocated: Failed to import buffers: %s",
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 8582bbf..932aa37 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -3,6 +3,7 @@
#include <dvr/dvr_api.h>
#include <inttypes.h>
#include <log/log.h>
+#include <system/window.h>
namespace android {
namespace dvr {
@@ -158,6 +159,8 @@
for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
LocalHandle fence;
auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
+ if (!buffer_status)
+ return NO_MEMORY;
buffer_producer = buffer_status.take();
if (!buffer_producer)
@@ -607,10 +610,12 @@
PixelFormat format,
uint64_t usage) {
size_t slot;
-
- if (queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot) <
- 0) {
- ALOGE("Failed to allocate new buffer in BufferHub.");
+ auto status =
+ queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot);
+ if (!status) {
+ ALOGE(
+ "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
+ status.GetErrorMessage().c_str());
return NO_MEMORY;
}
@@ -625,11 +630,11 @@
}
status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) {
- int ret = queue_->DetachBuffer(slot);
- if (ret < 0) {
- ALOGE("BufferHubQueueProducer::RemoveBuffer failed through RPC, ret=%s",
- strerror(-ret));
- return ret;
+ auto status = queue_->DetachBuffer(slot);
+ if (!status) {
+ ALOGE("BufferHubQueueProducer::RemoveBuffer: Failed to detach buffer: %s",
+ status.GetErrorMessage().c_str());
+ return INVALID_OPERATION;
}
// Reset in memory objects related the the buffer.
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 ed67f79..d8d326b 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
@@ -21,45 +21,39 @@
// automatically re-requeued when released by the remote side.
class BufferHubQueue : public pdx::Client {
public:
- using LocalHandle = pdx::LocalHandle;
- using LocalChannelHandle = pdx::LocalChannelHandle;
- template <typename T>
- using Status = pdx::Status<T>;
-
virtual ~BufferHubQueue() {}
- void Initialize();
- // Create a new consumer queue that is attached to the producer. Returns
+ // Creates a new consumer queue that is attached to the producer. Returns
// a new consumer queue client or nullptr on failure.
std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
- // Create a new consumer queue that is attached to the producer. This queue
+ // Creates a new consumer queue that is attached to the producer. This queue
// sets each of its imported consumer buffers to the ignored state to avoid
// participation in lifecycle events.
std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
- // Return the default buffer width of this buffer queue.
+ // Returns 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.
+ // Returns 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.
+ // Returns the default buffer format of this buffer queue.
int32_t default_format() const { return default_format_; }
- // Create a new consumer in handle form for immediate transport over RPC.
- Status<LocalChannelHandle> CreateConsumerQueueHandle();
+ // Creates a new consumer in handle form for immediate transport over RPC.
+ pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle();
- // Return the number of buffers avaiable for dequeue.
+ // Returns the number of buffers avaiable for dequeue.
size_t count() const { return available_buffers_.GetSize(); }
- // Return the total number of buffers that the queue is tracking.
+ // Returns the total number of buffers that the queue is tracking.
size_t capacity() const { return capacity_; }
- // Return the size of metadata structure associated with this BufferBubQueue.
+ // Returns the size of metadata structure associated with this queue.
size_t metadata_size() const { return meta_size_; }
- // Return whether the buffer queue is alrady full.
+ // Returns whether the buffer queue is full.
bool is_full() const { return available_buffers_.IsFull(); }
explicit operator bool() const { return epoll_fd_.IsValid(); }
@@ -68,7 +62,7 @@
return buffers_[slot];
}
- Status<int> GetEventMask(int events) {
+ pdx::Status<int> GetEventMask(int events) {
if (auto* client_channel = GetChannel()) {
return client_channel->GetEventMask(events);
} else {
@@ -86,81 +80,95 @@
// occurred.
bool HandleQueueEvents() { return WaitForBuffers(0); }
- // Enqueue a buffer marks buffer to be available (|Gain|'ed for producer
- // and |Acquire|'ed for consumer. This is only used for internal bookkeeping.
- void Enqueue(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
-
- // |BufferHubQueue| will keep track of at most this value of buffers.
+ // The queue tracks at most this many buffers.
static constexpr size_t kMaxQueueCapacity =
android::BufferQueueDefs::NUM_BUFFER_SLOTS;
- // Special epoll data field indicating that the epoll event refers to the
- // queue.
- static constexpr int64_t kEpollQueueEventIndex = -1;
-
- // When pass |kNoTimeout| to |Dequeue|, it will block indefinitely without a
- // timeout.
static constexpr int kNoTimeOut = -1;
int id() const { return id_; }
bool hung_up() const { return hung_up_; }
protected:
- BufferHubQueue(LocalChannelHandle channel);
+ BufferHubQueue(pdx::LocalChannelHandle channel);
BufferHubQueue(const std::string& endpoint_path);
// Imports the queue parameters by querying BufferHub for the parameters for
// this channel.
- Status<void> ImportQueue();
+ pdx::Status<void> ImportQueue();
// Sets up the queue with the given parameters.
void SetupQueue(size_t meta_size_bytes_, int id);
- // Called by ProducerQueue::AddBuffer and ConsumerQueue::AddBuffer only. to
- // register a buffer for epoll and internal bookkeeping.
- int AddBuffer(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
+ // Register a buffer for management by the queue. Used by subclasses to add a
+ // buffer to internal bookkeeping.
+ pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
+ size_t slot);
- // Called by ProducerQueue::DetachBuffer and ConsumerQueue::DetachBuffer only.
+ // Called by ProducerQueue::DetachBuffer and ConsumerQueue::DetachBuffer only
// to deregister a buffer for epoll and internal bookkeeping.
- virtual int DetachBuffer(size_t slot);
+ virtual pdx::Status<void> DetachBuffer(size_t slot);
// Dequeue a buffer from the free queue, blocking until one is available. The
// timeout argument specifies the number of milliseconds that |Dequeue()| will
- // block. Specifying a timeout of -1 causes |Dequeue()| to block indefinitely,
- // while specifying a timeout equal to zero cause |Dequeue()| to return
+ // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
+ // while specifying a timeout equal to zero cause Dequeue() to return
// immediately, even if no buffers are available.
- pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
- size_t* slot,
- void* meta,
- LocalHandle* fence);
+ pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(
+ int timeout, size_t* slot, void* meta, pdx::LocalHandle* fence);
- // Wait for buffers to be released and re-add them to the queue.
+ // Waits for buffers to become available and adds them to the available queue.
bool WaitForBuffers(int timeout);
- void HandleBufferEvent(size_t slot, int poll_events);
- void HandleQueueEvent(int poll_events);
- virtual int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
- LocalHandle* fence) = 0;
+ pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd,
+ int poll_events);
+ pdx::Status<void> HandleQueueEvent(int poll_events);
+
+ // Entry in the ring buffer of available buffers that stores related
+ // per-buffer data.
+ struct Entry {
+ Entry() : slot(0) {}
+ Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot)
+ : buffer(buffer), slot(slot) {}
+ Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
+ std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
+ size_t slot)
+ : buffer(buffer),
+ metadata(std::move(metadata)),
+ fence(std::move(fence)),
+ slot(slot) {}
+ Entry(Entry&&) = default;
+ Entry& operator=(Entry&&) = default;
+
+ std::shared_ptr<BufferHubBuffer> buffer;
+ std::unique_ptr<uint8_t[]> metadata;
+ pdx::LocalHandle fence;
+ size_t slot;
+ };
+
+ // Enqueues a buffer to the available list (Gained for producer or Acquireed
+ // for consumer).
+ pdx::Status<void> Enqueue(Entry entry);
+
+ virtual pdx::Status<Entry> OnBufferReady(
+ const std::shared_ptr<BufferHubBuffer>& buf, size_t slot) = 0;
// Called when a buffer is allocated remotely.
- virtual Status<void> OnBufferAllocated() { return {}; }
+ virtual pdx::Status<void> OnBufferAllocated() { return {}; }
- // Data members to handle arbitrary metadata passed through BufferHub. It is
- // fair to enforce that all buffers in the same queue share the same metadata
- // type. |meta_size_| is used to store the size of metadata on queue creation;
- // and |meta_buffer_tmp_| is allocated and resized to |meta_size_| on queue
- // creation to be later used as temporary space so that we can avoid
- // additional dynamic memory allocation in each |Enqueue| and |Dequeue| call.
- size_t meta_size_;
-
- // Here we intentionally choose |unique_ptr<uint8_t[]>| over vector<uint8_t>
- // to disallow dynamic resizing for stability reasons.
- std::unique_ptr<uint8_t[]> meta_buffer_tmp_;
+ // Size of the metadata that buffers in this queue cary.
+ size_t meta_size_{0};
private:
+ void Initialize();
+
+ // Special epoll data field indicating that the epoll event refers to the
+ // queue.
+ static constexpr int64_t kEpollQueueEventIndex = -1;
+
static constexpr size_t kMaxEvents = 128;
- // The |u64| data field of an epoll event is interpreted as int64_t:
+ // The u64 data field of an epoll event is interpreted as int64_t:
// When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific
// element of |buffers_| as a direct index;
static bool is_buffer_event_index(int64_t index) {
@@ -168,47 +176,11 @@
index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity);
}
- // When |index| == kEpollQueueEventIndex, it refers to the queue itself.
+ // When |index| == kEpollQueueEventIndex it refers to the queue itself.
static bool is_queue_event_index(int64_t index) {
return index == BufferHubQueue::kEpollQueueEventIndex;
}
- struct BufferInfo {
- // A logical slot number that is assigned to a buffer at allocation time.
- // The slot number remains unchanged during the entire life cycle of the
- // buffer and should not be confused with the enqueue and dequeue order.
- size_t slot;
-
- // A BufferHubBuffer client.
- std::shared_ptr<BufferHubBuffer> buffer;
-
- // Metadata associated with the buffer.
- std::unique_ptr<uint8_t[]> metadata;
-
- BufferInfo() : BufferInfo(-1, 0) {}
-
- BufferInfo(size_t slot, size_t metadata_size)
- : slot(slot),
- buffer(nullptr),
- metadata(metadata_size ? new uint8_t[metadata_size] : nullptr) {}
-
- BufferInfo(BufferInfo&& other)
- : slot(other.slot),
- buffer(std::move(other.buffer)),
- metadata(std::move(other.metadata)) {}
-
- BufferInfo& operator=(BufferInfo&& other) {
- slot = other.slot;
- buffer = std::move(other.buffer);
- metadata = std::move(other.metadata);
- return *this;
- }
-
- private:
- BufferInfo(const BufferInfo&) = delete;
- 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};
@@ -221,49 +193,18 @@
// 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_;
+ // Tracks the buffers belonging to this queue. Buffers are stored according to
+ // "slot" in this vector. Each slot is a logical id of the buffer within this
+ // queue regardless of its queue position or presence in the ring buffer.
+ std::vector<std::shared_ptr<BufferHubBuffer>> buffers_{kMaxQueueCapacity};
- // |epollhup_pending_| tracks whether a slot of |buffers_| get detached before
- // its corresponding EPOLLHUP event got handled. This could happen as the
- // following sequence:
- // 1. Producer queue's client side allocates a new buffer (at slot 1).
- // 2. Producer queue's client side replaces an existing buffer (at slot 0).
- // This is implemented by first detaching the buffer and then allocating a
- // new buffer.
- // 3. During the same epoll_wait, Consumer queue's client side gets EPOLLIN
- // event on the queue which indicates a new buffer is available and the
- // EPOLLHUP event for slot 0. Consumer handles these two events in order.
- // 4. Consumer client calls BufferHubRPC::ConsumerQueueImportBuffers and both
- // slot 0 and (the new) slot 1 buffer will be imported. During the import
- // of the buffer at slot 1, consumer client detaches the old buffer so that
- // the new buffer can be registered. At the same time
- // |epollhup_pending_[slot]| is marked to indicate that buffer at this slot
- // was detached prior to EPOLLHUP event.
- // 5. Consumer client continues to handle the EPOLLHUP. Since
- // |epollhup_pending_[slot]| is marked as true, it can safely ignore the
- // event without detaching the newly allocated buffer at slot 1.
- //
- // In normal situations where the previously described sequence doesn't
- // happen, an EPOLLHUP event should trigger a regular buffer detach.
- std::vector<bool> epollhup_pending_;
+ // Buffers and related data that are available for dequeue.
+ RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
- // |available_buffers_| uses |dvr::RingBuffer| to implementation queue
- // sematics. When |Dequeue|, we pop the front element from
- // |available_buffers_|, and that buffer's reference count will decrease by
- // one, while another reference in |buffers_| keeps the last reference to
- // prevent the buffer from being deleted.
- RingBuffer<BufferInfo> available_buffers_;
+ // Keeps track with how many buffers have been added into the queue.
+ size_t capacity_{0};
- // Fences (acquire fence for consumer and release fence for consumer) , one
- // for each buffer slot.
- std::vector<LocalHandle> fences_;
-
- // Keep track with how many buffers have been added into the queue.
- size_t capacity_;
-
- // Epoll fd used to wait for BufferHub events.
+ // Epoll fd used to manage buffer events.
EpollFileDescriptor epoll_fd_;
// Flag indicating that the other side hung up. For ProducerQueues this
@@ -273,7 +214,7 @@
bool hung_up_{false};
// Global id for the queue that is consistent across processes.
- int id_;
+ int id_{-1};
BufferHubQueue(const BufferHubQueue&) = delete;
void operator=(BufferHubQueue&) = delete;
@@ -317,15 +258,15 @@
usage_deny_set_mask, usage_deny_clear_mask);
}
- // Import a |ProducerQueue| from a channel handle.
- static std::unique_ptr<ProducerQueue> Import(LocalChannelHandle handle) {
+ // Import a ProducerQueue from a channel handle.
+ static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) {
return BASE::Create(std::move(handle));
}
// Get a buffer producer. Note that the method doesn't check whether the
// buffer slot has a valid buffer that has been allocated already. When no
- // buffer has been imported before it returns |nullptr|; otherwise it returns
- // a shared pointer to a |BufferProducer|.
+ // buffer has been imported before it returns nullptr; otherwise it returns
+ // a shared pointer to a BufferProducer.
std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
return std::static_pointer_cast<BufferProducer>(
BufferHubQueue::GetBuffer(slot));
@@ -333,26 +274,30 @@
// Allocate producer buffer to populate the queue. Once allocated, a producer
// buffer is automatically enqueue'd into the ProducerQueue and available to
- // use (i.e. in |Gain|'ed mode).
- // Returns Zero on success and negative error code when buffer allocation
- // fails.
- int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
- uint32_t format, uint64_t usage, size_t* out_slot);
+ // use (i.e. in GAINED state).
+ pdx::Status<void> AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t format,
+ uint64_t usage, size_t* out_slot);
// Add a producer buffer to populate the queue. Once added, a producer buffer
- // is available to use (i.e. in |Gain|'ed mode).
- int AddBuffer(const std::shared_ptr<BufferProducer>& buf, size_t slot);
+ // is available to use (i.e. in GAINED state).
+ pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
+ size_t slot);
// Detach producer buffer from the queue.
- // Returns Zero on success and negative error code when buffer detach
- // fails.
- int DetachBuffer(size_t slot) override;
+ pdx::Status<void> DetachBuffer(size_t slot) override;
// Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
// and caller should call Post() once it's done writing to release the buffer
// to the consumer side.
pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
- int timeout, size_t* slot, LocalHandle* release_fence);
+ int timeout, size_t* slot, pdx::LocalHandle* release_fence);
+
+ // Enqueues a producer buffer in the queue.
+ pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
+ size_t slot) {
+ return BufferHubQueue::Enqueue({buffer, slot});
+ }
private:
friend BASE;
@@ -361,13 +306,13 @@
// static template methods inherited from ClientBase, which take the same
// arguments as the constructors.
explicit ProducerQueue(size_t meta_size);
- ProducerQueue(LocalChannelHandle handle);
+ explicit ProducerQueue(pdx::LocalChannelHandle handle);
ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
uint64_t usage_clear_mask, uint64_t usage_deny_set_mask,
uint64_t usage_deny_clear_mask);
- int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
- LocalHandle* release_fence) override;
+ pdx::Status<Entry> OnBufferReady(
+ const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
};
// Explicit specializations of ProducerQueue::Create for void metadata type.
@@ -399,7 +344,7 @@
// used to avoid participation in the buffer lifecycle by a consumer queue
// that is only used to spawn other consumer queues, such as in an
// intermediate service.
- static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle,
+ static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle,
bool ignore_on_import = false) {
return std::unique_ptr<ConsumerQueue>(
new ConsumerQueue(std::move(handle), ignore_on_import));
@@ -407,7 +352,7 @@
// Import newly created buffers from the service side.
// Returns number of buffers successfully imported or an error.
- Status<size_t> ImportBuffers();
+ pdx::Status<size_t> ImportBuffers();
// Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
// mode, and caller should call Releasse() once it's done writing to release
@@ -417,33 +362,34 @@
// when the buffer is orignally created.
template <typename Meta>
pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
- int timeout, size_t* slot, Meta* meta, LocalHandle* acquire_fence) {
+ int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
}
pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
- int timeout, size_t* slot, LocalHandle* acquire_fence) {
+ int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
}
pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
int timeout, size_t* slot, void* meta, size_t meta_size,
- LocalHandle* acquire_fence);
+ pdx::LocalHandle* acquire_fence);
private:
friend BufferHubQueue;
- ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import = false);
+ ConsumerQueue(pdx::LocalChannelHandle handle, bool ignore_on_import = false);
// Add a consumer buffer to populate the queue. Once added, a consumer buffer
// is NOT available to use until the producer side |Post| it. |WaitForBuffers|
// will catch the |Post| and |Acquire| the buffer to make it available for
// consumer.
- int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
+ pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+ size_t slot);
- int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
- LocalHandle* acquire_fence) override;
+ pdx::Status<Entry> OnBufferReady(
+ const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
- Status<void> OnBufferAllocated() override;
+ pdx::Status<void> OnBufferAllocated() override;
// Flag indicating that imported (consumer) buffers should be ignored when
// imported to avoid participating in the buffer ownership flow.
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index fe0b12a..ff2e146 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -6,6 +6,9 @@
#include <vector>
+// Enable/disable debug logging.
+#define TRACE 0
+
namespace android {
namespace dvr {
@@ -51,13 +54,16 @@
CreateConsumerQueue();
}
- void AllocateBuffer() {
+ void AllocateBuffer(size_t* slot_out = nullptr) {
// Create producer buffer.
size_t slot;
- int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
- kBufferLayerCount, kBufferFormat,
- kBufferUsage, &slot);
- ASSERT_EQ(ret, 0);
+ auto status = producer_queue_->AllocateBuffer(
+ kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+ kBufferUsage, &slot);
+ ASSERT_TRUE(status.ok());
+
+ if (slot_out)
+ *slot_out = slot;
}
protected:
@@ -94,13 +100,13 @@
}
TEST_F(BufferHubQueueTest, TestProducerConsumer) {
- const size_t nb_buffer = 16;
+ const size_t kBufferCount = 16;
size_t slot;
uint64_t seq;
ASSERT_TRUE(CreateQueues<uint64_t>());
- for (size_t i = 0; i < nb_buffer; i++) {
+ for (size_t i = 0; i < kBufferCount; i++) {
AllocateBuffer();
// Producer queue has all the available buffers on initialize.
@@ -120,14 +126,23 @@
ASSERT_EQ(consumer_queue_->capacity(), i + 1);
}
- for (size_t i = 0; i < nb_buffer; i++) {
+ // Use /dev/zero as a stand-in for a fence. As long as BufferHub does not need
+ // to merge fences, which only happens when multiple consumers release the
+ // same buffer with release fences, the file object should simply pass
+ // through.
+ LocalHandle post_fence("/dev/zero", O_RDONLY);
+ struct stat post_fence_stat;
+ ASSERT_EQ(0, fstat(post_fence.Get(), &post_fence_stat));
+
+ for (size_t i = 0; i < kBufferCount; i++) {
LocalHandle fence;
- // First time, there is no buffer available to dequeue.
+
+ // First time there is no buffer available to dequeue.
auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
ASSERT_FALSE(consumer_status.ok());
ASSERT_EQ(ETIMEDOUT, consumer_status.error());
- // Make sure Producer buffer is Post()'ed so that it's ready to Accquire
+ // Make sure Producer buffer is POSTED so that it's ready to Accquire
// in the consumer's Dequeue() function.
auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_TRUE(producer_status.ok());
@@ -135,18 +150,133 @@
ASSERT_NE(nullptr, producer);
uint64_t seq_in = static_cast<uint64_t>(i);
- ASSERT_EQ(producer->Post({}, &seq_in, sizeof(seq_in)), 0);
+ ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
- // Second time, the just |Post()|'ed buffer should be dequeued.
+ // Second time the just the POSTED buffer should be dequeued.
uint64_t seq_out = 0;
consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
ASSERT_TRUE(consumer_status.ok());
+ EXPECT_TRUE(fence.IsValid());
+
+ struct stat acquire_fence_stat;
+ ASSERT_EQ(0, fstat(fence.Get(), &acquire_fence_stat));
+
+ // The file descriptors should refer to the same file object. Testing the
+ // device id and inode is a proxy for testing that the fds refer to the same
+ // file object.
+ EXPECT_NE(post_fence.Get(), fence.Get());
+ EXPECT_EQ(post_fence_stat.st_dev, acquire_fence_stat.st_dev);
+ EXPECT_EQ(post_fence_stat.st_ino, acquire_fence_stat.st_ino);
+
auto consumer = consumer_status.take();
ASSERT_NE(nullptr, consumer);
ASSERT_EQ(seq_in, seq_out);
}
}
+TEST_F(BufferHubQueueTest, TestDetach) {
+ ASSERT_TRUE(CreateProducerQueue<void>());
+
+ // Allocate buffers.
+ const size_t kBufferCount = 4u;
+ for (size_t i = 0; i < kBufferCount; i++) {
+ AllocateBuffer();
+ }
+ ASSERT_EQ(kBufferCount, producer_queue_->count());
+ ASSERT_EQ(kBufferCount, producer_queue_->capacity());
+
+ consumer_queue_ = producer_queue_->CreateConsumerQueue();
+ ASSERT_NE(nullptr, consumer_queue_);
+
+ // Check that buffers are correctly imported on construction.
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+ EXPECT_EQ(0u, consumer_queue_->count());
+
+ // Dequeue all the buffers and keep track of them in an array. This prevents
+ // the producer queue ring buffer ref counts from interfering with the tests.
+ struct Entry {
+ std::shared_ptr<BufferProducer> buffer;
+ LocalHandle fence;
+ size_t slot;
+ };
+ std::array<Entry, kBufferCount> buffers;
+
+ for (size_t i = 0; i < kBufferCount; i++) {
+ Entry* entry = &buffers[i];
+ auto producer_status =
+ producer_queue_->Dequeue(0, &entry->slot, &entry->fence);
+ ASSERT_TRUE(producer_status.ok());
+ entry->buffer = producer_status.take();
+ ASSERT_NE(nullptr, entry->buffer);
+ EXPECT_EQ(i, entry->slot);
+ }
+
+ // Detach a buffer and make sure both queues reflect the change.
+ ASSERT_TRUE(producer_queue_->DetachBuffer(buffers[0].slot));
+ EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+
+ // As long as the detached buffer is still alive the consumer queue won't know
+ // its gone.
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+ EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+ // Release the detached buffer.
+ buffers[0].buffer = nullptr;
+
+ // Now the consumer queue should know it's gone.
+ EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity());
+
+ // Allocate a new buffer. This should take the first empty slot.
+ size_t slot;
+ AllocateBuffer(&slot);
+ ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+ EXPECT_EQ(buffers[0].slot, slot);
+ EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+ // The consumer queue should pick up the new buffer.
+ EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity());
+ EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+ // Detach and allocate a buffer.
+ ASSERT_TRUE(producer_queue_->DetachBuffer(buffers[1].slot));
+ EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+ buffers[1].buffer = nullptr;
+
+ AllocateBuffer(&slot);
+ ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+ EXPECT_EQ(buffers[1].slot, slot);
+ EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+ // The consumer queue should pick up the new buffer but the count shouldn't
+ // change.
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+ EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+ // Detach and allocate a buffer, but don't free the buffer right away.
+ ASSERT_TRUE(producer_queue_->DetachBuffer(buffers[2].slot));
+ EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+
+ AllocateBuffer(&slot);
+ ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+ EXPECT_EQ(buffers[2].slot, slot);
+ EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+ EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+ // Release the producer buffer to trigger a POLLHUP event for an already
+ // detached buffer.
+ buffers[2].buffer = nullptr;
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+ EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+}
+
TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
ASSERT_TRUE(CreateProducerQueue<void>());
@@ -347,10 +477,10 @@
// When allocation, leave out |set_mask| from usage bits on purpose.
size_t slot;
- int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
- kBufferFormat, kBufferLayerCount,
- kBufferUsage & ~set_mask, &slot);
- ASSERT_EQ(0, ret);
+ auto status = producer_queue_->AllocateBuffer(
+ kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+ kBufferUsage & ~set_mask, &slot);
+ ASSERT_TRUE(status.ok());
LocalHandle fence;
auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
@@ -365,10 +495,10 @@
// When allocation, add |clear_mask| into usage bits on purpose.
size_t slot;
- int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
- kBufferLayerCount, kBufferFormat,
- kBufferUsage | clear_mask, &slot);
- ASSERT_EQ(0, ret);
+ auto status = producer_queue_->AllocateBuffer(
+ kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+ kBufferUsage | clear_mask, &slot);
+ ASSERT_TRUE(status.ok());
LocalHandle fence;
auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
@@ -384,16 +514,17 @@
// Now that |deny_set_mask| is illegal, allocation without those bits should
// be able to succeed.
size_t slot;
- int ret = producer_queue_->AllocateBuffer(
+ auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
kBufferUsage & ~deny_set_mask, &slot);
- ASSERT_EQ(ret, 0);
+ ASSERT_TRUE(status.ok());
// While allocation with those bits should fail.
- ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
- kBufferLayerCount, kBufferFormat,
- kBufferUsage | deny_set_mask, &slot);
- ASSERT_EQ(ret, -EINVAL);
+ status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+ kBufferLayerCount, kBufferFormat,
+ kBufferUsage | deny_set_mask, &slot);
+ ASSERT_FALSE(status.ok());
+ ASSERT_EQ(EINVAL, status.error());
}
TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
@@ -403,16 +534,17 @@
// Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
// mandatory), allocation with those bits should be able to succeed.
size_t slot;
- int ret = producer_queue_->AllocateBuffer(
+ auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
kBufferUsage | deny_clear_mask, &slot);
- ASSERT_EQ(ret, 0);
+ ASSERT_TRUE(status.ok());
// While allocation without those bits should fail.
- ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
- kBufferLayerCount, kBufferFormat,
- kBufferUsage & ~deny_clear_mask, &slot);
- ASSERT_EQ(ret, -EINVAL);
+ status = producer_queue_->AllocateBuffer(
+ kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+ kBufferUsage & ~deny_clear_mask, &slot);
+ ASSERT_FALSE(status.ok());
+ ASSERT_EQ(EINVAL, status.error());
}
} // namespace
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 2b6239f..c7692d0 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -192,7 +192,7 @@
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_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
EXPECT_EQ(NO_ERROR,
mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index d90521a..c0c7e2f 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -45,6 +45,7 @@
headerLibraries = [
"vulkan_headers",
+ "libdvr_headers",
]
cc_library {
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 935ca2e..5a0c3d0 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -138,13 +138,13 @@
ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
for (size_t i = 0; i < capacity; i++) {
size_t slot;
- const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
- format, usage, &slot);
- if (ret < 0) {
+ auto allocate_status = producer_queue->AllocateBuffer(
+ width, height, layer_count, format, usage, &slot);
+ if (!allocate_status) {
ALOGE(
"Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
- producer_queue->id(), strerror(-ret));
- return ErrorStatus(ENOMEM);
+ producer_queue->id(), allocate_status.GetErrorMessage().c_str());
+ return allocate_status.error_status();
}
ALOGD_IF(
TRACE,
@@ -176,14 +176,14 @@
return ErrorStatus(error);
}
-Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
- const std::string& name) {
- auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
+Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
+ DvrGlobalBufferKey key) {
+ auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
if (!status) {
ALOGE(
- "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
+ "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
"error=%s",
- name.c_str(), status.GetErrorMessage().c_str());
+ key, status.GetErrorMessage().c_str());
return status.error_status();
}
@@ -192,9 +192,9 @@
const int ret = native_buffer_handle.Import(ion_buffer.get());
if (ret < 0) {
ALOGE(
- "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
- "name=%s; error=%s",
- name.c_str(), strerror(-ret));
+ "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
+ "key=%d; error=%s",
+ key, strerror(-ret));
return ErrorStatus(-ret);
}
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdisplay/display_manager_client.cpp
index 82dacf7..47c4599 100644
--- a/libs/vr/libdisplay/display_manager_client.cpp
+++ b/libs/vr/libdisplay/display_manager_client.cpp
@@ -32,13 +32,13 @@
return status;
}
-pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupNamedBuffer(
- const std::string& name, size_t size, uint64_t usage) {
- auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
- name, size, usage);
+pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupGlobalBuffer(
+ DvrGlobalBufferKey key, size_t size, uint64_t usage) {
+ auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupGlobalBuffer>(
+ key, size, usage);
if (!status) {
ALOGE(
- "DisplayManagerClient::SetupPoseBuffer: Failed to create the named "
+ "DisplayManagerClient::SetupGlobalBuffer: Failed to create the global "
"buffer %s",
status.GetErrorMessage().c_str());
return status.error_status();
@@ -49,15 +49,29 @@
const int ret = native_buffer_handle.Import(ion_buffer.get());
if (ret < 0) {
ALOGE(
- "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
- "name=%s; error=%s",
- name.c_str(), strerror(-ret));
+ "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
+ "key=%d; error=%s",
+ key, strerror(-ret));
return ErrorStatus(-ret);
}
return {std::move(ion_buffer)};
}
+pdx::Status<std::string> DisplayManagerClient::GetConfigurationData(
+ ConfigFileType config_type) {
+ auto status =
+ InvokeRemoteMethod<DisplayManagerProtocol::GetConfigurationData>(
+ config_type);
+ if (!status && status.error() != ENOENT) {
+ ALOGE(
+ "DisplayManagerClient::GetConfigurationData: Unable to get "
+ "configuration data. Error: %s",
+ status.GetErrorMessage().c_str());
+ }
+ return status;
+}
+
pdx::Status<std::unique_ptr<ConsumerQueue>>
DisplayManagerClient::GetSurfaceQueue(int surface_id, int queue_id) {
auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 7a7f670..e5b3340 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -1,6 +1,7 @@
#ifndef ANDROID_DVR_DISPLAY_CLIENT_H_
#define ANDROID_DVR_DISPLAY_CLIENT_H_
+#include <dvr/dvr_api.h>
#include <hardware/hwcomposer.h>
#include <pdx/client.h>
#include <pdx/file_handle.h>
@@ -67,8 +68,8 @@
class DisplayClient : public pdx::ClientBase<DisplayClient> {
public:
pdx::Status<Metrics> GetDisplayMetrics();
- pdx::Status<std::unique_ptr<IonBuffer>> GetNamedBuffer(
- const std::string& name);
+ pdx::Status<std::unique_ptr<IonBuffer>> GetGlobalBuffer(
+ DvrGlobalBufferKey key);
pdx::Status<std::unique_ptr<Surface>> CreateSurface(
const SurfaceAttributes& attributes);
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
index fea8415..8bf12b6 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
@@ -21,11 +21,12 @@
~DisplayManagerClient() override;
pdx::Status<std::vector<SurfaceState>> GetSurfaceState();
- pdx::Status<std::unique_ptr<IonBuffer>> SetupNamedBuffer(
- const std::string& name, size_t size, uint64_t usage);
+ pdx::Status<std::unique_ptr<IonBuffer>> SetupGlobalBuffer(
+ DvrGlobalBufferKey key, size_t size, uint64_t usage);
pdx::Status<std::unique_ptr<ConsumerQueue>> GetSurfaceQueue(int surface_id,
int queue_id);
+ pdx::Status<std::string> GetConfigurationData(ConfigFileType config_type);
using Client::event_fd;
pdx::Status<int> GetEventMask(int events) {
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index f34d61f..b22ddfa 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -8,6 +8,8 @@
#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_api.h>
+#include <pdx/rpc/buffer_wrapper.h>
#include <pdx/rpc/remote_method.h>
#include <pdx/rpc/serializable.h>
#include <pdx/rpc/variant.h>
@@ -191,7 +193,7 @@
// Op codes.
enum {
kOpGetMetrics = 0,
- kOpGetNamedBuffer,
+ kOpGetGlobalBuffer,
kOpIsVrAppRunning,
kOpCreateSurface,
kOpGetSurfaceInfo,
@@ -205,8 +207,8 @@
// Methods.
PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, Metrics(Void));
- PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
- LocalNativeBufferHandle(std::string name));
+ PDX_REMOTE_METHOD(GetGlobalBuffer, kOpGetGlobalBuffer,
+ LocalNativeBufferHandle(DvrGlobalBufferKey key));
PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, bool(Void));
PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
SurfaceInfo(const SurfaceAttributes& attributes));
@@ -217,6 +219,12 @@
void(const SurfaceAttributes& attributes));
};
+enum class ConfigFileType : uint32_t {
+ kLensMetrics,
+ kDeviceMetrics,
+ kDeviceConfiguration
+};
+
struct DisplayManagerProtocol {
// Service path.
static constexpr char kClientPath[] = "system/vr/display/manager";
@@ -225,7 +233,8 @@
enum {
kOpGetSurfaceState = 0,
kOpGetSurfaceQueue,
- kOpSetupNamedBuffer,
+ kOpSetupGlobalBuffer,
+ kOpGetConfigurationData,
};
// Aliases.
@@ -237,9 +246,11 @@
std::vector<SurfaceState>(Void));
PDX_REMOTE_METHOD(GetSurfaceQueue, kOpGetSurfaceQueue,
LocalChannelHandle(int surface_id, int queue_id));
- PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
- LocalNativeBufferHandle(const std::string& name,
- size_t size, uint64_t usage));
+ PDX_REMOTE_METHOD(SetupGlobalBuffer, kOpSetupGlobalBuffer,
+ LocalNativeBufferHandle(DvrGlobalBufferKey key, size_t size,
+ uint64_t usage));
+ PDX_REMOTE_METHOD(GetConfigurationData, kOpGetConfigurationData,
+ std::string(ConfigFileType config_type));
};
struct VSyncSchedInfo {
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
index 87636ec..e67e8c3 100644
--- a/libs/vr/libdvr/dvr_display_manager.cpp
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -11,6 +11,7 @@
using android::AHardwareBuffer_convertToGrallocUsageBits;
using android::dvr::BufferConsumer;
+using android::dvr::display::ConfigFileType;
using android::dvr::display::DisplayManagerClient;
using android::dvr::display::SurfaceAttributes;
using android::dvr::display::SurfaceAttribute;
@@ -111,19 +112,20 @@
void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
-int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
- const char* name, size_t size,
- uint64_t usage, DvrBuffer** buffer_out) {
- if (!client || !name || !buffer_out)
+int dvrDisplayManagerSetupGlobalBuffer(DvrDisplayManager* client,
+ DvrGlobalBufferKey key, size_t size,
+ uint64_t usage, DvrBuffer** buffer_out) {
+ if (!client || !buffer_out)
return -EINVAL;
uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
auto buffer_status =
- client->client->SetupNamedBuffer(name, size, gralloc_usage);
+ client->client->SetupGlobalBuffer(key, size, gralloc_usage);
if (!buffer_status) {
- ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
- buffer_status.GetErrorMessage().c_str());
+ ALOGE(
+ "dvrDisplayManagerSetupGlobalBuffer: Failed to setup global buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
return -buffer_status.error();
}
@@ -131,6 +133,30 @@
return 0;
}
+int dvrConfigurationDataGet(DvrDisplayManager* client, int config_type,
+ uint8_t** data, size_t* data_size) {
+ if (!client || !data || !data_size) {
+ return -EINVAL;
+ }
+
+ ConfigFileType config_file_type = static_cast<ConfigFileType>(config_type);
+ auto config_data_status =
+ client->client->GetConfigurationData(config_file_type);
+
+ if (!config_data_status) {
+ return -config_data_status.error();
+ }
+
+ *data_size = config_data_status.get().size();
+ *data = new uint8_t[*data_size];
+ std::copy_n(config_data_status.get().begin(), *data_size, *data);
+ return 0;
+}
+
+void dvrConfigurationDataDestroy(DvrDisplayManager*, uint8_t* data) {
+ delete[] data;
+}
+
int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
if (!client)
return -EINVAL;
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index 89bef09..6431f1c 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -44,6 +44,8 @@
extern "C" {
+struct ANativeWindow;
+
struct DvrWriteBuffer {
std::shared_ptr<android::dvr::BufferProducer> write_buffer;
};
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index 67e2ae8..1fe9874 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -156,22 +156,22 @@
return 0;
}
-int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
+int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer) {
auto client = DisplayClient::Create();
if (!client) {
- ALOGE("dvrGetNamedBuffer: Failed to create display client!");
+ ALOGE("dvrGetGlobalBuffer: Failed to create display client!");
return -ECOMM;
}
- if (out_buffer == nullptr || name == nullptr) {
- ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+ if (out_buffer == nullptr) {
+ ALOGE("dvrGetGlobalBuffer: Invalid inputs: key=%d, out_buffer=%p.", key,
out_buffer);
return -EINVAL;
}
- auto status = client->GetNamedBuffer(name);
+ auto status = client->GetGlobalBuffer(key);
if (!status) {
- ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
+ ALOGE("dvrGetGlobalBuffer: Failed to find named buffer key=%d: %s", key,
status.GetErrorMessage().c_str());
return -status.error();
}
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 8a203e0..ef2c975 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -33,6 +33,7 @@
typedef struct DvrSurface DvrSurface;
typedef uint64_t DvrSurfaceAttributeType;
typedef int32_t DvrSurfaceAttributeKey;
+typedef int32_t DvrGlobalBufferKey;
typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
@@ -42,10 +43,11 @@
// dvr_display_manager.h
typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out);
typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client);
-typedef int (*DvrDisplayManagerSetupNamedBufferPtr)(DvrDisplayManager* client,
- const char* name,
- size_t size, uint64_t usage,
- DvrBuffer** buffer_out);
+typedef int (*DvrDisplayManagerSetupGlobalBufferPtr)(DvrDisplayManager* client,
+ DvrGlobalBufferKey key,
+ size_t size,
+ uint64_t usage,
+ DvrBuffer** buffer_out);
typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client);
typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)(
DvrDisplayManager* client, int in_events, int* out_events);
@@ -54,6 +56,11 @@
typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)(
DvrDisplayManager* client, int surface_id, int queue_id,
DvrReadBufferQueue** queue_out);
+typedef int (*DvrConfigurationDataGetPtr)(DvrDisplayManager* client,
+ int config_type, uint8_t** data,
+ size_t* data_size);
+typedef void (*DvrConfigurationDataDestroyPtr)(DvrDisplayManager* client,
+ uint8_t* data);
typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state);
typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state);
typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state,
@@ -151,7 +158,8 @@
size_t meta_size_bytes);
// dvr_surface.h
-typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
+typedef int (*DvrGetGlobalBufferPtr)(DvrGlobalBufferKey key,
+ DvrBuffer** out_buffer);
typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes,
size_t attribute_count,
DvrSurface** surface_out);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 09568fd..30d0a65 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -11,11 +11,13 @@
// Display manager client
DVR_V1_API_ENTRY(DisplayManagerCreate);
DVR_V1_API_ENTRY(DisplayManagerDestroy);
-DVR_V1_API_ENTRY(DisplayManagerSetupNamedBuffer);
+DVR_V1_API_ENTRY(DisplayManagerSetupGlobalBuffer);
DVR_V1_API_ENTRY(DisplayManagerGetEventFd);
DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask);
DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState);
DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue);
+DVR_V1_API_ENTRY(ConfigurationDataGet);
+DVR_V1_API_ENTRY(ConfigurationDataDestroy);
DVR_V1_API_ENTRY(SurfaceStateCreate);
DVR_V1_API_ENTRY(SurfaceStateDestroy);
DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount);
@@ -84,7 +86,7 @@
DVR_V1_API_ENTRY(SurfaceGetId);
DVR_V1_API_ENTRY(SurfaceSetAttributes);
DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue);
-DVR_V1_API_ENTRY(GetNamedBuffer);
+DVR_V1_API_ENTRY(GetGlobalBuffer);
// Pose client
DVR_V1_API_ENTRY(PoseCreate);
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
index d5aef8b..f8db182 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_manager.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -28,9 +28,24 @@
// Sets up a named buffer for shared memory data transfer between display
// clients and the display manager.
// @return 0 on success. Otherwise returns a negative error value.
-int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
- const char* name, size_t size,
- uint64_t usage, DvrBuffer** buffer_out);
+int dvrDisplayManagerSetupGlobalBuffer(DvrDisplayManager* client,
+ DvrGlobalBufferKey key, size_t size,
+ uint64_t usage, DvrBuffer** buffer_out);
+
+// Device metrics data type enums.
+enum {
+ DVR_CONFIGURATION_DATA_LENS_METRICS = 0,
+ DVR_CONFIGURATION_DATA_DEVICE_METRICS = 1,
+ DVR_CONFIGURATION_DATA_DEVICE_CONFIG = 2,
+};
+
+// Loads device configuration data of DVR_CONFIGURATION_DATA_*.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrConfigurationDataGet(DvrDisplayManager* client, int config_type,
+ uint8_t** data, size_t* data_size);
+
+// Destroy the configuration data returned from dvrGetConfigurationData.
+void dvrConfigurationDataDestroy(DvrDisplayManager* client, uint8_t* data);
// Returns an fd used to signal when surface updates occur. Note that depending
// on the underlying transport, only a subset of the real event bits may be
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 361488e..e3ab41b 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -6,16 +6,13 @@
#include <stdint.h>
#include <sys/cdefs.h>
+#include <dvr/dvr_api.h>
#include <dvr/dvr_buffer.h>
#include <dvr/dvr_buffer_queue.h>
#include <dvr/dvr_display_types.h>
__BEGIN_DECLS
-typedef struct DvrBuffer DvrBuffer;
-typedef struct DvrSurface DvrSurface;
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
-
// Attribute types. The values are one-hot encoded to support singluar types or
// masks of supported types.
enum {
@@ -82,9 +79,9 @@
size_t capacity,
DvrWriteBufferQueue** queue_out);
-// Get a named buffer from the display service.
+// Get a global buffer from the display service.
// @return 0 on success. Otherwise returns a negative error value.
-int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
+int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer);
__END_DECLS
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 474e968..5d12020 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -40,10 +40,11 @@
void AllocateBuffers(size_t buffer_count) {
size_t out_slot;
for (size_t i = 0; i < buffer_count; i++) {
- int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
- ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
- kBufferFormat, kBufferUsage, &out_slot);
- ASSERT_EQ(0, ret);
+ auto status =
+ GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
+ ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
+ kBufferFormat, kBufferUsage, &out_slot);
+ ASSERT_TRUE(status.ok());
}
}
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index a2414d6..6f11465 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -1,3 +1,4 @@
+#include <android-base/properties.h>
#include <base/logging.h>
#include <gtest/gtest.h>
#include <poll.h>
@@ -200,6 +201,24 @@
return {std::move(queue_ids)};
}
+ Status<std::vector<uint8_t>> GetConfigData(int config_type) {
+ uint8_t* data = nullptr;
+ size_t data_size = 0;
+ int error = dvrConfigurationDataGet(display_manager_.get(), config_type,
+ &data, &data_size);
+ if (error < 0) {
+ return ErrorStatus(-error);
+ }
+
+ if (!data || data_size == 0) {
+ return ErrorStatus(EINVAL);
+ }
+ std::vector<uint8_t> data_result(data, data + data_size);
+ dvrConfigurationDataDestroy(display_manager_.get(), data);
+ std::string s(data, data + data_size);
+ return {std::move(data_result)};
+ }
+
private:
UniqueDvrDisplayManager display_manager_;
UniqueDvrSurfaceState surface_state_;
@@ -573,6 +592,23 @@
dvrWriteBufferDestroy(buffer);
}
+TEST_F(DvrDisplayManagerTest, ConfigurationData) {
+ auto data1 = manager_->GetConfigData(-1);
+ ASSERT_STATUS_ERROR(data1);
+
+ const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
+
+ // This should be run on devices with and without built in metrics.
+ bool has_metric = !base::GetProperty(kDvrLensMetricsProperty, "").empty();
+ auto data2 = manager_->GetConfigData(DVR_CONFIGURATION_DATA_LENS_METRICS);
+ if (has_metric) {
+ ASSERT_STATUS_OK(data2);
+ ASSERT_NE(0u, data2.get().size());
+ } else {
+ ASSERT_STATUS_ERROR(data2);
+ }
+}
+
} // namespace
} // namespace dvr
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index e65f6d5..336f11f 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -29,16 +29,16 @@
};
TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
- const char* buffer_name = "same_name";
+ const DvrGlobalBufferKey buffer_key = 101;
DvrBuffer* buffer1 = nullptr;
int ret1 =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer1);
+ dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key, 10, 0, &buffer1);
ASSERT_EQ(0, ret1);
ASSERT_NE(nullptr, buffer1);
DvrBuffer* buffer2 = nullptr;
int ret2 =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer2);
+ dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key, 10, 0, &buffer2);
ASSERT_EQ(0, ret1);
ASSERT_NE(nullptr, buffer2);
@@ -71,7 +71,7 @@
dvrBufferDestroy(buffer2);
DvrBuffer* buffer3 = nullptr;
- int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+ int e3 = dvrGetGlobalBuffer(buffer_key, &buffer3);
ASSERT_NE(nullptr, buffer3);
ASSERT_EQ(0, e3);
@@ -96,37 +96,37 @@
}
TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
- const char* buffer_name1 = "test1";
- const char* buffer_name2 = "test2";
+ const DvrGlobalBufferKey buffer_key1 = 102;
+ const DvrGlobalBufferKey buffer_key2 = 103;
DvrBuffer* setup_buffer1 = nullptr;
- int ret1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0,
- &setup_buffer1);
+ int ret1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key1, 10, 0,
+ &setup_buffer1);
ASSERT_EQ(0, ret1);
ASSERT_NE(nullptr, setup_buffer1);
dvrBufferDestroy(setup_buffer1);
DvrBuffer* setup_buffer2 = nullptr;
- int ret2 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0,
- &setup_buffer2);
+ int ret2 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key2, 10, 0,
+ &setup_buffer2);
ASSERT_EQ(0, ret2);
ASSERT_NE(nullptr, setup_buffer2);
dvrBufferDestroy(setup_buffer2);
DvrBuffer* buffer1 = nullptr;
- int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+ int e1 = dvrGetGlobalBuffer(buffer_key1, &buffer1);
ASSERT_NE(nullptr, buffer1);
ASSERT_EQ(0, e1);
dvrBufferDestroy(buffer1);
DvrBuffer* buffer2 = nullptr;
- int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+ int e2 = dvrGetGlobalBuffer(buffer_key2, &buffer2);
ASSERT_NE(nullptr, buffer2);
ASSERT_EQ(0, e2);
dvrBufferDestroy(buffer2);
}
TEST_F(DvrNamedBufferTest, TestNamedBufferUsage) {
- const char* buffer_name = "buffer_usage";
+ const DvrGlobalBufferKey buffer_key = 100;
// Set usage to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE. We use this because
// internally AHARDWAREBUFFER_USAGE_VIDEO_ENCODE is converted to
@@ -136,8 +136,8 @@
const uint64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
DvrBuffer* setup_buffer = nullptr;
- int e1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage,
- &setup_buffer);
+ int e1 = dvrDisplayManagerSetupGlobalBuffer(client_, buffer_key, 10, usage,
+ &setup_buffer);
ASSERT_NE(nullptr, setup_buffer);
ASSERT_EQ(0, e1);
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index de26a74..d37031f 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -61,6 +61,10 @@
"libfmq",
]
+headerLibraries = [
+ "libdvr_headers"
+]
+
cc_library_static {
srcs: sourceFiles,
export_include_dirs: includeFiles,
@@ -73,6 +77,7 @@
"-DEGL_EGLEXT_PROTOTYPES",
],
shared_libs: sharedLibraries,
+ header_libs: headerLibraries,
whole_static_libs: staticLibraries,
name: "libvrflinger",
}
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index a0b3efe..7b5aa79 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -1,5 +1,7 @@
#include "display_manager_service.h"
+#include <android-base/file.h>
+#include <android-base/properties.h>
#include <pdx/channel_handle.h>
#include <pdx/default_transport/service_endpoint.h>
#include <private/android_filesystem_config.h>
@@ -19,6 +21,14 @@
using android::pdx::rpc::IfAnyOf;
using android::pdx::rpc::RemoteMethodError;
+namespace {
+
+const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
+const char kDvrDeviceMetricsProperty[] = "ro.dvr.device_metrics";
+const char kDvrDeviceConfigProperty[] = "ro.dvr.device_configuration";
+
+} // namespace
+
namespace android {
namespace dvr {
@@ -78,9 +88,14 @@
*this, &DisplayManagerService::OnGetSurfaceQueue, message);
return {};
- case DisplayManagerProtocol::SetupNamedBuffer::Opcode:
- DispatchRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
- *this, &DisplayManagerService::OnSetupNamedBuffer, message);
+ case DisplayManagerProtocol::SetupGlobalBuffer::Opcode:
+ DispatchRemoteMethod<DisplayManagerProtocol::SetupGlobalBuffer>(
+ *this, &DisplayManagerService::OnSetupGlobalBuffer, message);
+ return {};
+
+ case DisplayManagerProtocol::GetConfigurationData::Opcode:
+ DispatchRemoteMethod<DisplayManagerProtocol::GetConfigurationData>(
+ *this, &DisplayManagerService::OnGetConfigurationData, message);
return {};
default:
@@ -130,20 +145,49 @@
}
pdx::Status<BorrowedNativeBufferHandle>
-DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
- const std::string& name, size_t size,
- uint64_t usage) {
+DisplayManagerService::OnSetupGlobalBuffer(pdx::Message& message,
+ DvrGlobalBufferKey key, size_t size,
+ uint64_t usage) {
const int user_id = message.GetEffectiveUserId();
const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
if (!trusted) {
ALOGE(
- "DisplayService::SetupNamedBuffer: Named buffers may only be created "
+ "DisplayService::SetupGlobalBuffer: Global buffers may only be created "
"by trusted UIDs: user_id=%d",
user_id);
return ErrorStatus(EPERM);
}
- return display_service_->SetupNamedBuffer(name, size, usage);
+ return display_service_->SetupGlobalBuffer(key, size, usage);
+}
+
+pdx::Status<std::string> DisplayManagerService::OnGetConfigurationData(
+ pdx::Message& message, display::ConfigFileType config_type) {
+ std::string property_name;
+ switch (config_type) {
+ case display::ConfigFileType::kLensMetrics:
+ property_name = kDvrLensMetricsProperty;
+ break;
+ case display::ConfigFileType::kDeviceMetrics:
+ property_name = kDvrDeviceMetricsProperty;
+ break;
+ case display::ConfigFileType::kDeviceConfiguration:
+ property_name = kDvrDeviceConfigProperty;
+ break;
+ default:
+ return ErrorStatus(EINVAL);
+ }
+ std::string file_path = base::GetProperty(property_name, "");
+ if (file_path.empty()) {
+ return ErrorStatus(ENOENT);
+ }
+
+ std::string data;
+ if (!base::ReadFileToString(file_path, &data)) {
+ return ErrorStatus(errno);
+ }
+
+ return std::move(data);
}
void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 0857eb5..4a08405 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -56,9 +56,11 @@
pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message,
int surface_id,
int queue_id);
- pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
- pdx::Message& message, const std::string& name, size_t size,
+ pdx::Status<BorrowedNativeBufferHandle> OnSetupGlobalBuffer(
+ pdx::Message& message, DvrGlobalBufferKey key, size_t size,
uint64_t usage);
+ pdx::Status<std::string> OnGetConfigurationData(
+ pdx::Message& message, display::ConfigFileType config_type);
// Called by the display service to indicate changes to display surfaces that
// the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 47efa76..4cc5f02 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -65,9 +65,9 @@
*this, &DisplayService::OnCreateSurface, message);
return {};
- case DisplayProtocol::GetNamedBuffer::Opcode:
- DispatchRemoteMethod<DisplayProtocol::GetNamedBuffer>(
- *this, &DisplayService::OnGetNamedBuffer, message);
+ case DisplayProtocol::GetGlobalBuffer::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::GetGlobalBuffer>(
+ *this, &DisplayService::OnGetGlobalBuffer, message);
return {};
case DisplayProtocol::IsVrAppRunning::Opcode:
@@ -155,12 +155,12 @@
}
}
-pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
- pdx::Message& /* message */, const std::string& name) {
- ALOGD_IF(TRACE, "displayService::OnGetNamedBuffer: name=%s", name.c_str());
- auto named_buffer = named_buffers_.find(name);
- if (named_buffer != named_buffers_.end())
- return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetGlobalBuffer(
+ pdx::Message& /* message */, DvrGlobalBufferKey key) {
+ ALOGD_IF(TRACE, "DisplayService::OnGetGlobalBuffer: key=%d", key);
+ auto global_buffer = global_buffers_.find(key);
+ if (global_buffer != global_buffers_.end())
+ return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
else
return pdx::ErrorStatus(EINVAL);
}
@@ -221,18 +221,18 @@
hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
}
-pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
- const std::string& name, size_t size, uint64_t usage) {
- auto named_buffer = named_buffers_.find(name);
- if (named_buffer == named_buffers_.end()) {
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupGlobalBuffer(
+ DvrGlobalBufferKey key, size_t size, uint64_t usage) {
+ auto global_buffer = global_buffers_.find(key);
+ if (global_buffer == global_buffers_.end()) {
auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
HAL_PIXEL_FORMAT_BLOB, usage);
- named_buffer =
- named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+ global_buffer =
+ global_buffers_.insert(std::make_pair(key, std::move(ion_buffer)))
.first;
}
- return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
+ return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
}
void DisplayService::OnHardwareComposerRefresh() {
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index bb4eeef..77e45a4 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -1,6 +1,7 @@
#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
+#include <dvr/dvr_api.h>
#include <pdx/service.h>
#include <pdx/status.h>
#include <private/dvr/buffer_hub_client.h>
@@ -40,8 +41,8 @@
// any change to client/manager attributes that affect visibility or z order.
void UpdateActiveDisplaySurfaces();
- pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
- const std::string& name, size_t size, uint64_t usage);
+ pdx::Status<BorrowedNativeBufferHandle> SetupGlobalBuffer(
+ DvrGlobalBufferKey key, size_t size, uint64_t usage);
template <class A>
void ForEachDisplaySurface(SurfaceType surface_type, A action) const {
@@ -82,8 +83,8 @@
DisplayService(android::Hwc2::Composer* hidl,
RequestDisplayCallback request_display_callback);
- pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
- pdx::Message& message, const std::string& name);
+ pdx::Status<BorrowedNativeBufferHandle> OnGetGlobalBuffer(
+ pdx::Message& message, DvrGlobalBufferKey key);
pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
pdx::Status<display::SurfaceInfo> OnCreateSurface(
pdx::Message& message, const display::SurfaceAttributes& attributes);
@@ -113,7 +114,8 @@
EpollEventDispatcher dispatcher_;
DisplayConfigurationUpdateNotifier update_notifier_;
- std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
+ std::unordered_map<DvrGlobalBufferKey, std::unique_ptr<IonBuffer>>
+ global_buffers_;
DisplayService(const DisplayService&) = delete;
void operator=(const DisplayService&) = delete;
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index ed75f84..6802fa9 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -105,6 +105,8 @@
DVR_POSE_MODE_MOCK_ROTATE_MEDIUM,
DVR_POSE_MODE_MOCK_ROTATE_FAST,
DVR_POSE_MODE_MOCK_CIRCLE_STRAFE,
+ DVR_POSE_MODE_FLOAT,
+ DVR_POSE_MODE_MOCK_MOTION_SICKNESS,
// Always last.
DVR_POSE_MODE_COUNT,
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index d0996f0..7de8c62 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -625,6 +625,11 @@
#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
#endif
+#ifndef EGL_KHR_no_config_context
+#define EGL_KHR_no_config_context 1
+#define EGL_NO_CONFIG_KHR EGL_CAST(EGLConfig,0)
+#endif /* EGL_KHR_no_config_context */
+
#ifndef EGL_ANDROID_get_frame_timestamps
#define EGL_ANDROID_get_frame_timestamps 1
#define EGL_TIMESTAMPS_ANDROID 0x3430
@@ -667,6 +672,16 @@
#define EGL_GL_COLORSPACE_BT2020_PQ_EXT 0x3340
#endif /* EGL_EXT_gl_colorspace_bt2020_pq */
+#ifndef EGL_EXT_gl_colorspace_display_p3
+#define EGL_EXT_gl_colorspace_display_p3 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363
+#endif /* EGL_EXT_gl_colorspace_display_p3 */
+
+#ifndef EGL_EXT_gl_colorspace_display_p3_linear
+#define EGL_EXT_gl_colorspace_display_p3_linear 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
+#endif /* EGL_EXT_gl_colorspace_display_p3_linear */
+
#ifndef EGL_EXT_gl_colorspace_scrgb_linear
#define EGL_EXT_gl_colorspace_scrgb_linear 1
#define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 4b08749..c7635e2 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -26,7 +26,7 @@
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui libnativewindow
LOCAL_SRC_FILES_arm += fixed_asm.S iterators.S
LOCAL_CFLAGS_arm += -fstrict-aliasing
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 04f6d6d..b79051c 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -56,6 +56,24 @@
EGLBoolean EGLAPI eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
EGLint left, EGLint top, EGLint width, EGLint height);
+
+typedef struct egl_native_pixmap_t
+{
+ int32_t version; /* must be 32 */
+ int32_t width;
+ int32_t height;
+ int32_t stride;
+ uint8_t* data;
+ uint8_t format;
+ uint8_t rfu[3];
+ union {
+ uint32_t compressedFormat;
+ int32_t vstride;
+ };
+ int32_t reserved;
+} egl_native_pixmap_t;
+
+
// ----------------------------------------------------------------------------
namespace android {
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index a895e63..bff80cd 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -81,7 +81,7 @@
shared_libs: [
// ***** DO NOT ADD NEW DEPENDENCIES HERE *****
// In particular, DO NOT add libutils nor anything "above" libui
- "libui",
+ "libgraphicsenv",
"libnativewindow",
"libbacktrace",
],
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 7d20ba1..1116400 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -28,7 +28,7 @@
#include <cutils/properties.h>
#include <log/log.h>
-#include <ui/GraphicsEnv.h>
+#include <graphicsenv/GraphicsEnv.h>
#include "egl_trace.h"
#include "egldefs.h"
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 10f4e66..6bff38a 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -79,6 +79,7 @@
extern char const * const gBuiltinExtensionString;
extern char const * const gExtensionString;
+// clang-format off
char const * const gBuiltinExtensionString =
"EGL_KHR_get_all_proc_addresses "
"EGL_ANDROID_presentation_time "
@@ -86,6 +87,9 @@
"EGL_ANDROID_get_native_client_buffer "
"EGL_ANDROID_front_buffer_auto_refresh "
"EGL_ANDROID_get_frame_timestamps "
+ "EGL_EXT_gl_colorspace_scrgb_linear "
+ "EGL_EXT_gl_colorspace_display_p3_linear "
+ "EGL_EXT_gl_colorspace_display_p3 "
;
char const * const gExtensionString =
@@ -123,6 +127,7 @@
"EGL_IMG_context_priority "
"EGL_KHR_no_config_context "
;
+// clang-format on
// extensions not exposed to applications but used by the ANDROID system
// "EGL_ANDROID_blob_cache " // strongly recommended
@@ -458,10 +463,57 @@
return HAL_DATASPACE_SRGB_LINEAR;
} else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
return HAL_DATASPACE_SRGB;
+ } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
+ return HAL_DATASPACE_DISPLAY_P3_LINEAR;
+ } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
+ return HAL_DATASPACE_V0_SCRGB_LINEAR;
}
return dataSpace;
}
+static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
+ EGLint& colorSpace, android_dataspace& dataSpace) {
+ colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
+ dataSpace = HAL_DATASPACE_UNKNOWN;
+ if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+ for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
+ if (*attr == EGL_GL_COLORSPACE_KHR) {
+ colorSpace = attr[1];
+ bool found = false;
+ // Verify that color space is allowed
+ if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
+ colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
+ found = true;
+ } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
+ dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
+ found = true;
+ } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
+ dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
+ found = true;
+ } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
+ dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
+ found = true;
+ } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
+ dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
+ found = true;
+ } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
+ dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
+ found = true;
+ }
+ if (!found) {
+ return false;
+ }
+ // Only change the dataSpace from default if the application
+ // has explicitly set the color space with a EGL_GL_COLORSPACE_KHR attribute.
+ dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
+ }
+ }
+ }
+ return true;
+}
+
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
NativeWindowType window,
const EGLint *attrib_list)
@@ -502,7 +554,8 @@
&componentType);
EGLint format;
- android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+ EGLint colorSpace;
+ android_dataspace dataSpace;
EGLint a = 0;
EGLint r, g, b;
r = g = b = 0;
@@ -539,12 +592,9 @@
}
// now select a corresponding sRGB format if needed
- if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
- for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
- if (*attr == EGL_GL_COLORSPACE_KHR) {
- dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
- }
- }
+ if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+ ALOGE("error invalid colorspace: %d", colorSpace);
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
if (format != 0) {
@@ -575,8 +625,8 @@
EGLSurface surface = cnx->egl.eglCreateWindowSurface(
iDpy, config, window, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
- surface, cnx);
+ egl_surface_t* s =
+ new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
return s;
}
@@ -595,12 +645,19 @@
egl_connection_t* cnx = NULL;
egl_display_ptr dp = validate_display_connection(dpy, cnx);
+ EGLint colorSpace;
+ android_dataspace dataSpace;
if (dp) {
+ // now select a corresponding sRGB format if needed
+ if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+ ALOGE("error invalid colorspace: %d", colorSpace);
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
dp->disp.dpy, config, pixmap, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
- surface, cnx);
+ egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
return s;
}
}
@@ -614,12 +671,19 @@
egl_connection_t* cnx = NULL;
egl_display_ptr dp = validate_display_connection(dpy, cnx);
+ EGLint colorSpace;
+ android_dataspace dataSpace;
if (dp) {
+ // now select a corresponding sRGB format if needed
+ if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+ ALOGE("error invalid colorspace: %d", colorSpace);
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
dp->disp.dpy, config, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
- surface, cnx);
+ egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
return s;
}
}
@@ -658,6 +722,10 @@
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
egl_surface_t const * const s = get_surface(surface);
+ if (attribute == EGL_GL_COLORSPACE_KHR) {
+ *value = s->getColorSpace();
+ return EGL_TRUE;
+ }
return s->cnx->egl.eglQuerySurface(
dp->disp.dpy, s->surface, attribute, value);
}
@@ -1733,13 +1801,22 @@
egl_display_ptr dp = validate_display(dpy);
if (!dp) return EGL_NO_SURFACE;
+ EGLint colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
+ android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+ // TODO: Probably need to update EGL_KHR_stream_producer_eglsurface to
+ // indicate support for EGL_GL_COLORSPACE_KHR.
+ // now select a corresponding sRGB format if needed
+ if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+ ALOGE("error invalid colorspace: %d", colorSpace);
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
dp->disp.dpy, config, stream, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
- surface, cnx);
+ egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
return s;
}
}
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 6238780..837cfa9 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -55,12 +55,15 @@
// ----------------------------------------------------------------------------
-egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config,
- EGLNativeWindowType win, EGLSurface surface,
- egl_connection_t const* cnx) :
- egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
- connected(true)
-{
+egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win,
+ EGLSurface surface, EGLint colorSpace, egl_connection_t const* cnx)
+ : egl_object_t(dpy),
+ surface(surface),
+ config(config),
+ win(win),
+ cnx(cnx),
+ connected(true),
+ colorSpace(colorSpace) {
if (win) {
win->incStrong(this);
}
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 8988905..7c3075c 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -131,12 +131,12 @@
public:
typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
- egl_surface_t(egl_display_t* dpy, EGLConfig config,
- EGLNativeWindowType win, EGLSurface surface,
- egl_connection_t const* cnx);
+ egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
+ EGLint colorSpace, egl_connection_t const* cnx);
ANativeWindow* getNativeWindow() { return win; }
ANativeWindow* getNativeWindow() const { return win; }
+ EGLint getColorSpace() const { return colorSpace; }
// Try to keep the order of these fields and size unchanged. It's not public API, but
// it's not hard to imagine native games accessing them.
@@ -149,6 +149,7 @@
private:
bool connected;
void disconnect();
+ EGLint colorSpace;
};
class egl_context_t: public egl_object_t {
diff --git a/opengl/tests/Android.bp b/opengl/tests/Android.bp
new file mode 100644
index 0000000..bf7aeb1
--- /dev/null
+++ b/opengl/tests/Android.bp
@@ -0,0 +1,4 @@
+subdirs = [
+ "hwc",
+ "lib",
+]
diff --git a/opengl/tests/Android.mk b/opengl/tests/Android.mk
index 3ae3b4e..92d223c 100644
--- a/opengl/tests/Android.mk
+++ b/opengl/tests/Android.mk
@@ -12,7 +12,6 @@
gl_perf \
gl_yuvtex \
gralloc \
- hwc \
include \
lib \
linetex \
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 24b1315..62e6bd3 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -28,18 +28,17 @@
#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);
+bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
- size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
+ size_t cropExtLen = strlen(extensionName);
size_t extsLen = strlen(exts);
- bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
- bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
+ bool equal = !strcmp(extensionName, exts);
+ android::String8 extString(extensionName);
+ android::String8 space(" ");
+ bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
bool atEnd = (cropExtLen + 1) < extsLen &&
- !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
- bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
+ !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
+ bool inMiddle = strstr(exts, space + extString + space);
return equal || atStart || atEnd || inMiddle;
}
@@ -194,6 +193,176 @@
EXPECT_GE(components[3], 8);
}
+TEST_F(EGLTest, EGLDisplayP3) {
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+
+ if (!hasWideColorDisplay) {
+ // skip this test if device does not have wide-color display
+ return;
+ }
+
+ // Test that display-p3 extensions exist
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+
+ // Use 8-bit to keep forcus on Display-P3 aspect
+ EGLint attrs[] = {
+ // clang-format off
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+ EGL_NONE, EGL_NONE
+ // clang-format on
+ };
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ EGLint components[4];
+ EGLint value;
+ eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+ 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_EQ(components[0], 8);
+ EXPECT_EQ(components[1], 8);
+ EXPECT_EQ(components[2], 8);
+ EXPECT_EQ(components[3], 8);
+
+ 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;
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+ EGL_NONE, EGL_NONE
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLDisplayP31010102) {
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+
+ if (!hasWideColorDisplay) {
+ // skip this test if device does not have wide-color display
+ return;
+ }
+
+ // Test that display-p3 extensions exist
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+
+ // Use 8-bit to keep forcus on Display-P3 aspect
+ EGLint attrs[] = {
+ // clang-format off
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 10,
+ EGL_GREEN_SIZE, 10,
+ EGL_BLUE_SIZE, 10,
+ EGL_ALPHA_SIZE, 2,
+ EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+ EGL_NONE, EGL_NONE
+ // clang-format on
+ };
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ EGLint components[4];
+ EGLint value;
+ eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+ 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_EQ(components[0], 10);
+ EXPECT_EQ(components[1], 10);
+ EXPECT_EQ(components[2], 10);
+ EXPECT_EQ(components[3], 2);
+
+ 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;
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+ EGL_NONE, EGL_NONE
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
TEST_F(EGLTest, EGLConfigFP16) {
EGLint numConfigs;
EGLConfig config;
@@ -204,23 +373,20 @@
return;
}
- ASSERT_TRUE(hasEglPixelFormatFloat());
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
- 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};
+ EGLint attrs[] = {
+ // clang-format off
+ 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, EGL_NONE
+ // clang-format on
+ };
success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(1, numConfigs);
@@ -251,6 +417,108 @@
void onSidebandStreamChanged() override {}
};
+ 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));
+}
+
+TEST_F(EGLTest, EGL_KHR_no_config_context) {
+ if (!hasWideColorDisplay) {
+ // skip this test if device does not have wide-color display
+ return;
+ }
+
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ std::vector<EGLint> contextAttributes;
+ contextAttributes.reserve(4);
+ contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttributes.push_back(2);
+ contextAttributes.push_back(EGL_NONE);
+ contextAttributes.push_back(EGL_NONE);
+
+ EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
+ contextAttributes.data());
+ EXPECT_NE(EGL_NO_CONTEXT, eglContext);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+ if (eglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEglDisplay, eglContext);
+ }
+}
+
+// Emulate what a native application would do to create a
+// 10:10:10:2 surface.
+TEST_F(EGLTest, EGLConfig1010102) {
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+
+ if (!hasWideColorDisplay) {
+ // skip this test if device does not have wide-color display
+ return;
+ }
+
+ EGLint attrs[] = {
+ // clang-format off
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 10,
+ EGL_GREEN_SIZE, 10,
+ EGL_BLUE_SIZE, 10,
+ EGL_ALPHA_SIZE, 2,
+ EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+ EGL_NONE, EGL_NONE
+ // clang-format on
+ };
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ EGLint components[4];
+ EGLint value;
+ eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+ 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_EQ(components[0], 10);
+ EXPECT_EQ(components[1], 10);
+ EXPECT_EQ(components[2], 10);
+ EXPECT_EQ(components[3], 2);
+
+ 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;
diff --git a/opengl/tests/configdump/configdump.cpp b/opengl/tests/configdump/configdump.cpp
index 2a94598..c423105 100644
--- a/opengl/tests/configdump/configdump.cpp
+++ b/opengl/tests/configdump/configdump.cpp
@@ -66,8 +66,7 @@
};
// clang-format on
-int main(int argc, char** argv)
-{
+int main(int /*argc*/, char** /*argv*/) {
EGLConfig* configs;
EGLint n;
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index 9f8d166..ee88667 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -30,6 +30,7 @@
#include <EGLUtils.h>
using namespace android;
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
static void printGLString(const char *name, GLenum s) {
// fprintf(stderr, "printGLString %s, %d\n", name, s);
@@ -46,7 +47,8 @@
static void printEGLString(EGLDisplay dpy, const char *name, GLenum s) {
const char *v = (const char *) eglQueryString(dpy, s);
- fprintf(stderr, "GL %s = %s\n", name, v);
+ const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s);
+ fprintf(stderr, "GL %s = %s\nImplementationANDROID: %s\n", name, v, va);
}
static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
@@ -263,7 +265,7 @@
return true;
}
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
EGLBoolean returnValue;
EGLConfig myConfig = {0};
diff --git a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
index 98d8aa8..22128ab 100644
--- a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
+++ b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
@@ -331,7 +331,7 @@
printf("\n");
}
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
EGLBoolean returnValue;
EGLConfig myConfig = {0};
diff --git a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
index c923b07..fad26a6 100644
--- a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
+++ b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
@@ -221,7 +221,7 @@
printf("\n");
}
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
EGLBoolean returnValue;
EGLConfig myConfig = {0};
diff --git a/opengl/tests/hwc/Android.bp b/opengl/tests/hwc/Android.bp
new file mode 100644
index 0000000..425f374
--- /dev/null
+++ b/opengl/tests/hwc/Android.bp
@@ -0,0 +1,107 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+
+ name: "hwc_tests_defaults",
+ cflags: [
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+}
+
+cc_library_static {
+
+ name: "libhwcTest",
+ srcs: ["hwcTestLib.cpp"],
+
+ static_libs: [
+ "libarect",
+ "libglTest",
+ "libtestUtil",
+ ],
+ shared_libs: [
+ "libui",
+ "libnativewindow"
+ ],
+ defaults: ["hwc_tests_defaults"],
+}
+
+cc_defaults {
+
+ name: "hwc_lib_defaults",
+ shared_libs: [
+ "libcutils",
+ "libEGL",
+ "libGLESv2",
+ "libhardware",
+ "liblog",
+ "libui",
+ "libutils",
+ "libnativewindow"
+ ],
+
+ static_libs: [
+ "libglTest",
+ "libhwcTest",
+ "libtestUtil",
+ ],
+}
+
+cc_test {
+
+ name: "hwcStress",
+ srcs: ["hwcStress.cpp"],
+
+ defaults: [
+ "hwc_lib_defaults",
+ "hwc_tests_defaults",
+ ],
+}
+
+cc_test {
+
+ name: "hwcRects",
+ srcs: ["hwcRects.cpp"],
+
+ defaults: [
+ "hwc_lib_defaults",
+ "hwc_tests_defaults",
+ ],
+}
+
+cc_test {
+
+ name: "hwcColorEquiv",
+ srcs: ["hwcColorEquiv.cpp"],
+
+ defaults: [
+ "hwc_lib_defaults",
+ "hwc_tests_defaults",
+ ],
+}
+
+cc_test {
+
+ name: "hwcCommit",
+ srcs: ["hwcCommit.cpp"],
+
+ defaults: [
+ "hwc_lib_defaults",
+ "hwc_tests_defaults",
+ ],
+}
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
deleted file mode 100644
index 13337c2..0000000
--- a/opengl/tests/hwc/Android.mk
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE:= libhwcTest
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcTestLib.cpp
-LOCAL_C_INCLUDES += system/extras/tests/include \
- $(call include-path-for, opengl-tests-includes) \
-
-LOCAL_STATIC_LIBRARIES := libarect
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcStress
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcStress.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv2 \
- libutils \
- liblog \
- libui \
- libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
- libtestUtil \
- libglTest \
- libhwcTest \
-
-LOCAL_C_INCLUDES += \
- system/extras/tests/include \
- hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcRects
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcRects.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv2 \
- libutils \
- liblog \
- libui \
- libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
- libtestUtil \
- libglTest \
- libhwcTest \
-
-LOCAL_C_INCLUDES += \
- system/extras/tests/include \
- hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcColorEquiv
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcColorEquiv.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv2 \
- libutils \
- liblog \
- libui \
- libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
- libtestUtil \
- libglTest \
- libhwcTest \
-
-LOCAL_C_INCLUDES += \
- system/extras/tests/include \
- hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcCommit
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcCommit.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv2 \
- libutils \
- liblog \
- libui \
- libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
- libtestUtil \
- libglTest \
- libhwcTest \
-
-LOCAL_C_INCLUDES += \
- system/extras/tests/include \
- hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/opengl/tests/lib/Android.bp b/opengl/tests/lib/Android.bp
new file mode 100644
index 0000000..2f6095d
--- /dev/null
+++ b/opengl/tests/lib/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_static {
+
+ name: "libglTest",
+ srcs: [
+ "glTestLib.cpp",
+ "WindowSurface.cpp",
+ ],
+ export_include_dirs: ["include"],
+
+ cflags: [
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+
+ shared_libs: ["libgui"],
+ static_libs: [
+ "libarect",
+ "libtestUtil",
+ ],
+
+}
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
deleted file mode 100644
index ea94bc1..0000000
--- a/opengl/tests/lib/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE:= libglTest
-LOCAL_SRC_FILES:= glTestLib.cpp WindowSurface.cpp
-LOCAL_C_INCLUDES += system/extras/tests/include \
- $(call include-path-for, opengl-tests-includes)
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-
-LOCAL_SHARED_LIBRARIES += libgui
-LOCAL_STATIC_LIBRARIES := libarect
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h
similarity index 100%
rename from opengl/tests/include/EGLUtils.h
rename to opengl/tests/lib/include/EGLUtils.h
diff --git a/opengl/tests/include/WindowSurface.h b/opengl/tests/lib/include/WindowSurface.h
similarity index 100%
rename from opengl/tests/include/WindowSurface.h
rename to opengl/tests/lib/include/WindowSurface.h
diff --git a/opengl/tests/include/glTestLib.h b/opengl/tests/lib/include/glTestLib.h
similarity index 100%
rename from opengl/tests/include/glTestLib.h
rename to opengl/tests/lib/include/glTestLib.h
diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml
index af13395..c2d3494 100755
--- a/opengl/tools/glgen2/registry/egl.xml
+++ b/opengl/tools/glgen2/registry/egl.xml
@@ -191,6 +191,7 @@
<enum value="((EGLSync)0)" name="EGL_NO_SYNC"/>
<enum value="((EGLSyncKHR)0)" name="EGL_NO_SYNC_KHR" alias="EGL_NO_SYNC"/>
<enum value="((EGLSyncNV)0)" name="EGL_NO_SYNC_NV" alias="EGL_NO_SYNC"/>
+ <enum value="EGL_CAST(EGLConfig,0)" name="EGL_NO_CONFIG_KHR"/>
<enum value="10000" name="EGL_DISPLAY_SCALING"/>
<enum value="0xFFFFFFFFFFFFFFFF" name="EGL_FOREVER" type="ull"/>
<enum value="0xFFFFFFFFFFFFFFFF" name="EGL_FOREVER_KHR" type="ull" alias="EGL_FOREVER"/>
@@ -739,7 +740,10 @@
<enum value="50000" name="EGL_METADATA_SCALING_EXT"/>
<unused start="0x334B" end="0x334F"/>
<enum value="0x3350" name="EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT"/>
- <unused start="0x3351" end="0x339F"/>
+ <unused start="0x3351" end="0x3361"/>
+ <enum value="0x3362" name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/>
+ <enum value="0x3363" name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
+ <unused start="0x3364" end="0x339F"/>
</enums>
<enums namespace="EGL" start="0x33A0" end="0x33AF" vendor="ANGLE" comment="Reserved for Shannon Woods (Bug 13175)">
@@ -1891,6 +1895,16 @@
<enum name="EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT"/>
</require>
</extension>
+ <extension name="EGL_EXT_gl_colorspace_display_p3_linear" supported="egl">
+ <require>
+ <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/>
+ </require>
+ </extension>
+ <extension name="EGL_EXT_gl_colorspace_display_p3" supported="egl">
+ <require>
+ <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
+ </require>
+ </extension>
<extension name="EGL_EXT_image_dma_buf_import" supported="egl">
<require>
<enum name="EGL_LINUX_DMA_BUF_EXT"/>
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index d2f8995..50589b4 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -150,7 +150,8 @@
fd(fd), id(id), path(path), identifier(identifier),
classes(0), configuration(NULL), virtualKeyMap(NULL),
ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
- timestampOverrideSec(0), timestampOverrideUsec(0) {
+ timestampOverrideSec(0), timestampOverrideUsec(0), enabled(true),
+ isVirtual(fd < 0) {
memset(keyBitmask, 0, sizeof(keyBitmask));
memset(absBitmask, 0, sizeof(absBitmask));
memset(relBitmask, 0, sizeof(relBitmask));
@@ -173,6 +174,25 @@
}
}
+status_t EventHub::Device::enable() {
+ fd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ if(fd < 0) {
+ ALOGE("could not open %s, %s\n", path.string(), strerror(errno));
+ return -errno;
+ }
+ enabled = true;
+ return OK;
+}
+
+status_t EventHub::Device::disable() {
+ close();
+ enabled = false;
+ return OK;
+}
+
+bool EventHub::Device::hasValidFd() {
+ return !isVirtual && enabled;
+}
// --- EventHub ---
@@ -286,7 +306,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
+ if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
struct input_absinfo info;
if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -337,7 +357,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) {
+ if (device && device->hasValidFd() && test_bit(scanCode, device->keyBitmask)) {
uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
memset(keyState, 0, sizeof(keyState));
if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
@@ -352,7 +372,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) {
+ if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
Vector<int32_t> scanCodes;
device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
if (scanCodes.size() != 0) {
@@ -377,7 +397,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) {
+ if (device && device->hasValidFd() && test_bit(sw, device->swBitmask)) {
uint8_t swState[sizeof_bit_array(SW_MAX + 1)];
memset(swState, 0, sizeof(swState));
if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) {
@@ -395,7 +415,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
+ if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
struct input_absinfo info;
if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -532,7 +552,7 @@
void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
int32_t sc;
- if (device && !device->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
+ if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
struct input_event ev;
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
@@ -636,7 +656,7 @@
void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual()) {
+ if (device && device->hasValidFd()) {
ff_effect effect;
memset(&effect, 0, sizeof(effect));
effect.type = FF_RUMBLE;
@@ -670,7 +690,7 @@
void EventHub::cancelVibrate(int32_t deviceId) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual()) {
+ if (device && device->hasValidFd()) {
if (device->ffEffectPlaying) {
device->ffEffectPlaying = false;
@@ -1065,12 +1085,37 @@
AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
};
+status_t EventHub::registerDeviceForEpollLocked(Device* device) {
+ struct epoll_event eventItem;
+ memset(&eventItem, 0, sizeof(eventItem));
+ eventItem.events = EPOLLIN;
+ if (mUsingEpollWakeup) {
+ eventItem.events |= EPOLLWAKEUP;
+ }
+ eventItem.data.u32 = device->id;
+ if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, device->fd, &eventItem)) {
+ ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
+ return -errno;
+ }
+ return OK;
+}
+
+status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
+ if (device->hasValidFd()) {
+ if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
+ ALOGW("Could not remove device fd from epoll instance. errno=%d", errno);
+ return -errno;
+ }
+ }
+ return OK;
+}
+
status_t EventHub::openDeviceLocked(const char *devicePath) {
char buffer[80];
ALOGV("Opening device: %s", devicePath);
- int fd = open(devicePath, O_RDWR | O_CLOEXEC);
+ int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
if(fd < 0) {
ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
return -1;
@@ -1135,13 +1180,6 @@
// Fill in the descriptor.
assignDescriptorLocked(identifier);
- // Make file descriptor non-blocking for use with poll().
- if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
- ALOGE("Error %d making device file descriptor non-blocking.", errno);
- close(fd);
- return -1;
- }
-
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
@@ -1303,12 +1341,6 @@
break;
}
}
-
- // Disable kernel key repeat since we handle it ourselves
- unsigned int repeatRate[] = {0,0};
- if (ioctl(fd, EVIOCSREP, repeatRate)) {
- ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
- }
}
// If the device isn't recognized as something we handle, don't monitor it.
@@ -1332,23 +1364,41 @@
if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
&& device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
device->controllerNumber = getNextControllerNumberLocked(device);
- setLedForController(device);
+ setLedForControllerLocked(device);
}
- // Register with epoll.
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
- if (mUsingEpollWakeup) {
- eventItem.events |= EPOLLWAKEUP;
- }
- eventItem.data.u32 = deviceId;
- if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
- ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
+
+ if (registerDeviceForEpollLocked(device) != OK) {
delete device;
return -1;
}
+ configureFd(device);
+
+ ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
+ "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
+ deviceId, fd, devicePath, device->identifier.name.string(),
+ device->classes,
+ device->configurationFile.string(),
+ device->keyMap.keyLayoutFile.string(),
+ device->keyMap.keyCharacterMapFile.string(),
+ toString(mBuiltInKeyboardId == deviceId));
+
+ addDeviceLocked(device);
+ return OK;
+}
+
+void EventHub::configureFd(Device* device) {
+ // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
+ if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+ // Disable kernel key repeat since we handle it ourselves
+ unsigned int repeatRate[] = {0, 0};
+ if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
+ ALOGW("Unable to disable kernel key repeat for %s: %s",
+ device->path.string(), strerror(errno));
+ }
+ }
+
String8 wakeMechanism("EPOLLWAKEUP");
if (!mUsingEpollWakeup) {
#ifndef EVIOCSSUSPENDBLOCK
@@ -1357,44 +1407,67 @@
// this feature, we need to be prepared to define the ioctl ourselves.
#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
#endif
- if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) {
+ if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
wakeMechanism = "<none>";
} else {
wakeMechanism = "EVIOCSSUSPENDBLOCK";
}
}
-
// Tell the kernel that we want to use the monotonic clock for reporting timestamps
// associated with input events. This is important because the input system
// uses the timestamps extensively and assumes they were recorded using the monotonic
// clock.
- //
- // In older kernel, before Linux 3.4, there was no way to tell the kernel which
- // clock to use to input event timestamps. The standard kernel behavior was to
- // record a real time timestamp, which isn't what we want. Android kernels therefore
- // contained a patch to the evdev_event() function in drivers/input/evdev.c to
- // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
- // clock to be used instead of the real time clock.
- //
- // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
- // Therefore, we no longer require the Android-specific kernel patch described above
- // as long as we make sure to set select the monotonic clock. We do that here.
int clockId = CLOCK_MONOTONIC;
- bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
+ bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
+ ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
+ toString(usingClockIoctl));
+}
- ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
- "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
- "wakeMechanism=%s, usingClockIoctl=%s",
- deviceId, fd, devicePath, device->identifier.name.string(),
- device->classes,
- device->configurationFile.string(),
- device->keyMap.keyLayoutFile.string(),
- device->keyMap.keyCharacterMapFile.string(),
- toString(mBuiltInKeyboardId == deviceId),
- wakeMechanism.string(), toString(usingClockIoctl));
+bool EventHub::isDeviceEnabled(int32_t deviceId) {
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ if (device == NULL) {
+ ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+ return false;
+ }
+ return device->enabled;
+}
- addDeviceLocked(device);
- return 0;
+status_t EventHub::enableDevice(int32_t deviceId) {
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ if (device == NULL) {
+ ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+ return BAD_VALUE;
+ }
+ if (device->enabled) {
+ ALOGW("Duplicate call to %s, input device %" PRId32 " already enabled", __func__, deviceId);
+ return OK;
+ }
+ status_t result = device->enable();
+ if (result != OK) {
+ ALOGE("Failed to enable device %" PRId32, deviceId);
+ return result;
+ }
+
+ configureFd(device);
+
+ return registerDeviceForEpollLocked(device);
+}
+
+status_t EventHub::disableDevice(int32_t deviceId) {
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ if (device == NULL) {
+ ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+ return BAD_VALUE;
+ }
+ if (!device->enabled) {
+ ALOGW("Duplicate call to %s, input device already disabled", __func__);
+ return OK;
+ }
+ unregisterDeviceFromEpollLocked(device);
+ return device->disable();
}
void EventHub::createVirtualKeyboardLocked() {
@@ -1490,7 +1563,7 @@
mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
}
-void EventHub::setLedForController(Device* device) {
+void EventHub::setLedForControllerLocked(Device* device) {
for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
}
@@ -1500,7 +1573,7 @@
if (!device->keyMap.haveKeyLayout()) {
return false;
}
-
+
Vector<int32_t> scanCodes;
device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
const size_t N = scanCodes.size();
@@ -1510,7 +1583,7 @@
return true;
}
}
-
+
return false;
}
@@ -1556,11 +1629,7 @@
mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
}
- if (!device->isVirtual()) {
- if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
- ALOGW("Could not remove device fd from epoll instance. errno=%d", errno);
- }
- }
+ unregisterDeviceFromEpollLocked(device);
releaseControllerNumberLocked(device);
@@ -1691,6 +1760,7 @@
}
dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
+ dump.appendFormat(INDENT3 "Enabled: %s\n", toString(device->enabled));
dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
dump.appendFormat(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 6869253..727b73a 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -25,9 +25,8 @@
#include <input/KeyCharacterMap.h>
#include <input/VirtualKeyMap.h>
#include <utils/String8.h>
-#include <utils/threads.h>
+#include <utils/Mutex.h>
#include <utils/Log.h>
-#include <utils/threads.h>
#include <utils/List.h>
#include <utils/Errors.h>
#include <utils/PropertyMap.h>
@@ -267,6 +266,15 @@
/* Called by the heatbeat to ensures that the reader has not deadlocked. */
virtual void monitor() = 0;
+
+ /* Return true if the device is enabled. */
+ virtual bool isDeviceEnabled(int32_t deviceId) = 0;
+
+ /* Enable an input device */
+ virtual status_t enableDevice(int32_t deviceId) = 0;
+
+ /* Disable an input device. Closes file descriptor to that device. */
+ virtual status_t disableDevice(int32_t deviceId) = 0;
};
class EventHub : public EventHubInterface
@@ -335,7 +343,7 @@
struct Device {
Device* next;
- int fd; // may be -1 if device is virtual
+ int fd; // may be -1 if device is closed
const int32_t id;
const String8 path;
const InputDeviceIdentifier identifier;
@@ -371,7 +379,11 @@
void close();
- inline bool isVirtual() const { return fd < 0; }
+ bool enabled; // initially true
+ status_t enable();
+ status_t disable();
+ bool hasValidFd();
+ const bool isVirtual; // set if fd < 0 is passed to constructor
const sp<KeyCharacterMap>& getKeyCharacterMap() const {
if (combinedKeyMap != NULL) {
@@ -390,6 +402,14 @@
void closeDeviceLocked(Device* device);
void closeAllDevicesLocked();
+ void configureFd(Device* device);
+
+ bool isDeviceEnabled(int32_t deviceId);
+ status_t enableDevice(int32_t deviceId);
+ status_t disableDevice(int32_t deviceId);
+ status_t registerDeviceForEpollLocked(Device* device);
+ status_t unregisterDeviceFromEpollLocked(Device* device);
+
status_t scanDirLocked(const char *dirname);
void scanDevicesLocked();
status_t readNotifyLocked();
@@ -409,7 +429,7 @@
int32_t getNextControllerNumberLocked(Device* device);
void releaseControllerNumberLocked(Device* device);
- void setLedForController(Device* device);
+ void setLedForControllerLocked(Device* device);
status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
void setLedStateLocked(Device* device, int32_t led, bool on);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 73255dd..97565aa 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -835,6 +835,18 @@
}
}
+bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
+ AutoMutex _l(mLock);
+
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex >= 0) {
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ return device->isEnabled();
+ }
+ ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+ return false;
+}
+
void InputReader::dump(String8& dump) {
AutoMutex _l(mLock);
@@ -1011,6 +1023,26 @@
mMappers.clear();
}
+bool InputDevice::isEnabled() {
+ return getEventHub()->isDeviceEnabled(mId);
+}
+
+void InputDevice::setEnabled(bool enabled, nsecs_t when) {
+ if (isEnabled() == enabled) {
+ return;
+ }
+
+ if (enabled) {
+ getEventHub()->enableDevice(mId);
+ reset(when);
+ } else {
+ reset(when);
+ getEventHub()->disableDevice(mId);
+ }
+ // Must change generation to flag this device as changed
+ bumpGeneration();
+}
+
void InputDevice::dump(String8& dump) {
InputDeviceInfo deviceInfo;
getDeviceInfo(& deviceInfo);
@@ -1082,6 +1114,12 @@
}
}
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
+ ssize_t index = config->disabledDevices.indexOf(mId);
+ bool enabled = index < 0;
+ setEnabled(enabled, when);
+ }
+
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index edb6fcc..157fa4f 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -27,11 +27,14 @@
#include <input/VelocityTracker.h>
#include <ui/DisplayInfo.h>
#include <utils/KeyedVector.h>
-#include <utils/threads.h>
+#include <utils/Condition.h>
+#include <utils/Thread.h>
+#include <utils/Mutex.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/BitSet.h>
+#include <utils/SortedVector.h>
#include <stddef.h>
#include <unistd.h>
@@ -84,6 +87,9 @@
// The pointer capture mode has changed.
CHANGE_POINTER_CAPTURE = 1 << 8,
+ // The set of disabled input devices (disabledDevices) has changed.
+ CHANGE_ENABLED_STATE = 1 << 9,
+
// All devices must be reopened.
CHANGE_MUST_REOPEN = 1 << 31,
};
@@ -174,6 +180,9 @@
// True if pointer capture is enabled.
bool pointerCapture;
+ // The set of currently disabled input devices.
+ SortedVector<int32_t> disabledDevices;
+
InputReaderConfiguration() :
virtualKeyQuietTime(0),
pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
@@ -288,6 +297,9 @@
/* Called by the heatbeat to ensures that the reader has not deadlocked. */
virtual void monitor() = 0;
+ /* Returns true if the input device is enabled. */
+ virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
+
/* Runs a single iteration of the processing loop.
* Nominally reads and processes one incoming message from the EventHub.
*
@@ -407,6 +419,8 @@
virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);
+ virtual bool isInputDeviceEnabled(int32_t deviceId);
+
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t scanCode);
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
@@ -552,6 +566,9 @@
inline bool isIgnored() { return mMappers.isEmpty(); }
+ bool isEnabled();
+ void setEnabled(bool enabled, nsecs_t when);
+
void dump(String8& dump);
void addMapper(InputMapper* mapper);
void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index dcfe114..76291a5 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -16,6 +16,7 @@
#include "../InputReader.h"
+#include <inttypes.h>
#include <utils/List.h>
#include <gtest/gtest.h>
#include <math.h>
@@ -159,6 +160,22 @@
mConfig.excludedDeviceNames.push(deviceName);
}
+ void addDisabledDevice(int32_t deviceId) {
+ ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
+ bool currentlyEnabled = index < 0;
+ if (currentlyEnabled) {
+ mConfig.disabledDevices.add(deviceId);
+ }
+ }
+
+ void removeDisabledDevice(int32_t deviceId) {
+ ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
+ bool currentlyEnabled = index < 0;
+ if (!currentlyEnabled) {
+ mConfig.disabledDevices.remove(deviceId);
+ }
+ }
+
void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
mPointerControllers.add(deviceId, controller);
}
@@ -255,6 +272,11 @@
mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin());
}
+ void assertNotifyConfigurationChangedWasNotCalled() {
+ ASSERT_TRUE(mNotifyConfigurationChangedArgsQueue.empty())
+ << "Expected notifyConfigurationChanged() to not have been called.";
+ }
+
void assertNotifyDeviceResetWasCalled(
NotifyDeviceResetArgs* outEventArgs = NULL) {
ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty())
@@ -265,6 +287,11 @@
mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin());
}
+ void assertNotifyDeviceResetWasNotCalled() {
+ ASSERT_TRUE(mNotifyDeviceResetArgsQueue.empty())
+ << "Expected notifyDeviceReset() to not have been called.";
+ }
+
void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) {
ASSERT_FALSE(mNotifyKeyArgsQueue.empty())
<< "Expected notifyKey() to have been called.";
@@ -347,9 +374,20 @@
KeyedVector<int32_t, KeyInfo> keysByUsageCode;
KeyedVector<int32_t, bool> leds;
Vector<VirtualKeyDefinition> virtualKeys;
+ bool enabled;
+
+ status_t enable() {
+ enabled = true;
+ return OK;
+ }
+
+ status_t disable() {
+ enabled = false;
+ return OK;
+ }
explicit Device(uint32_t classes) :
- classes(classes) {
+ classes(classes), enabled(true) {
}
};
@@ -382,6 +420,43 @@
enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
}
+ bool isDeviceEnabled(int32_t deviceId) {
+ Device* device = getDevice(deviceId);
+ if (device == NULL) {
+ ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+ return false;
+ }
+ return device->enabled;
+ }
+
+ status_t enableDevice(int32_t deviceId) {
+ status_t result;
+ Device* device = getDevice(deviceId);
+ if (device == NULL) {
+ ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+ return BAD_VALUE;
+ }
+ if (device->enabled) {
+ ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
+ return OK;
+ }
+ result = device->enable();
+ return result;
+ }
+
+ status_t disableDevice(int32_t deviceId) {
+ Device* device = getDevice(deviceId);
+ if (device == NULL) {
+ ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+ return BAD_VALUE;
+ }
+ if (!device->enabled) {
+ ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
+ return OK;
+ }
+ return device->disable();
+ }
+
void finishDeviceScan() {
enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
}
@@ -1039,6 +1114,20 @@
mFakeEventHub->assertQueueIsEmpty();
}
+ void disableDevice(int32_t deviceId, InputDevice* device) {
+ mFakePolicy->addDisabledDevice(deviceId);
+ configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE, device);
+ }
+
+ void enableDevice(int32_t deviceId, InputDevice* device) {
+ mFakePolicy->removeDisabledDevice(deviceId);
+ configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE, device);
+ }
+
+ void configureDevice(uint32_t changes, InputDevice* device) {
+ device->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
+ }
+
FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
const String8& name, uint32_t classes, uint32_t sources,
const PropertyMap* configuration) {
@@ -1077,6 +1166,46 @@
ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
}
+TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
+ constexpr int32_t deviceId = 1;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ InputDevice* device = mReader->newDevice(deviceId, 0, String8("fake"), deviceClass);
+ // Must add at least one mapper or the device will be ignored!
+ FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD);
+ device->addMapper(mapper);
+ mReader->setNextDevice(device);
+ addDevice(deviceId, String8("fake"), deviceClass, NULL);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(NULL));
+
+ NotifyDeviceResetArgs resetArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+ ASSERT_EQ(deviceId, resetArgs.deviceId);
+
+ ASSERT_EQ(device->isEnabled(), true);
+ disableDevice(deviceId, device);
+ mReader->loopOnce();
+
+ mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+ ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+ ASSERT_EQ(deviceId, resetArgs.deviceId);
+ ASSERT_EQ(device->isEnabled(), false);
+
+ disableDevice(deviceId, device);
+ mReader->loopOnce();
+ mFakeListener->assertNotifyDeviceResetWasNotCalled();
+ mFakeListener->assertNotifyConfigurationChangedWasNotCalled();
+ ASSERT_EQ(device->isEnabled(), false);
+
+ enableDevice(deviceId, device);
+ mReader->loopOnce();
+ mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+ ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+ ASSERT_EQ(deviceId, resetArgs.deviceId);
+ ASSERT_EQ(device->isEnabled(), true);
+}
+
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
FakeInputMapper* mapper = NULL;
ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
@@ -1274,6 +1403,10 @@
ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
}
+TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsTrue) {
+ ASSERT_EQ(mDevice->isEnabled(), true);
+}
+
TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
// Configuration.
InputReaderConfiguration config;
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 8c2300e..8d381b1 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -1,3 +1,73 @@
subdirs = [
"hidl"
]
+cc_library_shared {
+ name: "libsensorservice",
+
+ srcs: [
+ "BatteryService.cpp",
+ "CorrectedGyroSensor.cpp",
+ "Fusion.cpp",
+ "GravitySensor.cpp",
+ "LinearAccelerationSensor.cpp",
+ "OrientationSensor.cpp",
+ "RecentEventLogger.cpp",
+ "RotationVectorSensor.cpp",
+ "SensorDevice.cpp",
+ "SensorDirectConnection.cpp",
+ "SensorEventConnection.cpp",
+ "SensorFusion.cpp",
+ "SensorInterface.cpp",
+ "SensorList.cpp",
+ "SensorRecord.cpp",
+ "SensorService.cpp",
+ "SensorServiceUtils.cpp",
+ ],
+
+ cflags: [
+ "-DLOG_TAG=\"SensorService\"",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-fvisibility=hidden"
+ ],
+
+ shared_libs: [
+ "libcutils",
+ "libhardware",
+ "libhardware_legacy",
+ "libutils",
+ "liblog",
+ "libbinder",
+ "libsensor",
+ "libcrypto",
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "android.hardware.sensors@1.0",
+ ],
+
+ static_libs: ["android.hardware.sensors@1.0-convert"],
+
+ // our public headers depend on libsensor
+ export_shared_lib_headers: ["libsensor"],
+}
+
+cc_binary {
+ name: "sensorservice",
+
+ srcs: ["main_sensorservice.cpp"],
+
+ shared_libs: [
+ "libsensorservice",
+ "libbinder",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
deleted file mode 100644
index cfb7231..0000000
--- a/services/sensorservice/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- BatteryService.cpp \
- CorrectedGyroSensor.cpp \
- Fusion.cpp \
- GravitySensor.cpp \
- LinearAccelerationSensor.cpp \
- OrientationSensor.cpp \
- RecentEventLogger.cpp \
- RotationVectorSensor.cpp \
- SensorDevice.cpp \
- SensorDirectConnection.cpp \
- SensorEventConnection.cpp \
- SensorFusion.cpp \
- SensorInterface.cpp \
- SensorList.cpp \
- SensorRecord.cpp \
- SensorService.cpp \
- SensorServiceUtils.cpp \
-
-LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-
-LOCAL_CFLAGS += -Wall -Werror -Wextra
-
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libhardware \
- libhardware_legacy \
- libutils \
- liblog \
- libbinder \
- libsensor \
- libcrypto \
- libbase \
- libhidlbase \
- libhidltransport \
- libhwbinder \
- android.hardware.sensors@1.0
-
-LOCAL_STATIC_LIBRARIES := \
- android.hardware.sensors@1.0-convert
-
-# our public headers depend on libsensor
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
- libsensor \
-
-LOCAL_MODULE:= libsensorservice
-
-include $(BUILD_SHARED_LIBRARY)
-
-#####################################################################
-# build executable
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- main_sensorservice.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libsensorservice \
- libbinder \
- libutils
-
-LOCAL_CFLAGS := -Wall -Werror -Wextra
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sensorservice
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index d60768c..b5baba8 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -394,6 +394,7 @@
}
} else if (!mSensors.hasAnySensor()) {
result.append("No Sensors on the device\n");
+ result.append("devInitCheck : %d\n", SensorDevice::getInstance().initCheck());
} else {
// Default dump the sensor list and debugging information.
//
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 06ff95c..991944e 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -42,9 +42,7 @@
using ::android::hardware::Void;
using ::android::sp;
-SensorManager::SensorManager()
- : mInternalManager{::android::SensorManager::getInstanceForPackage(
- String16(ISensorManager::descriptor))} {
+SensorManager::SensorManager() {
}
SensorManager::~SensorManager() {
@@ -58,7 +56,7 @@
// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
::android::Sensor const* const* list;
- ssize_t count = mInternalManager.getSensorList(&list);
+ ssize_t count = getInternalManager().getSensorList(&list);
if (count < 0 || !list) {
LOG(ERROR) << "::android::SensorManager::getSensorList encounters " << count;
_hidl_cb({}, Result::UNKNOWN_ERROR);
@@ -74,7 +72,7 @@
}
Return<void> SensorManager::getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) {
- ::android::Sensor const* sensor = mInternalManager.getDefaultSensor(static_cast<int>(type));
+ ::android::Sensor const* sensor = getInternalManager().getDefaultSensor(static_cast<int>(type));
if (!sensor) {
_hidl_cb({}, Result::NOT_EXIST);
return Void();
@@ -110,7 +108,7 @@
return Void();
}
- createDirectChannel(mInternalManager, size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
+ createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
mem.handle(), _hidl_cb);
return Void();
@@ -120,7 +118,7 @@
const hidl_handle& buffer, uint64_t size,
createGrallocDirectChannel_cb _hidl_cb) {
- createDirectChannel(mInternalManager, size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
+ createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
buffer.getNativeHandle(), _hidl_cb);
return Void();
@@ -157,6 +155,15 @@
return mLooper;
}
+::android::SensorManager& SensorManager::getInternalManager() {
+ std::lock_guard<std::mutex> lock(mInternalManagerMutex);
+ if (mInternalManager == nullptr) {
+ mInternalManager = &::android::SensorManager::getInstanceForPackage(
+ String16(ISensorManager::descriptor));
+ }
+ return *mInternalManager;
+}
+
Return<void> SensorManager::createEventQueue(
const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb) {
if (callback == nullptr) {
@@ -165,7 +172,7 @@
}
sp<::android::Looper> looper = getLooper();
- sp<::android::SensorEventQueue> internalQueue = mInternalManager.createEventQueue();
+ sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue();
if (internalQueue == nullptr) {
LOG(WARNING) << "::android::SensorManager::createEventQueue returns nullptr.";
_hidl_cb(nullptr, Result::UNKNOWN_ERROR);
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index a2372df..cc044bf 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -50,9 +50,13 @@
Return<void> createEventQueue(const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb);
private:
+ // Block until ::android::SensorManager is initialized.
+ ::android::SensorManager& getInternalManager();
sp<::android::Looper> getLooper();
- ::android::SensorManager& mInternalManager;
+ std::mutex mInternalManagerMutex;
+ ::android::SensorManager* mInternalManager = nullptr; // does not own
+
std::mutex mLooperMutex;
sp<::android::Looper> mLooper;
};
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 7bb20ba..0071851 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -54,11 +54,7 @@
LOCAL_SRC_FILES += \
SurfaceFlinger.cpp \
DisplayHardware/HWComposer.cpp
- ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
- LOCAL_CFLAGS += -DBYPASS_IHWC
- endif
else
- LOCAL_CFLAGS += -DBYPASS_IHWC
LOCAL_SRC_FILES += \
SurfaceFlinger_hwc1.cpp \
DisplayHardware/HWComposer_hwc1.cpp
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b5ffc60..a0abf12 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -121,7 +121,7 @@
ANativeWindow* const window = mNativeWindow.get();
#ifdef USE_HWC2
- mActiveColorMode = static_cast<android_color_mode_t>(-1);
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
mDisplayHasWideColor = supportWideColor;
#else
(void) supportWideColor;
@@ -610,23 +610,25 @@
void DisplayDevice::dump(String8& result) const {
const Transform& tr(mGlobalTransform);
- result.appendFormat(
- "+ DisplayDevice: %s\n"
- " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
- "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
- " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
- "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
- mDisplayName.string(), mType, mHwcDisplayId,
- mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
- mOrientation, tr.getType(), getPageFlipCount(),
- mIsSecure, mPowerMode, mActiveConfig,
- mVisibleLayersSortedByZ.size(),
- mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
- mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
- mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
- tr[0][0], tr[1][0], tr[2][0],
- tr[0][1], tr[1][1], tr[2][1],
- tr[0][2], tr[1][2], tr[2][2]);
+ EGLint redSize, greenSize, blueSize, alphaSize;
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &redSize);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &greenSize);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &blueSize);
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &alphaSize);
+ result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
+ result.appendFormat(" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
+ "(%d:%d:%d:%d), orient=%2d (type=%08x), "
+ "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+ mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight,
+ mNativeWindow.get(), redSize, greenSize, blueSize, alphaSize, mOrientation,
+ tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+ mVisibleLayersSortedByZ.size());
+ result.appendFormat(" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
+ "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
+ mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
+ mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
+ mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
+ tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
String8 surfaceDump;
mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 8270c39..1ac203b 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -88,55 +88,8 @@
// Device methods
-#ifdef BYPASS_IHWC
-Device::Device(hwc2_device_t* device)
- : mHwcDevice(device),
- mCreateVirtualDisplay(nullptr),
- mDestroyVirtualDisplay(nullptr),
- mDump(nullptr),
- mGetMaxVirtualDisplayCount(nullptr),
- mRegisterCallback(nullptr),
- mAcceptDisplayChanges(nullptr),
- mCreateLayer(nullptr),
- mDestroyLayer(nullptr),
- mGetActiveConfig(nullptr),
- mGetChangedCompositionTypes(nullptr),
- mGetColorModes(nullptr),
- mGetDisplayAttribute(nullptr),
- mGetDisplayConfigs(nullptr),
- mGetDisplayName(nullptr),
- mGetDisplayRequests(nullptr),
- mGetDisplayType(nullptr),
- mGetDozeSupport(nullptr),
- mGetHdrCapabilities(nullptr),
- mGetReleaseFences(nullptr),
- mPresentDisplay(nullptr),
- mSetActiveConfig(nullptr),
- mSetClientTarget(nullptr),
- mSetColorMode(nullptr),
- mSetColorTransform(nullptr),
- mSetOutputBuffer(nullptr),
- mSetPowerMode(nullptr),
- mSetVsyncEnabled(nullptr),
- mValidateDisplay(nullptr),
- mSetCursorPosition(nullptr),
- mSetLayerBuffer(nullptr),
- mSetLayerSurfaceDamage(nullptr),
- mSetLayerBlendMode(nullptr),
- mSetLayerColor(nullptr),
- mSetLayerCompositionType(nullptr),
- mSetLayerDataspace(nullptr),
- mSetLayerDisplayFrame(nullptr),
- mSetLayerPlaneAlpha(nullptr),
- mSetLayerSidebandStream(nullptr),
- mSetLayerSourceCrop(nullptr),
- mSetLayerTransform(nullptr),
- mSetLayerVisibleRegion(nullptr),
- mSetLayerZOrder(nullptr),
-#else
Device::Device(bool useVrComposer)
: mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
-#endif // BYPASS_IHWC
mCapabilities(),
mDisplays(),
mHotplug(),
@@ -147,18 +100,11 @@
mPendingVsyncs()
{
loadCapabilities();
- loadFunctionPointers();
registerCallbacks();
}
Device::~Device()
{
-#ifdef BYPASS_IHWC
- if (mHwcDevice == nullptr) {
- return;
- }
-#endif
-
for (auto element : mDisplays) {
auto display = element.second.lock();
if (!display) {
@@ -185,36 +131,18 @@
}
}
}
-
-#ifdef BYPASS_IHWC
- hwc2_close(mHwcDevice);
-#endif
}
// Required by HWC2 device
std::string Device::dump() const
{
-#ifdef BYPASS_IHWC
- uint32_t numBytes = 0;
- mDump(mHwcDevice, &numBytes, nullptr);
-
- std::vector<char> buffer(numBytes);
- mDump(mHwcDevice, &numBytes, buffer.data());
-
- return std::string(buffer.data(), buffer.size());
-#else
return mComposer->dumpDebugInfo();
-#endif
}
uint32_t Device::getMaxVirtualDisplayCount() const
{
-#ifdef BYPASS_IHWC
- return mGetMaxVirtualDisplayCount(mHwcDevice);
-#else
return mComposer->getMaxVirtualDisplayCount();
-#endif
}
Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
@@ -223,15 +151,9 @@
ALOGI("Creating virtual display");
hwc2_display_t displayId = 0;
-#ifdef BYPASS_IHWC
- int32_t intFormat = static_cast<int32_t>(*format);
- int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
- &intFormat, &displayId);
-#else
auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
auto intError = mComposer->createVirtualDisplay(width, height,
&intFormat, &displayId);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -285,9 +207,7 @@
{
if (connected == Connection::Connected) {
if (!display->isConnected()) {
-#ifndef BYPASS_IHWC
mComposer->setClientTargetSlotCount(display->getId());
-#endif
display->loadConfigs();
display->setConnected(true);
}
@@ -345,21 +265,10 @@
{
static_assert(sizeof(Capability) == sizeof(int32_t),
"Capability size has changed");
-#ifdef BYPASS_IHWC
- uint32_t numCapabilities = 0;
- mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
- std::vector<Capability> capabilities(numCapabilities);
- auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
- mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
- for (auto capability : capabilities) {
- mCapabilities.emplace(capability);
- }
-#else
auto capabilities = mComposer->getCapabilities();
for (auto capability : capabilities) {
mCapabilities.emplace(static_cast<Capability>(capability));
}
-#endif
}
bool Device::hasCapability(HWC2::Capability capability) const
@@ -368,105 +277,6 @@
capability) != mCapabilities.cend();
}
-void Device::loadFunctionPointers()
-{
-#ifdef BYPASS_IHWC
- // For all of these early returns, we log an error message inside
- // loadFunctionPointer specifying which function failed to load
-
- // Display function pointers
- if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
- mCreateVirtualDisplay)) return;
- if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
- mDestroyVirtualDisplay)) return;
- if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
- mGetMaxVirtualDisplayCount)) return;
- if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
- mRegisterCallback)) return;
-
- // Device function pointers
- if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
- mAcceptDisplayChanges)) return;
- if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
- mCreateLayer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
- mDestroyLayer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
- mGetActiveConfig)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
- mGetChangedCompositionTypes)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
- mGetColorModes)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
- mGetDisplayAttribute)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
- mGetDisplayConfigs)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
- mGetDisplayName)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
- mGetDisplayRequests)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
- mGetDisplayType)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
- mGetDozeSupport)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
- mGetHdrCapabilities)) return;
- if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
- mGetReleaseFences)) return;
- if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
- mPresentDisplay)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
- mSetActiveConfig)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
- mSetClientTarget)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
- mSetColorMode)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
- mSetColorTransform)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
- mSetOutputBuffer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
- mSetPowerMode)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
- mSetVsyncEnabled)) return;
- if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
- mValidateDisplay)) return;
-
- // Layer function pointers
- if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
- mSetCursorPosition)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
- mSetLayerBuffer)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
- mSetLayerSurfaceDamage)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
- mSetLayerBlendMode)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
- mSetLayerColor)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
- mSetLayerCompositionType)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
- mSetLayerDataspace)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
- mSetLayerDisplayFrame)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
- mSetLayerPlaneAlpha)) return;
- if (hasCapability(Capability::SidebandStream)) {
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
- mSetLayerSidebandStream)) return;
- }
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
- mSetLayerSourceCrop)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
- mSetLayerTransform)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
- mSetLayerVisibleRegion)) return;
- if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
- mSetLayerZOrder)) return;
-#endif // BYPASS_IHWC
-}
-
namespace {
class ComposerCallback : public Hwc2::IComposerCallback {
public:
@@ -498,14 +308,8 @@
void Device::registerCallbacks()
{
-#ifdef BYPASS_IHWC
- registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
- registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
- registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
-#else
sp<ComposerCallback> callback = new ComposerCallback(this);
mComposer->registerCallback(callback);
-#endif
}
@@ -514,11 +318,7 @@
void Device::destroyVirtualDisplay(hwc2_display_t display)
{
ALOGI("Destroying virtual display");
-#ifdef BYPASS_IHWC
- int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
-#else
auto intError = mComposer->destroyVirtualDisplay(display);
-#endif
auto error = static_cast<Error>(intError);
ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
" %s (%d)", display, to_string(error).c_str(), intError);
@@ -535,13 +335,8 @@
{
ALOGV("Created display %" PRIu64, id);
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
- reinterpret_cast<int32_t *>(&mType));
-#else
auto intError = mDevice.mComposer->getDisplayType(mId,
reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
@@ -588,22 +383,14 @@
Error Display::acceptChanges()
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
-#else
auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
-#endif
return static_cast<Error>(intError);
}
Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
{
hwc2_layer_t layerId = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
-#else
auto intError = mDevice.mComposer->createLayer(mId, &layerId);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -620,12 +407,7 @@
{
ALOGV("[%" PRIu64 "] getActiveConfig", mId);
hwc2_config_t configId = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
- &configId);
-#else
auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -650,27 +432,12 @@
Error Display::getChangedCompositionTypes(
std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
{
-#ifdef BYPASS_IHWC
- uint32_t numElements = 0;
- int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
- mId, &numElements, nullptr, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<hwc2_layer_t> layerIds(numElements);
- std::vector<int32_t> types(numElements);
- intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
- &numElements, layerIds.data(), types.data());
-#else
std::vector<Hwc2::Layer> layerIds;
std::vector<Hwc2::IComposerClient::Composition> types;
auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
&layerIds, &types);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
-#endif
error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -696,25 +463,10 @@
Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
{
-#ifdef BYPASS_IHWC
- uint32_t numModes = 0;
- int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
- &numModes, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<int32_t> modes(numModes);
- intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
- modes.data());
- error = static_cast<Error>(intError);
-#else
std::vector<Hwc2::ColorMode> modes;
auto intError = mDevice.mComposer->getColorModes(mId, &modes);
uint32_t numModes = modes.size();
auto error = static_cast<Error>(intError);
-#endif
if (error != Error::None) {
return error;
}
@@ -737,52 +489,14 @@
Error Display::getName(std::string* outName) const
{
-#ifdef BYPASS_IHWC
- uint32_t size;
- int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
- nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<char> rawName(size);
- intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
- rawName.data());
- error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- *outName = std::string(rawName.cbegin(), rawName.cend());
- return Error::None;
-#else
auto intError = mDevice.mComposer->getDisplayName(mId, outName);
return static_cast<Error>(intError);
-#endif
}
Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
outLayerRequests)
{
-#ifdef BYPASS_IHWC
- int32_t intDisplayRequests = 0;
- uint32_t numElements = 0;
- int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
- &intDisplayRequests, &numElements, nullptr, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<hwc2_layer_t> layerIds(numElements);
- std::vector<int32_t> layerRequests(numElements);
- intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
- &intDisplayRequests, &numElements, layerIds.data(),
- layerRequests.data());
- error = static_cast<Error>(intError);
-#else
uint32_t intDisplayRequests;
std::vector<Hwc2::Layer> layerIds;
std::vector<uint32_t> layerRequests;
@@ -790,7 +504,6 @@
&intDisplayRequests, &layerIds, &layerRequests);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
-#endif
if (error != Error::None) {
return error;
}
@@ -821,14 +534,8 @@
Error Display::supportsDoze(bool* outSupport) const
{
-#ifdef BYPASS_IHWC
- int32_t intSupport = 0;
- int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
- &intSupport);
-#else
bool intSupport = false;
auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -844,20 +551,6 @@
float maxLuminance = -1.0f;
float maxAverageLuminance = -1.0f;
float minLuminance = -1.0f;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
- &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
- &minLuminance);
- auto error = static_cast<HWC2::Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<int32_t> types(numTypes);
- intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
- types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
- error = static_cast<HWC2::Error>(intError);
-#else
std::vector<Hwc2::Hdr> intTypes;
auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
&maxLuminance, &maxAverageLuminance, &minLuminance);
@@ -868,7 +561,6 @@
types.push_back(static_cast<int32_t>(type));
}
numTypes = types.size();
-#endif
if (error != Error::None) {
return error;
}
@@ -881,28 +573,12 @@
Error Display::getReleaseFences(
std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
{
-#ifdef BYPASS_IHWC
- uint32_t numElements = 0;
- int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
- &numElements, nullptr, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- std::vector<hwc2_layer_t> layerIds(numElements);
- std::vector<int32_t> fenceFds(numElements);
- intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
- layerIds.data(), fenceFds.data());
- error = static_cast<Error>(intError);
-#else
std::vector<Hwc2::Layer> layerIds;
std::vector<int> fenceFds;
auto intError = mDevice.mComposer->getReleaseFences(mId,
&layerIds, &fenceFds);
auto error = static_cast<Error>(intError);
uint32_t numElements = layerIds.size();
-#endif
if (error != Error::None) {
return error;
}
@@ -928,12 +604,7 @@
Error Display::present(sp<Fence>* outPresentFence)
{
int32_t presentFenceFd = -1;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
- &presentFenceFd);
-#else
auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -951,12 +622,7 @@
config->getDisplayId(), mId);
return Error::BadConfig;
}
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
- config->getId());
-#else
auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
-#endif
return static_cast<Error>(intError);
}
@@ -965,44 +631,24 @@
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
- (void) slot;
- buffer_handle_t handle = nullptr;
- if (target.get() && target->getNativeBuffer()) {
- handle = target->getNativeBuffer()->handle;
- }
-
- int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
- fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
-#else
auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
std::vector<Hwc2::IComposerClient::Rect>());
-#endif
return static_cast<Error>(intError);
}
Error Display::setColorMode(android_color_mode_t mode)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
-#else
auto intError = mDevice.mComposer->setColorMode(mId,
static_cast<Hwc2::ColorMode>(mode));
-#endif
return static_cast<Error>(intError);
}
Error Display::setColorTransform(const android::mat4& matrix,
android_color_transform_t hint)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
- matrix.asArray(), static_cast<int32_t>(hint));
-#else
auto intError = mDevice.mComposer->setColorTransform(mId,
matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
-#endif
return static_cast<Error>(intError);
}
@@ -1011,38 +657,22 @@
{
int32_t fenceFd = releaseFence->dup();
auto handle = buffer->getNativeBuffer()->handle;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
- fenceFd);
-#else
auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
-#endif
close(fenceFd);
return static_cast<Error>(intError);
}
Error Display::setPowerMode(PowerMode mode)
{
-#ifdef BYPASS_IHWC
- auto intMode = static_cast<int32_t>(mode);
- int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
-#else
auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
-#endif
return static_cast<Error>(intError);
}
Error Display::setVsyncEnabled(Vsync enabled)
{
-#ifdef BYPASS_IHWC
- auto intEnabled = static_cast<int32_t>(enabled);
- int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
- intEnabled);
-#else
auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
-#endif
return static_cast<Error>(intError);
}
@@ -1050,13 +680,8 @@
{
uint32_t numTypes = 0;
uint32_t numRequests = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
- &numTypes, &numRequests);
-#else
auto intError = mDevice.mComposer->validateDisplay(mId,
&numTypes, &numRequests);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None && error != Error::HasChanges) {
return error;
@@ -1072,14 +697,9 @@
int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
{
int32_t value = 0;
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
- configId, static_cast<int32_t>(attribute), &value);
-#else
auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
static_cast<Hwc2::IComposerClient::Attribute>(attribute),
&value);
-#endif
auto error = static_cast<Error>(intError);
if (error != Error::None) {
ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
@@ -1108,26 +728,9 @@
{
ALOGV("[%" PRIu64 "] loadConfigs", mId);
-#ifdef BYPASS_IHWC
- uint32_t numConfigs = 0;
- int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
- &numConfigs, nullptr);
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
- to_string(error).c_str(), intError);
- return;
- }
-
- std::vector<hwc2_config_t> configIds(numConfigs);
- intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
- configIds.data());
- error = static_cast<Error>(intError);
-#else
std::vector<Hwc2::Config> configIds;
auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
auto error = static_cast<Error>(intError);
-#endif
if (error != Error::None) {
ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
to_string(error).c_str(), intError);
@@ -1143,11 +746,7 @@
void Display::destroyLayer(hwc2_layer_t layerId)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
-#else
auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
-#endif
auto error = static_cast<Error>(intError);
ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
" failed: %s (%d)", mId, layerId, to_string(error).c_str(),
@@ -1189,13 +788,8 @@
Error Layer::setCursorPosition(int32_t x, int32_t y)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
- mDisplayId, mId, x, y);
-#else
auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
mId, x, y);
-#endif
return static_cast<Error>(intError);
}
@@ -1203,19 +797,8 @@
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
- (void) slot;
- buffer_handle_t handle = nullptr;
- if (buffer.get() && buffer->getNativeBuffer()) {
- handle = buffer->getNativeBuffer()->handle;
- }
-
- int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
- mId, handle, fenceFd);
-#else
auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
mId, slot, buffer, fenceFd);
-#endif
return static_cast<Error>(intError);
}
@@ -1223,44 +806,22 @@
{
// We encode default full-screen damage as INVALID_RECT upstream, but as 0
// rects for HWC
-#ifdef BYPASS_IHWC
- int32_t intError = 0;
-#else
Hwc2::Error intError = Hwc2::Error::NONE;
-#endif
if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
-#ifdef BYPASS_IHWC
- intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
- mDisplayId, mId, {0, nullptr});
-#else
intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
mId, std::vector<Hwc2::IComposerClient::Rect>());
-#endif
} else {
size_t rectCount = 0;
auto rectArray = damage.getArray(&rectCount);
-#ifdef BYPASS_IHWC
- std::vector<hwc_rect_t> hwcRects;
-#else
std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
for (size_t rect = 0; rect < rectCount; ++rect) {
hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
rectArray[rect].right, rectArray[rect].bottom});
}
-#ifdef BYPASS_IHWC
- hwc_region_t hwcRegion = {};
- hwcRegion.numRects = rectCount;
- hwcRegion.rects = hwcRects.data();
-
- intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRegion);
-#else
intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
mId, hwcRects);
-#endif
}
return static_cast<Error>(intError);
@@ -1268,83 +829,49 @@
Error Layer::setBlendMode(BlendMode mode)
{
-#ifdef BYPASS_IHWC
- auto intMode = static_cast<int32_t>(mode);
- int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
- mDisplayId, mId, intMode);
-#else
auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
mId, intMode);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setColor(hwc_color_t color)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
- mId, color);
-#else
Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
mId, hwcColor);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setCompositionType(Composition type)
{
-#ifdef BYPASS_IHWC
- auto intType = static_cast<int32_t>(type);
- int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
- mDisplayId, mId, intType);
-#else
auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
mId, intType);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setDataspace(android_dataspace_t dataspace)
{
-#ifdef BYPASS_IHWC
- auto intDataspace = static_cast<int32_t>(dataspace);
- int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
- mDisplayId, mId, intDataspace);
-#else
auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
mId, intDataspace);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setDisplayFrame(const Rect& frame)
{
-#ifdef BYPASS_IHWC
- hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
- int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRect);
-#else
Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
frame.right, frame.bottom};
auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
mId, hwcRect);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setPlaneAlpha(float alpha)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
- mDisplayId, mId, alpha);
-#else
auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
mId, alpha);
-#endif
return static_cast<Error>(intError);
}
@@ -1355,42 +882,25 @@
"device supports sideband streams");
return Error::Unsupported;
}
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
- mDisplayId, mId, stream);
-#else
auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
mId, stream);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setSourceCrop(const FloatRect& crop)
{
-#ifdef BYPASS_IHWC
- hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
- int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRect);
-#else
Hwc2::IComposerClient::FRect hwcRect{
crop.left, crop.top, crop.right, crop.bottom};
auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
mId, hwcRect);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setTransform(Transform transform)
{
-#ifdef BYPASS_IHWC
- auto intTransform = static_cast<int32_t>(transform);
- int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
- mDisplayId, mId, intTransform);
-#else
auto intTransform = static_cast<Hwc2::Transform>(transform);
auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
mId, intTransform);
-#endif
return static_cast<Error>(intError);
}
@@ -1399,50 +909,26 @@
size_t rectCount = 0;
auto rectArray = region.getArray(&rectCount);
-#ifdef BYPASS_IHWC
- std::vector<hwc_rect_t> hwcRects;
-#else
std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
for (size_t rect = 0; rect < rectCount; ++rect) {
hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
rectArray[rect].right, rectArray[rect].bottom});
}
-#ifdef BYPASS_IHWC
- hwc_region_t hwcRegion = {};
- hwcRegion.numRects = rectCount;
- hwcRegion.rects = hwcRects.data();
-
- int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
- mDisplayId, mId, hwcRegion);
-#else
auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
mId, hwcRects);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setZOrder(uint32_t z)
{
-#ifdef BYPASS_IHWC
- int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
- mId, z);
-#else
auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
-#endif
return static_cast<Error>(intError);
}
Error Layer::setInfo(uint32_t type, uint32_t appId)
{
-#ifdef BYPASS_IHWC
- (void)type;
- (void)appId;
- int32_t intError = 0;
-#else
auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
-#endif
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 643b1e0..97582a7 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -62,14 +62,10 @@
class Device
{
public:
-#ifdef BYPASS_IHWC
- explicit Device(hwc2_device_t* device);
-#else
// useVrComposer is passed to the composer HAL. When true, the composer HAL
// will use the vr composer service, otherwise it uses the real hardware
// composer.
Device(bool useVrComposer);
-#endif
~Device();
friend class HWC2::Display;
@@ -107,43 +103,12 @@
bool hasCapability(HWC2::Capability capability) const;
-#ifdef BYPASS_IHWC
- android::Hwc2::Composer* getComposer() { return nullptr; }
-#else
android::Hwc2::Composer* getComposer() { return mComposer.get(); }
-#endif
private:
// Initialization methods
-#ifdef BYPASS_IHWC
- template <typename PFN>
- [[clang::warn_unused_result]] bool loadFunctionPointer(
- FunctionDescriptor desc, PFN& outPFN) {
- auto intDesc = static_cast<int32_t>(desc);
- auto pfn = mHwcDevice->getFunction(mHwcDevice, intDesc);
- if (pfn != nullptr) {
- outPFN = reinterpret_cast<PFN>(pfn);
- return true;
- } else {
- ALOGE("Failed to load function %s", to_string(desc).c_str());
- return false;
- }
- }
-
- template <typename PFN, typename HOOK>
- void registerCallback(Callback callback, HOOK hook) {
- static_assert(std::is_same<PFN, HOOK>::value,
- "Incompatible function pointer");
- auto intCallback = static_cast<int32_t>(callback);
- auto callbackData = static_cast<hwc2_callback_data_t>(this);
- auto pfn = reinterpret_cast<hwc2_function_pointer_t>(hook);
- mRegisterCallback(mHwcDevice, intCallback, callbackData, pfn);
- }
-#endif
-
void loadCapabilities();
- void loadFunctionPointers();
void registerCallbacks();
// For use by Display
@@ -151,60 +116,7 @@
void destroyVirtualDisplay(hwc2_display_t display);
// Member variables
-
-#ifdef BYPASS_IHWC
- hwc2_device_t* mHwcDevice;
-
- // Device function pointers
- HWC2_PFN_CREATE_VIRTUAL_DISPLAY mCreateVirtualDisplay;
- HWC2_PFN_DESTROY_VIRTUAL_DISPLAY mDestroyVirtualDisplay;
- HWC2_PFN_DUMP mDump;
- HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT mGetMaxVirtualDisplayCount;
- HWC2_PFN_REGISTER_CALLBACK mRegisterCallback;
-
- // Display function pointers
- HWC2_PFN_ACCEPT_DISPLAY_CHANGES mAcceptDisplayChanges;
- HWC2_PFN_CREATE_LAYER mCreateLayer;
- HWC2_PFN_DESTROY_LAYER mDestroyLayer;
- HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig;
- HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes;
- HWC2_PFN_GET_COLOR_MODES mGetColorModes;
- HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute;
- HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs;
- HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName;
- HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
- HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
- HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
- HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
- HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
- HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
- HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
- HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget;
- HWC2_PFN_SET_COLOR_MODE mSetColorMode;
- HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform;
- HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer;
- HWC2_PFN_SET_POWER_MODE mSetPowerMode;
- HWC2_PFN_SET_VSYNC_ENABLED mSetVsyncEnabled;
- HWC2_PFN_VALIDATE_DISPLAY mValidateDisplay;
-
- // Layer function pointers
- HWC2_PFN_SET_CURSOR_POSITION mSetCursorPosition;
- HWC2_PFN_SET_LAYER_BUFFER mSetLayerBuffer;
- HWC2_PFN_SET_LAYER_SURFACE_DAMAGE mSetLayerSurfaceDamage;
- HWC2_PFN_SET_LAYER_BLEND_MODE mSetLayerBlendMode;
- HWC2_PFN_SET_LAYER_COLOR mSetLayerColor;
- HWC2_PFN_SET_LAYER_COMPOSITION_TYPE mSetLayerCompositionType;
- HWC2_PFN_SET_LAYER_DATASPACE mSetLayerDataspace;
- HWC2_PFN_SET_LAYER_DISPLAY_FRAME mSetLayerDisplayFrame;
- HWC2_PFN_SET_LAYER_PLANE_ALPHA mSetLayerPlaneAlpha;
- HWC2_PFN_SET_LAYER_SIDEBAND_STREAM mSetLayerSidebandStream;
- HWC2_PFN_SET_LAYER_SOURCE_CROP mSetLayerSourceCrop;
- HWC2_PFN_SET_LAYER_TRANSFORM mSetLayerTransform;
- HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
- HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
-#else
std::unique_ptr<android::Hwc2::Composer> mComposer;
-#endif // BYPASS_IHWC
std::unordered_set<Capability> mCapabilities;
std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 04ab78f..0f49e61 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -108,45 +108,7 @@
void HWComposer::loadHwcModule(bool useVrComposer)
{
ALOGV("loadHwcModule");
-
-#ifdef BYPASS_IHWC
- (void)useVrComposer; // Silence unused parameter warning.
-
- hw_module_t const* module;
-
- if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
- ALOGE("%s module not found, aborting", HWC_HARDWARE_MODULE_ID);
- abort();
- }
-
- hw_device_t* device = nullptr;
- int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
- if (error != 0) {
- ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
- abort();
- }
-
- uint32_t majorVersion = (device->version >> 24) & 0xF;
- if (majorVersion == 2) {
- mHwcDevice = std::make_unique<HWC2::Device>(
- reinterpret_cast<hwc2_device_t*>(device));
- } else {
- mAdapter = std::make_unique<HWC2On1Adapter>(
- reinterpret_cast<hwc_composer_device_1_t*>(device));
- uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
- if (minorVersion < 1) {
- ALOGE("Cannot adapt to HWC version %d.%d",
- static_cast<int32_t>((minorVersion >> 8) & 0xF),
- static_cast<int32_t>(minorVersion & 0xF));
- abort();
- }
- mHwcDevice = std::make_unique<HWC2::Device>(
- static_cast<hwc2_device_t*>(mAdapter.get()));
- }
-#else
mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
-#endif
-
mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
}
@@ -870,11 +832,7 @@
*/
bool HWComposer::isUsingVrComposer() const {
-#ifdef BYPASS_IHWC
- return false;
-#else
return getComposer()->isUsingVrComposer();
-#endif
}
void HWComposer::dump(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
index 6b91224..a234b63 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
@@ -29,10 +29,6 @@
const sp<GraphicBuffer>& buffer,
uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
{
-#ifdef BYPASS_IHWC
- *outSlot = slot;
- *outBuffer = buffer;
-#else
if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
// default to slot 0
slot = 0;
@@ -53,7 +49,6 @@
// update cache
mBuffers[slot] = buffer;
}
-#endif
}
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 8217540..6e843d9 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -22,6 +22,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/IProducerListener.h>
+#include <system/window.h>
// ---------------------------------------------------------------------------
namespace android {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b43b30d..0f93cd7 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -34,6 +34,7 @@
#include <utils/StopWatch.h>
#include <utils/Trace.h>
+#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
@@ -125,6 +126,7 @@
mPremultipliedAlpha = false;
mName = name;
+ mTransactionName = String8("TX - ") + mName;
mCurrentState.active.w = w;
mCurrentState.active.h = h;
@@ -882,9 +884,6 @@
}
}
-android_dataspace Layer::getDataSpace() const {
- return mCurrentState.dataSpace;
-}
#else
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
@@ -1493,6 +1492,7 @@
mFlinger->setTransactionFlags(eTraversalNeeded);
}
mPendingStates.push_back(mCurrentState);
+ ATRACE_INT(mTransactionName.string(), mPendingStates.size());
}
void Layer::popPendingState(State* stateToCommit) {
@@ -1502,6 +1502,7 @@
(stateToCommit->flags & stateToCommit->mask);
mPendingStates.removeAt(0);
+ ATRACE_INT(mTransactionName.string(), mPendingStates.size());
}
bool Layer::applyPendingStates(State* stateToCommit) {
@@ -1895,6 +1896,10 @@
return true;
}
+android_dataspace Layer::getDataSpace() const {
+ return mCurrentState.dataSpace;
+}
+
uint32_t Layer::getLayerStack() const {
auto p = getParent();
if (p == nullptr) {
@@ -2340,11 +2345,17 @@
visibleRegion.dump(result, "visibleRegion");
surfaceDamageRegion.dump(result, "surfaceDamageRegion");
sp<Client> client(mClientRef.promote());
+ PixelFormat pf = PIXEL_FORMAT_UNKNOWN;
+ const sp<GraphicBuffer>& buffer(getActiveBuffer());
+ if (buffer != NULL) {
+ pf = buffer->getPixelFormat();
+ }
result.appendFormat( " "
"layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), "
"crop=(%4d,%4d,%4d,%4d), finalCrop=(%4d,%4d,%4d,%4d), "
"isOpaque=%1d, invalidate=%1d, "
+ "dataspace=%s, pixelformat=%s "
#ifdef USE_HWC2
"alpha=%.3f, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
#else
@@ -2359,6 +2370,7 @@
s.finalCrop.left, s.finalCrop.top,
s.finalCrop.right, s.finalCrop.bottom,
isOpaque(s), contentDirty,
+ dataspaceDetails(getDataSpace()).c_str(), decodePixelFormat(pf).c_str(),
s.alpha, s.flags,
s.active.transform[0][0], s.active.transform[0][1],
s.active.transform[1][0], s.active.transform[1][1],
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9f45435..d1ef57d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -192,6 +192,7 @@
bool setFlags(uint8_t flags, uint8_t mask);
bool setLayerStack(uint32_t layerStack);
bool setDataSpace(android_dataspace dataSpace);
+ android_dataspace getDataSpace() const;
uint32_t getLayerStack() const;
void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber);
void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber);
@@ -275,8 +276,6 @@
void forceClientComposition(int32_t hwcId);
void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
- android_dataspace getDataSpace() const;
-
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
void setCompositionType(int32_t hwcId, HWC2::Composition type,
@@ -658,6 +657,7 @@
uint32_t mTextureName; // from GLES
bool mPremultipliedAlpha;
String8 mName;
+ String8 mTransactionName; // A cached version of "TX - " + mName for systraces
PixelFormat mFormat;
// these are protected by an external lock
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 0b302eb..f152495 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -17,6 +17,7 @@
#include "LayerRejecter.h"
#include <gui/BufferItem.h>
+#include <system/window.h>
#include "clz.h"
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 04fe182..18b2e1b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -143,7 +143,7 @@
// 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();
+ mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
// color transform needs to be transposed and expanded to 4x4
// to be what the shader wants
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 7564269..f8785db 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -54,12 +54,16 @@
// both a 16-bit primary display framebuffer and a 32-bit virtual display
// framebuffer.
//
+ // EGL_KHR_no_config_context is official extension to allow creating a
+ // context that works with any surface of a display.
+ //
// The code assumes that ES2 or later is available if this extension is
// supported.
EGLConfig config = EGL_NO_CONFIG;
- if (!findExtension(
- eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
- "EGL_ANDROIDX_no_config_context")) {
+ if (!findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+ "EGL_ANDROIDX_no_config_context") &&
+ !findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+ "EGL_KHR_no_config_context")) {
config = chooseEglConfig(display, hwcFormat);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 29a8292..12afdf7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2651,6 +2651,8 @@
{
Mutex::Autolock _l(mStateLock);
if (mNumLayers >= MAX_LAYERS) {
+ ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
+ MAX_LAYERS);
return NO_MEMORY;
}
if (parent == nullptr) {
@@ -3184,7 +3186,8 @@
if (currentMode == HWC_POWER_MODE_OFF) {
// Turn on the display
getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY &&
+ mode != HWC_POWER_MODE_DOZE_SUSPEND) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
@@ -3216,7 +3219,25 @@
getHwComposer().setPowerMode(type, mode);
mVisibleRegionsDirty = true;
// from this point on, SF will stop drawing on this display
+ } else if (mode == HWC_POWER_MODE_DOZE ||
+ mode == HWC_POWER_MODE_NORMAL) {
+ // Update display while dozing
+ getHwComposer().setPowerMode(type, mode);
+ if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ // FIXME: eventthread only knows about the main display right now
+ mEventThread->onScreenAcquired();
+ resyncToHardwareVsync(true);
+ }
+ } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+ // Leave display going to doze
+ if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ disableHardwareVsync(true); // also cancels any in-progress resync
+ // FIXME: eventthread only knows about the main display right now
+ mEventThread->onScreenReleased();
+ }
+ getHwComposer().setPowerMode(type, mode);
} else {
+ ALOGE("Attempting to set unknown power mode: %d\n", mode);
getHwComposer().setPowerMode(type, mode);
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 7070b97..f6ee660 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2845,7 +2845,8 @@
if (currentMode == HWC_POWER_MODE_OFF) {
// Turn on the display
getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY &&
+ mode != HWC_POWER_MODE_DOZE_SUSPEND) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
@@ -2877,7 +2878,25 @@
getHwComposer().setPowerMode(type, mode);
mVisibleRegionsDirty = true;
// from this point on, SF will stop drawing on this display
+ } else if (mode == HWC_POWER_MODE_DOZE ||
+ mode == HWC_POWER_MODE_NORMAL) {
+ // Update display while dozing
+ getHwComposer().setPowerMode(type, mode);
+ if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ // FIXME: eventthread only knows about the main display right now
+ mEventThread->onScreenAcquired();
+ resyncToHardwareVsync(true);
+ }
+ } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+ // Leave display going to doze
+ if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ disableHardwareVsync(true); // also cancels any in-progress resync
+ // FIXME: eventthread only knows about the main display right now
+ mEventThread->onScreenReleased();
+ }
+ getHwComposer().setPowerMode(type, mode);
} else {
+ ALOGE("Attempting to set unknown power mode: %d\n", mode);
getHwComposer().setPowerMode(type, mode);
}
}
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index 16041da..43e22a0 100644
--- a/services/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
@@ -4,7 +4,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := SurfaceFlinger_test
-
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := \
diff --git a/services/surfaceflinger/tests/AndroidTest.xml b/services/surfaceflinger/tests/AndroidTest.xml
new file mode 100644
index 0000000..8315037
--- /dev/null
+++ b/services/surfaceflinger/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for SurfaceFlinger_test">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="SurfaceFlinger_test->/data/local/tmp/SurfaceFlinger_test" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="SurfaceFlinger_test" />
+ </test>
+</configuration>
diff --git a/services/surfaceflinger/tests/vsync/Android.mk b/services/surfaceflinger/tests/vsync/Android.mk
index 9181760..8e41617 100644
--- a/services/surfaceflinger/tests/vsync/Android.mk
+++ b/services/surfaceflinger/tests/vsync/Android.mk
@@ -15,4 +15,6 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -Werror
+
include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp
index aa72c79..a1b45e6 100644
--- a/services/surfaceflinger/tests/vsync/vsync.cpp
+++ b/services/surfaceflinger/tests/vsync/vsync.cpp
@@ -20,7 +20,7 @@
using namespace android;
-int receiver(int fd, int events, void* data)
+int receiver(int /*fd*/, int /*events*/, void* data)
{
DisplayEventReceiver* q = (DisplayEventReceiver*)data;
@@ -47,7 +47,7 @@
return 1;
}
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
{
DisplayEventReceiver myDisplayEvent;
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.mk b/services/surfaceflinger/tests/waitforvsync/Android.mk
index c25f5ab..932d2be 100644
--- a/services/surfaceflinger/tests/waitforvsync/Android.mk
+++ b/services/surfaceflinger/tests/waitforvsync/Android.mk
@@ -11,4 +11,6 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -Werror
+
include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
index b88b04a..65eaae5 100644
--- a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
+++ b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
@@ -29,7 +29,7 @@
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
#endif
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
int fd = open("/dev/graphics/fb0", O_RDWR);
if (fd >= 0) {
do {
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index 43a9a9c..d3e5f0f 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -17,7 +17,7 @@
#ifndef __VK_ANDROID_NATIVE_BUFFER_H__
#define __VK_ANDROID_NATIVE_BUFFER_H__
-#include <system/window.h>
+#include <cutils/native_handle.h>
#include <vulkan/vulkan.h>
#ifdef __cplusplus
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 6149894..5f9b357 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -75,6 +75,7 @@
"libbase",
"liblog",
"libui",
+ "libgraphicsenv",
"libutils",
"libcutils",
"libz",
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 0005a90..a869317 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -28,7 +28,7 @@
#include <android/dlext.h>
#include <cutils/properties.h>
-#include <ui/GraphicsEnv.h>
+#include <graphicsenv/GraphicsEnv.h>
#include <utils/Vector.h>
#include "driver.h"
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index caa2674..cb893aa 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -22,6 +22,7 @@
#include <sync/sync.h>
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include <system/window.h>
#include "driver.h"