Merge "vrwm: Add 2D Mode + control app change"
diff --git a/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl b/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl
index b5dbb8b..67fd927 100644
--- a/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl
+++ b/services/vr/vr_window_manager/aidl/android/service/vr/IVrWindowManager.aidl
@@ -24,5 +24,6 @@
     void enterVrMode() = 2;
     void exitVrMode() = 3;
     void setDebugMode(int mode) = 4;
+    void set2DMode(int mode) = 5;
 }
 
diff --git a/services/vr/vr_window_manager/display_view.cpp b/services/vr/vr_window_manager/display_view.cpp
index 5f1e73e..8a1c84d 100644
--- a/services/vr/vr_window_manager/display_view.cpp
+++ b/services/vr/vr_window_manager/display_view.cpp
@@ -8,7 +8,6 @@
 namespace {
 
 constexpr float kLayerScaleFactor = 3.0f;
-constexpr unsigned int kVRAppLayerCount = 2;
 constexpr unsigned int kMaximumPendingFrames = 8;
 
 // clang-format off
@@ -99,7 +98,7 @@
 
 // Determine if ths frame should be shown or hidden.
 ViewMode CalculateVisibilityFromLayerConfig(const HwcCallback::Frame& frame,
-                                            uint32_t vr_app) {
+                                            uint32_t *appid) {
   auto& layers = frame.layers();
 
   // TODO(achaulk): Figure out how to identify the current VR app for 2D app
@@ -120,6 +119,11 @@
     return ViewMode::Hidden;
   }
 
+  if(layers[index].appid != *appid) {
+    *appid = layers[index].appid;
+    return ViewMode::App;
+  }
+
   // This is the VR app, ignore it.
   index++;
 
@@ -136,6 +140,7 @@
     if (!layers[i].should_skip_layer())
       return ViewMode::VR;
   }
+
   return ViewMode::Hidden;
 }
 
@@ -198,16 +203,25 @@
 
 base::unique_fd DisplayView::OnFrame(std::unique_ptr<HwcCallback::Frame> frame,
                                      bool debug_mode, bool* showing) {
-  ViewMode visibility =
-      CalculateVisibilityFromLayerConfig(*frame.get(), current_vr_app_);
+  uint32_t app = current_vr_app_;
+  ViewMode visibility = CalculateVisibilityFromLayerConfig(*frame.get(), &app);
 
   if (visibility == ViewMode::Hidden && debug_mode)
     visibility = ViewMode::VR;
 
-  if (frame->layers().empty())
+  if (frame->layers().empty()) {
     current_vr_app_ = 0;
-  else
-    current_vr_app_ = frame->layers().front().appid;
+  } else if (visibility == ViewMode::App) {
+    // This is either a VR app switch or a 2D app launching.
+    // If we can have VR apps, update if it's 0.
+    if (!always_2d_ && (current_vr_app_ == 0 || !use_2dmode_)) {
+      visibility = ViewMode::Hidden;
+      current_vr_app_ = app;
+    }
+  } else if (!current_vr_app_) {
+    // The VR app is running.
+    current_vr_app_ = app;
+  }
 
   pending_frames_.emplace_back(std::move(frame), visibility);
 
diff --git a/services/vr/vr_window_manager/display_view.h b/services/vr/vr_window_manager/display_view.h
index 0a27781..9483e8b 100644
--- a/services/vr/vr_window_manager/display_view.h
+++ b/services/vr/vr_window_manager/display_view.h
@@ -44,6 +44,9 @@
   uint32_t id() const { return id_; }
   int touchpad_id() const { return touchpad_id_; }
 
+  void set_2dmode(bool mode) { use_2dmode_ = mode; }
+  void set_always_2d(bool mode) { always_2d_ = mode; }
+
  private:
   bool IsHit(const vec3& view_location, const vec3& view_direction,
              vec3* hit_location, vec2* hit_location_in_window_coord,
@@ -79,6 +82,8 @@
   vec2 ime_top_left_;
   vec2 ime_size_;
   bool has_ime_ = false;
+  bool use_2dmode_ = false;
+  bool always_2d_ = false;
 
   struct PendingFrame {
     PendingFrame() = default;
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index a21e883..e17b2ae 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -16,6 +16,8 @@
 
 namespace {
 
+constexpr uint32_t kPrimaryDisplayId = 1;
+
 const std::string kVertexShader = SHADER0([]() {
   layout(location = 0) in vec4 aPosition;
   layout(location = 1) in vec4 aTexCoord;
@@ -96,8 +98,8 @@
 }
 
 int GetTouchIdForDisplay(uint32_t display) {
-  return display == 1 ? DVR_VIRTUAL_TOUCHPAD_PRIMARY
-                      : DVR_VIRTUAL_TOUCHPAD_VIRTUAL;
+  return display == kPrimaryDisplayId ? DVR_VIRTUAL_TOUCHPAD_PRIMARY
+                                      : DVR_VIRTUAL_TOUCHPAD_VIRTUAL;
 }
 
 }  // namespace
@@ -190,6 +192,11 @@
   result.append("\n");
 }
 
+void ShellView::Set2DMode(bool mode) {
+  if (!displays_.empty())
+    displays_[0]->set_2dmode(mode);
+}
+
 void ShellView::OnDrawFrame() {
   bool visible = false;
 
@@ -253,6 +260,9 @@
   }
 
   auto display = new DisplayView(id, GetTouchIdForDisplay(id));
+  // Virtual displays only ever have 2D apps so force it.
+  if (id != kPrimaryDisplayId)
+    display->set_always_2d(true);
   new_displays_.emplace_back(display);
   return display;
 }
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index 856c8b8..6887e7e 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -32,6 +32,8 @@
   void EnableDebug(bool debug) override;
   void VrMode(bool mode) override;
   void dumpInternal(String8& result) override;
+  void Set2DMode(bool mode) override;
+
 
  protected:
   void DrawEye(EyeType eye, const mat4& perspective, const mat4& eye_matrix,
diff --git a/services/vr/vr_window_manager/shell_view_binder_interface.h b/services/vr/vr_window_manager/shell_view_binder_interface.h
index b58e4bd..9f77e5a 100644
--- a/services/vr/vr_window_manager/shell_view_binder_interface.h
+++ b/services/vr/vr_window_manager/shell_view_binder_interface.h
@@ -12,6 +12,7 @@
   virtual void EnableDebug(bool debug) = 0;
   virtual void VrMode(bool mode) = 0;
   virtual void dumpInternal(String8& result) = 0;
+  virtual void Set2DMode(bool mode) = 0;
 };
 
 }  // namespace dvr
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder.cpp b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
index bd3f3ee..8868588 100644
--- a/services/vr/vr_window_manager/vr_window_manager_binder.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
@@ -133,6 +133,11 @@
   return binder::Status::ok();
 }
 
+binder::Status VrWindowManagerBinder::set2DMode(int32_t mode) {
+  app_.Set2DMode(static_cast<bool>(mode));
+  return binder::Status::ok();
+}
+
 status_t VrWindowManagerBinder::dump(
     int fd, const Vector<String16>& args [[gnu::unused]]) {
   String8 result;
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder.h b/services/vr/vr_window_manager/vr_window_manager_binder.h
index 99ca27a..1915ffc 100644
--- a/services/vr/vr_window_manager/vr_window_manager_binder.h
+++ b/services/vr/vr_window_manager/vr_window_manager_binder.h
@@ -59,6 +59,7 @@
   ::android::binder::Status enterVrMode() override;
   ::android::binder::Status exitVrMode() override;
   ::android::binder::Status setDebugMode(int32_t mode) override;
+  ::android::binder::Status set2DMode(int32_t mode) override;
 
   // Implements BBinder::dump().
   status_t dump(int fd, const Vector<String16>& args) override;
diff --git a/services/vr/vr_window_manager/vr_wm_ctl.cpp b/services/vr/vr_window_manager/vr_wm_ctl.cpp
index c67b2eb..2e5c488 100644
--- a/services/vr/vr_window_manager/vr_wm_ctl.cpp
+++ b/services/vr/vr_window_manager/vr_wm_ctl.cpp
@@ -39,6 +39,8 @@
     exit(report(vrwm->exitVrMode()));
   } else if ((argc == 3) && (strcmp(argv[1], "debug") == 0)) {
     exit(report(vrwm->setDebugMode(atoi(argv[2]))));
+  } else if ((argc == 3) && (strcmp(argv[1], "2d") == 0)) {
+    exit(report(vrwm->set2DMode(atoi(argv[2]))));
   } else {
     usage();
     exit(2);