screen_ui: Allow setting screen margin space.
am: 8f7547edfa  -s ours

Change-Id: Ie480acb2efab18ec32c4964914457aac4f34e74e
diff --git a/Android.mk b/Android.mk
index e619db0..5ce9d33 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,6 +76,7 @@
     rotate_logs.cpp \
     screen_ui.cpp \
     ui.cpp \
+    vr_ui.cpp \
     wear_ui.cpp \
     wear_touch.cpp \
 
@@ -92,6 +93,18 @@
 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
 LOCAL_CFLAGS += -Wno-unused-parameter -Werror
 
+ifneq ($(TARGET_RECOVERY_UI_MARGIN_HEIGHT),)
+LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_HEIGHT=$(TARGET_RECOVERY_UI_MARGIN_HEIGHT)
+else
+LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_HEIGHT=0
+endif
+
+ifneq ($(TARGET_RECOVERY_UI_MARGIN_WIDTH),)
+LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_WIDTH=$(TARGET_RECOVERY_UI_MARGIN_WIDTH)
+else
+LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_WIDTH=0
+endif
+
 LOCAL_C_INCLUDES += \
     system/vold \
 
@@ -182,6 +195,17 @@
 LOCAL_CFLAGS := -Werror
 include $(BUILD_STATIC_LIBRARY)
 
+# vr headset default device
+# ===============================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := vr_device.cpp
+
+# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
+LOCAL_MODULE := librecovery_ui_vr
+
+include $(BUILD_STATIC_LIBRARY)
+
 include \
     $(LOCAL_PATH)/applypatch/Android.mk \
     $(LOCAL_PATH)/boot_control/Android.mk \
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..09754c6
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+enh+aosp-gerrit@google.com
+tbao@google.com
+xunchang@google.com
diff --git a/install.cpp b/install.cpp
index a1f2e4f..db4ba93 100644
--- a/install.cpp
+++ b/install.cpp
@@ -27,6 +27,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <atomic>
 #include <chrono>
 #include <condition_variable>
 #include <functional>
@@ -294,11 +295,12 @@
 }
 #endif  // !AB_OTA_UPDATER
 
-static void log_max_temperature(int* max_temperature) {
+static void log_max_temperature(int* max_temperature, const std::atomic<bool>& logger_finished) {
   CHECK(max_temperature != nullptr);
   std::mutex mtx;
   std::unique_lock<std::mutex> lck(mtx);
-  while (finish_log_temperature.wait_for(lck, 20s) == std::cv_status::timeout) {
+  while (!logger_finished.load() &&
+         finish_log_temperature.wait_for(lck, 20s) == std::cv_status::timeout) {
     *max_temperature = std::max(*max_temperature, GetMaxValueFromThermalZone());
   }
 }
@@ -403,7 +405,8 @@
   }
   close(pipefd[1]);
 
-  std::thread temperature_logger(log_max_temperature, max_temperature);
+  std::atomic<bool> logger_finished(false);
+  std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));
 
   *wipe_cache = false;
   bool retry_update = false;
@@ -467,6 +470,7 @@
   int status;
   waitpid(pid, &status, 0);
 
+  logger_finished.store(true);
   finish_log_temperature.notify_one();
   temperature_logger.join();
 
diff --git a/screen_ui.cpp b/screen_ui.cpp
index 10e56de..d21a648 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -51,7 +51,9 @@
 }
 
 ScreenRecoveryUI::ScreenRecoveryUI()
-    : density_(static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f),
+    : kMarginWidth(RECOVERY_UI_MARGIN_WIDTH),
+      kMarginHeight(RECOVERY_UI_MARGIN_HEIGHT),
+      density_(static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f),
       currentIcon(NONE),
       progressBarType(EMPTY),
       progressScopeStart(0),
@@ -78,8 +80,6 @@
       animation_fps(30),  // TODO: there's currently no way to infer this.
       stage(-1),
       max_stage(-1),
-      margin_width_(0),
-      margin_height_(0),
       updateMutex(PTHREAD_MUTEX_INITIALIZER) {}
 
 GRSurface* ScreenRecoveryUI::GetCurrentFrame() {
@@ -257,6 +257,10 @@
     *y += 4;
 }
 
+void ScreenRecoveryUI::DrawHighlightBar(int x, int y, int width, int height) const {
+    gr_fill(x, y, x + width, y + height);
+}
+
 void ScreenRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) const {
     gr_text(gr_sys_font(), x, *y, line, bold);
     *y += char_height_ + 4;
@@ -292,8 +296,8 @@
   gr_clear();
 
   static constexpr int TEXT_INDENT = 4;
-  int x = TEXT_INDENT + margin_width_;
-  int y = margin_height_;
+  int x = TEXT_INDENT + kMarginWidth;
+  int y = kMarginHeight;
   if (show_menu) {
     std::string recovery_fingerprint =
         android::base::GetProperty("ro.bootimage.build.fingerprint", "");
@@ -315,15 +319,14 @@
       if (i == menu_sel) {
         // Draw the highlight bar.
         SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG);
-        gr_fill(0, y - 2, gr_fb_width(), y + char_height_ + 2);
+        DrawHighlightBar(0, y - 2, gr_fb_width(), char_height_ + 4);
         // Bold white text for the selected item.
         SetColor(MENU_SEL_FG);
-        gr_text(gr_sys_font(), 4, y, menu_[i], true);
+        DrawTextLine(x, &y, menu_[i], true);
         SetColor(MENU);
       } else {
-        gr_text(gr_sys_font(), 4, y, menu_[i], false);
+        DrawTextLine(x, &y, menu_[i], false);
       }
-      y += char_height_ + 4;
     }
     DrawHorizontalRule(&y);
   }
@@ -333,9 +336,10 @@
   SetColor(LOG);
   int row = (text_top_ + text_rows_ - 1) % text_rows_;
   size_t count = 0;
-  for (int ty = gr_fb_height() - margin_height_ - char_height_;
+  for (int ty = gr_fb_height() - kMarginHeight - char_height_ - log_bottom_offset_;
        ty >= y && count < text_rows_; ty -= char_height_, ++count) {
-    gr_text(gr_sys_font(), 0, ty, text_[row], false);
+    int temp_y = ty;
+    DrawTextLine(x, &temp_y, text_[row], false);
     --row;
     if (row < 0) row = text_rows_ - 1;
   }
@@ -453,8 +457,9 @@
   }
 
   gr_font_size(gr_sys_font(), &char_width_, &char_height_);
-  text_rows_ = (gr_fb_height() - margin_height_ * 2) / char_height_;
-  text_cols_ = (gr_fb_width() - margin_width_ * 2) / char_width_;
+  text_rows_ = (gr_fb_height() - kMarginHeight * 2) / char_height_;
+  text_cols_ = (gr_fb_width() - kMarginWidth * 2) / char_width_;
+  log_bottom_offset_ = 0;
   return true;
 }
 
diff --git a/screen_ui.h b/screen_ui.h
index 86cbd5c..e961c1c 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -72,6 +72,11 @@
     void SetColor(UIElement e);
 
   protected:
+    // The margin that we don't want to use for showing texts (e.g. round screen, or screen with
+    // rounded corners).
+    const int kMarginWidth;
+    const int kMarginHeight;
+
     // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi.
     const float density_;
 
@@ -108,6 +113,7 @@
     // Log text overlay, displayed when a magic key is pressed.
     char** text_;
     size_t text_col_, text_row_, text_top_;
+    int log_bottom_offset_;
 
     bool show_text;
     bool show_text_ever;   // has show_text ever been true?
@@ -137,11 +143,6 @@
     int char_width_;
     int char_height_;
 
-    // The margin that we don't want to use for showing texts (e.g. round screen, or screen with
-    // rounded corners).
-    int margin_width_;
-    int margin_height_;
-
     pthread_mutex_t updateMutex;
 
     virtual bool InitTextParams();
@@ -172,8 +173,9 @@
     virtual int GetProgressBaseline();
     virtual int GetTextBaseline();
 
-    void DrawHorizontalRule(int* y);
-    void DrawTextLine(int x, int* y, const char* line, bool bold) const;
+    virtual void DrawHorizontalRule(int* y);
+    virtual void DrawHighlightBar(int x, int y, int width, int height) const;
+    virtual void DrawTextLine(int x, int* y, const char* line, bool bold) const;
     void DrawTextLines(int x, int* y, const char* const* lines) const;
 };
 
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 35e87fd..0298a76 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -224,102 +224,6 @@
     expect("", script6.c_str(), kNoCause);
 }
 
-TEST_F(UpdaterTest, package_extract_dir) {
-  // package_extract_dir expects 2 arguments.
-  expect(nullptr, "package_extract_dir()", kArgsParsingFailure);
-  expect(nullptr, "package_extract_dir(\"arg1\")", kArgsParsingFailure);
-  expect(nullptr, "package_extract_dir(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
-
-  std::string zip_path = from_testdata_base("ziptest_valid.zip");
-  ZipArchiveHandle handle;
-  ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
-  // Need to set up the ziphandle.
-  UpdaterInfo updater_info;
-  updater_info.package_zip = handle;
-
-  // Extract "b/c.txt" and "b/d.txt" with package_extract_dir("b", "<dir>").
-  TemporaryDir td;
-  std::string temp_dir(td.path);
-  std::string script("package_extract_dir(\"b\", \"" + temp_dir + "\")");
-  expect("t", script.c_str(), kNoCause, &updater_info);
-
-  // Verify.
-  std::string data;
-  std::string file_c = temp_dir + "/c.txt";
-  ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
-  ASSERT_EQ(kCTxtContents, data);
-
-  std::string file_d = temp_dir + "/d.txt";
-  ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
-  ASSERT_EQ(kDTxtContents, data);
-
-  // Modify the contents in order to retry. It's expected to be overwritten.
-  ASSERT_TRUE(android::base::WriteStringToFile("random", file_c));
-  ASSERT_TRUE(android::base::WriteStringToFile("random", file_d));
-
-  // Extract again and verify.
-  expect("t", script.c_str(), kNoCause, &updater_info);
-
-  ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
-  ASSERT_EQ(kCTxtContents, data);
-  ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
-  ASSERT_EQ(kDTxtContents, data);
-
-  // Clean up the temp files under td.
-  ASSERT_EQ(0, unlink(file_c.c_str()));
-  ASSERT_EQ(0, unlink(file_d.c_str()));
-
-  // Extracting "b/" (with slash) should give the same result.
-  script = "package_extract_dir(\"b/\", \"" + temp_dir + "\")";
-  expect("t", script.c_str(), kNoCause, &updater_info);
-
-  ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
-  ASSERT_EQ(kCTxtContents, data);
-  ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
-  ASSERT_EQ(kDTxtContents, data);
-
-  ASSERT_EQ(0, unlink(file_c.c_str()));
-  ASSERT_EQ(0, unlink(file_d.c_str()));
-
-  // Extracting "" is allowed. The entries will carry the path name.
-  script = "package_extract_dir(\"\", \"" + temp_dir + "\")";
-  expect("t", script.c_str(), kNoCause, &updater_info);
-
-  std::string file_a = temp_dir + "/a.txt";
-  ASSERT_TRUE(android::base::ReadFileToString(file_a, &data));
-  ASSERT_EQ(kATxtContents, data);
-  std::string file_b = temp_dir + "/b.txt";
-  ASSERT_TRUE(android::base::ReadFileToString(file_b, &data));
-  ASSERT_EQ(kBTxtContents, data);
-  std::string file_b_c = temp_dir + "/b/c.txt";
-  ASSERT_TRUE(android::base::ReadFileToString(file_b_c, &data));
-  ASSERT_EQ(kCTxtContents, data);
-  std::string file_b_d = temp_dir + "/b/d.txt";
-  ASSERT_TRUE(android::base::ReadFileToString(file_b_d, &data));
-  ASSERT_EQ(kDTxtContents, data);
-
-  ASSERT_EQ(0, unlink(file_a.c_str()));
-  ASSERT_EQ(0, unlink(file_b.c_str()));
-  ASSERT_EQ(0, unlink(file_b_c.c_str()));
-  ASSERT_EQ(0, unlink(file_b_d.c_str()));
-  ASSERT_EQ(0, rmdir((temp_dir + "/b").c_str()));
-
-  // Extracting non-existent entry should still give "t".
-  script = "package_extract_dir(\"doesntexist\", \"" + temp_dir + "\")";
-  expect("t", script.c_str(), kNoCause, &updater_info);
-
-  // Only relative zip_path is allowed.
-  script = "package_extract_dir(\"/b\", \"" + temp_dir + "\")";
-  expect("", script.c_str(), kNoCause, &updater_info);
-
-  // Only absolute dest_path is allowed.
-  script = "package_extract_dir(\"b\", \"path\")";
-  expect("", script.c_str(), kNoCause, &updater_info);
-
-  CloseArchive(handle);
-}
-
 // TODO: Test extracting to block device.
 TEST_F(UpdaterTest, package_extract_file) {
   // package_extract_file expects 1 or 2 arguments.
diff --git a/vr_device.cpp b/vr_device.cpp
new file mode 100644
index 0000000..61e15cb
--- /dev/null
+++ b/vr_device.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "device.h"
+#include "vr_ui.h"
+
+Device* make_device() {
+    return new Device(new VrRecoveryUI);
+}
+
diff --git a/vr_ui.cpp b/vr_ui.cpp
new file mode 100644
index 0000000..b2c65e3
--- /dev/null
+++ b/vr_ui.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vr_ui.h"
+
+#include <minui/minui.h>
+
+VrRecoveryUI::VrRecoveryUI() :
+  x_offset(400),
+  y_offset(400),
+  stereo_offset(100) {
+}
+
+bool VrRecoveryUI::InitTextParams() {
+  if (gr_init() < 0) {
+    return false;
+  }
+
+  gr_font_size(gr_sys_font(), &char_width_, &char_height_);
+  int mid_divide = gr_fb_width() / 2;
+  text_rows_ = (gr_fb_height() - 2 * y_offset) / char_height_;
+  text_cols_ = (mid_divide - x_offset - stereo_offset) / char_width_;
+  log_bottom_offset_ = gr_fb_height() - 2 * y_offset;
+  return true;
+}
+
+void VrRecoveryUI::DrawHorizontalRule(int* y) {
+  SetColor(MENU);
+  *y += 4;
+  gr_fill(0, *y + y_offset, gr_fb_width(), *y + y_offset + 2);
+  *y += 4;
+}
+
+void VrRecoveryUI::DrawHighlightBar(int x, int y, int width, int height) const {
+  gr_fill(x, y + y_offset, x + width, y + y_offset + height);
+}
+
+void VrRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) const {
+  int mid_divide = gr_fb_width() / 2;
+  gr_text(gr_sys_font(), x + x_offset + stereo_offset, *y + y_offset, line, bold);
+  gr_text(gr_sys_font(), x + x_offset - stereo_offset + mid_divide, *y + y_offset, line, bold);
+  *y += char_height_ + 4;
+}
diff --git a/vr_ui.h b/vr_ui.h
new file mode 100644
index 0000000..85c5708
--- /dev/null
+++ b/vr_ui.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RECOVERY_VR_UI_H
+#define RECOVERY_VR_UI_H
+
+#include "screen_ui.h"
+
+class VrRecoveryUI : public ScreenRecoveryUI {
+  public:
+    VrRecoveryUI();
+
+  protected:
+    // Pixel offsets to move drawing functions to visible range.
+    // Can vary per device depending on screen size and lens distortion.
+    int x_offset, y_offset, stereo_offset;
+
+    bool InitTextParams() override;
+
+    void DrawHorizontalRule(int* y) override;
+    void DrawHighlightBar(int x, int y, int width, int height) const override;
+    void DrawTextLine(int x, int* y, const char* line, bool bold) const override;
+};
+
+#endif  // RECOVERY_VR_UI_H