Allow VRWM to show 2D apps

2D apps appear as a single app layer at the front of the stack. We can
distinguish them from VR apps as VR has two layers at the front.
When we detect a 2D app we don't skip the first layers for rendering

Test: launch VR app, launch calculator
Bug: None
Change-Id: Iea8420870852b84ab790b5185ac1a44103c2aae5
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 72a9c1a..8075bf9 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -194,16 +194,22 @@
 }
 
 // Determine if ths frame should be shown or hidden.
-bool CalculateVisibilityFromLayerConfig(const HwcCallback::Frame& frame,
-                                        uint32_t vr_app) {
+ViewMode CalculateVisibilityFromLayerConfig(const HwcCallback::Frame& frame,
+                                            uint32_t vr_app) {
   auto& layers = frame.layers();
 
   // We assume the first two layers are the VR app.
   if (layers.size() < kVRAppLayerCount)
-    return false;
+    return ViewMode::Hidden;
 
-  if (vr_app != layers[0].appid || layers[0].appid == 0)
-    return false;
+  if (vr_app != layers[0].appid || layers[0].appid == 0 ||
+      layers[1].appid != layers[0].appid) {
+    if (layers[1].appid != layers[0].appid && layers[0].appid) {
+      // This might be a 2D app.
+      return ViewMode::App;
+    }
+    return ViewMode::Hidden;
+  }
 
   // If a non-VR-app, non-skipped layer appears, show.
   size_t index = kVRAppLayerCount;
@@ -219,11 +225,12 @@
   // If any non-skipped layers exist now then we show, otherwise hide.
   for (size_t i = index; i < layers.size(); i++) {
     if (!layers[i].should_skip_layer())
-      return true;
+      return ViewMode::VR;
   }
-  return false;
+  return ViewMode::Hidden;
 }
 
+
 }  // namespace
 
 ShellView::ShellView() {
@@ -308,7 +315,7 @@
     if (!pending_frames_.empty()) {
       // Check if we should advance the frame.
       auto& frame = pending_frames_.front();
-      if (!frame.visibility ||
+      if (frame.visibility == ViewMode::Hidden ||
           frame.frame->Finish() == HwcCallback::FrameStatus::kFinished) {
         current_frame_ = std::move(frame);
         pending_frames_.pop_front();
@@ -316,17 +323,20 @@
     }
   }
 
-  if (!debug_mode_ && current_frame_.visibility != is_visible_) {
-    SetVisibility(current_frame_.visibility);
+  bool visible = current_frame_.visibility != ViewMode::Hidden;
+
+  if (!debug_mode_ && visible != is_visible_) {
+    SetVisibility(current_frame_.visibility != ViewMode::Hidden);
   }
 
-  if (!current_frame_.visibility)
+  if (!visible)
     return;
 
   ime_texture_ = TextureLayer();
 
   surface_flinger_view_->GetTextures(*current_frame_.frame.get(), &textures_,
-                                     &ime_texture_, debug_mode_);
+                                     &ime_texture_, debug_mode_,
+                                     view_mode_ == ViewMode::VR);
   has_ime_ = ime_texture_.texture != nullptr;
 }
 
@@ -373,14 +383,17 @@
   if (!frame || frame->layers().empty())
     return;
 
-  bool visibility = debug_mode_ || CalculateVisibilityFromLayerConfig(
-                                       *frame.get(), current_vr_app_);
+  ViewMode visibility =
+      CalculateVisibilityFromLayerConfig(*frame.get(), current_vr_app_);
+
+  if (visibility == ViewMode::Hidden && debug_mode_)
+    visibility = ViewMode::VR;
   current_vr_app_ = frame->layers().front().appid;
 
   // If we are not showing the frame there's no need to keep anything around.
-  if (!visibility) {
+  if (visibility == ViewMode::Hidden) {
     // Hidden, no change so drop it completely
-    if (!current_frame_.visibility)
+    if (current_frame_.visibility == ViewMode::Hidden)
       return;
 
     frame.reset(nullptr);
@@ -395,7 +408,7 @@
 
   // If we are showing ourselves the main thread is not processing anything,
   // so give it a kick.
-  if (visibility && !current_frame_.visibility) {
+  if (visibility != ViewMode::Hidden && current_frame_.visibility == ViewMode::Hidden) {
     QueueTask(MainThreadTask::EnteringVrMode);
     QueueTask(MainThreadTask::Show);
   }
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index 589902e..e19a71d 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -14,6 +14,12 @@
 namespace android {
 namespace dvr {
 
+enum class ViewMode {
+  Hidden,
+  VR,
+  App,
+};
+
 class ShellView : public Application, public HwcCallback::Client {
  public:
   ShellView();
@@ -64,6 +70,8 @@
   std::unique_ptr<ShaderProgram> overlay_program_;
   std::unique_ptr<ShaderProgram> controller_program_;
 
+  ViewMode view_mode_ = ViewMode::Hidden;
+
   uint32_t current_vr_app_;
 
   // Used to center the scene when the shell becomes visible.
@@ -92,7 +100,7 @@
 
   struct PendingFrame {
     PendingFrame() = default;
-    PendingFrame(std::unique_ptr<HwcCallback::Frame>&& frame, bool visibility)
+    PendingFrame(std::unique_ptr<HwcCallback::Frame>&& frame, ViewMode visibility)
         : frame(std::move(frame)), visibility(visibility) {}
     PendingFrame(PendingFrame&& r)
         : frame(std::move(r.frame)), visibility(r.visibility) {}
@@ -103,7 +111,7 @@
     }
 
     std::unique_ptr<HwcCallback::Frame> frame;
-    bool visibility = false;
+    ViewMode visibility = ViewMode::Hidden;
   };
   std::deque<PendingFrame> pending_frames_;
   std::mutex pending_frame_mutex_;
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index d38fcc0..6cc654a 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -38,13 +38,13 @@
 bool SurfaceFlingerView::GetTextures(const HwcCallback::Frame& frame,
                                      std::vector<TextureLayer>* texture_layers,
                                      TextureLayer* ime_layer,
-                                     bool debug) const {
+                                     bool debug, bool skip_first_layer) const {
   auto& layers = frame.layers();
   texture_layers->clear();
 
   size_t start = 0;
   // Skip the second layer if it is from the VR app.
-  if (!debug) {
+  if (!debug && skip_first_layer) {
     start = 1;
     if (layers[0].appid && layers[0].appid == layers[1].appid)
       start = 2;
diff --git a/services/vr/vr_window_manager/surface_flinger_view.h b/services/vr/vr_window_manager/surface_flinger_view.h
index e079cdb..c39ab41 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.h
+++ b/services/vr/vr_window_manager/surface_flinger_view.h
@@ -33,7 +33,8 @@
 
   bool GetTextures(const HwcCallback::Frame& layers,
                    std::vector<TextureLayer>* texture_layers,
-                   TextureLayer* ime_layer, bool debug) const;
+                   TextureLayer* ime_layer, bool debug,
+                   bool skip_first_layer) const;
 
  private:
   sp<IVrComposerView> composer_service_;