From 4704f1d95f1f777c00ee312e8a1276fcfc23c694 Mon Sep 17 00:00:00 2001 From: Pallavi G Date: Mon, 20 Feb 2017 15:10:18 +0530 Subject: [PATCH] Added the doze power mode support Added the suport for the doze and doze suspend power modes. For more details about doze and doze suspend refer the below link https://developer.android.com/training/monitoring-device-state/doze-standby.html Jira: IAHWC-21 Test: Not able to test the exact doze path device not entering into the idle mode Signed-off-by: Pallavi G --- common/display/display.cpp | 6 ++-- common/display/display.h | 7 ++++- common/display/displayqueue.cpp | 63 ++++++++++++++++++++++++++++------------- common/display/displayqueue.h | 4 ++- common/display/headless.cpp | 2 +- common/display/headless.h | 6 +++- os/android/drmhwctwo.cpp | 31 +++++++++++++++----- public/hwcdefs.h | 9 ++++++ public/nativedisplay.h | 4 ++- 9 files changed, 99 insertions(+), 33 deletions(-) diff --git a/common/display/display.cpp b/common/display/display.cpp index 50cfb9e..14512fb 100644 --- a/common/display/display.cpp +++ b/common/display/display.cpp @@ -184,8 +184,10 @@ bool Display::GetActiveConfig(uint32_t *config) { return true; } -bool Display::SetDpmsMode(uint32_t dpms_mode) { - return display_queue_->SetDpmsMode(dpms_mode); +bool Display::SetPowerMode(uint32_t power_mode) { + uint32_t power_mode_ = power_mode; + + return display_queue_->SetPowerMode(power_mode); } bool Display::Present(std::vector &source_layers) { diff --git a/common/display/display.h b/common/display/display.h index 32e75a1..a356642 100644 --- a/common/display/display.h +++ b/common/display/display.h @@ -67,6 +67,10 @@ class Display : public NativeDisplay { return refresh_; } + uint32_t PowerMode() const override { + return power_mode_; + } + bool GetDisplayAttribute(uint32_t config, HWCDisplayAttribute attribute, int32_t *value) override; @@ -75,7 +79,7 @@ class Display : public NativeDisplay { bool SetActiveConfig(uint32_t config) override; bool GetActiveConfig(uint32_t *config) override; - bool SetDpmsMode(uint32_t dpms_mode) override; + bool SetPowerMode(uint32_t power_mode) override; bool Present(std::vector &source_layers) override; @@ -117,6 +121,7 @@ class Display : public NativeDisplay { float refresh_; bool is_connected_; bool is_powered_off_; + uint32_t power_mode_; std::unique_ptr flip_handler_; std::unique_ptr display_queue_; }; diff --git a/common/display/displayqueue.cpp b/common/display/displayqueue.cpp index ab425dc..d51b1d4 100644 --- a/common/display/displayqueue.cpp +++ b/common/display/displayqueue.cpp @@ -106,7 +106,7 @@ bool DisplayQueue::Initialize(uint32_t width, uint32_t height, uint32_t pipe, void DisplayQueue::Exit() { IHOTPLUGEVENTTRACE("DisplayQueue::Exit recieved."); - HWCThread::Exit(); + HandleExit(); } bool DisplayQueue::GetFence(drmModeAtomicReqPtr property_set, @@ -159,27 +159,29 @@ bool DisplayQueue::ApplyPendingModeset(drmModeAtomicReqPtr property_set) { return true; } -bool DisplayQueue::SetDpmsMode(uint32_t dpms_mode) { +bool DisplayQueue::SetPowerMode(uint32_t power_mode) { ScopedSpinLock lock(spin_lock_); - if (dpms_mode_ == dpms_mode) + + if ((power_mode == kOff) || (power_mode == kDoze)) { + dpms_mode_ = DRM_MODE_DPMS_OFF; + Flush(); + HWCThread::ConditionalSuspend(); + drmModeConnectorSetProperty(gpu_fd_, connector_, dpms_prop_, dpms_mode_); return true; + } - dpms_mode_ = dpms_mode; - if (dpms_mode_ == DRM_MODE_DPMS_OFF) { - Exit(); + if (power_mode == kDozeSuspend) { + Flush(); + HWCThread::ConditionalSuspend(); return true; } - if (dpms_mode_ == DRM_MODE_DPMS_ON) { + if (power_mode == kOn) { + dpms_mode_ = DRM_MODE_DPMS_ON; needs_modeset_ = true; - if (!InitWorker()) { - ETRACE("Failed to initalize thread for DisplayQueue. %s", PRINTERROR()); - return false; - } + drmModeConnectorSetProperty(gpu_fd_, connector_, dpms_prop_, dpms_mode_); } - drmModeConnectorSetProperty(gpu_fd_, connector_, dpms_prop_, dpms_mode); - return true; } @@ -225,8 +227,19 @@ bool DisplayQueue::QueueUpdate(std::vector& source_layers) { return true; } +void DisplayQueue::GetNextQueueItem(DisplayQueueItem& item) { + display_queue_.lock(); + DisplayQueueItem& queue_item = queue_.front(); + item.layers_.swap(queue_item.layers_); + item.layers_rects_.swap(queue_item.layers_rects_); + item.sync_object_.reset(queue_item.sync_object_.release()); + queue_.pop(); + display_queue_.unlock(); +} + void DisplayQueue::HandleUpdateRequest(DisplayQueueItem& queue_item) { CTRACE(); + ScopedSpinLock lock(spin_lock_); // Reset any DisplayQueue Manager and Compositor state. if (!display_plane_manager_->BeginFrameUpdate(&queue_item.layers_)) { @@ -324,18 +337,27 @@ void DisplayQueue::HandleRoutine() { ConditionalSuspend(); return; } + display_queue_.unlock(); - DisplayQueueItem& queue_item = queue_.front(); DisplayQueueItem item; - item.layers_.swap(queue_item.layers_); - item.layers_rects_.swap(queue_item.layers_rects_); - item.sync_object_.reset(queue_item.sync_object_.release()); - queue_.pop(); - display_queue_.unlock(); + GetNextQueueItem(item); HandleUpdateRequest(item); } +void DisplayQueue::Flush() { + display_queue_.lock(); + + while (queue_.size()) { + DisplayQueueItem item; + + GetNextQueueItem(item); + HandleUpdateRequest(item); + } + + display_queue_.unlock(); +} + void DisplayQueue::HandleExit() { ScopedSpinLocks lock(spin_lock_, display_queue_); ScopedDrmAtomicReqPtr pset(drmModeAtomicAlloc()); @@ -344,6 +366,8 @@ void DisplayQueue::HandleExit() { return; } + Flush(); + bool active = false; int ret = drmModeAtomicAddProperty(pset.get(), crtc_id_, active_prop_, active) < 0; @@ -361,6 +385,7 @@ void DisplayQueue::HandleExit() { std::queue().swap(queue_); current_sync_.reset(nullptr); compositor_.Reset(); + HWCThread::Exit(); } void DisplayQueue::GetDrmObjectProperty(const char* name, diff --git a/common/display/displayqueue.h b/common/display/displayqueue.h index 5c42641..fa06160 100644 --- a/common/display/displayqueue.h +++ b/common/display/displayqueue.h @@ -52,7 +52,7 @@ class DisplayQueue : public HWCThread { void Exit(); bool QueueUpdate(std::vector& source_layers); - bool SetDpmsMode(uint32_t dpms_mode); + bool SetPowerMode(uint32_t power_mode); protected: void HandleRoutine() override; @@ -65,6 +65,8 @@ class DisplayQueue : public HWCThread { std::unique_ptr sync_object_; }; + void GetNextQueueItem(DisplayQueueItem& item); + void Flush(); void HandleUpdateRequest(DisplayQueueItem& queue_item); bool ApplyPendingModeset(drmModeAtomicReqPtr property_set); bool GetFence(drmModeAtomicReqPtr property_set, uint64_t* out_fence); diff --git a/common/display/headless.cpp b/common/display/headless.cpp index 28aabcc..4fca20d 100644 --- a/common/display/headless.cpp +++ b/common/display/headless.cpp @@ -113,7 +113,7 @@ bool Headless::GetActiveConfig(uint32_t *config) { return true; } -bool Headless::SetDpmsMode(uint32_t /*dpms_mode*/) { +bool Headless::SetPowerMode(uint32_t /*power_mode*/) { return true; } diff --git a/common/display/headless.h b/common/display/headless.h index f1489f9..3d8e223 100644 --- a/common/display/headless.h +++ b/common/display/headless.h @@ -53,6 +53,10 @@ class Headless : public NativeDisplay { return 0; } + uint32_t PowerMode() const override { + return 0; + } + bool GetDisplayAttribute(uint32_t config, HWCDisplayAttribute attribute, int32_t *value) override; @@ -61,7 +65,7 @@ class Headless : public NativeDisplay { bool SetActiveConfig(uint32_t config) override; bool GetActiveConfig(uint32_t *config) override; - bool SetDpmsMode(uint32_t dpms_mode) override; + bool SetPowerMode(uint32_t power_mode) override; bool Present(std::vector &source_layers) override; diff --git a/os/android/drmhwctwo.cpp b/os/android/drmhwctwo.cpp index bc1a19d..fd2b180 100644 --- a/os/android/drmhwctwo.cpp +++ b/os/android/drmhwctwo.cpp @@ -355,7 +355,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayType(int32_t *type) { HWC2::Error DrmHwcTwo::HwcDisplay::GetDozeSupport(int32_t *support) { supported(__func__); - *support = 0; + *support = true; return HWC2::Error::None; } @@ -396,6 +396,14 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *retire_fence) { uint32_t client_z_order = 0; *retire_fence = -1; std::map z_map; + + // if the power mode is doze suspend then its the hint that the drawing + // into the display has suspended and remain in the low power state and + // continue displaying the current state and stop applying display + // update from the client + if (display_->PowerMode() == HWC2_POWER_MODE_DOZE_SUSPEND) + return HWC2::Error::None; + for (std::pair &l : layers_) { switch (l.second.validated_type()) { case HWC2::Composition::Device: @@ -495,21 +503,27 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetOutputBuffer(buffer_handle_t buffer, HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) { supported(__func__); - uint64_t dpms_value = 0; + uint32_t power_mode = 0; auto mode = static_cast(mode_in); switch (mode) { case HWC2::PowerMode::Off: - dpms_value = DRM_MODE_DPMS_OFF; + power_mode = HWC2_POWER_MODE_OFF; + break; + case HWC2::PowerMode::Doze: + power_mode = HWC2_POWER_MODE_DOZE; + break; + case HWC2::PowerMode::DozeSuspend: + power_mode = HWC2_POWER_MODE_DOZE_SUSPEND; break; case HWC2::PowerMode::On: - dpms_value = DRM_MODE_DPMS_ON; + power_mode = HWC2_POWER_MODE_ON; break; default: ALOGI("Power mode %d is unsupported\n", mode); - return HWC2::Error::Unsupported; + return HWC2::Error::BadParameter; }; - display_->SetDpmsMode(dpms_value); + display_->SetPowerMode(power_mode); return HWC2::Error::None; } @@ -544,7 +558,10 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types, #ifdef DISABLE_OVERLAY_USAGE layer.set_validated_type(HWC2::Composition::Client); #else - layer.set_validated_type(layer.sf_type()); + if (display_->PowerMode() == HWC2_POWER_MODE_DOZE_SUSPEND) + layer.set_validated_type(HWC2::Composition::Client); + else + layer.set_validated_type(layer.sf_type()); #endif break; } diff --git a/public/hwcdefs.h b/public/hwcdefs.h index e499b19..fd584a5 100644 --- a/public/hwcdefs.h +++ b/public/hwcdefs.h @@ -63,5 +63,14 @@ enum class DisplayType : int32_t { kHeadless = 3 }; +enum DisplayPowerMode { + kOff = 0, // Display is off + kDoze = 1, // Display is off and used by the app during any inactivity + // when the device is on battery + kOn = 2, // Display is on + kDozeSuspend = 3 // Dispaly in low power mode and stop applying + // updates from the client +}; + } // namespace hwcomposer #endif // PUBLIC_HWCDEFS_H_ diff --git a/public/nativedisplay.h b/public/nativedisplay.h index e7c08ba..4944763 100644 --- a/public/nativedisplay.h +++ b/public/nativedisplay.h @@ -57,6 +57,8 @@ class NativeDisplay { virtual int32_t GetRefreshRate() const = 0; + virtual uint32_t PowerMode() const = 0; + virtual bool GetDisplayAttribute(uint32_t config, HWCDisplayAttribute attribute, int32_t *value) = 0; @@ -66,7 +68,7 @@ class NativeDisplay { virtual bool SetActiveConfig(uint32_t config) = 0; virtual bool GetActiveConfig(uint32_t *config) = 0; - virtual bool SetDpmsMode(uint32_t dpms_mode) = 0; + virtual bool SetPowerMode(uint32_t power_mode) = 0; virtual bool Present(std::vector &source_layers) = 0; -- 2.11.0