support wrist orientation in recovery/fastbootd

Add support for wrist orientation in recovery. Feature controlled by
the property "config.enable_wristorientation".

Read 'ro.boot.wrist_orientation' property to determine if screen
orientation should be flipped and swipes inverted.

Bug: 257123026
Bug: 309982093

Test: build boot/recovery
Test: recovery/fastbootd uses same orientation as android

Change-Id: I29e0e682cca81d302dae502382b6270afe105d72
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index 41a3661..cc82094 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -503,6 +503,10 @@
   rotation = rot;
 }
 
+GRRotation gr_get_rotation() {
+  return rotation;
+}
+
 bool gr_has_multiple_connectors() {
   return gr_backend->HasMultipleConnectors();
 }
diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h
index 2353ed3..6a71ad3 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -153,6 +153,9 @@
 // Sets rotation, flips gr_fb_width/height if 90 degree rotation difference
 void gr_rotate(GRRotation rotation);
 
+// Get current rotation
+GRRotation gr_get_rotation();
+
 // Returns the current PixelFormat being used.
 PixelFormat gr_pixel_format();
 
diff --git a/recovery_ui/include/recovery_ui/wear_ui.h b/recovery_ui/include/recovery_ui/wear_ui.h
index e27e940..5dc432a 100644
--- a/recovery_ui/include/recovery_ui/wear_ui.h
+++ b/recovery_ui/include/recovery_ui/wear_ui.h
@@ -26,6 +26,8 @@
  public:
   WearRecoveryUI();
 
+  bool Init(const std::string& locale) override;
+
   void SetStage(int current, int max) override;
 
  protected:
diff --git a/recovery_ui/ui.cpp b/recovery_ui/ui.cpp
index 8bc0244..9b0fd94 100644
--- a/recovery_ui/ui.cpp
+++ b/recovery_ui/ui.cpp
@@ -197,8 +197,23 @@
   return true;
 }
 
+enum SwipeDirection { UP, DOWN, RIGHT, LEFT };
+
+static SwipeDirection FlipSwipeDirection(SwipeDirection direction) {
+  switch (direction) {
+    case UP:
+      return SwipeDirection::DOWN;
+    case DOWN:
+      return SwipeDirection::UP;
+    case RIGHT:
+      return SwipeDirection::LEFT;
+    case LEFT:
+      return SwipeDirection::RIGHT;
+  }
+}
+
 void RecoveryUI::OnTouchDetected(int dx, int dy) {
-  enum SwipeDirection { UP, DOWN, RIGHT, LEFT } direction;
+  SwipeDirection direction;
 
   // We only consider a valid swipe if:
   // - the delta along one axis is below touch_low_threshold_;
@@ -219,6 +234,11 @@
     return;
   }
 
+  // Flip swipe direction if screen is rotated upside down
+  if (gr_get_rotation() == GRRotation::DOWN) {
+    direction = FlipSwipeDirection(direction);
+  }
+
   LOG(DEBUG) << "Swipe direction=" << direction;
   switch (direction) {
     case SwipeDirection::UP:
diff --git a/recovery_ui/wear_ui.cpp b/recovery_ui/wear_ui.cpp
index 7b9ecf8..552f0cf 100644
--- a/recovery_ui/wear_ui.cpp
+++ b/recovery_ui/wear_ui.cpp
@@ -22,6 +22,7 @@
 #include <string>
 #include <vector>
 
+#include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
 
@@ -44,6 +45,50 @@
   touch_screen_allowed_ = true;
 }
 
+static void FlipOrientation() {
+  auto rotation = gr_get_rotation();
+  if (rotation == GRRotation::NONE) {
+    gr_rotate(GRRotation::DOWN);
+  } else if (rotation == GRRotation::DOWN) {
+    gr_rotate(GRRotation::NONE);
+  } else {
+    LOG(WARNING) << "Unsupported rotation for wrist orientation" << static_cast<int>(rotation);
+  }
+}
+
+// Match values in
+// frameworks/opt/wear/src/com/android/clockwork/wristorientation/WristOrientationService.java
+enum class WristOrientation : unsigned {
+  LEFT_WRIST_ROTATION_0 = 0,
+  LEFT_WRIST_ROTATION_180 = 1,
+  RIGHT_WRIST_ROTATION_0 = 2,
+  RIGHT_WRIST_ROTATION_180 = 3,
+};
+
+static void InitWristOrientation() {
+  auto prop = android::base::GetUintProperty("ro.boot.wrist_orientation", 0u);
+  WristOrientation orientation{ prop };
+  if (orientation == WristOrientation::LEFT_WRIST_ROTATION_180 ||
+      orientation == WristOrientation::RIGHT_WRIST_ROTATION_180) {
+    LOG(INFO)
+        << "InitWristOrientation(): flipping orientation because, 'ro.boot.wrist_orientation'="
+        << prop;
+
+    FlipOrientation();
+  }
+}
+
+bool WearRecoveryUI::Init(const std::string& locale) {
+  auto result = ScreenRecoveryUI::Init(locale);
+  auto wrist_orientation_enabled =
+      android::base::GetBoolProperty("config.enable_wristorientation", false);
+  LOG(INFO) << "WearRecoveryUI::Init(): enable_wristorientation=" << wrist_orientation_enabled;
+  if (wrist_orientation_enabled) {
+    InitWristOrientation();
+  }
+  return result;
+}
+
 // Draw background frame on the screen.  Does not flip pages.
 // Should only be called with updateMutex locked.
 // TODO merge drawing routines with screen_ui