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 <pallavi.g@intel.com>
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<HwcLayer *> &source_layers) {
return refresh_;
}
+ uint32_t PowerMode() const override {
+ return power_mode_;
+ }
+
bool GetDisplayAttribute(uint32_t config, HWCDisplayAttribute attribute,
int32_t *value) override;
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<HwcLayer *> &source_layers) override;
float refresh_;
bool is_connected_;
bool is_powered_off_;
+ uint32_t power_mode_;
std::unique_ptr<PageFlipEventHandler> flip_handler_;
std::unique_ptr<DisplayQueue> display_queue_;
};
void DisplayQueue::Exit() {
IHOTPLUGEVENTTRACE("DisplayQueue::Exit recieved.");
- HWCThread::Exit();
+ HandleExit();
}
bool DisplayQueue::GetFence(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;
}
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_)) {
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());
return;
}
+ Flush();
+
bool active = false;
int ret =
drmModeAtomicAddProperty(pset.get(), crtc_id_, active_prop_, active) < 0;
std::queue<DisplayQueueItem>().swap(queue_);
current_sync_.reset(nullptr);
compositor_.Reset();
+ HWCThread::Exit();
}
void DisplayQueue::GetDrmObjectProperty(const char* name,
void Exit();
bool QueueUpdate(std::vector<HwcLayer*>& source_layers);
- bool SetDpmsMode(uint32_t dpms_mode);
+ bool SetPowerMode(uint32_t power_mode);
protected:
void HandleRoutine() override;
std::unique_ptr<NativeSync> 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);
return true;
}
-bool Headless::SetDpmsMode(uint32_t /*dpms_mode*/) {
+bool Headless::SetPowerMode(uint32_t /*power_mode*/) {
return true;
}
return 0;
}
+ uint32_t PowerMode() const override {
+ return 0;
+ }
+
bool GetDisplayAttribute(uint32_t config, HWCDisplayAttribute attribute,
int32_t *value) override;
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<HwcLayer *> &source_layers) override;
HWC2::Error DrmHwcTwo::HwcDisplay::GetDozeSupport(int32_t *support) {
supported(__func__);
- *support = 0;
+ *support = true;
return HWC2::Error::None;
}
uint32_t client_z_order = 0;
*retire_fence = -1;
std::map<uint32_t, DrmHwcTwo::HwcLayer *> 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<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
switch (l.second.validated_type()) {
case HWC2::Composition::Device:
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<HWC2::PowerMode>(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;
}
#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;
}
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_
virtual int32_t GetRefreshRate() const = 0;
+ virtual uint32_t PowerMode() const = 0;
+
virtual bool GetDisplayAttribute(uint32_t config,
HWCDisplayAttribute attribute,
int32_t *value) = 0;
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<HwcLayer *> &source_layers) = 0;