Merge "Fix virtual touchpad re-attachment."
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 66808ca..66e9925 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -40,7 +40,8 @@
manager_visible_(false),
manager_z_order_(0),
manager_blur_(0.0f),
- layer_order_(0) {}
+ layer_order_(0),
+ allocated_buffer_index_(0) {}
DisplaySurface::~DisplaySurface() {
ALOGD_IF(LOCAL_TRACE,
@@ -104,6 +105,14 @@
return;
}
+ // Save buffer index, associated with the buffer id so that it can be looked
+ // up later.
+ int buffer_id = buffer_consumer->id();
+ if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
+ buffer_id_to_index_[buffer_id] = allocated_buffer_index_;
+ ++allocated_buffer_index_;
+ }
+
if (!IsVisible()) {
ATRACE_NAME("DropFrameOnInvisibleSurface");
ALOGD_IF(TRACE,
@@ -171,6 +180,17 @@
return buffer;
}
+uint32_t DisplaySurface::GetRenderBufferIndex(int buffer_id) {
+ std::lock_guard<std::mutex> autolock(lock_);
+
+ if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
+ ALOGW("DisplaySurface::GetRenderBufferIndex: unknown buffer_id %d.",
+ buffer_id);
+ return 0;
+ }
+ return buffer_id_to_index_[buffer_id];
+}
+
bool DisplaySurface::IsBufferAvailable() {
std::lock_guard<std::mutex> autolock(lock_);
DequeueBuffersLocked();
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index feb173e..d31a3a9 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -60,10 +60,7 @@
}
}
- uint32_t GetRenderBufferIndex(int buffer_id) {
- return buffer_id_to_index_[buffer_id];
- }
-
+ uint32_t GetRenderBufferIndex(int buffer_id);
bool IsBufferAvailable();
bool IsBufferPosted();
AcquiredBuffer AcquireCurrentBuffer();
@@ -172,6 +169,8 @@
float manager_blur_;
int layer_order_;
+ // The monotonically increasing index for allocated buffers in this surface.
+ uint32_t allocated_buffer_index_;
// Maps from the buffer id to the corresponding allocated buffer index.
std::unordered_map<int, uint32_t> buffer_id_to_index_;
};
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index b8ca812..22a4616 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2416,7 +2416,7 @@
struct KeyReplacement replacement = {keyCode, args->deviceId};
mReplacedKeys.add(replacement, newKeyCode);
keyCode = newKeyCode;
- metaState &= ~AMETA_META_ON;
+ metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
}
} else if (args->action == AKEY_EVENT_ACTION_UP) {
// In order to maintain a consistent stream of up and down events, check to see if the key
@@ -2428,7 +2428,7 @@
if (index >= 0) {
keyCode = mReplacedKeys.valueAt(index);
mReplacedKeys.removeItemsAt(index);
- metaState &= ~AMETA_META_ON;
+ metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
}
}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index c87a8d9..647a4c0 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -64,10 +64,6 @@
DisplayHardware/HWComposer_hwc1.cpp
endif
-ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
- LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
-endif
-
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
LOCAL_HEADER_LIBRARIES := \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 11df4e2..c3b48ca 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -64,9 +64,8 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
-static bool useTripleFramebuffer = getBool<
- ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::useTripleFramebuffer>(false);
+static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) == 3;
#if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
// Dummy implementation in case it is missing.
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 9a0e94e..1b598f8 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -40,10 +40,7 @@
#include "FramebufferSurface.h"
#include "HWComposer.h"
-
-#ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
-#define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
-#endif
+#include "../SurfaceFlinger.h"
// ----------------------------------------------------------------------------
namespace android {
@@ -88,7 +85,8 @@
mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
#endif
- mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
+ mConsumer->setMaxAcquiredBufferCount(
+ SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9df49f6..a63b9b4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -118,6 +118,7 @@
uint64_t SurfaceFlinger::maxVirtualDisplaySize;
bool SurfaceFlinger::hasSyncFramework;
bool SurfaceFlinger::useVrFlinger;
+int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -185,6 +186,9 @@
useVrFlinger = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useVrFlinger>(false);
+ maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
+
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
@@ -3226,6 +3230,8 @@
result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
+ result.appendFormat(" NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
+ maxFrameBufferAcquiredBuffers);
result.append("]");
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2a24cb2..581bbfd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -147,6 +147,10 @@
// Equal to min(max_height, max_width).
static uint64_t maxVirtualDisplaySize;
+ // Controls the number of buffers SurfaceFlinger will allocate for use in
+ // FramebufferSurface
+ static int64_t maxFrameBufferAcquiredBuffers;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 0ff9f54..cd02b13 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -116,6 +116,7 @@
bool SurfaceFlinger::useHwcForRgbToYuv;
uint64_t SurfaceFlinger::maxVirtualDisplaySize;
bool SurfaceFlinger::hasSyncFramework;
+int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -175,6 +176,9 @@
useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
+ maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
+
char value[PROPERTY_VALUE_MAX];
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
@@ -3024,6 +3028,8 @@
result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
+ result.appendFormat(" NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
+ maxFrameBufferAcquiredBuffers);
result.append("]");
}
diff --git a/services/vr/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc
index ceedf1a..65b7293 100644
--- a/services/vr/bufferhubd/bufferhubd.rc
+++ b/services/vr/bufferhubd/bufferhubd.rc
@@ -2,5 +2,5 @@
class core
user system
group system
- cpuset /
+ writepid /dev/cpuset/tasks
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
new file mode 100644
index 0000000..629d65b
--- /dev/null
+++ b/services/vr/hardware_composer/Android.bp
@@ -0,0 +1,96 @@
+cc_library_static {
+ name: "libvr_hwc-binder",
+ srcs: [
+ "aidl/android/dvr/IVrComposer.aidl",
+ "aidl/android/dvr/IVrComposerCallback.aidl",
+ "aidl/android/dvr/parcelable_composer_frame.cpp",
+ "aidl/android/dvr/parcelable_composer_layer.cpp",
+ "aidl/android/dvr/parcelable_unique_fd.cpp",
+ ],
+ aidl: {
+ include_dirs: ["frameworks/native/services/vr/hardware_composer/aidl"],
+ export_aidl_headers: true,
+ },
+ export_include_dirs: ["aidl"],
+ shared_libs: [
+ "libbinder",
+ "libui",
+ "libutils",
+ "libvrhwc",
+ ],
+}
+
+cc_library_static {
+ name: "libvr_hwc-impl",
+ srcs: [
+ "vr_composer.cpp",
+ ],
+ static_libs: [
+ "libvr_hwc-binder",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libui",
+ "libutils",
+ "libvrhwc",
+ ],
+ export_shared_lib_headers: [
+ "libvrhwc",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"vr_hwc\"",
+ ],
+}
+
+cc_binary {
+ name: "vr_hwc",
+ srcs: [
+ "vr_hardware_composer_service.cpp"
+ ],
+ static_libs: [
+ "libvr_hwc-impl",
+ // NOTE: This needs to be included after the *-impl lib otherwise the
+ // symbols in the *-binder library get optimized out.
+ "libvr_hwc-binder",
+ ],
+ shared_libs: [
+ "android.dvr.composer@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libhardware",
+ "libhwbinder",
+ "libui",
+ "libutils",
+ "libvrhwc",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"vr_hwc\"",
+ ],
+ init_rc: [
+ "vr_hwc.rc",
+ ],
+}
+
+cc_test {
+ name: "vr_hwc_test",
+ gtest: true,
+ srcs: ["tests/vr_composer_test.cpp"],
+ static_libs: [
+ "libgtest",
+ "libvr_hwc-impl",
+ // NOTE: This needs to be included after the *-impl lib otherwise the
+ // symbols in the *-binder library get optimized out.
+ "libvr_hwc-binder",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libui",
+ "libutils",
+ ],
+}
diff --git a/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl b/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl
new file mode 100644
index 0000000..5fd5c36
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl
@@ -0,0 +1,20 @@
+package android.dvr;
+
+import android.dvr.IVrComposerCallback;
+
+/**
+ * Service interface exposed by VR HWC exposed to system apps which allows one
+ * system app to connect to get SurfaceFlinger's outputs (all displays). This
+ * is active when SurfaceFlinger is in VR mode, where all 2D output is
+ * redirected to VR HWC.
+ *
+ * @hide */
+interface IVrComposer
+{
+ const String SERVICE_NAME = "vr_hwc";
+
+ /**
+ * Registers a callback used to receive frame notifications.
+ */
+ void registerObserver(in IVrComposerCallback callback);
+}
diff --git a/services/vr/hardware_composer/aidl/android/dvr/IVrComposerCallback.aidl b/services/vr/hardware_composer/aidl/android/dvr/IVrComposerCallback.aidl
new file mode 100644
index 0000000..aa70de1
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/IVrComposerCallback.aidl
@@ -0,0 +1,22 @@
+package android.dvr;
+
+import android.dvr.ParcelableComposerFrame;
+import android.dvr.ParcelableUniqueFd;
+
+/**
+ * A system app will implement and register this callback with VRComposer
+ * to receive the layers SurfaceFlinger presented when in VR mode.
+ *
+ * @hide */
+interface IVrComposerCallback {
+ /**
+ * Called by the VR HWC service when a new frame is ready to be presented.
+ *
+ * @param frame The new frame VR HWC wants to present.
+ * @return A fence FD used to signal when the previous frame is no longer
+ * used by the client. This may be an invalid fence (-1) if the client is not
+ * using the previous frame, in which case the previous frame may be re-used
+ * at any point in time.
+ */
+ ParcelableUniqueFd onNewFrame(in ParcelableComposerFrame frame);
+}
diff --git a/services/vr/hardware_composer/aidl/android/dvr/ParcelableComposerFrame.aidl b/services/vr/hardware_composer/aidl/android/dvr/ParcelableComposerFrame.aidl
new file mode 100644
index 0000000..84abc19
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/ParcelableComposerFrame.aidl
@@ -0,0 +1,3 @@
+package android.dvr;
+
+parcelable ParcelableComposerFrame cpp_header "android/dvr/parcelable_composer_frame.h";
diff --git a/services/vr/hardware_composer/aidl/android/dvr/ParcelableComposerLayer.aidl b/services/vr/hardware_composer/aidl/android/dvr/ParcelableComposerLayer.aidl
new file mode 100644
index 0000000..a200345
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/ParcelableComposerLayer.aidl
@@ -0,0 +1,3 @@
+package android.dvr;
+
+parcelable ParcelableComposerLayer cpp_header "android/dvr/parcelable_composer_layer.h";
diff --git a/services/vr/hardware_composer/aidl/android/dvr/ParcelableUniqueFd.aidl b/services/vr/hardware_composer/aidl/android/dvr/ParcelableUniqueFd.aidl
new file mode 100644
index 0000000..eee9d13
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/ParcelableUniqueFd.aidl
@@ -0,0 +1,3 @@
+package android.dvr;
+
+parcelable ParcelableUniqueFd cpp_header "android/dvr/parcelable_unique_fd.h";
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
new file mode 100644
index 0000000..cb3e49d
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
@@ -0,0 +1,53 @@
+#include "aidl/android/dvr/parcelable_composer_frame.h"
+
+#include <binder/Parcel.h>
+
+#include "aidl/android/dvr/parcelable_composer_layer.h"
+
+namespace android {
+namespace dvr {
+
+ParcelableComposerFrame::ParcelableComposerFrame() {}
+
+ParcelableComposerFrame::ParcelableComposerFrame(
+ const ComposerView::Frame& frame)
+ : frame_(frame) {}
+
+ParcelableComposerFrame::~ParcelableComposerFrame() {}
+
+status_t ParcelableComposerFrame::writeToParcel(Parcel* parcel) const {
+ status_t ret = parcel->writeUint64(frame_.display_id);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeBool(frame_.removed);
+ if (ret != OK) return ret;
+
+ std::vector<ParcelableComposerLayer> layers;
+ for (size_t i = 0; i < frame_.layers.size(); ++i)
+ layers.push_back(ParcelableComposerLayer(frame_.layers[i]));
+
+ ret = parcel->writeParcelableVector(layers);
+
+ return ret;
+}
+
+status_t ParcelableComposerFrame::readFromParcel(const Parcel* parcel) {
+ status_t ret = parcel->readUint64(&frame_.display_id);
+ if (ret != OK) return ret;
+
+ ret = parcel->readBool(&frame_.removed);
+ if (ret != OK) return ret;
+
+ std::vector<ParcelableComposerLayer> layers;
+ ret = parcel->readParcelableVector(&layers);
+ if (ret != OK) return ret;
+
+ frame_.layers.clear();
+ for (size_t i = 0; i < layers.size(); ++i)
+ frame_.layers.push_back(layers[i].layer());
+
+ return ret;
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
new file mode 100644
index 0000000..b478bb5
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
@@ -0,0 +1,28 @@
+#ifndef ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_COMPOSER_FRAME_H
+#define ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_COMPOSER_FRAME_H
+
+#include <binder/Parcelable.h>
+#include <impl/vr_hwc.h>
+
+namespace android {
+namespace dvr {
+
+class ParcelableComposerFrame : public Parcelable {
+ public:
+ ParcelableComposerFrame();
+ ParcelableComposerFrame(const ComposerView::Frame& frame);
+ ~ParcelableComposerFrame() override;
+
+ ComposerView::Frame frame() const { return frame_; }
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ ComposerView::Frame frame_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_COMPOSER_FRAME_H
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
new file mode 100644
index 0000000..34e2b7e
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
@@ -0,0 +1,166 @@
+#include "aidl/android/dvr/parcelable_composer_layer.h"
+
+#include <binder/Parcel.h>
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+
+namespace android {
+namespace dvr {
+namespace {
+
+sp<GraphicBuffer> GetBufferFromHandle(native_handle_t* handle) {
+ uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
+ uint64_t producer_usage = 0, consumer_usage = 0;
+ int32_t format = 0;
+
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ // Need to register |handle| otherwise we can't read its properties.
+ if (mapper.registerBuffer(handle) != OK) {
+ ALOGE("Failed to register buffer");
+ return nullptr;
+ }
+
+ if (mapper.getDimensions(handle, &width, &height) ||
+ mapper.getStride(handle, &stride) ||
+ mapper.getFormat(handle, &format) ||
+ mapper.getProducerUsage(handle, &producer_usage) ||
+ mapper.getConsumerUsage(handle, &consumer_usage)) {
+ ALOGE("Failed to read handle properties");
+ return nullptr;
+ }
+
+ // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
+ // capability. Otherwise assume a count of 1.
+ mapper.getLayerCount(handle, &layer_count);
+
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ width, height, format, layer_count, producer_usage, consumer_usage,
+ stride, handle, true);
+
+ return buffer;
+}
+
+} // namespace
+
+ParcelableComposerLayer::ParcelableComposerLayer() {}
+
+ParcelableComposerLayer::ParcelableComposerLayer(
+ const ComposerView::ComposerLayer& layer) : layer_(layer) {}
+
+ParcelableComposerLayer::~ParcelableComposerLayer() {}
+
+status_t ParcelableComposerLayer::writeToParcel(Parcel* parcel) const {
+ status_t ret = parcel->writeUint64(layer_.id);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeNativeHandle(layer_.buffer->getNativeBuffer()->handle);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeBool(layer_.fence->isValid());
+ if (ret != OK) return ret;
+
+ if (layer_.fence->isValid()) {
+ ret = parcel->writeFileDescriptor(layer_.fence->dup(), true);
+ if (ret != OK) return ret;
+ }
+
+ ret = parcel->writeInt32(layer_.display_frame.left);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.display_frame.top);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.display_frame.right);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.display_frame.bottom);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeFloat(layer_.crop.left);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeFloat(layer_.crop.top);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeFloat(layer_.crop.right);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeFloat(layer_.crop.bottom);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(static_cast<int32_t>(layer_.blend_mode));
+ if (ret != OK) return ret;
+
+ ret = parcel->writeFloat(layer_.alpha);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeUint32(layer_.type);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeUint32(layer_.app_id);
+ if (ret != OK) return ret;
+
+ return OK;
+}
+
+status_t ParcelableComposerLayer::readFromParcel(const Parcel* parcel) {
+ status_t ret = parcel->readUint64(&layer_.id);
+ if (ret != OK) return ret;
+
+ native_handle* handle = parcel->readNativeHandle();
+ if (!handle) return BAD_VALUE;
+
+ layer_.buffer = GetBufferFromHandle(handle);
+ if (!layer_.buffer.get()) return BAD_VALUE;
+
+ bool has_fence = 0;
+ ret = parcel->readBool(&has_fence);
+ if (ret != OK) return ret;
+
+ if (has_fence)
+ layer_.fence = new Fence(dup(parcel->readFileDescriptor()));
+ else
+ layer_.fence = new Fence();
+
+ ret = parcel->readInt32(&layer_.display_frame.left);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&layer_.display_frame.top);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&layer_.display_frame.right);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&layer_.display_frame.bottom);
+ if (ret != OK) return ret;
+
+ ret = parcel->readFloat(&layer_.crop.left);
+ if (ret != OK) return ret;
+
+ ret = parcel->readFloat(&layer_.crop.top);
+ if (ret != OK) return ret;
+
+ ret = parcel->readFloat(&layer_.crop.right);
+ if (ret != OK) return ret;
+
+ ret = parcel->readFloat(&layer_.crop.bottom);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(reinterpret_cast<int32_t*>(&layer_.blend_mode));
+ if (ret != OK) return ret;
+
+ ret = parcel->readFloat(&layer_.alpha);
+ if (ret != OK) return ret;
+
+ ret = parcel->readUint32(&layer_.type);
+ if (ret != OK) return ret;
+
+ ret = parcel->readUint32(&layer_.app_id);
+ if (ret != OK) return ret;
+
+ return OK;
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
new file mode 100644
index 0000000..4cf48f1
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
@@ -0,0 +1,30 @@
+#ifndef ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_COMPOSER_LAYER_H
+#define ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_COMPOSER_LAYER_H
+
+#include <binder/Parcelable.h>
+#include <impl/vr_hwc.h>
+
+#include <memory>
+
+namespace android {
+namespace dvr {
+
+class ParcelableComposerLayer : public Parcelable {
+ public:
+ ParcelableComposerLayer();
+ ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
+ ~ParcelableComposerLayer() override;
+
+ ComposerView::ComposerLayer layer() const { return layer_; }
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ ComposerView::ComposerLayer layer_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_COMPOSER_LAYER_H
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.cpp
new file mode 100644
index 0000000..9486f3c
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.cpp
@@ -0,0 +1,37 @@
+#include "android/dvr/parcelable_unique_fd.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace dvr {
+
+ParcelableUniqueFd::ParcelableUniqueFd() {}
+
+ParcelableUniqueFd::ParcelableUniqueFd(const base::unique_fd& fence)
+ : fence_(dup(fence.get())) {}
+
+ParcelableUniqueFd::~ParcelableUniqueFd() {}
+
+status_t ParcelableUniqueFd::writeToParcel(Parcel* parcel) const {
+ status_t ret = parcel->writeBool(fence_.get() >= 0);
+ if (ret != OK) return ret;
+
+ if (fence_.get() >= 0)
+ ret = parcel->writeUniqueFileDescriptor(fence_);
+
+ return ret;
+}
+
+status_t ParcelableUniqueFd::readFromParcel(const Parcel* parcel) {
+ bool has_fence = 0;
+ status_t ret = parcel->readBool(&has_fence);
+ if (ret != OK) return ret;
+
+ if (has_fence)
+ ret = parcel->readUniqueFileDescriptor(&fence_);
+
+ return ret;
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
new file mode 100644
index 0000000..daf9e6d
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
@@ -0,0 +1,34 @@
+#ifndef ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_UNIQUE_FD_H
+#define ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_UNIQUE_FD_H
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace dvr {
+
+// Provide a wrapper to serialized base::unique_fd. The wrapper also handles the
+// case where the FD is invalid (-1), unlike FileDescriptor which expects a
+// valid FD.
+class ParcelableUniqueFd : public Parcelable {
+ public:
+ ParcelableUniqueFd();
+ ParcelableUniqueFd(const base::unique_fd& fence);
+ ~ParcelableUniqueFd() override;
+
+ void set_fence(const base::unique_fd& fence) {
+ fence_.reset(dup(fence.get()));
+ }
+ base::unique_fd fence() const { return base::unique_fd(dup(fence_.get())); }
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ base::unique_fd fence_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_HARDWARE_COMPOSER_AIDL_ANDROID_DVR_PARCELABLE_UNIQUE_FD_H
diff --git a/services/vr/hardware_composer/tests/vr_composer_test.cpp b/services/vr/hardware_composer/tests/vr_composer_test.cpp
new file mode 100644
index 0000000..cfc2708
--- /dev/null
+++ b/services/vr/hardware_composer/tests/vr_composer_test.cpp
@@ -0,0 +1,147 @@
+#include <android/dvr/BnVrComposerCallback.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <sys/eventfd.h>
+#include <vr_composer.h>
+
+namespace android {
+namespace dvr {
+namespace {
+
+const char kVrDisplayName[] = "VrDisplay_Test";
+
+class TestComposerCallback : public BnVrComposerCallback {
+ public:
+ TestComposerCallback() {}
+ ~TestComposerCallback() override = default;
+
+ ComposerView::Frame last_frame() const { return last_frame_; }
+
+ binder::Status onNewFrame(
+ const ParcelableComposerFrame& frame,
+ ParcelableUniqueFd* /* fence */) override {
+ last_frame_ = frame.frame();
+ return binder::Status::ok();
+ }
+
+ private:
+ ComposerView::Frame last_frame_;
+
+ TestComposerCallback(const TestComposerCallback&) = delete;
+ void operator=(const TestComposerCallback&) = delete;
+};
+
+class TestComposerCallbackWithFence : public TestComposerCallback {
+ public:
+ ~TestComposerCallbackWithFence() override = default;
+
+ binder::Status onNewFrame(
+ const ParcelableComposerFrame& frame,
+ ParcelableUniqueFd* fence) override {
+ binder::Status status = TestComposerCallback::onNewFrame(frame, fence);
+
+ base::unique_fd fd(eventfd(0, 0));
+ EXPECT_LE(0, fd.get());
+ fence->set_fence(fd);
+
+ return status;
+ }
+};
+
+sp<GraphicBuffer> CreateBuffer() {
+ return new GraphicBuffer(600, 400, PIXEL_FORMAT_RGBA_8888,
+ GraphicBuffer::USAGE_HW_TEXTURE);
+}
+
+} // namespace
+
+class VrComposerTest : public testing::Test {
+ public:
+ VrComposerTest() : composer_(new VrComposer()) {}
+ ~VrComposerTest() override = default;
+
+ sp<IVrComposer> GetComposerProxy() const {
+ sp<IServiceManager> sm(defaultServiceManager());
+ return interface_cast<IVrComposer>(sm->getService(String16(kVrDisplayName)));
+ }
+
+ void SetUp() override {
+ sp<IServiceManager> sm(defaultServiceManager());
+ EXPECT_EQ(OK,
+ sm->addService(String16(kVrDisplayName), composer_, false));
+ }
+
+ protected:
+ sp<VrComposer> composer_;
+
+ VrComposerTest(const VrComposerTest&) = delete;
+ void operator=(const VrComposerTest&) = delete;
+};
+
+TEST_F(VrComposerTest, TestWithoutObserver) {
+ sp<IVrComposer> composer = GetComposerProxy();
+ ComposerView::Frame frame;
+
+ base::unique_fd fence = composer_->OnNewFrame(frame);
+ ASSERT_EQ(-1, fence.get());
+}
+
+TEST_F(VrComposerTest, TestWithObserver) {
+ sp<IVrComposer> composer = GetComposerProxy();
+ sp<TestComposerCallback> callback = new TestComposerCallback();
+ ASSERT_TRUE(composer->registerObserver(callback).isOk());
+
+ ComposerView::Frame frame;
+ base::unique_fd fence = composer_->OnNewFrame(frame);
+ ASSERT_EQ(-1, fence.get());
+}
+
+TEST_F(VrComposerTest, TestWithOneLayer) {
+ sp<IVrComposer> composer = GetComposerProxy();
+ sp<TestComposerCallback> callback = new TestComposerCallbackWithFence();
+ ASSERT_TRUE(composer->registerObserver(callback).isOk());
+
+ ComposerView::Frame frame;
+ frame.display_id = 1;
+ frame.removed = false;
+ frame.layers.push_back(ComposerView::ComposerLayer{
+ .id = 1,
+ .buffer = CreateBuffer(),
+ .fence = new Fence(eventfd(0, 0)),
+ .display_frame = {0, 0, 600, 400},
+ .crop = {0.0f, 0.0f, 600.0f, 400.0f},
+ .blend_mode = IComposerClient::BlendMode::NONE,
+ .alpha = 1.0f,
+ .type = 1,
+ .app_id = 1,
+ });
+ base::unique_fd fence = composer_->OnNewFrame(frame);
+ ASSERT_LE(0, fence.get());
+
+ ComposerView::Frame received_frame = callback->last_frame();
+ ASSERT_EQ(frame.display_id, received_frame.display_id);
+ ASSERT_EQ(frame.removed, received_frame.removed);
+ ASSERT_EQ(1u, received_frame.layers.size());
+ ASSERT_EQ(frame.layers[0].id, received_frame.layers[0].id);
+ ASSERT_NE(nullptr, received_frame.layers[0].buffer.get());
+ ASSERT_TRUE(received_frame.layers[0].fence->isValid());
+ ASSERT_EQ(frame.layers[0].display_frame.left,
+ received_frame.layers[0].display_frame.left);
+ ASSERT_EQ(frame.layers[0].display_frame.top,
+ received_frame.layers[0].display_frame.top);
+ ASSERT_EQ(frame.layers[0].display_frame.right,
+ received_frame.layers[0].display_frame.right);
+ ASSERT_EQ(frame.layers[0].display_frame.bottom,
+ received_frame.layers[0].display_frame.bottom);
+ ASSERT_EQ(frame.layers[0].crop.left, received_frame.layers[0].crop.left);
+ ASSERT_EQ(frame.layers[0].crop.top, received_frame.layers[0].crop.top);
+ ASSERT_EQ(frame.layers[0].crop.right, received_frame.layers[0].crop.right);
+ ASSERT_EQ(frame.layers[0].crop.bottom, received_frame.layers[0].crop.bottom);
+ ASSERT_EQ(frame.layers[0].blend_mode, received_frame.layers[0].blend_mode);
+ ASSERT_EQ(frame.layers[0].alpha, received_frame.layers[0].alpha);
+ ASSERT_EQ(frame.layers[0].type, received_frame.layers[0].type);
+ ASSERT_EQ(frame.layers[0].app_id, received_frame.layers[0].app_id);
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/services/vr/hardware_composer/vr_composer.cpp b/services/vr/hardware_composer/vr_composer.cpp
new file mode 100644
index 0000000..c15f8fd
--- /dev/null
+++ b/services/vr/hardware_composer/vr_composer.cpp
@@ -0,0 +1,46 @@
+#include "vr_composer.h"
+
+namespace android {
+namespace dvr {
+
+VrComposer::VrComposer() {}
+
+VrComposer::~VrComposer() {}
+
+binder::Status VrComposer::registerObserver(
+ const sp<IVrComposerCallback>& callback) {
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ if (callback_.get()) {
+ ALOGE("Failed to register callback, already registered");
+ return binder::Status::fromStatusT(ALREADY_EXISTS);
+ }
+
+ callback_ = callback;
+ IInterface::asBinder(callback_)->linkToDeath(this);
+ return binder::Status::ok();
+}
+
+base::unique_fd VrComposer::OnNewFrame(const ComposerView::Frame& frame) {
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ if (!callback_.get())
+ return base::unique_fd();
+
+ ParcelableComposerFrame parcelable_frame(frame);
+ ParcelableUniqueFd fence;
+ binder::Status ret = callback_->onNewFrame(parcelable_frame, &fence);
+ if (!ret.isOk())
+ ALOGE("Failed to send new frame: %s", ret.toString8().string());
+
+ return fence.fence();
+}
+
+void VrComposer::binderDied(const wp<IBinder>& /* who */) {
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ callback_ = nullptr;
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/services/vr/hardware_composer/vr_composer.h b/services/vr/hardware_composer/vr_composer.h
new file mode 100644
index 0000000..93d1f2b
--- /dev/null
+++ b/services/vr/hardware_composer/vr_composer.h
@@ -0,0 +1,48 @@
+#ifndef ANDROID_DVR_HARDWARE_COMPOSER_VR_COMPOSER_H
+#define ANDROID_DVR_HARDWARE_COMPOSER_VR_COMPOSER_H
+
+#include <android/dvr/BnVrComposer.h>
+#include <impl/vr_hwc.h>
+
+namespace android {
+namespace dvr {
+
+class VrComposerCallback;
+
+// Implementation of the IVrComposer service used to notify VR Window Manager
+// when SurfaceFlinger presents 2D UI changes.
+//
+// VR HWC updates the presented frame via the ComposerView::Observer interface.
+// On notification |callback_| is called to update VR Window Manager.
+// NOTE: If VR Window Manager isn't connected, the notification is a no-op.
+class VrComposer
+ : public BnVrComposer,
+ public ComposerView::Observer,
+ public IBinder::DeathRecipient {
+ public:
+ VrComposer();
+ ~VrComposer() override;
+
+ // BnVrComposer:
+ binder::Status registerObserver(
+ const sp<IVrComposerCallback>& callback) override;
+
+ // ComposerView::Observer:
+ base::unique_fd OnNewFrame(const ComposerView::Frame& frame) override;
+
+ private:
+ // IBinder::DeathRecipient:
+ void binderDied(const wp<IBinder>& who) override;
+
+ std::mutex mutex_;
+
+ sp<IVrComposerCallback> callback_;
+
+ VrComposer(const VrComposer&) = delete;
+ void operator=(const VrComposer&) = delete;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_HARDWARE_COMPOSER_VR_COMPOSER_H
diff --git a/services/vr/hardware_composer/vr_hardware_composer_service.cpp b/services/vr/hardware_composer/vr_hardware_composer_service.cpp
new file mode 100644
index 0000000..9591748
--- /dev/null
+++ b/services/vr/hardware_composer/vr_hardware_composer_service.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <hwbinder/IPCThreadState.h>
+#include <impl/vr_hwc.h>
+#include <inttypes.h>
+
+#include "vr_composer.h"
+
+int main() {
+ android::ProcessState::self()->startThreadPool();
+
+ // Register the hwbinder HWC HAL service used by SurfaceFlinger while in VR
+ // mode.
+ const char instance[] = "vr_hwcomposer";
+ android::sp<IComposer> service =
+ android::dvr::HIDL_FETCH_IComposer(instance);
+
+ LOG_ALWAYS_FATAL_IF(!service.get(), "Failed to get service");
+ LOG_ALWAYS_FATAL_IF(service->isRemote(), "Service is remote");
+
+ LOG_ALWAYS_FATAL_IF(service->registerAsService(instance) != android::OK,
+ "Failed to register service");
+
+ android::sp<android::dvr::VrComposer> composer =
+ new android::dvr::VrComposer();
+
+ android::dvr::ComposerView* composer_view =
+ android::dvr::GetComposerViewFromIComposer(service.get());
+ composer_view->RegisterObserver(composer.get());
+
+ android::sp<android::IServiceManager> sm(android::defaultServiceManager());
+
+ // Register the binder service used by VR Window Manager service to receive
+ // frame information from VR HWC HAL.
+ android::status_t status = sm->addService(
+ android::dvr::VrComposer::SERVICE_NAME(), composer.get(),
+ false /* allowIsolated */);
+ LOG_ALWAYS_FATAL_IF(status != android::OK,
+ "VrDisplay service failed to start: %" PRId32, status);
+
+ android::hardware::ProcessState::self()->startThreadPool();
+ android::hardware::IPCThreadState::self()->joinThreadPool();
+
+ composer_view->UnregisterObserver(composer.get());
+
+ return 0;
+}
diff --git a/services/vr/hardware_composer/vr_hwc.rc b/services/vr/hardware_composer/vr_hwc.rc
new file mode 100644
index 0000000..5d3c4f7
--- /dev/null
+++ b/services/vr/hardware_composer/vr_hwc.rc
@@ -0,0 +1,6 @@
+service vr_hwc /system/bin/vr_hwc
+ class hal
+ user system
+ group system graphics
+ onrestart restart surfaceflinger
+ disabled
diff --git a/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc
index 754c97f..5042982 100644
--- a/services/vr/performanced/performanced.rc
+++ b/services/vr/performanced/performanced.rc
@@ -2,4 +2,4 @@
class core
user root
group system readproc
- cpuset /
+ writepid /dev/cpuset/tasks
diff --git a/services/vr/sensord/sensord.rc b/services/vr/sensord/sensord.rc
index d868a7e..f8d28fd 100644
--- a/services/vr/sensord/sensord.rc
+++ b/services/vr/sensord/sensord.rc
@@ -6,4 +6,4 @@
class core
user system
group system camera sdcard_rw
- cpuset /system
+ writepid /dev/cpuset/system/tasks
diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc
index b4f9f00..99315ef 100644
--- a/services/vr/virtual_touchpad/virtual_touchpad.rc
+++ b/services/vr/virtual_touchpad/virtual_touchpad.rc
@@ -2,4 +2,4 @@
class core
user system
group system input
- cpuset /system
+ writepid /dev/cpuset/system/tasks
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index 4349269..f28818a 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -34,6 +34,14 @@
"libutils",
],
+ export_static_lib_headers: [
+ "libhwcomposer-client",
+ ],
+
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1",
+ ],
+
export_include_dirs: ["."],
cflags: [
diff --git a/services/vr/vr_window_manager/composer_view/vr_composer_view.rc b/services/vr/vr_window_manager/composer_view/vr_composer_view.rc
index abb5265..bd9982b 100644
--- a/services/vr/vr_window_manager/composer_view/vr_composer_view.rc
+++ b/services/vr/vr_window_manager/composer_view/vr_composer_view.rc
@@ -2,4 +2,4 @@
class core
user system
group system graphics
- cpuset /system
+ writepid /dev/cpuset/system/tasks
diff --git a/services/vr/vr_window_manager/vr_wm.rc b/services/vr/vr_window_manager/vr_wm.rc
index 951515b..e515bb7 100644
--- a/services/vr/vr_window_manager/vr_wm.rc
+++ b/services/vr/vr_window_manager/vr_wm.rc
@@ -2,4 +2,4 @@
class core
user system
group system graphics input
- cpuset /system
+ writepid /dev/cpuset/system/tasks