Merge "Add 180 rotation to sensord orientation" into oc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 6a75237..cba8f36 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -112,6 +112,7 @@
 
 // Must be hardcoded because dumpstate HAL implementation need SELinux access to it
 static const std::string kDumpstateBoardPath = "/bugreports/dumpstate_board.txt";
+static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
 
 static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
 static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
@@ -962,7 +963,19 @@
                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
     RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
 
-    RunCommand("HARDWARE HALS", {"lshal"}, CommandOptions::AS_ROOT);
+    if (ds.IsZipping()) {
+        RunCommand(
+                "HARDWARE HALS",
+                {"lshal", std::string("--debug=") + kLsHalDebugPath},
+                CommandOptions::AS_ROOT);
+
+        ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
+
+        unlink(kLsHalDebugPath.c_str());
+    } else {
+        RunCommand(
+                "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
+    }
 
     RunCommand("PRINTENV", {"printenv"});
     RunCommand("NETSTAT", {"netstat", "-nW"});
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_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index b0b5a2a..4ce0b22 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -23,8 +23,8 @@
   return write_queue->producer_queue_->capacity();
 }
 
-void* dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                            JNIEnv* env) {
+jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                              JNIEnv* env) {
   CHECK_PARAM(env);
   CHECK_PARAM(write_queue);
 
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 6fd50ee..bee4d66 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -22,8 +22,9 @@
 typedef struct dvr_vsync_client dvr_vsync_client;
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
-typedef DvrDisplayManagerClient* (*DisplayManagerClientCreatePtr)(void);
-typedef void (*DisplayManagerClientDestroyPtr)(DvrDisplayManagerClient* client);
+typedef DvrDisplayManagerClient* (*DvrDisplayManagerClientCreatePtr)(void);
+typedef void (*DvrDisplayManagerClientDestroyPtr)(
+    DvrDisplayManagerClient* client);
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
@@ -32,27 +33,29 @@
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 
+typedef struct DvrSurface DvrSurface;
+
 // display_manager_client.h
-typedef int (*DisplayManagerClientGetSurfaceListPtr)(
+typedef int (*DvrDisplayManagerClientGetSurfaceListPtr)(
     DvrDisplayManagerClient* client,
     DvrDisplayManagerClientSurfaceList** surface_list);
-typedef void (*DisplayManagerClientSurfaceListDestroyPtr)(
+typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrWriteBuffer* (*DisplayManagerSetupPoseBufferPtr)(
+typedef DvrWriteBuffer* (*DvrDisplayManagerSetupPoseBufferPtr)(
     DvrDisplayManagerClient* client, size_t extended_region_size,
     uint64_t usage0, uint64_t usage1);
-typedef size_t (*DisplayManagerClientSurfaceListGetSizePtr)(
+typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
-typedef int (*DisplayManagerClientSurfaceListGetSurfaceIdPtr)(
+typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
     DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-typedef int (*DisplayManagerClientGetSurfaceBufferListPtr)(
+typedef int (*DvrDisplayManagerClientGetSurfaceBufferListPtr)(
     DvrDisplayManagerClient* client, int surface_id,
     DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-typedef void (*DisplayManagerClientSurfaceBufferListDestroyPtr)(
+typedef void (*DvrDisplayManagerClientSurfaceBufferListDestroyPtr)(
     DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef size_t (*DisplayManagerClientSurfaceBufferListGetSizePtr)(
+typedef size_t (*DvrDisplayManagerClientSurfaceBufferListGetSizePtr)(
     DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef int (*DisplayManagerClientSurfaceBufferListGetFdPtr)(
+typedef int (*DvrDisplayManagerClientSurfaceBufferListGetFdPtr)(
     DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
 
 // dvr_buffer.h
@@ -85,7 +88,7 @@
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
 typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
     DvrWriteBufferQueue* write_queue);
-typedef void* (*DvrWriteBufferQueueGetExternalSurfacePtr)(
+typedef jobject (*DvrWriteBufferQueueGetExternalSurfacePtr)(
     DvrWriteBufferQueue* write_queue, JNIEnv* env);
 typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
     DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
@@ -106,55 +109,61 @@
 
 // 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* (*VSyncClientCreatePtr)();
-typedef void (*VSyncClientDestroyPtr)(dvr_vsync_client* client);
-typedef int (*VSyncClientGetSchedInfoPtr)(dvr_vsync_client* client,
-                                          int64_t* vsync_period_ns,
-                                          int64_t* next_timestamp_ns,
-                                          uint32_t* next_vsync_count);
+typedef dvr_vsync_client* (*DvrVSyncClientCreatePtr)();
+typedef void (*DvrVSyncClientDestroyPtr)(dvr_vsync_client* client);
+typedef int (*DvrVSyncClientGetSchedInfoPtr)(dvr_vsync_client* client,
+                                             int64_t* vsync_period_ns,
+                                             int64_t* next_timestamp_ns,
+                                             uint32_t* next_vsync_count);
 
 // pose_client.h
-typedef DvrPose* (*PoseClientCreatePtr)(void);
-typedef void (*PoseClientDestroyPtr)(DvrPose* client);
-typedef int (*PoseGetPtr)(DvrPose* client, uint32_t vsync_count,
-                          DvrPoseAsync* out_pose);
-typedef uint32_t (*PoseGetVsyncCountPtr)(DvrPose* client);
-typedef int (*PoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
-                                    uint32_t vsync_count,
-                                    DvrPoseAsync* out_pose);
+typedef DvrPose* (*DvrPoseClientCreatePtr)(void);
+typedef void (*DvrPoseClientDestroyPtr)(DvrPose* client);
+typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
+                             DvrPoseAsync* out_pose);
+typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
+typedef int (*DvrPoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
+                                       uint32_t vsync_count,
+                                       DvrPoseAsync* out_pose);
 
 // virtual_touchpad_client.h
-typedef DvrVirtualTouchpad* (*VirtualTouchpadCreatePtr)(void);
-typedef void (*VirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client);
-typedef int (*VirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client);
-typedef int (*VirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client);
-typedef int (*VirtualTouchpadTouchPtr)(DvrVirtualTouchpad* client, int touchpad,
-                                       float x, float y, float pressure);
-typedef int (*VirtualTouchpadButtonStatePtr)(DvrVirtualTouchpad* client,
-                                             int touchpad, int buttons);
+typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
+typedef void (*DvrVirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client);
+typedef int (*DvrVirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client);
+typedef int (*DvrVirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client);
+typedef int (*DvrVirtualTouchpadTouchPtr)(DvrVirtualTouchpad* client,
+                                          int touchpad, float x, float y,
+                                          float pressure);
+typedef int (*DvrVirtualTouchpadButtonStatePtr)(DvrVirtualTouchpad* client,
+                                                int touchpad, int buttons);
 
 struct DvrApi_v1 {
   // Display manager client
-  DisplayManagerClientCreatePtr display_manager_client_create_;
-  DisplayManagerClientDestroyPtr display_manager_client_destroy_;
-  DisplayManagerClientGetSurfaceListPtr
+  DvrDisplayManagerClientCreatePtr display_manager_client_create_;
+  DvrDisplayManagerClientDestroyPtr display_manager_client_destroy_;
+  DvrDisplayManagerClientGetSurfaceListPtr
       display_manager_client_get_surface_list_;
-  DisplayManagerClientSurfaceListDestroyPtr
+  DvrDisplayManagerClientSurfaceListDestroyPtr
       display_manager_client_surface_list_destroy_;
-  DisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer_;
-  DisplayManagerClientSurfaceListGetSizePtr
+  DvrDisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer_;
+  DvrDisplayManagerClientSurfaceListGetSizePtr
       display_manager_client_surface_list_get_size_;
-  DisplayManagerClientSurfaceListGetSurfaceIdPtr
+  DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
       display_manager_client_surface_list_get_surface_id_;
-  DisplayManagerClientGetSurfaceBufferListPtr
+  DvrDisplayManagerClientGetSurfaceBufferListPtr
       display_manager_client_get_surface_buffer_list_;
-  DisplayManagerClientSurfaceBufferListDestroyPtr
+  DvrDisplayManagerClientSurfaceBufferListDestroyPtr
       display_manager_client_surface_buffer_list_destroy_;
-  DisplayManagerClientSurfaceBufferListGetSizePtr
+  DvrDisplayManagerClientSurfaceBufferListGetSizePtr
       display_manager_client_surface_buffer_list_get_size_;
-  DisplayManagerClientSurfaceBufferListGetFdPtr
+  DvrDisplayManagerClientSurfaceBufferListGetFdPtr
       display_manager_client_surface_buffer_list_get_fd_;
 
   // Write buffer
@@ -188,27 +197,29 @@
   DvrReadBufferQueueDequeuePtr read_buffer_queue_dequeue;
 
   // V-Sync client
-  VSyncClientCreatePtr vsync_client_create_;
-  VSyncClientDestroyPtr vsync_client_destroy_;
-  VSyncClientGetSchedInfoPtr vsync_client_get_sched_info_;
+  DvrVSyncClientCreatePtr vsync_client_create_;
+  DvrVSyncClientDestroyPtr vsync_client_destroy_;
+  DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info_;
 
   // Display surface
   DvrGetPoseBufferPtr get_pose_buffer_;
+  DvrSurfaceCreatePtr surface_create_;
+  DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue_;
 
   // Pose client
-  PoseClientCreatePtr pose_client_create_;
-  PoseClientDestroyPtr pose_client_destroy_;
-  PoseGetPtr pose_get_;
-  PoseGetVsyncCountPtr pose_get_vsync_count_;
-  PoseGetControllerPtr pose_get_controller_;
+  DvrPoseClientCreatePtr pose_client_create_;
+  DvrPoseClientDestroyPtr pose_client_destroy_;
+  DvrPoseGetPtr pose_get_;
+  DvrPoseGetVsyncCountPtr pose_get_vsync_count_;
+  DvrPoseGetControllerPtr pose_get_controller_;
 
   // Virtual touchpad client
-  VirtualTouchpadCreatePtr virtual_touchpad_create_;
-  VirtualTouchpadDestroyPtr virtual_touchpad_destroy_;
-  VirtualTouchpadAttachPtr virtual_touchpad_attach_;
-  VirtualTouchpadDetachPtr virtual_touchpad_detach_;
-  VirtualTouchpadTouchPtr virtual_touchpad_touch_;
-  VirtualTouchpadButtonStatePtr virtual_touchpad_button_state_;
+  DvrVirtualTouchpadCreatePtr virtual_touchpad_create_;
+  DvrVirtualTouchpadDestroyPtr virtual_touchpad_destroy_;
+  DvrVirtualTouchpadAttachPtr virtual_touchpad_attach_;
+  DvrVirtualTouchpadDetachPtr virtual_touchpad_detach_;
+  DvrVirtualTouchpadTouchPtr virtual_touchpad_touch_;
+  DvrVirtualTouchpadButtonStatePtr virtual_touchpad_button_state_;
 };
 
 int dvrGetApi(void* api, size_t struct_size, int version);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index 86b3ae2..80c9779 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -17,8 +17,8 @@
 
 // Returns ANativeWindow in the form of jobject. Can be casted to ANativeWindow
 // using ANativeWindow_fromSurface NDK API.
-void* dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                            JNIEnv* env);
+jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                              JNIEnv* env);
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
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/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 c270be2..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);
 }
 
@@ -378,6 +384,9 @@
           case 0x3:
             OnTouchpadButton(false, AMOTION_EVENT_BUTTON_BACK);
             break;
+          case 0x4:
+            should_recenter_ = true;
+            break;
           case 0x9:
             OnClick(true);
             break;
@@ -473,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);
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index dbb217d..5fbf5f5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -34,6 +34,9 @@
 #include "driver.h"
 #include "stubhal.h"
 
+// Set to true to enable exposing unratified extensions for development
+static const bool kEnableUnratifiedExtensions = false;
+
 // #define ENABLE_ALLOC_CALLSTACKS 1
 #if ENABLE_ALLOC_CALLSTACKS
 #include <utils/CallStack.h>
@@ -675,16 +678,24 @@
     const char* pLayerName,
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
-    static const std::array<VkExtensionProperties, 4> loader_extensions = {{
-        // WSI extensions
-        {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
-        {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
-         VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
-        {VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
-         VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION},
-        {VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
-         VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION},
-    }};
+
+    android::Vector<VkExtensionProperties> loader_extensions;
+    loader_extensions.push_back({
+        VK_KHR_SURFACE_EXTENSION_NAME,
+        VK_KHR_SURFACE_SPEC_VERSION});
+    loader_extensions.push_back({
+        VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+        VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
+    loader_extensions.push_back({
+        VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
+        VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
+
+    if (kEnableUnratifiedExtensions) {
+        loader_extensions.push_back({
+            VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+            VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
+    }
+
     static const VkExtensionProperties loader_debug_report_extension = {
         VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
     };
@@ -782,13 +793,15 @@
         VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
         VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
 
-    // conditionally add shared_presentable_image if supportable
-    VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
-    if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
-        presentation_properties.sharedImage) {
-        loader_extensions.push_back({
-            VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
-            VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
+    if (kEnableUnratifiedExtensions) {
+        // conditionally add shared_presentable_image if supportable
+        VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
+        if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
+            presentation_properties.sharedImage) {
+            loader_extensions.push_back({
+                VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
+                        VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
+        }
     }
 
     // enumerate our extensions first