Merge "Ensure deviceTimestamp is cleared"
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index ee3e1dc..7a95c78 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -66,6 +66,7 @@
 static constexpr const char* kMinidebugInfoSystemProperty = "dalvik.vm.dex2oat-minidebuginfo";
 static constexpr bool kMinidebugInfoSystemPropertyDefault = false;
 static constexpr const char* kMinidebugDex2oatFlag = "--generate-mini-debug-info";
+static constexpr const char* kDisableCompactDexFlag = "--compact-dex-level=none";
 
 // Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
 struct FreeDelete {
@@ -414,6 +415,10 @@
 
     ALOGV("Running %s in=%s out=%s\n", dex2oat_bin, relative_input_file_name, output_file_name);
 
+    // Disable cdex if update input vdex is true since this combination of options is not
+    // supported.
+    const bool disable_cdex = input_vdex_fd == output_vdex_fd;
+
     const char* argv[9  // program name, mandatory arguments and the final NULL
                      + (have_dex2oat_isa_variant ? 1 : 0)
                      + (have_dex2oat_isa_features ? 1 : 0)
@@ -432,6 +437,7 @@
                      + (class_loader_context != nullptr ? 1 : 0)
                      + (has_base_dir ? 1 : 0)
                      + (have_dex2oat_large_app_threshold ? 1 : 0)
+                     + (disable_cdex ? 1 : 0)
                      + (generate_minidebug_info ? 1 : 0)];
     int i = 0;
     argv[i++] = dex2oat_bin;
@@ -499,6 +505,9 @@
     if (generate_minidebug_info) {
         argv[i++] = kMinidebugDex2oatFlag;
     }
+    if (disable_cdex) {
+        argv[i++] = kDisableCompactDexFlag;
+    }
 
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index 622f866..f371320 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -18,6 +18,8 @@
 
 #include "Lshal.h"
 
+#include <hidl-util/FQName.h>
+
 namespace android {
 namespace lshal {
 
@@ -46,7 +48,15 @@
     if (status != OK) {
         return status;
     }
+
     auto pair = splitFirst(mInterfaceName, '/');
+
+    FQName fqName(pair.first);
+    if (!fqName.isValid() || fqName.isIdentifier() || !fqName.isFullyQualified()) {
+        mLshal.err() << "Invalid fully-qualified name '" << pair.first << "'\n\n";
+        return USAGE;
+    }
+
     return mLshal.emitDebugInfo(
             pair.first, pair.second.empty() ? "default" : pair.second, mOptions,
             mLshal.out().buf(),
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index a3ee7bb..316f15a 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -71,6 +71,7 @@
 
   void GrantDisplayOwnership() { hardware_composer_.Enable(); }
   void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
+  void OnBootFinished() { hardware_composer_.OnBootFinished(); }
 
  private:
   friend BASE;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index be17ecf..5d796dc 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -53,6 +53,9 @@
 
 const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
 
+// How long to wait after boot finishes before we turn the display off.
+constexpr int kBootFinishedDisplayOffTimeoutSec = 10;
+
 // Get time offset from a vsync to when the pose for that vsync should be
 // predicted out to. For example, if scanout gets halfway through the frame
 // at the halfway point between vsyncs, then this could be half the period.
@@ -190,6 +193,16 @@
   UpdatePostThreadState(PostThreadState::Suspended, true);
 }
 
+void HardwareComposer::OnBootFinished() {
+  std::lock_guard<std::mutex> lock(post_thread_mutex_);
+  if (boot_finished_)
+    return;
+  boot_finished_ = true;
+  post_thread_wait_.notify_one();
+  if (is_standalone_device_)
+    request_display_callback_(true);
+}
+
 // Update the post thread quiescent state based on idle and suspended inputs.
 void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
                                              bool suspend) {
@@ -276,6 +289,25 @@
   property_set(kDvrPerformanceProperty, "idle");
 }
 
+bool HardwareComposer::PostThreadCondWait(std::unique_lock<std::mutex>& lock,
+                                          int timeout_sec,
+                                          const std::function<bool()>& pred) {
+  auto pred_with_quit = [&] {
+    return pred() || (post_thread_state_ & PostThreadState::Quit);
+  };
+  if (timeout_sec >= 0) {
+    post_thread_wait_.wait_for(lock, std::chrono::seconds(timeout_sec),
+                               pred_with_quit);
+  } else {
+    post_thread_wait_.wait(lock, pred_with_quit);
+  }
+  if (post_thread_state_ & PostThreadState::Quit) {
+    ALOGI("HardwareComposer::PostThread: Quitting.");
+    return true;
+  }
+  return false;
+}
+
 HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
   uint32_t num_types;
   uint32_t num_requests;
@@ -508,7 +540,7 @@
     pending_surfaces_ = std::move(surfaces);
   }
 
-  if (request_display_callback_ && (!is_standalone_device_ || !composer_))
+  if (request_display_callback_ && !is_standalone_device_)
     request_display_callback_(!display_idle);
 
   // Set idle state based on whether there are any surfaces to handle.
@@ -697,6 +729,28 @@
 
   bool was_running = false;
 
+  if (is_standalone_device_) {
+    // First, wait until boot finishes.
+    std::unique_lock<std::mutex> lock(post_thread_mutex_);
+    if (PostThreadCondWait(lock, -1, [this] { return boot_finished_; })) {
+      return;
+    }
+
+    // Then, wait until we're either leaving the quiescent state, or the boot
+    // finished display off timeout expires.
+    if (PostThreadCondWait(lock, kBootFinishedDisplayOffTimeoutSec,
+                           [this] { return !post_thread_quiescent_; })) {
+      return;
+    }
+
+    LOG_ALWAYS_FATAL_IF(post_thread_state_ & PostThreadState::Suspended,
+                        "Vr flinger should own the display by now.");
+    post_thread_resumed_ = true;
+    post_thread_ready_.notify_all();
+    OnPostThreadResumed();
+    was_running = true;
+  }
+
   while (1) {
     ATRACE_NAME("HardwareComposer::PostThread");
 
@@ -715,13 +769,12 @@
       post_thread_resumed_ = false;
       post_thread_ready_.notify_all();
 
-      if (post_thread_state_ & PostThreadState::Quit) {
-        ALOGI("HardwareComposer::PostThread: Quitting.");
+      if (PostThreadCondWait(lock, -1,
+                             [this] { return !post_thread_quiescent_; })) {
+        // A true return value means we've been asked to quit.
         return;
       }
 
-      post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
-
       post_thread_resumed_ = true;
       post_thread_ready_.notify_all();
 
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 9ed4b22..1d0c7ef 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -327,6 +327,9 @@
   // it's paused. This should only be called from surface flinger's main thread.
   void Disable();
 
+  // Called on a binder thread.
+  void OnBootFinished();
+
   // Get the HMD display metrics for the current display.
   display::Metrics GetHmdDisplayMetrics() const;
 
@@ -434,6 +437,16 @@
   // Called on the post thread when the post thread is paused or quits.
   void OnPostThreadPaused();
 
+  // Use post_thread_wait_ to wait for a specific condition, specified by pred.
+  // timeout_sec < 0 means wait indefinitely, otherwise it specifies the timeout
+  // in seconds.
+  // The lock must be held when this function is called.
+  // Returns true if the wait was interrupted because the post thread was asked
+  // to quit.
+  bool PostThreadCondWait(std::unique_lock<std::mutex>& lock,
+                          int timeout_sec,
+                          const std::function<bool()>& pred);
+
   // Map the given shared memory buffer to our broadcast ring to track updates
   // to the config parameters.
   int MapConfigBuffer(IonBuffer& ion_buffer);
@@ -482,6 +495,10 @@
   std::condition_variable post_thread_wait_;
   std::condition_variable post_thread_ready_;
 
+  // When boot is finished this will be set to true and the post thread will be
+  // notified via post_thread_wait_.
+  bool boot_finished_ = false;
+
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
 
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 5e7abd7..26aed4f 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -115,6 +115,7 @@
 }
 
 void VrFlinger::OnBootFinished() {
+  display_service_->OnBootFinished();
   sp<IVrManager> vr_manager = interface_cast<IVrManager>(
       defaultServiceManager()->checkService(String16("vrmanager")));
   if (vr_manager.get()) {