Allow surfaceflinger to run vrflinger

* Allows surface flinger to switch in and out of vr mode

Bug: None
Test: Manually ran various vr test programs.
Change-Id: I15fbba0eb67cbcffeef41be31429550448a1db9c
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 0e05d54..aa8f189 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -49,14 +49,11 @@
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
-ifeq ($(TARGET_IN_VR_MODE),true)
-    LOCAL_CFLAGS += -DIN_VR_MODE
-endif
-
 ifeq ($(TARGET_USES_HWC2),true)
     LOCAL_CFLAGS += -DUSE_HWC2
     LOCAL_SRC_FILES += \
         SurfaceFlinger.cpp \
+        VrStateCallbacks.cpp \
         DisplayHardware/HWComposer.cpp
     ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
         LOCAL_CFLAGS += -DBYPASS_IHWC
@@ -134,7 +131,13 @@
 
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
 
-LOCAL_STATIC_LIBRARIES := libhwcomposer-command-buffer libtrace_proto libvkjson
+LOCAL_STATIC_LIBRARIES := \
+    libhwcomposer-command-buffer \
+    libtrace_proto \
+    libvkjson \
+    libvr_manager \
+    libvrflinger
+
 LOCAL_SHARED_LIBRARIES := \
     android.dvr.composer@1.0 \
     android.hardware.graphics.allocator@2.0 \
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 6cb1af1..3e9ef24 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -124,13 +124,11 @@
     endCommand();
 }
 
-Composer::Composer() : mWriter(kWriterInitialSize)
+Composer::Composer(bool useVrComposer)
+    : mWriter(kWriterInitialSize),
+      mIsUsingVrComposer(useVrComposer)
 {
-#if defined(IN_VR_MODE)
-    mIsInVrMode = true;
-#endif
-
-    if (mIsInVrMode) {
+    if (mIsUsingVrComposer) {
         mComposer = IComposer::getService("vr_hwcomposer");
     } else {
         mComposer = IComposer::getService("hwcomposer");
@@ -622,8 +620,7 @@
 Error Composer::setLayerInfo(Display display, Layer layer, uint32_t type,
                              uint32_t appId)
 {
-    if (mIsInVrMode)
-    {
+    if (mIsUsingVrComposer) {
         mWriter.selectDisplay(display);
         mWriter.selectLayer(layer);
         mWriter.setLayerInfo(type, appId);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 1ede705..18af9dd 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -26,7 +26,6 @@
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <utils/StrongPointer.h>
 #include <IComposerCommandBuffer.h>
-#include <MessageQueue.h>
 
 namespace android {
 
@@ -128,7 +127,7 @@
 // Composer is a wrapper to IComposer, a proxy to server-side composer.
 class Composer {
 public:
-    Composer();
+    Composer(bool useVrComposer);
 
     std::vector<IComposer::Capability> getCapabilities();
     std::string dumpDebugInfo();
@@ -136,6 +135,7 @@
     void registerCallback(const sp<IComposerCallback>& callback);
 
     uint32_t getMaxVirtualDisplayCount();
+    bool isUsingVrComposer() const { return mIsUsingVrComposer; }
     Error createVirtualDisplay(uint32_t width, uint32_t height,
             PixelFormat* format, Display* outDisplay);
     Error destroyVirtualDisplay(Display display);
@@ -248,7 +248,9 @@
     CommandWriter mWriter;
     CommandReader mReader;
 
-    bool mIsInVrMode = false;
+    // When true, the we attach to the vr_hwcomposer service instead of the
+    // hwcomposer. This allows us to redirect surfaces to 3d surfaces in vr.
+    const bool mIsUsingVrComposer;
 };
 
 } // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 99a6d71..a25e8a1 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -135,8 +135,8 @@
     mSetLayerVisibleRegion(nullptr),
     mSetLayerZOrder(nullptr),
 #else
-Device::Device()
-  : mComposer(std::make_unique<Hwc2::Composer>()),
+Device::Device(bool useVrComposer)
+  : mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
 #endif // BYPASS_IHWC
     mCapabilities(),
     mDisplays(),
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index d770f22..93eb999 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -67,7 +67,10 @@
 #ifdef BYPASS_IHWC
     explicit Device(hwc2_device_t* device);
 #else
-    Device();
+    // 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();
 
@@ -106,6 +109,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
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index e86a071..1c99036 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -49,6 +49,7 @@
 #include "HWComposer.h"
 #include "HWC2On1Adapter.h"
 #include "HWC2.h"
+#include "ComposerHal.h"
 
 #include "../Layer.h"           // needed only for debugging
 #include "../SurfaceFlinger.h"
@@ -59,7 +60,7 @@
 
 // ---------------------------------------------------------------------------
 
-HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
+HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer)
     : mFlinger(flinger),
       mAdapter(),
       mHwcDevice(),
@@ -76,7 +77,7 @@
         mVSyncCounts[i] = 0;
     }
 
-    loadHwcModule();
+    loadHwcModule(useVrComposer);
 }
 
 HWComposer::~HWComposer() {}
@@ -105,11 +106,13 @@
 }
 
 // Load and prepare the hardware composer module.  Sets mHwc.
-void HWComposer::loadHwcModule()
+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) {
@@ -142,7 +145,7 @@
                 static_cast<hwc2_device_t*>(mAdapter.get()));
     }
 #else
-    mHwcDevice = std::make_unique<HWC2::Device>();
+    mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
 #endif
 
     mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
@@ -867,6 +870,14 @@
 }
 */
 
+bool HWComposer::isUsingVrComposer() const {
+#ifdef BYPASS_IHWC
+    return false;
+#else
+    return getComposer()->isUsingVrComposer();
+#endif
+}
+
 void HWComposer::dump(String8& result) const {
     // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
     // all the state going into the layers. This is probably better done in
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 37f12e4..7b61e0e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -77,7 +77,10 @@
         virtual ~EventHandler() {}
     };
 
-    HWComposer(const sp<SurfaceFlinger>& flinger);
+    // 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.
+    HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer);
 
     ~HWComposer();
 
@@ -165,13 +168,16 @@
 
     status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode);
 
+    bool isUsingVrComposer() const;
+
     // for debugging ----------------------------------------------------------
     void dump(String8& out) const;
 
+    android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
 private:
     static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
 
-    void loadHwcModule();
+    void loadHwcModule(bool useVrComposer);
 
     bool isValidDisplay(int32_t displayId) const;
     static void validateChange(HWC2::Composition from, HWC2::Composition to);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 76c710a..12166a8 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -413,6 +413,10 @@
         }
     }
 
+    void clearHwcLayers() {
+        mHwcLayers.clear();
+    }
+
 #endif
     // -----------------------------------------------------------------------
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index de7795b..6289bdb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -36,6 +36,8 @@
 #include <binder/MemoryHeapBase.h>
 #include <binder/PermissionCache.h>
 
+#include <dvr/vr_flinger.h>
+
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 
@@ -73,6 +75,7 @@
 #include "LayerDim.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
+#include "VrStateCallbacks.h"
 
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
@@ -155,7 +158,10 @@
         mLayersRemoved(false),
         mLayersAdded(false),
         mRepaintEverything(0),
-        mRenderEngine(NULL),
+        mHwc(nullptr),
+        mRealHwc(nullptr),
+        mVrHwc(nullptr),
+        mRenderEngine(nullptr),
         mBootTime(systemTime()),
         mBuiltinDisplays(),
         mVisibleRegionsDirty(false),
@@ -180,7 +186,8 @@
         mFrameBuckets(),
         mTotalTime(0),
         mLastSwapTime(0),
-        mNumLayers(0)
+        mNumLayers(0),
+        mEnterVrMode(false)
 {
     ALOGI("SurfaceFlinger is starting");
 
@@ -227,6 +234,14 @@
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(display);
+
+    if (mVrStateCallbacks.get()) {
+        sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
+            defaultServiceManager()->checkService(String16("vrmanager")));
+        if (vrManagerService.get()) {
+            vrManagerService->unregisterListener(mVrStateCallbacks);
+        }
+    }
 }
 
 void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
@@ -361,6 +376,13 @@
     const int LOGTAG_SF_STOP_BOOTANIM = 60110;
     LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                    ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+
+    sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
+        defaultServiceManager()->checkService(String16("vrmanager")));
+    if (vrManagerService.get()) {
+        mVrStateCallbacks = new VrStateCallbacks(*this);
+        vrManagerService->registerListener(mVrStateCallbacks);
+    }
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -556,7 +578,9 @@
     // Drop the state lock while we initialize the hardware composer. We drop
     // the lock because on creation, it will call back into SurfaceFlinger to
     // initialize the primary display.
-    mHwc = new HWComposer(this);
+    LOG_ALWAYS_FATAL_IF(mEnterVrMode, "Starting in vr mode is not currently supported.");
+    mRealHwc = new HWComposer(this, false);
+    mHwc = mRealHwc;
     mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
 
     Mutex::Autolock _l(mStateLock);
@@ -1104,7 +1128,13 @@
         bool isSecure = true;
 
         int32_t type = DisplayDevice::DISPLAY_PRIMARY;
-        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+
+        // When we're using the vr composer, the assumption is that we've
+        // already created the IBinder object for the primary display.
+        if (!mHwc->isUsingVrComposer()) {
+            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+        }
+
         wp<IBinder> token = mBuiltinDisplays[type];
 
         sp<IGraphicBufferProducer> producer;
@@ -1139,10 +1169,79 @@
             enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
 }
 
+void SurfaceFlinger::clearHwcLayers(const LayerVector& layers) {
+    for (size_t i = 0; i < layers.size(); ++i) {
+        layers[i]->clearHwcLayers();
+    }
+}
+
+void SurfaceFlinger::resetHwc() {
+    disableHardwareVsync(true);
+    clearHwcLayers(mDrawingState.layersSortedByZ);
+    clearHwcLayers(mCurrentState.layersSortedByZ);
+    // Clear the drawing state so that the logic inside of
+    // handleTransactionLocked will fire. It will determine the delta between
+    // mCurrentState and mDrawingState and re-apply all changes when we make the
+    // transition.
+    mDrawingState.displays.clear();
+    mDisplays.clear();
+}
+
+void SurfaceFlinger::updateVrMode() {
+    {
+        Mutex::Autolock _l(mStateLock);
+        bool enteringVrMode = mEnterVrMode;
+        if (enteringVrMode == mHwc->isUsingVrComposer()) {
+            return;
+        }
+
+        if (enteringVrMode) {
+            // Start vrflinger thread, if it hasn't been started already.
+            if (!mVrFlinger) {
+                mVrFlinger = std::make_unique<dvr::VrFlinger>();
+                int err = mVrFlinger->Run(mHwc->getComposer());
+                if (err != NO_ERROR) {
+                    ALOGE("Failed to run vrflinger: %s (%d)", strerror(-err), err);
+                    mVrFlinger.reset();
+                    mEnterVrMode = false;
+                    return;
+                }
+            }
+
+            if (!mVrHwc) {
+                mVrHwc = new HWComposer(this, true);
+                ALOGV("Vr HWC created");
+            }
+
+            resetHwc();
+
+            mHwc = mVrHwc;
+            mVrFlinger->EnterVrMode();
+        } else {
+            mVrFlinger->ExitVrMode();
+
+            resetHwc();
+
+            mHwc = mRealHwc;
+            enableHardwareVsync();
+        }
+
+        mVisibleRegionsDirty = true;
+        invalidateHwcGeometry();
+        android_atomic_or(1, &mRepaintEverything);
+        setTransactionFlags(eDisplayTransactionNeeded);
+    }
+    if (mVrHwc) {
+        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
+    }
+}
+
 void SurfaceFlinger::onMessageReceived(int32_t what) {
     ATRACE_CALL();
     switch (what) {
         case MessageQueue::INVALIDATE: {
+            updateVrMode();
+
             bool frameMissed = !mHadClientComposition &&
                     mPreviousPresentFence != Fence::NO_FENCE &&
                     mPreviousPresentFence->getSignalTime() == INT64_MAX;
@@ -1763,16 +1862,10 @@
                                 "adding a supported display, but rendering "
                                 "surface is provided (%p), ignoring it",
                                 state.surface.get());
-                        if (state.type == DisplayDevice::DISPLAY_EXTERNAL) {
-                            hwcId = DisplayDevice::DISPLAY_EXTERNAL;
-                            dispSurface = new FramebufferSurface(*mHwc,
-                                    DisplayDevice::DISPLAY_EXTERNAL,
-                                    bqConsumer);
-                            producer = bqProducer;
-                        } else {
-                            ALOGE("Attempted to add non-external non-virtual"
-                                    " display");
-                        }
+
+                        hwcId = state.type;
+                        dispSurface = new FramebufferSurface(*mHwc, hwcId, bqConsumer);
+                        producer = bqProducer;
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 55735b1..384e345 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SURFACE_FLINGER_H
 #define ANDROID_SURFACE_FLINGER_H
 
+#include <memory>
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -81,6 +82,11 @@
 class EventControlThread;
 class VSyncSource;
 class InjectVSyncSource;
+class VrStateCallbacks;
+
+namespace dvr {
+class VrFlinger;
+} // namespace dvr
 
 // ---------------------------------------------------------------------------
 
@@ -156,6 +162,7 @@
     friend class EventThread;
     friend class Layer;
     friend class MonitoredProducer;
+    friend class VrStateCallbacks;
 
     // This value is specified in number of frames.  Log frame stats at most
     // every half hour.
@@ -460,6 +467,19 @@
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
     }
+
+#ifdef USE_HWC2
+    /* ------------------------------------------------------------------------
+     * VrFlinger
+     */
+    void clearHwcLayers(const LayerVector& layers);
+    void resetHwc();
+
+    // Check to see if we should change to or from vr mode, and if so, perform
+    // the handoff.
+    void updateVrMode();
+#endif
+
     /* ------------------------------------------------------------------------
      * Attributes
      */
@@ -481,8 +501,13 @@
     // access must be protected by mInvalidateLock
     volatile int32_t mRepaintEverything;
 
-    // constant members (no synchronization needed for access)
+    // current, real and vr hardware composers.
     HWComposer* mHwc;
+#ifdef USE_HWC2
+    HWComposer* mRealHwc;
+    HWComposer* mVrHwc;
+#endif
+    // constant members (no synchronization needed for access)
     RenderEngine* mRenderEngine;
     nsecs_t mBootTime;
     bool mGpuToCpuSupported;
@@ -495,6 +520,10 @@
     EGLDisplay mEGLDisplay;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
 
+#ifdef USE_HWC2
+    std::unique_ptr<dvr::VrFlinger> mVrFlinger;
+#endif
+
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState;
@@ -601,6 +630,12 @@
     // Verify that transaction is being called by an approved process:
     // either AID_GRAPHICS or AID_SYSTEM.
     status_t CheckTransactCodeCredentials(uint32_t code);
+
+#ifdef USE_HWC2
+    sp<VrStateCallbacks> mVrStateCallbacks;
+
+    std::atomic<bool> mEnterVrMode;
+#endif
     };
 
 }; // namespace android
diff --git a/services/surfaceflinger/VrStateCallbacks.cpp b/services/surfaceflinger/VrStateCallbacks.cpp
new file mode 100644
index 0000000..a924def
--- /dev/null
+++ b/services/surfaceflinger/VrStateCallbacks.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VrStateCallbacks.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+VrStateCallbacks::VrStateCallbacks(SurfaceFlinger& flinger)
+    : mFlinger(flinger) {}
+
+void VrStateCallbacks::onVrStateChanged(bool enabled) {
+    mFlinger.mEnterVrMode = enabled;
+    mFlinger.signalTransaction();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/VrStateCallbacks.h b/services/surfaceflinger/VrStateCallbacks.h
new file mode 100644
index 0000000..4e655d3
--- /dev/null
+++ b/services/surfaceflinger/VrStateCallbacks.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_VR_STATE_CALLBACKS_H
+#define ANDROID_VR_STATE_CALLBACKS_H
+
+#include <vr/vr_manager/vr_manager.h>
+
+namespace android {
+
+class SurfaceFlinger;
+
+class VrStateCallbacks : public BnVrStateCallbacks {
+public:
+    VrStateCallbacks(SurfaceFlinger& flinger);
+    void onVrStateChanged(bool enabled) override;
+
+private:
+    SurfaceFlinger& mFlinger;
+};
+
+} // namespace android
+
+#endif // ANDROID_VR_STATE_CALLBACKS_H