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()) {