1 /*
2 * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above
10 *       copyright notice, this list of conditions and the following
11 *       disclaimer in the documentation and/or other materials provided
12 *       with the distribution.
13 *     * Neither the name of The Linux Foundation nor the names of its
14 *       contributors may be used to endorse or promote products derived
15 *       from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <android-base/file.h>
31 #include <cutils/properties.h>
32 #include <cutils/sockets.h>
33 #include <utils/constants.h>
34 #include <utils/debug.h>
35 #include <utils/utils.h>
36 #include <stdarg.h>
37 #include <sync/sync.h>
38 #include <sys/mman.h>
39 
40 #include <map>
41 #include <iostream>
42 #include <string>
43 #include <vector>
44 
45 #include "hwc_display_builtin.h"
46 #include "hwc_debugger.h"
47 #include "hwc_session.h"
48 
49 #define __CLASS__ "HWCDisplayBuiltIn"
50 
51 namespace sdm {
52 
SetRect(LayerRect & src_rect,GLRect * target)53 static void SetRect(LayerRect &src_rect, GLRect *target) {
54   target->left = src_rect.left;
55   target->top = src_rect.top;
56   target->right = src_rect.right;
57   target->bottom = src_rect.bottom;
58 }
59 
LoadPanelGammaCalibration()60 static std::string LoadPanelGammaCalibration() {
61   constexpr char file[] = "/mnt/vendor/persist/display/gamma_calib_data.cal";
62   std::ifstream ifs(file);
63 
64   if (!ifs.is_open()) {
65     DLOGW("Unable to open gamma calibration '%s', error = %s", file, strerror(errno));
66     return {};
67   }
68 
69   std::string raw_data, gamma;
70   while (std::getline(ifs, raw_data, '\r')) {
71     gamma.append(raw_data.c_str());
72     gamma.append(" ");
73     std::getline(ifs, raw_data);
74   }
75   ifs.close();
76 
77   /* eliminate space character in the last byte */
78   if (!gamma.empty()) {
79     gamma.pop_back();
80   }
81 
82   return gamma;
83 }
84 
WritePanelGammaTableToDriver(const std::string & gamma_data)85 static DisplayError WritePanelGammaTableToDriver(const std::string &gamma_data) {
86   constexpr char gamma_path[] = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/gamma";
87   int fd = open(gamma_path, O_WRONLY);
88   if (fd < 0) {
89     DLOGW("Unable to open gamma node '%s', error = %s", gamma_path, strerror(errno));
90     return kErrorFileDescriptor;
91   }
92 
93   constexpr int max_retries = 5;
94   ssize_t len;
95   int retry_count = 0;
96   DisplayError error = kErrorNone;
97   while ((len = pwrite(fd, gamma_data.c_str(), gamma_data.size(), 0)) != gamma_data.size()) {
98     if ((len == -1 && errno != EINTR && errno != EAGAIN) || (++retry_count > max_retries)) {
99       DLOGE("Failed to write gamma calibration(retry %d), error = %s", retry_count,
100             strerror(errno));
101       break;
102     }
103   }
104   close(fd);
105 
106   if (len != gamma_data.size()) {
107     error = kErrorResources;
108   }
109 
110   return error;
111 }
112 
UpdatePanelGammaTable(enum HWCDisplay::PanelGammaSource source)113 static DisplayError UpdatePanelGammaTable(enum HWCDisplay::PanelGammaSource source) {
114   std::string gamma_data = {};
115   DisplayError error;
116   if (source == HWCDisplay::kGammaDefault) {
117     gamma_data = "default";
118   } else if (source == HWCDisplay::kGammaCalibration) {
119     gamma_data = LoadPanelGammaCalibration();
120   }
121 
122   if (!gamma_data.empty()) {
123     error = WritePanelGammaTableToDriver(gamma_data);
124   } else {
125     error = kErrorParameters;
126   }
127 
128   return error;
129 }
130 
Create(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,HWCDisplayEventHandler * event_handler,qService::QService * qservice,hwc2_display_t id,int32_t sdm_id,HWCDisplay ** hwc_display)131 int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
132                               HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
133                               qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
134                               HWCDisplay **hwc_display) {
135   int status = 0;
136   uint32_t builtin_width = 0;
137   uint32_t builtin_height = 0;
138 
139   HWCDisplay *hwc_display_builtin =
140       new HWCDisplayBuiltIn(core_intf, buffer_allocator, callbacks, event_handler, qservice, id,
141                             sdm_id);
142   status = hwc_display_builtin->Init();
143   if (status) {
144     delete hwc_display_builtin;
145     return status;
146   }
147 
148   hwc_display_builtin->GetMixerResolution(&builtin_width, &builtin_height);
149   int width = 0, height = 0;
150   HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
151   HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
152   if (width > 0 && height > 0) {
153     builtin_width = UINT32(width);
154     builtin_height = UINT32(height);
155   }
156 
157   status = hwc_display_builtin->SetFrameBufferResolution(builtin_width, builtin_height);
158   if (status) {
159     Destroy(hwc_display_builtin);
160     return status;
161   }
162 
163   *hwc_display = hwc_display_builtin;
164 
165   return status;
166 }
167 
Destroy(HWCDisplay * hwc_display)168 void HWCDisplayBuiltIn::Destroy(HWCDisplay *hwc_display) {
169   hwc_display->Deinit();
170   delete hwc_display;
171 }
172 
HWCDisplayBuiltIn(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,HWCDisplayEventHandler * event_handler,qService::QService * qservice,hwc2_display_t id,int32_t sdm_id)173 HWCDisplayBuiltIn::HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
174                                      HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
175                                      qService::QService *qservice, hwc2_display_t id,
176                                      int32_t sdm_id)
177     : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
178                  sdm_id, DISPLAY_CLASS_BUILTIN),
179       buffer_allocator_(buffer_allocator),
180       cpu_hint_(NULL), layer_stitch_task_(*this) {
181 }
182 
Init()183 int HWCDisplayBuiltIn::Init() {
184   cpu_hint_ = new CPUHint();
185   if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
186     delete cpu_hint_;
187     cpu_hint_ = NULL;
188   }
189 
190   use_metadata_refresh_rate_ = true;
191   int disable_metadata_dynfps = 0;
192   HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
193   if (disable_metadata_dynfps) {
194     use_metadata_refresh_rate_ = false;
195   }
196 
197   int status = HWCDisplay::Init();
198   if (status) {
199     return status;
200   }
201   color_mode_ = new HWCColorMode(display_intf_);
202   color_mode_->Init();
203 
204   int value = 0;
205   HWCDebugHandler::Get()->GetProperty(ENABLE_OPTIMIZE_REFRESH, &value);
206   enable_optimize_refresh_ = (value == 1);
207   if (enable_optimize_refresh_) {
208     DLOGI("Drop redundant drawcycles %" PRIu64 , id_);
209   }
210 
211   int vsyncs = 0;
212   HWCDebugHandler::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &vsyncs);
213   if (vsyncs > 0) {
214     SetVsyncsApplyRateChange(UINT32(vsyncs));
215   }
216 
217   is_primary_ = display_intf_->IsPrimaryDisplay();
218 
219   if (is_primary_) {
220     int enable_bw_limits = 0;
221     HWCDebugHandler::Get()->GetProperty(ENABLE_BW_LIMITS, &enable_bw_limits);
222     enable_bw_limits_ = (enable_bw_limits == 1);
223     if (enable_bw_limits_) {
224       DLOGI("Enable BW Limits %" PRIu64, id_);
225     }
226     windowed_display_ = Debug::GetWindowRect(&window_rect_.left, &window_rect_.top,
227                       &window_rect_.right, &window_rect_.bottom) != kErrorUndefined;
228     DLOGI("Window rect : [%f %f %f %f]", window_rect_.left, window_rect_.top,
229           window_rect_.right, window_rect_.bottom);
230 
231     value = 0;
232     HWCDebugHandler::Get()->GetProperty(ENABLE_POMS_DURING_DOZE, &value);
233     enable_poms_during_doze_ = (value == 1);
234     if (enable_poms_during_doze_) {
235       DLOGI("Enable POMS during Doze mode %" PRIu64 , id_);
236     }
237   }
238 
239   value = 0;
240   DebugHandler::Get()->GetProperty(DISABLE_DYNAMIC_FPS, &value);
241   disable_dyn_fps_ = (value == 1);
242   DLOGI("disable_dyn_fps_: %d", disable_dyn_fps_);
243 
244   uint32_t config_index = 0;
245   GetActiveDisplayConfig(&config_index);
246   DisplayConfigVariableInfo attr = {};
247   GetDisplayAttributesForConfig(INT(config_index), &attr);
248   active_refresh_rate_ = attr.fps;
249 
250   DLOGI("active_refresh_rate: %d", active_refresh_rate_);
251 
252   value = 0;
253   HWCDebugHandler::Get()->GetProperty(ENHANCE_IDLE_TIME, &value);
254   enhance_idle_time_ = (value == 1);
255   DLOGI("enhance_idle_time: %d", enhance_idle_time_);
256 
257   HWCDebugHandler::Get()->GetProperty(PERF_HINT_WINDOW_PROP, &perf_hint_window_);
258   HWCDebugHandler::Get()->GetProperty(ENABLE_PERF_HINT_LARGE_COMP_CYCLE,
259                                       &perf_hint_large_comp_cycle_);
260 
261   return status;
262 }
263 
Dump(std::ostringstream * os)264 void HWCDisplayBuiltIn::Dump(std::ostringstream *os) {
265   HWCDisplay::Dump(os);
266   *os << histogram.Dump();
267 }
268 
ValidateUiScaling()269 void HWCDisplayBuiltIn::ValidateUiScaling() {
270   if (is_primary_ || !is_cmd_mode_) {
271     force_reset_validate_ = false;
272     return;
273   }
274 
275   for (auto &hwc_layer : layer_set_) {
276     Layer *layer = hwc_layer->GetSDMLayer();
277     if (hwc_layer->IsScalingPresent() && !layer->input_buffer.flags.video) {
278       force_reset_validate_ = true;
279       return;
280     }
281   }
282   force_reset_validate_ = false;
283 }
284 
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)285 HWC2::Error HWCDisplayBuiltIn::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
286   auto status = HWC2::Error::None;
287   DisplayError error = kErrorNone;
288 
289   DTRACE_SCOPED();
290 
291   if (display_paused_) {
292     MarkLayersForGPUBypass();
293     return status;
294   }
295 
296   if (color_tranform_failed_) {
297     // Must fall back to client composition
298     MarkLayersForClientComposition();
299   }
300 
301   // Fill in the remaining blanks in the layers and add them to the SDM layerstack
302   BuildLayerStack();
303 
304   // Check for scaling layers during Doze mode
305   ValidateUiScaling();
306 
307   // Add stitch layer to layer stack.
308   AppendStitchLayer();
309 
310   // Checks and replaces layer stack for solid fill
311   SolidFillPrepare();
312 
313   // Apply current Color Mode and Render Intent.
314   if (color_mode_->ApplyCurrentColorModeWithRenderIntent(
315       static_cast<bool>(layer_stack_.flags.hdr_present)) != HWC2::Error::None) {
316     // Fallback to GPU Composition, if Color Mode can't be applied.
317     MarkLayersForClientComposition();
318   }
319 
320   bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
321 
322   if (readback_buffer_queued_ || pending_output_dump) {
323     // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
324     // here in a subsequent draw round. Readback is not allowed for any secure use case.
325     readback_configured_ = !layer_stack_.flags.secure_present;
326     if (readback_configured_) {
327       DisablePartialUpdateOneFrame();
328       layer_stack_.output_buffer = &output_buffer_;
329       layer_stack_.flags.post_processed_output = post_processed_output_;
330     }
331   }
332 
333   uint32_t num_updating_layers = GetUpdatingLayersCount();
334   bool one_updating_layer = (num_updating_layers == 1);
335   if (num_updating_layers != 0) {
336     ToggleCPUHint(one_updating_layer);
337   }
338 
339   uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
340   bool idle_screen = GetUpdatingAppLayersCount() == 0;
341   error = display_intf_->SetRefreshRate(refresh_rate, force_refresh_rate_, idle_screen);
342 
343   // Get the refresh rate set.
344   display_intf_->GetRefreshRate(&refresh_rate);
345   bool vsync_source = (callbacks_->GetVsyncSource() == id_);
346 
347   if (error == kErrorNone) {
348     if (vsync_source && ((current_refresh_rate_ < refresh_rate) ||
349                          (enhance_idle_time_ && (current_refresh_rate_ != refresh_rate)))) {
350       DTRACE_BEGIN("HWC2::Vsync::Enable");
351       // Display is ramping up from idle.
352       // Client realizes need for resync upon change in config.
353       // Since we know config has changed, triggering vsync proactively
354       // can help in reducing pipeline delays to enable events.
355       SetVsyncEnabled(HWC2::Vsync::Enable);
356       DTRACE_END();
357     }
358     // On success, set current refresh rate to new refresh rate.
359     current_refresh_rate_ = refresh_rate;
360   }
361 
362   if (layer_set_.empty()) {
363     // Avoid flush for Command mode panel.
364     flush_ = !client_connected_;
365     validated_ = true;
366     return status;
367   }
368 
369   status = PrepareLayerStack(out_num_types, out_num_requests);
370   SetCpuPerfHintLargeCompCycle();
371   pending_commit_ = true;
372   return status;
373 }
374 
CommitLayerStack()375 HWC2::Error HWCDisplayBuiltIn::CommitLayerStack() {
376   skip_commit_ = CanSkipCommit();
377   return HWCDisplay::CommitLayerStack();
378 }
379 
CanSkipCommit()380 bool HWCDisplayBuiltIn::CanSkipCommit() {
381   if (layer_stack_invalid_) {
382     return false;
383   }
384 
385   // Reject repeated drawcycle requests if it satisfies all conditions.
386   // 1. None of the layerstack attributes changed.
387   // 2. No new buffer latched.
388   // 3. No refresh request triggered by HWC.
389   // 4. This display is not source of vsync.
390   bool buffers_latched = false;
391   for (auto &hwc_layer : layer_set_) {
392     buffers_latched |= hwc_layer->BufferLatched();
393     hwc_layer->ResetBufferFlip();
394   }
395 
396   bool vsync_source = (callbacks_->GetVsyncSource() == id_);
397   bool skip_commit = enable_optimize_refresh_ && !pending_commit_ && !buffers_latched &&
398                      !pending_refresh_ && !vsync_source;
399   pending_refresh_ = false;
400 
401   return skip_commit;
402 }
403 
CommitStitchLayers()404 HWC2::Error HWCDisplayBuiltIn::CommitStitchLayers() {
405   if (disable_layer_stitch_) {
406     return HWC2::Error::None;
407   }
408 
409   if (!validated_ || skip_commit_) {
410     return HWC2::Error::None;
411   }
412 
413   LayerStitchContext ctx = {};
414   Layer *stitch_layer = stitch_target_->GetSDMLayer();
415   LayerBuffer &output_buffer = stitch_layer->input_buffer;
416   for (auto &layer : layer_stack_.layers) {
417     LayerComposition &composition = layer->composition;
418     if (composition != kCompositionStitch) {
419       continue;
420     }
421 
422     StitchParams params = {};
423     // Stitch target doesn't have an input fence.
424     // Render all layers at specified destination.
425     LayerBuffer &input_buffer = layer->input_buffer;
426     params.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
427     params.dst_hnd = reinterpret_cast<const private_handle_t *>(output_buffer.buffer_id);
428     SetRect(layer->stitch_info.dst_rect, &params.dst_rect);
429     SetRect(layer->stitch_info.slice_rect, &params.scissor_rect);
430     params.src_acquire_fence = input_buffer.acquire_fence;
431 
432     ctx.stitch_params.push_back(params);
433   }
434 
435   if (!ctx.stitch_params.size()) {
436     // No layers marked for stitch.
437     return HWC2::Error::None;
438   }
439 
440   layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeStitch, &ctx);
441   // Set release fence.
442   output_buffer.acquire_fence = ctx.release_fence;
443 
444   return HWC2::Error::None;
445 }
446 
CacheAvrStatus()447 void HWCDisplayBuiltIn::CacheAvrStatus() {
448   QSyncMode qsync_mode = kQSyncModeNone;
449 
450   DisplayError error = display_intf_->GetQSyncMode(&qsync_mode);
451   if (error != kErrorNone) {
452     return;
453   }
454 
455   bool qsync_enabled = (qsync_mode != kQSyncModeNone);
456   if (qsync_enabled_ != qsync_enabled) {
457     qsync_reconfigured_ = true;
458     qsync_enabled_ = qsync_enabled;
459   } else {
460     qsync_reconfigured_ = false;
461   }
462 }
463 
IsQsyncCallbackNeeded(bool * qsync_enabled,int32_t * refresh_rate,int32_t * qsync_refresh_rate)464 bool HWCDisplayBuiltIn::IsQsyncCallbackNeeded(bool *qsync_enabled, int32_t *refresh_rate,
465                            int32_t *qsync_refresh_rate) {
466   if (!qsync_reconfigured_) {
467     return false;
468   }
469 
470   bool vsync_source = (callbacks_->GetVsyncSource() == id_);
471   // Qsync callback not needed if this display is not the source of vsync
472   if (!vsync_source) {
473     return false;
474   }
475 
476   *qsync_enabled = qsync_enabled_;
477   uint32_t current_rate = 0;
478   display_intf_->GetRefreshRate(&current_rate);
479   *refresh_rate = INT32(current_rate);
480   *qsync_refresh_rate = min_refresh_rate_;
481 
482   return true;
483 }
484 
GetBwCode(const DisplayConfigVariableInfo & attr)485 int HWCDisplayBuiltIn::GetBwCode(const DisplayConfigVariableInfo &attr) {
486   uint32_t min_refresh_rate = 0, max_refresh_rate = 0;
487   display_intf_->GetRefreshRateRange(&min_refresh_rate, &max_refresh_rate);
488   uint32_t fps = attr.smart_panel ? attr.fps : max_refresh_rate;
489 
490   if (fps <= 60) {
491     return kBwLow;
492   } else if (fps <= 90) {
493     return kBwMedium;
494   } else {
495     return kBwHigh;
496   }
497 }
498 
SetBwLimitHint(bool enable)499 void HWCDisplayBuiltIn::SetBwLimitHint(bool enable) {
500   if (!enable_bw_limits_) {
501     return;
502   }
503 
504   if (!enable) {
505     thermal_bandwidth_client_cancel_request(const_cast<char*>(kDisplayBwName));
506     curr_refresh_rate_ = 0;
507     return;
508   }
509 
510   uint32_t config_index = 0;
511   DisplayConfigVariableInfo attr = {};
512   GetActiveDisplayConfig(&config_index);
513   GetDisplayAttributesForConfig(INT(config_index), &attr);
514   if (attr.fps != curr_refresh_rate_ || attr.smart_panel != is_smart_panel_) {
515     int bw_code = GetBwCode(attr);
516     int req_data = thermal_bandwidth_client_merge_input_info(bw_code, 0);
517     int error = thermal_bandwidth_client_request(const_cast<char*>(kDisplayBwName), req_data);
518     if (error) {
519       DLOGE("Thermal bandwidth request failed %d", error);
520     }
521     curr_refresh_rate_ = attr.fps;
522     is_smart_panel_ = attr.smart_panel;
523   }
524 }
525 
SetPartialUpdate(DisplayConfigFixedInfo fixed_info)526 void HWCDisplayBuiltIn::SetPartialUpdate(DisplayConfigFixedInfo fixed_info) {
527   partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
528   for (auto hwc_layer : layer_set_) {
529     hwc_layer->SetPartialUpdate(partial_update_enabled_);
530   }
531   client_target_->SetPartialUpdate(partial_update_enabled_);
532 }
533 
SetPowerMode(HWC2::PowerMode mode,bool teardown)534 HWC2::Error HWCDisplayBuiltIn::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
535   DisplayConfigFixedInfo fixed_info = {};
536   display_intf_->GetConfig(&fixed_info);
537   bool command_mode = fixed_info.is_cmdmode;
538 
539   auto status = HWCDisplay::SetPowerMode(mode, teardown);
540   if (status != HWC2::Error::None) {
541     return status;
542   }
543 
544   display_intf_->GetConfig(&fixed_info);
545   is_cmd_mode_ = fixed_info.is_cmdmode;
546   if (is_cmd_mode_ != command_mode) {
547     SetPartialUpdate(fixed_info);
548   }
549 
550   if (mode == HWC2::PowerMode::Off) {
551     SetBwLimitHint(false);
552   }
553 
554   return HWC2::Error::None;
555 }
556 
Present(shared_ptr<Fence> * out_retire_fence)557 HWC2::Error HWCDisplayBuiltIn::Present(shared_ptr<Fence> *out_retire_fence) {
558   auto status = HWC2::Error::None;
559 
560   DTRACE_SCOPED();
561 
562   if (display_paused_) {
563     DisplayError error = display_intf_->Flush(&layer_stack_);
564     validated_ = false;
565     if (error != kErrorNone) {
566       DLOGE("Flush failed. Error = %d", error);
567     }
568   } else {
569     CacheAvrStatus();
570     DisplayConfigFixedInfo fixed_info = {};
571     display_intf_->GetConfig(&fixed_info);
572     bool command_mode = fixed_info.is_cmdmode;
573 
574     status = CommitStitchLayers();
575     if (status != HWC2::Error::None) {
576       DLOGE("Stitch failed: %d", status);
577       return status;
578     }
579 
580     status = CommitLayerStack();
581     if (status == HWC2::Error::None) {
582       HandleFrameOutput();
583       PostCommitStitchLayers();
584       status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
585       SetBwLimitHint(true);
586       display_intf_->GetConfig(&fixed_info);
587       is_cmd_mode_ = fixed_info.is_cmdmode;
588       if (is_cmd_mode_ != command_mode) {
589         SetPartialUpdate(fixed_info);
590       }
591 
592       // For video mode panel with dynamic fps, update the active mode index.
593       // This is needed to report the correct Vsync period when client queries
594       // using GetDisplayVsyncPeriod API.
595       if (!is_cmd_mode_ && !disable_dyn_fps_) {
596         hwc2_config_t active_config = hwc_config_map_.at(0);
597         GetActiveConfig(&active_config);
598         SetActiveConfigIndex(active_config);
599       }
600     }
601   }
602 
603   if (CC_UNLIKELY(!has_config_hbm_threshold_)) {
604     uint32_t panel_x, panel_y;
605     GetPanelResolution(&panel_x, &panel_y);
606     hbm_threshold_px_ = float(panel_x * panel_y) * hbm_threshold_pct_;
607     DLOGI("Configure hbm_threshold_px_ to %f", hbm_threshold_px_);
608 
609     has_config_hbm_threshold_ = true;
610   }
611 
612   const bool enable_hbm(hdr_largest_layer_px_ > hbm_threshold_px_);
613   if (high_brightness_mode_ != enable_hbm) {
614     HbmState state = enable_hbm ? HbmState::HDR : HbmState::OFF;
615     auto status = SetHbm(state, HWC);
616     if (status == HWC2::Error::None) {
617       high_brightness_mode_ = enable_hbm;
618     } else {
619       DLOGE("failed to setHbm to %d", enable_hbm);
620     }
621   }
622 
623   pending_commit_ = false;
624 
625   // In case of scaling UI layer for command mode, reset validate
626   if (force_reset_validate_) {
627     validated_ = false;
628     display_intf_->ClearLUTs();
629   }
630   return status;
631 }
632 
PostCommitStitchLayers()633 void HWCDisplayBuiltIn::PostCommitStitchLayers() {
634   if (disable_layer_stitch_) {
635     return;
636   }
637 
638   // Close Stitch buffer acquire fence.
639   Layer *stitch_layer = stitch_target_->GetSDMLayer();
640   LayerBuffer &output_buffer = stitch_layer->input_buffer;
641   for (auto &layer : layer_stack_.layers) {
642     LayerComposition &composition = layer->composition;
643     if (composition != kCompositionStitch) {
644       continue;
645     }
646     LayerBuffer &input_buffer = layer->input_buffer;
647     input_buffer.release_fence = output_buffer.acquire_fence;
648   }
649 }
650 
GetColorModes(uint32_t * out_num_modes,ColorMode * out_modes)651 HWC2::Error HWCDisplayBuiltIn::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
652   if (out_modes == nullptr) {
653     *out_num_modes = color_mode_->GetColorModeCount();
654   } else {
655     color_mode_->GetColorModes(out_num_modes, out_modes);
656   }
657 
658   return HWC2::Error::None;
659 }
660 
GetRenderIntents(ColorMode mode,uint32_t * out_num_intents,RenderIntent * out_intents)661 HWC2::Error HWCDisplayBuiltIn::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
662                                                 RenderIntent *out_intents) {
663   if (out_intents == nullptr) {
664     *out_num_intents = color_mode_->GetRenderIntentCount(mode);
665   } else {
666     color_mode_->GetRenderIntents(mode, out_num_intents, out_intents);
667   }
668   return HWC2::Error::None;
669 }
670 
SetColorMode(ColorMode mode)671 HWC2::Error HWCDisplayBuiltIn::SetColorMode(ColorMode mode) {
672   return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
673 }
674 
SetColorModeWithRenderIntent(ColorMode mode,RenderIntent intent)675 HWC2::Error HWCDisplayBuiltIn::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
676   auto status = color_mode_->CacheColorModeWithRenderIntent(mode, intent);
677   if (status != HWC2::Error::None) {
678     DLOGE("failed for mode = %d intent = %d", mode, intent);
679     return status;
680   }
681   callbacks_->Refresh(id_);
682   validated_ = false;
683   return status;
684 }
685 
SetColorModeById(int32_t color_mode_id)686 HWC2::Error HWCDisplayBuiltIn::SetColorModeById(int32_t color_mode_id) {
687   auto status = color_mode_->SetColorModeById(color_mode_id);
688   if (status != HWC2::Error::None) {
689     DLOGE("failed for mode = %d", color_mode_id);
690     return status;
691   }
692 
693   callbacks_->Refresh(id_);
694   validated_ = false;
695 
696   return status;
697 }
698 
SetColorModeFromClientApi(int32_t color_mode_id)699 HWC2::Error HWCDisplayBuiltIn::SetColorModeFromClientApi(int32_t color_mode_id) {
700   DisplayError error = kErrorNone;
701   std::string mode_string;
702 
703   error = display_intf_->GetColorModeName(color_mode_id, &mode_string);
704   if (error) {
705     DLOGE("Failed to get mode name for mode %d", color_mode_id);
706     return HWC2::Error::BadParameter;
707   }
708 
709   auto status = color_mode_->SetColorModeFromClientApi(mode_string);
710   if (status != HWC2::Error::None) {
711     DLOGE("Failed to set mode = %d", color_mode_id);
712     return status;
713   }
714 
715   return status;
716 }
717 
RestoreColorTransform()718 HWC2::Error HWCDisplayBuiltIn::RestoreColorTransform() {
719   auto status = color_mode_->RestoreColorTransform();
720   if (status != HWC2::Error::None) {
721     DLOGE("failed to RestoreColorTransform");
722     return status;
723   }
724 
725   callbacks_->Refresh(id_);
726 
727   return status;
728 }
729 
SetColorTransform(const float * matrix,android_color_transform_t hint)730 HWC2::Error HWCDisplayBuiltIn::SetColorTransform(const float *matrix,
731                                                  android_color_transform_t hint) {
732   if (!matrix) {
733     return HWC2::Error::BadParameter;
734   }
735 
736   auto status = color_mode_->SetColorTransform(matrix, hint);
737   if (status != HWC2::Error::None) {
738     DLOGE("failed for hint = %d", hint);
739     color_tranform_failed_ = true;
740     return status;
741   }
742 
743   callbacks_->Refresh(id_);
744   color_tranform_failed_ = false;
745   validated_ = false;
746 
747   return status;
748 }
749 
SetReadbackBuffer(const native_handle_t * buffer,shared_ptr<Fence> acquire_fence,bool post_processed_output,CWBClient client)750 HWC2::Error HWCDisplayBuiltIn::SetReadbackBuffer(const native_handle_t *buffer,
751                                                  shared_ptr<Fence> acquire_fence,
752                                                  bool post_processed_output, CWBClient client) {
753   if (cwb_client_ != client && cwb_client_ != kCWBClientNone) {
754     DLOGE("CWB is in use with client = %d", cwb_client_);
755     return HWC2::Error::NoResources;
756   }
757 
758   const private_handle_t *handle = reinterpret_cast<const private_handle_t *>(buffer);
759   if (!handle || (handle->fd < 0)) {
760     return HWC2::Error::BadParameter;
761   }
762 
763   // Configure the output buffer as Readback buffer
764   output_buffer_.width = UINT32(handle->width);
765   output_buffer_.height = UINT32(handle->height);
766   output_buffer_.unaligned_width = UINT32(handle->unaligned_width);
767   output_buffer_.unaligned_height = UINT32(handle->unaligned_height);
768   output_buffer_.format = HWCLayer::GetSDMFormat(handle->format, handle->flags);
769   output_buffer_.planes[0].fd = handle->fd;
770   output_buffer_.planes[0].stride = UINT32(handle->width);
771   output_buffer_.acquire_fence = acquire_fence;
772   output_buffer_.handle_id = handle->id;
773 
774   post_processed_output_ = post_processed_output;
775   readback_buffer_queued_ = true;
776   readback_configured_ = false;
777   validated_ = false;
778   cwb_client_ = client;
779 
780   return HWC2::Error::None;
781 }
782 
GetReadbackBufferFence(shared_ptr<Fence> * release_fence)783 HWC2::Error HWCDisplayBuiltIn::GetReadbackBufferFence(shared_ptr<Fence> *release_fence) {
784   auto status = HWC2::Error::None;
785 
786   if (readback_configured_ && output_buffer_.release_fence) {
787     *release_fence = output_buffer_.release_fence;
788   } else {
789     status = HWC2::Error::Unsupported;
790   }
791 
792   post_processed_output_ = false;
793   readback_buffer_queued_ = false;
794   readback_configured_ = false;
795   output_buffer_ = {};
796   cwb_client_ = kCWBClientNone;
797 
798   return status;
799 }
800 
TeardownConcurrentWriteback(void)801 DisplayError HWCDisplayBuiltIn::TeardownConcurrentWriteback(void) {
802   DisplayError error = kErrorNotSupported;
803   if (Fence::Wait(output_buffer_.release_fence) != kErrorNone) {
804     DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
805     return kErrorResources;
806   }
807 
808   if (display_intf_) {
809     error = display_intf_->TeardownConcurrentWriteback();
810   }
811 
812   return error;
813 }
814 
SetDisplayDppsAdROI(uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)815 HWC2::Error HWCDisplayBuiltIn::SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
816                                                    uint32_t v_start, uint32_t v_end,
817                                                    uint32_t factor_in, uint32_t factor_out) {
818   DisplayError error = kErrorNone;
819   DisplayDppsAd4RoiCfg dpps_ad4_roi_cfg = {};
820   uint32_t panel_width = 0, panel_height = 0;
821   constexpr uint16_t kMaxFactorVal = 0xffff;
822 
823   if (h_start >= h_end || v_start >= v_end || factor_in > kMaxFactorVal ||
824       factor_out > kMaxFactorVal) {
825     DLOGE("Invalid roi region = [%u, %u, %u, %u, %u, %u]",
826            h_start, h_end, v_start, v_end, factor_in, factor_out);
827     return HWC2::Error::BadParameter;
828   }
829 
830   GetPanelResolution(&panel_width, &panel_height);
831 
832   if (h_start >= panel_width || h_end > panel_width ||
833       v_start >= panel_height || v_end > panel_height) {
834     DLOGE("Invalid roi region = [%u, %u, %u, %u], panel resolution = [%u, %u]",
835            h_start, h_end, v_start, v_end, panel_width, panel_height);
836     return HWC2::Error::BadParameter;
837   }
838 
839   dpps_ad4_roi_cfg.h_start = h_start;
840   dpps_ad4_roi_cfg.h_end = h_end;
841   dpps_ad4_roi_cfg.v_start = v_start;
842   dpps_ad4_roi_cfg.v_end = v_end;
843   dpps_ad4_roi_cfg.factor_in = factor_in;
844   dpps_ad4_roi_cfg.factor_out = factor_out;
845 
846   error = display_intf_->SetDisplayDppsAdROI(&dpps_ad4_roi_cfg);
847   if (error)
848     return HWC2::Error::BadConfig;
849 
850   callbacks_->Refresh(id_);
851 
852   return HWC2::Error::None;
853 }
854 
SetFrameTriggerMode(uint32_t mode)855 HWC2::Error HWCDisplayBuiltIn::SetFrameTriggerMode(uint32_t mode) {
856   DisplayError error = kErrorNone;
857   FrameTriggerMode trigger_mode = kFrameTriggerDefault;
858 
859   if (mode >= kFrameTriggerMax) {
860     DLOGE("Invalid input mode %d", mode);
861     return HWC2::Error::BadParameter;
862   }
863 
864   trigger_mode = static_cast<FrameTriggerMode>(mode);
865   error = display_intf_->SetFrameTriggerMode(trigger_mode);
866   if (error)
867     return HWC2::Error::BadConfig;
868 
869   callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
870   validated_ = false;
871 
872   return HWC2::Error::None;
873 }
874 
Perform(uint32_t operation,...)875 int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
876   va_list args;
877   va_start(args, operation);
878   int val = 0;
879   LayerSolidFill *solid_fill_color;
880   LayerRect *rect = NULL;
881 
882   switch (operation) {
883     case SET_METADATA_DYN_REFRESH_RATE:
884       val = va_arg(args, int32_t);
885       SetMetaDataRefreshRateFlag(val);
886       break;
887     case SET_BINDER_DYN_REFRESH_RATE:
888       val = va_arg(args, int32_t);
889       ForceRefreshRate(UINT32(val));
890       break;
891     case SET_DISPLAY_MODE:
892       val = va_arg(args, int32_t);
893       SetDisplayMode(UINT32(val));
894       break;
895     case SET_QDCM_SOLID_FILL_INFO:
896       solid_fill_color = va_arg(args, LayerSolidFill*);
897       SetQDCMSolidFillInfo(true, *solid_fill_color);
898       break;
899     case UNSET_QDCM_SOLID_FILL_INFO:
900       solid_fill_color = va_arg(args, LayerSolidFill*);
901       SetQDCMSolidFillInfo(false, *solid_fill_color);
902       break;
903     case SET_QDCM_SOLID_FILL_RECT:
904       rect = va_arg(args, LayerRect*);
905       solid_fill_rect_ = *rect;
906       break;
907     default:
908       DLOGW("Invalid operation %d", operation);
909       va_end(args);
910       return -EINVAL;
911   }
912   va_end(args);
913   validated_ = false;
914 
915   return 0;
916 }
917 
SetDisplayMode(uint32_t mode)918 DisplayError HWCDisplayBuiltIn::SetDisplayMode(uint32_t mode) {
919   DisplayError error = kErrorNone;
920 
921   if (display_intf_) {
922     error = display_intf_->SetDisplayMode(mode);
923     if (error == kErrorNone) {
924       DisplayConfigFixedInfo fixed_info = {};
925       display_intf_->GetConfig(&fixed_info);
926       is_cmd_mode_ = fixed_info.is_cmdmode;
927       partial_update_enabled_ = fixed_info.partial_update;
928       for (auto hwc_layer : layer_set_) {
929         hwc_layer->SetPartialUpdate(partial_update_enabled_);
930       }
931       client_target_->SetPartialUpdate(partial_update_enabled_);
932     }
933   }
934 
935   return error;
936 }
937 
SetMetaDataRefreshRateFlag(bool enable)938 void HWCDisplayBuiltIn::SetMetaDataRefreshRateFlag(bool enable) {
939   int disable_metadata_dynfps = 0;
940 
941   HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
942   if (disable_metadata_dynfps) {
943     return;
944   }
945   use_metadata_refresh_rate_ = enable;
946 }
947 
SetQDCMSolidFillInfo(bool enable,const LayerSolidFill & color)948 void HWCDisplayBuiltIn::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
949   solid_fill_enable_ = enable;
950   solid_fill_color_ = color;
951 }
952 
ToggleCPUHint(bool set)953 void HWCDisplayBuiltIn::ToggleCPUHint(bool set) {
954   if (!cpu_hint_ || !perf_hint_window_) {
955     return;
956   }
957 
958   if (set) {
959     cpu_hint_->Set();
960   } else {
961     cpu_hint_->Reset();
962   }
963 }
964 
HandleSecureSession(const std::bitset<kSecureMax> & secure_sessions,bool * power_on_pending,bool is_active_secure_display)965 int HWCDisplayBuiltIn::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
966                                            bool *power_on_pending, bool is_active_secure_display) {
967   if (!power_on_pending) {
968     return -EINVAL;
969   }
970 
971   if (!is_active_secure_display) {
972     // Do handling as done on non-primary displays.
973     DLOGI("Default handling for display %" PRIu64 " %d-%d", id_, sdm_id_, type_);
974     return HWCDisplay::HandleSecureSession(secure_sessions, power_on_pending,
975                                            is_active_secure_display);
976   }
977 
978   if (current_power_mode_ != HWC2::PowerMode::On) {
979     return 0;
980   }
981 
982   if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
983     SecureEvent secure_event =
984         secure_sessions.test(kSecureDisplay) ? kSecureDisplayStart : kSecureDisplayEnd;
985     DisplayError err = display_intf_->HandleSecureEvent(secure_event, &layer_stack_);
986     if (err != kErrorNone) {
987       DLOGE("Set secure event failed");
988       return err;
989     }
990 
991     DLOGI("SecureDisplay state changed from %d to %d for display %" PRIu64 " %d-%d",
992           active_secure_sessions_.test(kSecureDisplay), secure_sessions.test(kSecureDisplay),
993           id_, sdm_id_, type_);
994   }
995   active_secure_sessions_ = secure_sessions;
996   *power_on_pending = false;
997   return 0;
998 }
999 
ForceRefreshRate(uint32_t refresh_rate)1000 void HWCDisplayBuiltIn::ForceRefreshRate(uint32_t refresh_rate) {
1001   if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
1002       force_refresh_rate_ == refresh_rate) {
1003     // Cannot honor force refresh rate, as its beyond the range or new request is same
1004     return;
1005   }
1006 
1007   force_refresh_rate_ = refresh_rate;
1008 
1009   callbacks_->Refresh(id_);
1010 
1011   return;
1012 }
1013 
GetOptimalRefreshRate(bool one_updating_layer)1014 uint32_t HWCDisplayBuiltIn::GetOptimalRefreshRate(bool one_updating_layer) {
1015   if (force_refresh_rate_) {
1016     return force_refresh_rate_;
1017   } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
1018     return metadata_refresh_rate_;
1019   }
1020 
1021   DLOGV_IF(kTagClient, "active_refresh_rate_: %d", active_refresh_rate_);
1022   return active_refresh_rate_;
1023 }
1024 
SetIdleTimeoutMs(uint32_t timeout_ms)1025 void HWCDisplayBuiltIn::SetIdleTimeoutMs(uint32_t timeout_ms) {
1026   display_intf_->SetIdleTimeoutMs(timeout_ms);
1027   validated_ = false;
1028 }
1029 
HandleFrameOutput()1030 void HWCDisplayBuiltIn::HandleFrameOutput() {
1031   if (readback_buffer_queued_) {
1032     validated_ = false;
1033   }
1034 
1035   if (frame_capture_buffer_queued_) {
1036     HandleFrameCapture();
1037   } else if (dump_output_to_file_) {
1038     HandleFrameDump();
1039   }
1040 }
1041 
HandleFrameCapture()1042 void HWCDisplayBuiltIn::HandleFrameCapture() {
1043   if (readback_configured_ && output_buffer_.release_fence) {
1044     frame_capture_status_ = Fence::Wait(output_buffer_.release_fence);
1045   }
1046 
1047   frame_capture_buffer_queued_ = false;
1048   readback_buffer_queued_ = false;
1049   post_processed_output_ = false;
1050   readback_configured_ = false;
1051   output_buffer_ = {};
1052   cwb_client_ = kCWBClientNone;
1053 }
1054 
HandleFrameDump()1055 void HWCDisplayBuiltIn::HandleFrameDump() {
1056   if (dump_frame_count_) {
1057     int ret = 0;
1058     ret = Fence::Wait(output_buffer_.release_fence);
1059     if (ret != kErrorNone) {
1060       DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
1061     }
1062 
1063     if (!ret) {
1064       DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence);
1065       validated_ = false;
1066     }
1067 
1068     if (0 == (dump_frame_count_ - 1)) {
1069       dump_output_to_file_ = false;
1070       // Unmap and Free buffer
1071       if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
1072         DLOGE("unmap failed with err %d", errno);
1073       }
1074       if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
1075         DLOGE("FreeBuffer failed");
1076       }
1077 
1078       readback_buffer_queued_ = false;
1079       post_processed_output_ = false;
1080       readback_configured_ = false;
1081 
1082       output_buffer_ = {};
1083       output_buffer_info_ = {};
1084       output_buffer_base_ = nullptr;
1085       cwb_client_ = kCWBClientNone;
1086     }
1087   }
1088 }
1089 
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type,int32_t format,bool post_processed)1090 HWC2::Error HWCDisplayBuiltIn::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
1091                                                   int32_t format, bool post_processed) {
1092   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type, format, post_processed);
1093   dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
1094   DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
1095 
1096   if (dump_output_to_file_) {
1097     if (cwb_client_ != kCWBClientNone) {
1098       DLOGW("CWB is in use with client = %d", cwb_client_);
1099       return HWC2::Error::NoResources;
1100     }
1101   }
1102 
1103   if (!count || !dump_output_to_file_ || (output_buffer_info_.alloc_buffer_info.fd >= 0)) {
1104     return HWC2::Error::None;
1105   }
1106 
1107   // Allocate and map output buffer
1108   if (post_processed) {
1109     // To dump post-processed (DSPP) output, use Panel resolution.
1110     GetPanelResolution(&output_buffer_info_.buffer_config.width,
1111                        &output_buffer_info_.buffer_config.height);
1112   } else {
1113     // To dump Layer Mixer output, use FrameBuffer resolution.
1114     GetFrameBufferResolution(&output_buffer_info_.buffer_config.width,
1115                              &output_buffer_info_.buffer_config.height);
1116   }
1117 
1118   output_buffer_info_.buffer_config.format = HWCLayer::GetSDMFormat(format, 0);
1119   output_buffer_info_.buffer_config.buffer_count = 1;
1120   if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
1121     DLOGE("Buffer allocation failed");
1122     output_buffer_info_ = {};
1123     return HWC2::Error::NoResources;
1124   }
1125 
1126   void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
1127                       MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
1128 
1129   if (buffer == MAP_FAILED) {
1130     DLOGE("mmap failed with err %d", errno);
1131     buffer_allocator_->FreeBuffer(&output_buffer_info_);
1132     output_buffer_info_ = {};
1133     return HWC2::Error::NoResources;
1134   }
1135 
1136   output_buffer_base_ = buffer;
1137   const native_handle_t *handle = static_cast<native_handle_t *>(output_buffer_info_.private_data);
1138   SetReadbackBuffer(handle, nullptr, post_processed, kCWBClientFrameDump);
1139 
1140   return HWC2::Error::None;
1141 }
1142 
FrameCaptureAsync(const BufferInfo & output_buffer_info,bool post_processed_output)1143 int HWCDisplayBuiltIn::FrameCaptureAsync(const BufferInfo &output_buffer_info,
1144                                          bool post_processed_output) {
1145   if (cwb_client_ != kCWBClientNone) {
1146     DLOGE("CWB is in use with client = %d", cwb_client_);
1147     return -1;
1148   }
1149 
1150   // Note: This function is called in context of a binder thread and a lock is already held
1151   if (output_buffer_info.alloc_buffer_info.fd < 0) {
1152     DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
1153     return -1;
1154   }
1155 
1156   auto panel_width = 0u;
1157   auto panel_height = 0u;
1158   auto fb_width = 0u;
1159   auto fb_height = 0u;
1160 
1161   GetPanelResolution(&panel_width, &panel_height);
1162   GetFrameBufferResolution(&fb_width, &fb_height);
1163 
1164   if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
1165                                 output_buffer_info.buffer_config.height < panel_height)) {
1166     DLOGE("Buffer dimensions should not be less than panel resolution");
1167     return -1;
1168   } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
1169                                         output_buffer_info.buffer_config.height < fb_height)) {
1170     DLOGE("Buffer dimensions should not be less than FB resolution");
1171     return -1;
1172   }
1173 
1174   const native_handle_t *buffer = static_cast<native_handle_t *>(output_buffer_info.private_data);
1175   SetReadbackBuffer(buffer, nullptr, post_processed_output, kCWBClientColor);
1176   frame_capture_buffer_queued_ = true;
1177   frame_capture_status_ = -EAGAIN;
1178 
1179   return 0;
1180 }
1181 
SetDetailEnhancerConfig(const DisplayDetailEnhancerData & de_data)1182 DisplayError HWCDisplayBuiltIn::SetDetailEnhancerConfig
1183                                    (const DisplayDetailEnhancerData &de_data) {
1184   DisplayError error = kErrorNotSupported;
1185 
1186   if (display_intf_) {
1187     error = display_intf_->SetDetailEnhancerData(de_data);
1188     validated_ = false;
1189   }
1190   return error;
1191 }
1192 
ControlPartialUpdate(bool enable,uint32_t * pending)1193 DisplayError HWCDisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
1194   DisplayError error = kErrorNone;
1195 
1196   if (display_intf_) {
1197     error = display_intf_->ControlPartialUpdate(enable, pending);
1198     validated_ = false;
1199   }
1200 
1201   return error;
1202 }
1203 
DisablePartialUpdateOneFrame()1204 DisplayError HWCDisplayBuiltIn::DisablePartialUpdateOneFrame() {
1205   DisplayError error = kErrorNone;
1206 
1207   if (display_intf_) {
1208     error = display_intf_->DisablePartialUpdateOneFrame();
1209     validated_ = false;
1210   }
1211 
1212   return error;
1213 }
1214 
SetDisplayedContentSamplingEnabledVndService(bool enabled)1215 HWC2::Error HWCDisplayBuiltIn::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
1216   std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
1217   vndservice_sampling_vote = enabled;
1218   if (api_sampling_vote || vndservice_sampling_vote) {
1219     histogram.start();
1220     display_intf_->colorSamplingOn();
1221   } else {
1222     display_intf_->colorSamplingOff();
1223     histogram.stop();
1224   }
1225   return HWC2::Error::None;
1226 }
1227 
SetDisplayedContentSamplingEnabled(int32_t enabled,uint8_t component_mask,uint64_t max_frames)1228 HWC2::Error HWCDisplayBuiltIn::SetDisplayedContentSamplingEnabled(int32_t enabled,
1229                                                                   uint8_t component_mask,
1230                                                                   uint64_t max_frames) {
1231   if ((enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) &&
1232       (enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_DISABLE))
1233     return HWC2::Error::BadParameter;
1234 
1235   std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
1236   if (enabled == HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) {
1237     api_sampling_vote = true;
1238   } else {
1239     api_sampling_vote = false;
1240   }
1241 
1242   auto start = api_sampling_vote || vndservice_sampling_vote;
1243   if (start && max_frames == 0) {
1244     histogram.start();
1245     display_intf_->colorSamplingOn();
1246   } else if (start) {
1247     histogram.start(max_frames);
1248     display_intf_->colorSamplingOn();
1249   } else {
1250     display_intf_->colorSamplingOff();
1251     histogram.stop();
1252   }
1253   return HWC2::Error::None;
1254 }
1255 
GetDisplayedContentSamplingAttributes(int32_t * format,int32_t * dataspace,uint8_t * supported_components)1256 HWC2::Error HWCDisplayBuiltIn::GetDisplayedContentSamplingAttributes(
1257     int32_t *format, int32_t *dataspace, uint8_t *supported_components) {
1258   return histogram.getAttributes(format, dataspace, supported_components);
1259 }
1260 
GetDisplayedContentSample(uint64_t max_frames,uint64_t timestamp,uint64_t * numFrames,int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],uint64_t * samples[NUM_HISTOGRAM_COLOR_COMPONENTS])1261 HWC2::Error HWCDisplayBuiltIn::GetDisplayedContentSample(
1262     uint64_t max_frames, uint64_t timestamp, uint64_t *numFrames,
1263     int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
1264     uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
1265   histogram.collect(max_frames, timestamp, samples_size, samples, numFrames);
1266   return HWC2::Error::None;
1267 }
1268 
SetMixerResolution(uint32_t width,uint32_t height)1269 DisplayError HWCDisplayBuiltIn::SetMixerResolution(uint32_t width, uint32_t height) {
1270   DisplayError error = display_intf_->SetMixerResolution(width, height);
1271   callbacks_->Refresh(id_);
1272   validated_ = false;
1273   return error;
1274 }
1275 
GetMixerResolution(uint32_t * width,uint32_t * height)1276 DisplayError HWCDisplayBuiltIn::GetMixerResolution(uint32_t *width, uint32_t *height) {
1277   return display_intf_->GetMixerResolution(width, height);
1278 }
1279 
SetQSyncMode(QSyncMode qsync_mode)1280 HWC2::Error HWCDisplayBuiltIn::SetQSyncMode(QSyncMode qsync_mode) {
1281   // Client needs to ensure that config change and qsync mode change
1282   // are not triggered in the same drawcycle.
1283   if (pending_config_) {
1284     DLOGE("Failed to set qsync mode. Pending active config transition");
1285     return HWC2::Error::Unsupported;
1286   }
1287 
1288   auto err = display_intf_->SetQSyncMode(qsync_mode);
1289   if (err != kErrorNone) {
1290     return HWC2::Error::Unsupported;
1291   }
1292 
1293   validated_ = false;
1294   return HWC2::Error::None;
1295 }
1296 
ControlIdlePowerCollapse(bool enable,bool synchronous)1297 DisplayError HWCDisplayBuiltIn::ControlIdlePowerCollapse(bool enable, bool synchronous) {
1298   DisplayError error = kErrorNone;
1299 
1300   if (display_intf_) {
1301     error = display_intf_->ControlIdlePowerCollapse(enable, synchronous);
1302     validated_ = false;
1303   }
1304   return error;
1305 }
1306 
SetDynamicDSIClock(uint64_t bitclk)1307 DisplayError HWCDisplayBuiltIn::SetDynamicDSIClock(uint64_t bitclk) {
1308   DisablePartialUpdateOneFrame();
1309   DisplayError error = display_intf_->SetDynamicDSIClock(bitclk);
1310   if (error != kErrorNone) {
1311     DLOGE(" failed: Clk: %" PRIu64 " Error: %d", bitclk, error);
1312     return error;
1313   }
1314 
1315   callbacks_->Refresh(id_);
1316   validated_ = false;
1317 
1318   return kErrorNone;
1319 }
1320 
GetDynamicDSIClock(uint64_t * bitclk)1321 DisplayError HWCDisplayBuiltIn::GetDynamicDSIClock(uint64_t *bitclk) {
1322   if (display_intf_) {
1323     return display_intf_->GetDynamicDSIClock(bitclk);
1324   }
1325 
1326   return kErrorNotSupported;
1327 }
1328 
GetSupportedDSIClock(std::vector<uint64_t> * bitclk_rates)1329 DisplayError HWCDisplayBuiltIn::GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) {
1330   if (display_intf_) {
1331     return display_intf_->GetSupportedDSIClock(bitclk_rates);
1332   }
1333 
1334   return kErrorNotSupported;
1335 }
1336 
SetStandByMode(bool enable)1337 DisplayError HWCDisplayBuiltIn::SetStandByMode(bool enable) {
1338   if (enable) {
1339     if (!display_null_.IsActive()) {
1340       stored_display_intf_ = display_intf_;
1341       display_intf_ = &display_null_;
1342       display_null_.SetActive(true);
1343       DLOGD("Null display is connected successfully");
1344     } else {
1345       DLOGD("Null display is already connected.");
1346     }
1347   } else {
1348     if (display_null_.IsActive()) {
1349       display_intf_ = stored_display_intf_;
1350       validated_ = false;
1351       display_null_.SetActive(false);
1352       DLOGD("Display is connected successfully");
1353     } else {
1354       DLOGD("Display is already connected.");
1355     }
1356   }
1357   return kErrorNone;
1358 }
1359 
UpdateDisplayId(hwc2_display_t id)1360 HWC2::Error HWCDisplayBuiltIn::UpdateDisplayId(hwc2_display_t id) {
1361   id_ = id;
1362   return HWC2::Error::None;
1363 }
1364 
SetPendingRefresh()1365 HWC2::Error HWCDisplayBuiltIn::SetPendingRefresh() {
1366   pending_refresh_ = true;
1367   return HWC2::Error::None;
1368 }
1369 
SetPanelBrightness(float brightness)1370 HWC2::Error HWCDisplayBuiltIn::SetPanelBrightness(float brightness) {
1371   DisplayError ret = display_intf_->SetPanelBrightness(brightness);
1372   if (ret != kErrorNone) {
1373     return HWC2::Error::NoResources;
1374   }
1375 
1376   return HWC2::Error::None;
1377 }
1378 
GetPanelBrightness(float * brightness)1379 HWC2::Error HWCDisplayBuiltIn::GetPanelBrightness(float *brightness) {
1380   DisplayError ret = display_intf_->GetPanelBrightness(brightness);
1381   if (ret != kErrorNone) {
1382     return HWC2::Error::NoResources;
1383   }
1384 
1385   return HWC2::Error::None;
1386 }
1387 
GetPanelMaxBrightness(uint32_t * max_brightness_level)1388 HWC2::Error HWCDisplayBuiltIn::GetPanelMaxBrightness(uint32_t *max_brightness_level) {
1389   DisplayError ret = display_intf_->GetPanelMaxBrightness(max_brightness_level);
1390   if (ret != kErrorNone) {
1391     return HWC2::Error::NoResources;
1392   }
1393 
1394   return HWC2::Error::None;
1395 }
1396 
SetCurrentPanelGammaSource(enum PanelGammaSource source)1397 DisplayError HWCDisplayBuiltIn::SetCurrentPanelGammaSource(enum PanelGammaSource source) {
1398   DisplayError error = UpdatePanelGammaTable(source);
1399   if (error == kErrorNone) {
1400     current_panel_gamma_source_ = source;
1401   }
1402 
1403   return error;
1404 }
1405 
SetBLScale(uint32_t level)1406 HWC2::Error HWCDisplayBuiltIn::SetBLScale(uint32_t level) {
1407   DisplayError ret = display_intf_->SetBLScale(level);
1408   if (ret != kErrorNone) {
1409     return HWC2::Error::NoResources;
1410   }
1411   return HWC2::Error::None;
1412 }
1413 
UpdatePowerMode(HWC2::PowerMode mode)1414 HWC2::Error HWCDisplayBuiltIn::UpdatePowerMode(HWC2::PowerMode mode) {
1415   current_power_mode_ = mode;
1416   validated_ = false;
1417   return HWC2::Error::None;
1418 }
1419 
SetClientTarget(buffer_handle_t target,shared_ptr<Fence> acquire_fence,int32_t dataspace,hwc_region_t damage)1420 HWC2::Error HWCDisplayBuiltIn::SetClientTarget(buffer_handle_t target,
1421                                                shared_ptr<Fence> acquire_fence,
1422                                                int32_t dataspace, hwc_region_t damage) {
1423   HWC2::Error error = HWCDisplay::SetClientTarget(target, acquire_fence, dataspace, damage);
1424   if (error != HWC2::Error::None) {
1425     return error;
1426   }
1427 
1428   // windowed_display and dynamic scaling are not supported.
1429   if (windowed_display_) {
1430     return HWC2::Error::None;
1431   }
1432 
1433   Layer *sdm_layer = client_target_->GetSDMLayer();
1434   uint32_t fb_width = 0, fb_height = 0;
1435 
1436   GetFrameBufferResolution(&fb_width, &fb_height);
1437 
1438   if (fb_width != sdm_layer->input_buffer.unaligned_width ||
1439       fb_height != sdm_layer->input_buffer.unaligned_height) {
1440     if (SetFrameBufferConfig(sdm_layer->input_buffer.unaligned_width,
1441                              sdm_layer->input_buffer.unaligned_height)) {
1442       return HWC2::Error::BadParameter;
1443     }
1444   }
1445 
1446   return HWC2::Error::None;
1447 }
1448 
IsSmartPanelConfig(uint32_t config_id)1449 bool HWCDisplayBuiltIn::IsSmartPanelConfig(uint32_t config_id) {
1450   if (config_id < hwc_config_map_.size()) {
1451     uint32_t index = hwc_config_map_.at(config_id);
1452     return variable_config_map_.at(index).smart_panel;
1453   }
1454 
1455   return false;
1456 }
1457 
HasSmartPanelConfig(void)1458 bool HWCDisplayBuiltIn::HasSmartPanelConfig(void) {
1459   if (!enable_poms_during_doze_) {
1460     uint32_t config = 0;
1461     GetActiveDisplayConfig(&config);
1462     return IsSmartPanelConfig(config);
1463   }
1464 
1465   for (auto &config : variable_config_map_) {
1466     if (config.second.smart_panel) {
1467       return true;
1468     }
1469   }
1470 
1471   return false;
1472 }
1473 
Deinit()1474 int HWCDisplayBuiltIn::Deinit() {
1475   // Destory color convert instance. This destroys thread and underlying GL resources.
1476   if (gl_layer_stitch_) {
1477     layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeDestroyInstance, nullptr);
1478   }
1479 
1480   histogram.stop();
1481   return HWCDisplay::Deinit();
1482 }
1483 
OnTask(const LayerStitchTaskCode & task_code,SyncTask<LayerStitchTaskCode>::TaskContext * task_context)1484 void HWCDisplayBuiltIn::OnTask(const LayerStitchTaskCode &task_code,
1485                                SyncTask<LayerStitchTaskCode>::TaskContext *task_context) {
1486   switch (task_code) {
1487     case LayerStitchTaskCode::kCodeGetInstance: {
1488         gl_layer_stitch_ = GLLayerStitch::GetInstance(false /* Non-secure */);
1489       }
1490       break;
1491     case LayerStitchTaskCode::kCodeStitch: {
1492         DTRACE_SCOPED();
1493         LayerStitchContext* ctx = reinterpret_cast<LayerStitchContext*>(task_context);
1494         gl_layer_stitch_->Blit(ctx->stitch_params, &(ctx->release_fence));
1495       }
1496       break;
1497     case LayerStitchTaskCode::kCodeDestroyInstance: {
1498         if (gl_layer_stitch_) {
1499           GLLayerStitch::Destroy(gl_layer_stitch_);
1500         }
1501       }
1502       break;
1503   }
1504 }
1505 
InitLayerStitch()1506 bool HWCDisplayBuiltIn::InitLayerStitch() {
1507   if (!is_primary_) {
1508     // Disable on all non-primary builtins.
1509     DLOGI("Non-primary builtin.");
1510     disable_layer_stitch_ = true;
1511     return true;
1512   }
1513 
1514   // Disable by default.
1515   int value = 1;
1516   Debug::Get()->GetProperty(DISABLE_LAYER_STITCH, &value);
1517   disable_layer_stitch_ = (value == 1);
1518 
1519   if (disable_layer_stitch_) {
1520     DLOGI("Layer Stitch Disabled !!!");
1521     return true;
1522   }
1523 
1524   // Initialize stitch context. This will be non-secure.
1525   layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeGetInstance, nullptr);
1526   if (gl_layer_stitch_ == nullptr) {
1527     DLOGE("Failed to get LayerStitch Instance");
1528     return false;
1529   }
1530 
1531   if (!AllocateStitchBuffer()) {
1532     return true;
1533   }
1534 
1535   stitch_target_ = new HWCLayer(id_, static_cast<HWCBufferAllocator *>(buffer_allocator_));
1536 
1537   // Populate buffer params and pvt handle.
1538   InitStitchTarget();
1539 
1540   DLOGI("Created LayerStitch instance: %p", gl_layer_stitch_);
1541 
1542   return true;
1543 }
1544 
AllocateStitchBuffer()1545 bool HWCDisplayBuiltIn::AllocateStitchBuffer() {
1546   // Buffer dimensions: FB width * (1.5 * height)
1547 
1548   DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config_);
1549   if (error != kErrorNone) {
1550     DLOGE("Get frame buffer config failed. Error = %d", error);
1551     return false;
1552   }
1553 
1554   BufferConfig &config = buffer_info_.buffer_config;
1555   config.width = fb_config_.x_pixels;
1556   config.height = fb_config_.y_pixels * kBufferHeightFactor;
1557 
1558   // By default UBWC is enabled and below property is global enable/disable for all
1559   // buffers allocated through gralloc , including framebuffer targets.
1560   int ubwc_disabled = 0;
1561   HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
1562   config.format = ubwc_disabled ? kFormatRGBA8888 : kFormatRGBA8888Ubwc;
1563 
1564   config.gfx_client = true;
1565 
1566   // Populate default params.
1567   config.secure = false;
1568   config.cache = false;
1569   config.secure_camera = false;
1570 
1571   error = buffer_allocator_->AllocateBuffer(&buffer_info_);
1572 
1573   if (error != kErrorNone) {
1574     DLOGE("Failed to allocate buffer. Error: %d", error);
1575     return false;
1576   }
1577 
1578   return true;
1579 }
1580 
InitStitchTarget()1581 void HWCDisplayBuiltIn::InitStitchTarget() {
1582   LayerBuffer buffer = {};
1583   buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
1584   buffer.planes[0].offset = 0;
1585   buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
1586   buffer.size = buffer_info_.alloc_buffer_info.size;
1587   buffer.handle_id = buffer_info_.alloc_buffer_info.id;
1588   buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
1589   buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
1590   buffer.unaligned_width = fb_config_.x_pixels;
1591   buffer.unaligned_height = fb_config_.y_pixels * kBufferHeightFactor;
1592   buffer.format = buffer_info_.alloc_buffer_info.format;
1593 
1594   Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
1595   sdm_stitch_target->composition = kCompositionStitchTarget;
1596   sdm_stitch_target->input_buffer = buffer;
1597   sdm_stitch_target->input_buffer.buffer_id = reinterpret_cast<uint64_t>(buffer_info_.private_data);
1598 }
1599 
AppendStitchLayer()1600 void HWCDisplayBuiltIn::AppendStitchLayer() {
1601   if (disable_layer_stitch_) {
1602     return;
1603   }
1604 
1605   // Append stitch target buffer to layer stack.
1606   Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
1607   sdm_stitch_target->composition = kCompositionStitchTarget;
1608   sdm_stitch_target->dst_rect = {0, 0, FLOAT(fb_config_.x_pixels), FLOAT(fb_config_.y_pixels)};
1609   layer_stack_.layers.push_back(sdm_stitch_target);
1610 }
1611 
HistogramEvent(int fd,uint32_t blob_id)1612 DisplayError HWCDisplayBuiltIn::HistogramEvent(int fd, uint32_t blob_id) {
1613   histogram.notify_histogram_event(fd, blob_id);
1614   return kErrorNone;
1615 }
1616 
PostInit()1617 int HWCDisplayBuiltIn::PostInit() {
1618   auto status = InitLayerStitch();
1619   if (!status) {
1620     DLOGW("Failed to initialize Layer Stitch context");
1621     // Disable layer stitch.
1622     disable_layer_stitch_ = true;
1623   }
1624 
1625   return 0;
1626 }
1627 
HasReadBackBufferSupport()1628 bool HWCDisplayBuiltIn::HasReadBackBufferSupport() {
1629   DisplayConfigFixedInfo fixed_info = {};
1630   display_intf_->GetConfig(&fixed_info);
1631 
1632   return fixed_info.readback_supported;
1633 }
1634 
GetUpdatingAppLayersCount()1635 uint32_t HWCDisplayBuiltIn::GetUpdatingAppLayersCount() {
1636   uint32_t updating_count = 0;
1637 
1638   for (auto layer:layer_stack_.layers) {
1639     if (layer->composition == kCompositionGPUTarget) {
1640       break;
1641     }
1642     if (layer->flags.updating) {
1643       updating_count++;
1644     }
1645   }
1646 
1647   return updating_count;
1648 }
1649 
IsDisplayIdle()1650 bool HWCDisplayBuiltIn::IsDisplayIdle() {
1651   // Notify only if this display is source of vsync.
1652   bool vsync_source = (callbacks_->GetVsyncSource() == id_);
1653   return vsync_source && display_idle_;
1654 }
1655 
SetCpuPerfHintLargeCompCycle()1656 void HWCDisplayBuiltIn::SetCpuPerfHintLargeCompCycle() {
1657   if (!cpu_hint_ || !perf_hint_large_comp_cycle_) {
1658     DLOGV_IF(kTagResources, "cpu_hint_ not initialized or property not set");
1659     return;
1660   }
1661 
1662   for (auto hwc_layer : layer_set_) {
1663     Layer *layer = hwc_layer->GetSDMLayer();
1664     if (layer->composition == kCompositionGPU) {
1665       DLOGV_IF(kTagResources, "Set perf hint for large comp cycle");
1666       int hwc_tid = gettid();
1667       cpu_hint_->ReqHintsOffload(kPerfHintLargeCompCycle, hwc_tid);
1668       break;
1669     }
1670   }
1671 }
1672 
ApplyHbmLocked()1673 HWC2::Error HWCDisplayBuiltIn::ApplyHbmLocked() {
1674   if (!mHasHbmNode)
1675     return HWC2::Error::Unsupported;
1676 
1677   HbmState state = HbmState::OFF;
1678   for (auto req : mHbmSates) {
1679     if (req == HbmState::SUNLIGHT) {
1680       state = HbmState::SUNLIGHT;
1681       break;
1682     } else if (req == HbmState::HDR) {
1683       state = HbmState::HDR;
1684     }
1685   }
1686 
1687   if (state == mCurHbmState)
1688     return HWC2::Error::None;
1689 
1690   std::string action = std::to_string(static_cast<int>(state));
1691   if (!android::base::WriteStringToFile(action, kHighBrightnessModeNode)) {
1692     DLOGE("Failed to write hbm node = %s, error = %s ", kHighBrightnessModeNode, strerror(errno));
1693   } else {
1694     DLOGI("write %s to HBM sysfs file succeeded", action.c_str());
1695   }
1696 
1697   mCurHbmState = state;
1698 
1699   return HWC2::Error::None;
1700 }
1701 
IsHbmSupported()1702 bool HWCDisplayBuiltIn::IsHbmSupported() {
1703   if (!mHasHbmNode)
1704     return false;
1705 
1706   bool is_hbm_supported = false;
1707   std::string buffer;
1708   if (!android::base::ReadFileToString(kHighBrightnessModeNode, &buffer)) {
1709     DLOGE("Failed to read hbm node = %s, error = %s ", kHighBrightnessModeNode, strerror(errno));
1710   } else if (buffer == "unsupported") {
1711     DLOGI("kernel driver does not support hbm");
1712   } else {
1713     is_hbm_supported = true;
1714   }
1715 
1716   return is_hbm_supported;
1717 }
1718 
SetHbm(HbmState state,HbmClient client)1719 HWC2::Error HWCDisplayBuiltIn::SetHbm(HbmState state, HbmClient client) {
1720   auto status = HWC2::Error::None;
1721   if (client >= CLIENT_MAX)
1722     return HWC2::Error::BadParameter;
1723 
1724   std::unique_lock<decltype(hbm_mutex)> lk(hbm_mutex);
1725 
1726   /* save and apply the request state */
1727   if (mHbmSates[client] != state) {
1728     mHbmSates[client] = state;
1729 
1730     status = ApplyHbmLocked();
1731     if (INT32(status) != HWC2_ERROR_NONE)
1732       DLOGE("Failed to apply hbm node, error = %d", status);
1733   }
1734 
1735   return status;
1736 }
1737 
GetHbm()1738 HbmState HWCDisplayBuiltIn::GetHbm() {
1739   return mCurHbmState;
1740 }
1741 
1742 }  // namespace sdm
1743