Merge "vndk/window.h must be C compatible" into oc-dev
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 4dd49da..5aa9652 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -77,6 +77,8 @@
 
     // dvr_surface.h
     dvr_api->get_pose_buffer_ = dvrGetPoseBuffer;
+    dvr_api->surface_create_ = dvrSurfaceCreate;
+    dvr_api->surface_get_write_buffer_queue_ = dvrSurfaceGetWriteBufferQueue;
 
     // vsync_client_api.h
     dvr_api->vsync_client_create_ = dvr_vsync_client_create;
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index 2abbe63..a3cbba5 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -4,8 +4,60 @@
 
 using namespace android;
 
+struct DvrSurface {
+  std::unique_ptr<dvr::DisplaySurfaceClient> display_surface_;
+};
+
 extern "C" {
 
+int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
+                     uint64_t usage1, int flags, DvrSurface** out_surface) {
+  if (out_surface == nullptr) {
+    ALOGE("dvrSurfaceCreate: invalid inputs: out_surface=%p.", out_surface);
+    return -EINVAL;
+  }
+
+  int error;
+  auto client = dvr::DisplayClient::Create(&error);
+  if (!client) {
+    ALOGE("Failed to create display client!");
+    return error;
+  }
+
+  // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
+  std::unique_ptr<dvr::DisplaySurfaceClient> surface =
+      client->CreateDisplaySurface(
+          width, height, static_cast<int>(usage0 | usage1), format, flags);
+
+  DvrSurface* dvr_surface = new DvrSurface;
+  dvr_surface->display_surface_ = std::move(surface);
+  *out_surface = dvr_surface;
+  return 0;
+}
+
+int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
+                                  DvrWriteBufferQueue** out_writer) {
+  if (surface == nullptr || out_writer == nullptr) {
+    ALOGE(
+        "dvrSurfaceGetWriteBufferQueue: Invalid inputs: surface=%p, "
+        "out_writer=%p.",
+        surface, out_writer);
+    return -EINVAL;
+  }
+  DvrWriteBufferQueue* buffer_writer = new DvrWriteBufferQueue;
+  buffer_writer->producer_queue_ =
+      surface->display_surface_->GetProducerQueue();
+  if (buffer_writer->producer_queue_ == nullptr) {
+    ALOGE(
+        "dvrSurfaceGetWriteBufferQueue: Failed to get producer queue from "
+        "display surface.");
+    return -ENOMEM;
+  }
+
+  *out_writer = buffer_writer;
+  return 0;
+}
+
 int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
   auto client = android::dvr::DisplayClient::Create();
   if (!client) {
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 504a046..bee4d66 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -33,6 +33,8 @@
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 
+typedef struct DvrSurface DvrSurface;
+
 // display_manager_client.h
 typedef int (*DvrDisplayManagerClientGetSurfaceListPtr)(
     DvrDisplayManagerClient* client,
@@ -107,6 +109,11 @@
 
 // dvr_surface.h
 typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
+                                   uint64_t usage0, uint64_t usage1, int flags,
+                                   DvrSurface** out_surface);
+typedef int (*DvrSurfaceGetWriteBufferQueuePtr)(
+    DvrSurface* surface, DvrWriteBufferQueue** out_writer);
 
 // vsync_client_api.h
 typedef dvr_vsync_client* (*DvrVSyncClientCreatePtr)();
@@ -196,6 +203,8 @@
 
   // Display surface
   DvrGetPoseBufferPtr get_pose_buffer_;
+  DvrSurfaceCreatePtr surface_create_;
+  DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue_;
 
   // Pose client
   DvrPoseClientCreatePtr pose_client_create_;
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index fa8d228..2712f24 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -2,14 +2,25 @@
 #define ANDROID_DVR_SURFACE_H_
 
 #include <dvr/dvr_buffer.h>
+#include <dvr/dvr_buffer_queue.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef struct DvrSurface DvrSurface;
+typedef struct DvrSurfaceParameter DvrSurfaceParameter;
+
 // Get a pointer to the global pose buffer.
 int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
 
+int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
+                     uint64_t usage1, int flags, DvrSurface** out_surface);
+
+// TODO(eieio, jwcai) Change this once we have multiple buffer queue support.
+int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
+                                  DvrWriteBufferQueue** out_writer);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/services/vr/sensord/pose_service.cpp b/services/vr/sensord/pose_service.cpp
index 32a2160..2c4fc30 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -435,6 +435,15 @@
             kRotX90 * Rotationd(AngleAxisd(-k90DegInRad, kVecAxisY));
         start_from_head_rotation =
             (pose_state.sensor_from_start_rotation * kPostRotation).inverse();
+      } else if (device_orientation_type_ == kOrientationTypeLandscape180) {
+        const Rotationd kPreRotation =
+            Rotationd(AngleAxisd(k90DegInRad * 2.0, kVecAxisY)) *
+            Rotationd(AngleAxisd(k90DegInRad * 2.0, kVecAxisZ));
+        const Rotationd kPostRotation = kRotX90;
+        start_from_head_rotation =
+            (kPreRotation *
+             pose_state.sensor_from_start_rotation * kPostRotation)
+                .inverse();
       } else {
         const Rotationd kPreRotation =
             Rotationd(AngleAxisd(k90DegInRad, kVecAxisZ));
diff --git a/services/vr/sensord/pose_service.h b/services/vr/sensord/pose_service.h
index 899d5fb..4df5036 100644
--- a/services/vr/sensord/pose_service.h
+++ b/services/vr/sensord/pose_service.h
@@ -43,6 +43,8 @@
     kOrientationTypePortrait = 1,
     // Landscape device.
     kOrientationTypeLandscape = 2,
+    // 180 Landscape device.
+    kOrientationTypeLandscape180 = 3,
   };
 
   // Initializes the service. Keeps a reference to sensor_thread, which must be
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 67fd927..b16049f 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
@@ -25,5 +25,6 @@
     void exitVrMode() = 3;
     void setDebugMode(int mode) = 4;
     void set2DMode(int mode) = 5;
+    void setRotation(int angle) = 6;
 }
 
diff --git a/services/vr/vr_window_manager/display_view.cpp b/services/vr/vr_window_manager/display_view.cpp
index e88e7d0..311e27f 100644
--- a/services/vr/vr_window_manager/display_view.cpp
+++ b/services/vr/vr_window_manager/display_view.cpp
@@ -146,16 +146,18 @@
 
 DisplayView::DisplayView(uint32_t id, int touchpad_id)
     : id_(id), touchpad_id_(touchpad_id) {
-  translate_ = Eigen::Translation3f(0, 0, -2.5f);
+  translate_ = Eigen::Translation3f(0, 0, -5.0f);
   ime_translate_ = mat4(Eigen::Translation3f(0.0f, -0.5f, 0.25f));
   ime_top_left_ = vec2(0, 0);
   ime_size_ = vec2(0, 0);
+  rotation_ = mat4::Identity();
 }
 
 DisplayView::~DisplayView() {}
 
 void DisplayView::Recenter(const mat4& initial) {
-  initial_head_matrix_ = initial;
+  initial_head_matrix_ =
+      initial * Eigen::AngleAxisf(M_PI * 0.5f, vec3::UnitZ());
 }
 
 void DisplayView::SetPrograms(ShaderProgram* program,
@@ -248,7 +250,7 @@
 bool DisplayView::IsHit(const vec3& view_location, const vec3& view_direction,
                         vec3* hit_location, vec2* hit_location_in_window_coord,
                         bool test_ime) {
-  mat4 m = initial_head_matrix_ * translate_;
+  mat4 m = GetStandardTransform();
   if (test_ime)
     m = m * ime_translate_;
   mat4 inverse = (m * scale_).inverse();
@@ -314,8 +316,7 @@
     mat4 layer_transform =
         GetLayerTransform(texture_layer, size_.x(), size_.y());
 
-    mat4 transform =
-        initial_head_matrix_ * translate_ * scale_ * layer_transform;
+    mat4 transform = GetStandardTransform() * scale_ * layer_transform;
     DrawWithTransform(transform, *program_);
 
     glDisable(GL_BLEND);
@@ -351,14 +352,21 @@
   }
 }
 
+mat4 DisplayView::GetStandardTransform() {
+  mat4 m = initial_head_matrix_ * rotation_ * translate_;
+  if (current_frame_.visibility == ViewMode::App)
+    m *= Eigen::AngleAxisf(M_PI * -0.5f, vec3::UnitZ());
+  return m;
+}
+
 void DisplayView::DrawIme() {
   program_->Use();
   glBindTexture(GL_TEXTURE_2D, ime_texture_.texture->id());
 
   mat4 layer_transform = GetLayerTransform(ime_texture_, size_.x(), size_.y());
 
-  mat4 transform = initial_head_matrix_ * translate_ * ime_translate_ * scale_ *
-                   layer_transform;
+  mat4 transform =
+      GetStandardTransform() * ime_translate_ * scale_ * layer_transform;
 
   DrawWithTransform(transform, *program_);
 }
@@ -377,7 +385,7 @@
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   mat4 layer_transform = GetLayerTransform(layer, size_.x(), size_.y());
 
-  mat4 transform = initial_head_matrix_ * translate_ * scale_ * layer_transform;
+  mat4 transform = GetStandardTransform() * scale_ * layer_transform;
   DrawWithTransform(transform, *overlay_program_);
   glDisable(GL_BLEND);
 }
diff --git a/services/vr/vr_window_manager/display_view.h b/services/vr/vr_window_manager/display_view.h
index 0d1355e..aaf4677 100644
--- a/services/vr/vr_window_manager/display_view.h
+++ b/services/vr/vr_window_manager/display_view.h
@@ -47,6 +47,8 @@
   void set_2dmode(bool mode) { use_2dmode_ = mode; }
   void set_always_2d(bool mode) { always_2d_ = mode; }
 
+  void set_rotation(const mat4& rotation) { rotation_ = rotation; }
+
  private:
   bool IsHit(const vec3& view_location, const vec3& view_direction,
              vec3* hit_location, vec2* hit_location_in_window_coord,
@@ -60,6 +62,9 @@
                       const vec2& top_left, const vec2& bottom_right);
   void DrawWithTransform(const mat4& transform, const ShaderProgram& program);
 
+  // This is the rotated, translated but unscaled transform to apply everywhere.
+  mat4 GetStandardTransform();
+
   uint32_t id_;
   int touchpad_id_;
 
@@ -72,6 +77,7 @@
   mat4 scale_;
   mat4 translate_;
   mat4 ime_translate_;
+  mat4 rotation_;
   vec2 size_;
 
   std::vector<TextureLayer> textures_;
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index fba599f..3aae228 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -205,6 +205,12 @@
     displays_[0]->set_2dmode(mode);
 }
 
+void ShellView::SetRotation(int angle) {
+  mat4 m(Eigen::AngleAxisf(M_PI * -0.5f * angle, vec3::UnitZ()));
+  for (auto& d: displays_)
+    d->set_rotation(m);
+}
+
 void ShellView::OnDrawFrame() {
   bool visible = false;
 
@@ -323,10 +329,6 @@
 
   size_ = vec2(surface_flinger_view_->width(), surface_flinger_view_->height());
 
-  // TODO(alexst): Replicate controller rendering from VR Home.
-  // Current approach in the function below is a quick visualization.
-  DrawController(perspective, eye_matrix, head_matrix);
-
   for (auto& display : displays_) {
     if (display->visible()) {
       display->DrawEye(eye, perspective, eye_matrix, head_matrix, size_,
@@ -334,6 +336,10 @@
     }
   }
 
+  // TODO(alexst): Replicate controller rendering from VR Home.
+  // Current approach in the function below is a quick visualization.
+  DrawController(perspective, eye_matrix, head_matrix);
+
   DrawReticle(perspective, eye_matrix, head_matrix);
 }
 
@@ -476,12 +482,14 @@
 
   const vec2& hit_location = active_display_->hit_location();
 
+  float x = hit_location.x() / size_.x();
+  float y = hit_location.y() / size_.y();
+
   // Device is portrait, but in landscape when in VR.
   // Rotate touch input appropriately.
   const android::status_t status = dvrVirtualTouchpadTouch(
       virtual_touchpad_.get(), active_display_->touchpad_id(),
-      1.0f - hit_location.y() / size_.y(), hit_location.x() / size_.x(),
-      is_touching_ ? 1.0f : 0.0f);
+      x, y, is_touching_ ? 1.0f : 0.0f);
   if (status != OK) {
     ALOGE("touch failed: %d", status);
   }
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index d265866..8548dc1 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -34,6 +34,7 @@
   void VrMode(bool mode) override;
   void dumpInternal(String8& result) override;
   void Set2DMode(bool mode) override;
+  void SetRotation(int angle) override;
 
 
  protected:
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 9f77e5a..c66e4a1 100644
--- a/services/vr/vr_window_manager/shell_view_binder_interface.h
+++ b/services/vr/vr_window_manager/shell_view_binder_interface.h
@@ -13,6 +13,7 @@
   virtual void VrMode(bool mode) = 0;
   virtual void dumpInternal(String8& result) = 0;
   virtual void Set2DMode(bool mode) = 0;
+  virtual void SetRotation(int angle) = 0;
 };
 
 }  // namespace dvr
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index 427ad70..7ecc542 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -59,9 +59,8 @@
     ALOGI("Setting display metrics to default : width=%d height=%d", metrics.display_native_height, metrics.display_native_width);
   }
 
-  // TODO(alexst): Refactor ShellView to account for orientation and change this back.
-  width_ = metrics.display_native_height;
-  height_ = metrics.display_native_width;
+  width_ = metrics.display_native_width;
+  height_ = metrics.display_native_height;
   return true;
 }
 
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 8868588..fdcb8b2 100644
--- a/services/vr/vr_window_manager/vr_window_manager_binder.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
@@ -138,6 +138,11 @@
   return binder::Status::ok();
 }
 
+binder::Status VrWindowManagerBinder::setRotation(int32_t angle) {
+  app_.SetRotation(angle);
+  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 1915ffc..9d0f0b2 100644
--- a/services/vr/vr_window_manager/vr_window_manager_binder.h
+++ b/services/vr/vr_window_manager/vr_window_manager_binder.h
@@ -60,6 +60,7 @@
   ::android::binder::Status exitVrMode() override;
   ::android::binder::Status setDebugMode(int32_t mode) override;
   ::android::binder::Status set2DMode(int32_t mode) override;
+  ::android::binder::Status setRotation(int32_t angle) 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 2e5c488..758e02b 100644
--- a/services/vr/vr_window_manager/vr_wm_ctl.cpp
+++ b/services/vr/vr_window_manager/vr_wm_ctl.cpp
@@ -41,6 +41,8 @@
     exit(report(vrwm->setDebugMode(atoi(argv[2]))));
   } else if ((argc == 3) && (strcmp(argv[1], "2d") == 0)) {
     exit(report(vrwm->set2DMode(atoi(argv[2]))));
+  } else if ((argc == 3) && (strcmp(argv[1], "rotate") == 0)) {
+    exit(report(vrwm->setRotation(atoi(argv[2]))));
   } else {
     usage();
     exit(2);