1 /*
2  * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
3  * Not a Contribution.
4  *
5  * Copyright 2015 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #include <QService.h>
21 #include <binder/Parcel.h>
22 #include <core/buffer_allocator.h>
23 #include <cutils/properties.h>
24 #include <display_config.h>
25 #include <hardware_legacy/uevent.h>
26 #include <private/color_params.h>
27 #include <qd_utils.h>
28 #include <sync/sync.h>
29 #include <sys/prctl.h>
30 #include <sys/resource.h>
31 #include <utils/String16.h>
32 #include <utils/constants.h>
33 #include <utils/debug.h>
34 #include <QService.h>
35 #include <utils/utils.h>
36 #include <algorithm>
37 #include <utility>
38 #include <bitset>
39 #include <iterator>
40 #include <memory>
41 #include <string>
42 #include <thread>
43 #include <vector>
44 #include <cutils/sockets.h>
45 
46 #include "hwc_buffer_allocator.h"
47 #include "hwc_session.h"
48 #include "hwc_debugger.h"
49 
50 #define __CLASS__ "HWCSession"
51 
52 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
53 #define HWC_UEVENT_DRM_EXT_HOTPLUG "mdss_mdp/drm/card"
54 
55 using HwcAttribute = composer_V2_4::IComposerClient::Attribute;
56 extern void DisplayInit(sdm::HWCSession *hwc_session);
57 
58 namespace sdm {
59 
60 static HWCUEvent g_hwc_uevent_;
61 Locker HWCSession::locker_[HWCCallbacks::kNumDisplays];
62 bool HWCSession::pending_power_mode_[HWCCallbacks::kNumDisplays];
63 Locker HWCSession::power_state_[HWCCallbacks::kNumDisplays];
64 Locker HWCSession::hdr_locker_[HWCCallbacks::kNumDisplays];
65 Locker HWCSession::display_config_locker_;
66 Locker HWCSession::system_locker_;
67 static const int kSolidFillDelay = 100 * 1000;
68 int HWCSession::null_display_mode_ = 0;
69 static const uint32_t kBrightnessScaleMax = 100;
70 static const uint32_t kSvBlScaleMax = 65535;
71 
72 // Map the known color modes to dataspace.
GetDataspaceFromColorMode(ColorMode mode)73 int32_t GetDataspaceFromColorMode(ColorMode mode) {
74   switch (mode) {
75     case ColorMode::SRGB:
76     case ColorMode::NATIVE:
77       return HAL_DATASPACE_V0_SRGB;
78     case ColorMode::DCI_P3:
79       return HAL_DATASPACE_DCI_P3;
80     case ColorMode::DISPLAY_P3:
81       return HAL_DATASPACE_DISPLAY_P3;
82     case ColorMode::BT2100_PQ:
83       return HAL_DATASPACE_BT2020_PQ;
84     case ColorMode::BT2100_HLG:
85       return HAL_DATASPACE_BT2020_HLG;
86     case ColorMode::DISPLAY_BT2020:
87       return HAL_DATASPACE_DISPLAY_BT2020;
88     default:
89       return HAL_DATASPACE_UNKNOWN;
90   }
91 }
92 
UEventThread(HWCUEvent * hwc_uevent)93 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
94   const char *uevent_thread_name = "HWC_UeventThread";
95 
96   prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
97   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
98 
99   int status = uevent_init();
100   if (!status) {
101     std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
102     hwc_uevent->caller_cv_.notify_one();
103     DLOGE("Failed to init uevent with err %d", status);
104     return;
105   }
106 
107   {
108     // Signal caller thread that worker thread is ready to listen to events.
109     std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
110     hwc_uevent->init_done_ = true;
111     hwc_uevent->caller_cv_.notify_one();
112   }
113 
114   while (1) {
115     char uevent_data[PAGE_SIZE] = {};
116 
117     // keep last 2 zeros to ensure double 0 termination
118     int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
119 
120     // scope of lock to this block only, so that caller is free to set event handler to nullptr;
121     {
122       std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
123       if (hwc_uevent->uevent_listener_) {
124         hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
125       } else {
126         DLOGW("UEvent dropped. No uevent listener.");
127       }
128     }
129   }
130 }
131 
HWCUEvent()132 HWCUEvent::HWCUEvent() {
133   std::unique_lock<std::mutex> caller_lock(mutex_);
134   std::thread thread(HWCUEvent::UEventThread, this);
135   thread.detach();
136   caller_cv_.wait(caller_lock);
137 }
138 
Register(HWCUEventListener * uevent_listener)139 void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
140   DLOGI("Set uevent listener = %p", uevent_listener);
141 
142   std::lock_guard<std::mutex> obj(mutex_);
143   uevent_listener_ = uevent_listener;
144 }
145 
HWCSession()146 HWCSession::HWCSession() : cwb_(this) {}
147 
GetInstance()148 HWCSession *HWCSession::GetInstance() {
149   // executed only once for the very first call.
150   // GetInstance called multiple times from Composer and ComposerClient
151   static HWCSession *hwc_session = new HWCSession();
152   return hwc_session;
153 }
154 
Init()155 int HWCSession::Init() {
156   SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
157 
158   int status = -EINVAL;
159   const char *qservice_name = "display.qservice";
160 
161   if (!g_hwc_uevent_.InitDone()) {
162     return status;
163   }
164 
165 
166   // Start QService and connect to it.
167   qService::QService::init();
168   android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
169       android::defaultServiceManager()->getService(android::String16(qservice_name)));
170 
171   if (iqservice.get()) {
172     iqservice->connect(android::sp<qClient::IQClient>(this));
173     qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
174   } else {
175     DLOGE("Failed to acquire %s", qservice_name);
176     return -EINVAL;
177   }
178 
179   DisplayInit(this);
180 
181   HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
182   HWCDebugHandler::Get()->GetProperty(DISABLE_HOTPLUG_BWCHECK, &disable_hotplug_bwcheck_);
183   HWCDebugHandler::Get()->GetProperty(DISABLE_MASK_LAYER_HINT, &disable_mask_layer_hint_);
184   HWCDebugHandler::Get()->GetProperty(LBE_SUPPORTED, &is_lbe_supported_);
185 
186   if (!null_display_mode_) {
187     g_hwc_uevent_.Register(this);
188   }
189 
190   int value = 0;  // Default value when property is not present.
191   Debug::Get()->GetProperty(ENABLE_ASYNC_POWERMODE, &value);
192   async_powermode_ = (value == 1);
193   DLOGI("builtin_powermode_override: %d", async_powermode_);
194 
195   value = 0;
196   Debug::Get()->GetProperty(ENABLE_ASYNC_VDS_CREATION, &value);
197   async_vds_creation_ = (value == 1);
198   DLOGI("async_vds_creation: %d", async_vds_creation_);
199 
200   InitSupportedDisplaySlots();
201   // Create primary display here. Remaining builtin displays will be created after client has set
202   // display indexes which may happen sometime before callback is registered.
203   status = CreatePrimaryDisplay();
204   if (status) {
205     Deinit();
206     return status;
207   }
208 
209   is_composer_up_ = true;
210   StartServices();
211 
212   PostInit();
213 
214   return 0;
215 }
216 
PostInit()217 void HWCSession::PostInit() {
218   if (null_display_mode_) {
219     return;
220   }
221 
222   // Start services which need IDisplayConfig to be up.
223   // This avoids deadlock between composer and its clients.
224   auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
225   hwc_display->PostInit();
226 }
227 
Deinit()228 int HWCSession::Deinit() {
229   if (pps_socket_ >= 0)
230     close(pps_socket_);
231 
232   // Destroy all connected displays
233   DestroyDisplay(&map_info_primary_);
234 
235   for (auto &map_info : map_info_builtin_) {
236     DestroyDisplay(&map_info);
237   }
238 
239   for (auto &map_info : map_info_pluggable_) {
240     DestroyDisplay(&map_info);
241   }
242 
243   for (auto &map_info : map_info_virtual_) {
244     DestroyDisplay(&map_info);
245   }
246 
247   if (color_mgr_) {
248     color_mgr_->DestroyColorManager();
249   }
250 
251   if (!null_display_mode_) {
252     g_hwc_uevent_.Register(nullptr);
253 
254     DisplayError error = CoreInterface::DestroyCore();
255     if (error != kErrorNone) {
256       DLOGE("Display core de-initialization failed. Error = %d", error);
257     }
258   }
259 
260   return 0;
261 }
262 
InitSupportedDisplaySlots()263 void HWCSession::InitSupportedDisplaySlots() {
264   // Default slots:
265   //    Primary = 0, External = 1
266   //    Additional external displays 2,3,...max_pluggable_count.
267   //    Additional builtin displays max_pluggable_count + 1, max_pluggable_count + 2,...
268   //    Last slots for virtual displays.
269   // Virtual display id is only for SF <--> HWC communication.
270   // It need not align with hwccomposer_defs
271 
272   map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
273 
274   if (null_display_mode_) {
275     InitSupportedNullDisplaySlots();
276     return;
277   }
278 
279   DisplayError error = CoreInterface::CreateCore(&buffer_allocator_, nullptr,
280                                                  &socket_handler_, &core_intf_);
281   if (error != kErrorNone) {
282     DLOGE("Failed to create CoreInterface");
283     return;
284   }
285 
286   HWDisplayInterfaceInfo hw_disp_info = {};
287   error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
288   if (error != kErrorNone) {
289     CoreInterface::DestroyCore();
290     DLOGE("Primary display type not recognized. Error = %d", error);
291     return;
292   }
293 
294   int max_builtin = 0;
295   int max_pluggable = 0;
296   int max_virtual = 0;
297 
298   error = core_intf_->GetMaxDisplaysSupported(kBuiltIn, &max_builtin);
299   if (error != kErrorNone) {
300     CoreInterface::DestroyCore();
301     DLOGE("Could not find maximum built-in displays supported. Error = %d", error);
302     return;
303   }
304 
305   error = core_intf_->GetMaxDisplaysSupported(kPluggable, &max_pluggable);
306   if (error != kErrorNone) {
307     CoreInterface::DestroyCore();
308     DLOGE("Could not find maximum pluggable displays supported. Error = %d", error);
309     return;
310   }
311 
312   error = core_intf_->GetMaxDisplaysSupported(kVirtual, &max_virtual);
313   if (error != kErrorNone) {
314     CoreInterface::DestroyCore();
315     DLOGE("Could not find maximum virtual displays supported. Error = %d", error);
316     return;
317   }
318 
319   if (max_virtual == 0) {
320     // Check if WB using GPU is supported.
321     max_virtual += virtual_display_factory_.IsGPUColorConvertSupported() ? 1 : 0;
322   }
323 
324   if (kPluggable == hw_disp_info.type) {
325     // If primary is a pluggable display, we have already used one pluggable display interface.
326     max_pluggable--;
327   } else {
328     max_builtin--;
329   }
330 
331   // Init slots in accordance to h/w capability.
332   uint32_t disp_count = UINT32(std::min(max_pluggable, HWCCallbacks::kNumPluggable));
333   hwc2_display_t base_id = qdutils::DISPLAY_EXTERNAL;
334   map_info_pluggable_.resize(disp_count);
335   for (auto &map_info : map_info_pluggable_) {
336     map_info.client_id = base_id++;
337   }
338 
339   disp_count = UINT32(std::min(max_builtin, HWCCallbacks::kNumBuiltIn));
340   map_info_builtin_.resize(disp_count);
341   for (auto &map_info : map_info_builtin_) {
342     map_info.client_id = base_id++;
343   }
344 
345   disp_count = UINT32(std::min(max_virtual, HWCCallbacks::kNumVirtual));
346   map_info_virtual_.resize(disp_count);
347   for (auto &map_info : map_info_virtual_) {
348     map_info.client_id = base_id++;
349   }
350 
351   // resize HDR supported map to total number of displays.
352   is_hdr_display_.resize(UINT32(base_id));
353 
354   if (!async_powermode_) {
355     return;
356   }
357 
358   int start_index = HWCCallbacks::kNumRealDisplays;
359   std::vector<DisplayMapInfo> map_info = {map_info_primary_};
360   std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
361   std::copy(map_info_pluggable_.begin(), map_info_pluggable_.end(), std::back_inserter(map_info));
362   for (auto &map : map_info) {
363     DLOGI("Display Pairs: map.client_id: %d, start_index: %d", INT32(map.client_id),
364           INT32(start_index));
365     map_hwc_display_.insert(std::make_pair(map.client_id, start_index++));
366   }
367 }
368 
InitSupportedNullDisplaySlots()369 void HWCSession::InitSupportedNullDisplaySlots() {
370   if (!null_display_mode_) {
371     DLOGE("Should only be invoked during null display");
372     return;
373   }
374 
375   map_info_primary_.client_id = 0;
376   // Resize HDR supported map to total number of displays
377   is_hdr_display_.resize(1);
378 
379   if (!async_powermode_) {
380     return;
381   }
382 
383   DLOGI("Display Pairs: map.client_id: %d, start_index: %d", INT32(map_info_primary_.client_id),
384                                                              HWCCallbacks::kNumRealDisplays);
385   map_hwc_display_.insert(std::make_pair(map_info_primary_.client_id,
386                                          HWCCallbacks::kNumRealDisplays));
387 }
388 
GetDisplayIndex(int dpy)389 int HWCSession::GetDisplayIndex(int dpy) {
390   DisplayMapInfo *map_info = nullptr;
391   switch (dpy) {
392     case qdutils::DISPLAY_PRIMARY:
393       map_info = &map_info_primary_;
394       break;
395     case qdutils::DISPLAY_EXTERNAL:
396       map_info = map_info_pluggable_.size() ? &map_info_pluggable_[0] : nullptr;
397       break;
398     case qdutils::DISPLAY_EXTERNAL_2:
399       map_info = (map_info_pluggable_.size() > 1) ? &map_info_pluggable_[1] : nullptr;
400       break;
401     case qdutils::DISPLAY_VIRTUAL:
402       map_info = map_info_virtual_.size() ? &map_info_virtual_[0] : nullptr;
403       break;
404     case qdutils::DISPLAY_BUILTIN_2:
405       map_info = map_info_builtin_.size() ? &map_info_builtin_[0] : nullptr;
406       break;
407     default:
408       DLOGW("Unknown display %d.", dpy);
409       break;
410   }
411 
412   if (!map_info) {
413     DLOGE("Display index not found for display %d.", dpy);
414     return -1;
415   }
416 
417   return INT(map_info->client_id);
418 }
419 
GetCapabilities(uint32_t * outCount,int32_t * outCapabilities)420 void HWCSession::GetCapabilities(uint32_t *outCount, int32_t *outCapabilities) {
421   if (!outCount) {
422     return;
423   }
424 
425   int value = 0;
426   bool disable_skip_validate = false;
427   if (Debug::Get()->GetProperty(DISABLE_SKIP_VALIDATE_PROP, &value) == kErrorNone) {
428     disable_skip_validate = (value == 1);
429   }
430   uint32_t count = 1 + (disable_skip_validate ? 0 : 1);
431 
432   if (outCapabilities != nullptr && (*outCount >= count)) {
433     outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
434     if (!disable_skip_validate) {
435       outCapabilities[1] = HWC2_CAPABILITY_SKIP_VALIDATE;
436     }
437   }
438   *outCount = count;
439 }
440 
441 template <typename PFN, typename T>
AsFP(T function)442 static hwc2_function_pointer_t AsFP(T function) {
443   static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
444   return reinterpret_cast<hwc2_function_pointer_t>(function);
445 }
446 
447 // HWC2 functions returned in GetFunction
448 // Defined in the same order as in the HWC2 header
449 
AcceptDisplayChanges(hwc2_display_t display)450 int32_t HWCSession::AcceptDisplayChanges(hwc2_display_t display) {
451   return CallDisplayFunction(display, &HWCDisplay::AcceptDisplayChanges);
452 }
453 
CreateLayer(hwc2_display_t display,hwc2_layer_t * out_layer_id)454 int32_t HWCSession::CreateLayer(hwc2_display_t display,
455                                 hwc2_layer_t *out_layer_id) {
456   if (!out_layer_id) {
457     return  HWC2_ERROR_BAD_PARAMETER;
458   }
459 
460   return CallDisplayFunction(display, &HWCDisplay::CreateLayer, out_layer_id);
461 }
462 
CreateVirtualDisplay(uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)463 int32_t HWCSession::CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format,
464                                          hwc2_display_t *out_display_id) {
465   // TODO(user): Handle concurrency with HDMI
466 
467   if (!out_display_id || !width || !height || !format) {
468     return  HWC2_ERROR_BAD_PARAMETER;
469   }
470 
471   if (null_display_mode_) {
472     return 0;
473   }
474 
475   if (async_vds_creation_ && virtual_id_ != HWCCallbacks::kNumDisplays) {
476     *out_display_id = virtual_id_;
477     return HWC2_ERROR_NONE;
478   }
479 
480   auto status = CreateVirtualDisplayObj(width, height, format, out_display_id);
481   if (status == HWC2::Error::None) {
482     DLOGI("Created virtual display id:%" PRIu64 ", res: %dx%d", *out_display_id, width, height);
483   } else {
484     DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
485   }
486   return INT32(status);
487 }
488 
DestroyLayer(hwc2_display_t display,hwc2_layer_t layer)489 int32_t HWCSession::DestroyLayer(hwc2_display_t display, hwc2_layer_t layer) {
490   return CallDisplayFunction(display, &HWCDisplay::DestroyLayer, layer);
491 }
492 
DestroyVirtualDisplay(hwc2_display_t display)493 int32_t HWCSession::DestroyVirtualDisplay(hwc2_display_t display) {
494   if (display >= HWCCallbacks::kNumDisplays) {
495     return HWC2_ERROR_BAD_DISPLAY;
496   }
497 
498   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
499 
500   if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
501     Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
502     std::bitset<kSecureMax> secure_sessions = 0;
503     hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
504     if (secure_sessions.any()) {
505       DLOGW("Secure session is active, defer destruction of virtual display id:%" PRIu64, display);
506       destroy_virtual_disp_pending_ = true;
507       return HWC2_ERROR_NONE;
508     }
509   }
510 
511   for (auto &map_info : map_info_virtual_) {
512     if (map_info.client_id == display) {
513       DLOGI("Destroying virtual display id:%" PRIu64, display);
514       DestroyDisplay(&map_info);
515       break;
516     }
517   }
518   virtual_id_ = HWCCallbacks::kNumDisplays;
519 
520   return HWC2_ERROR_NONE;
521 }
522 
GetVirtualDisplayId()523 int32_t HWCSession::GetVirtualDisplayId() {
524   HWDisplaysInfo hw_displays_info = {};
525   core_intf_->GetDisplaysStatus(&hw_displays_info);
526   for (auto &iter : hw_displays_info) {
527     auto &info = iter.second;
528     if (info.display_type != kVirtual) {
529       continue;
530     }
531 
532     return info.display_id;
533   }
534 
535   return -1;
536 }
537 
Dump(uint32_t * out_size,char * out_buffer)538 void HWCSession::Dump(uint32_t *out_size, char *out_buffer) {
539   if (!out_size) {
540     return;
541   }
542 
543   const size_t max_dump_size = 16384;  // 16 kB
544 
545   if (out_buffer == nullptr) {
546     *out_size = max_dump_size;
547   } else {
548     std::ostringstream os;
549     for (int id = 0; id < HWCCallbacks::kNumRealDisplays; id++) {
550       SCOPE_LOCK(locker_[id]);
551       if (hwc_display_[id]) {
552         hwc_display_[id]->Dump(&os);
553       }
554     }
555     Fence::Dump(&os);
556 
557     std::string s = os.str();
558     auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
559     *out_size = UINT32(copied);
560   }
561 }
562 
GetMaxVirtualDisplayCount()563 uint32_t HWCSession::GetMaxVirtualDisplayCount() {
564   return map_info_virtual_.size();
565 }
566 
GetActiveConfig(hwc2_display_t display,hwc2_config_t * out_config)567 int32_t HWCSession::GetActiveConfig(hwc2_display_t display, hwc2_config_t *out_config) {
568   return CallDisplayFunction(display, &HWCDisplay::GetActiveConfig, out_config);
569 }
570 
GetChangedCompositionTypes(hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_types)571 int32_t HWCSession::GetChangedCompositionTypes(hwc2_display_t display, uint32_t *out_num_elements,
572                                                hwc2_layer_t *out_layers, int32_t *out_types) {
573   // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
574   if (!out_num_elements) {
575     return  HWC2_ERROR_BAD_PARAMETER;
576   }
577   return CallDisplayFunction(display, &HWCDisplay::GetChangedCompositionTypes, out_num_elements,
578                              out_layers, out_types);
579 }
580 
GetClientTargetSupport(hwc2_display_t display,uint32_t width,uint32_t height,int32_t format,int32_t dataspace)581 int32_t HWCSession::GetClientTargetSupport(hwc2_display_t display, uint32_t width, uint32_t height,
582                                            int32_t format, int32_t dataspace) {
583   return CallDisplayFunction(display, &HWCDisplay::GetClientTargetSupport, width, height, format,
584                              dataspace);
585 }
586 
GetColorModes(hwc2_display_t display,uint32_t * out_num_modes,int32_t * int_out_modes)587 int32_t HWCSession::GetColorModes(hwc2_display_t display, uint32_t *out_num_modes,
588                                   int32_t /*ColorMode*/ *int_out_modes) {
589   auto out_modes = reinterpret_cast<ColorMode *>(int_out_modes);
590   if (out_num_modes == nullptr) {
591     return HWC2_ERROR_BAD_PARAMETER;
592   }
593   return CallDisplayFunction(display, &HWCDisplay::GetColorModes, out_num_modes, out_modes);
594 }
595 
GetRenderIntents(hwc2_display_t display,int32_t int_mode,uint32_t * out_num_intents,int32_t * int_out_intents)596 int32_t HWCSession::GetRenderIntents(hwc2_display_t display, int32_t /*ColorMode*/ int_mode,
597                                      uint32_t *out_num_intents,
598                                      int32_t /*RenderIntent*/ *int_out_intents) {
599   auto mode = static_cast<ColorMode>(int_mode);
600   auto out_intents = reinterpret_cast<RenderIntent *>(int_out_intents);
601   if (out_num_intents == nullptr) {
602     return HWC2_ERROR_BAD_PARAMETER;
603   }
604 
605   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
606     DLOGE("Invalid ColorMode: %d", mode);
607     return HWC2_ERROR_BAD_PARAMETER;
608   }
609   return CallDisplayFunction(display, &HWCDisplay::GetRenderIntents, mode, out_num_intents,
610                              out_intents);
611 }
612 
GetDataspaceSaturationMatrix(int32_t int_dataspace,float * out_matrix)613 int32_t HWCSession::GetDataspaceSaturationMatrix(int32_t /*Dataspace*/ int_dataspace,
614                                                  float *out_matrix) {
615   auto dataspace = static_cast<Dataspace>(int_dataspace);
616   if (out_matrix == nullptr || dataspace != Dataspace::SRGB_LINEAR) {
617     return HWC2_ERROR_BAD_PARAMETER;
618   }
619   // We only have the matrix for sRGB
620   float saturation_matrix[kDataspaceSaturationMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
621                                                                0.0, 1.0, 0.0, 0.0, \
622                                                                0.0, 0.0, 1.0, 0.0, \
623                                                                0.0, 0.0, 0.0, 1.0 };
624 
625   for (int32_t i = 0; i < kDataspaceSaturationMatrixCount; i += 4) {
626     DLOGD("%f %f %f %f", saturation_matrix[i], saturation_matrix[i + 1], saturation_matrix[i + 2],
627           saturation_matrix[i + 3]);
628   }
629   for (uint32_t i = 0; i < kDataspaceSaturationMatrixCount; i++) {
630     out_matrix[i] = saturation_matrix[i];
631   }
632   return HWC2_ERROR_NONE;
633 }
634 
GetPerFrameMetadataKeys(hwc2_display_t display,uint32_t * out_num_keys,int32_t * int_out_keys)635 int32_t HWCSession::GetPerFrameMetadataKeys(hwc2_display_t display, uint32_t *out_num_keys,
636                                             int32_t *int_out_keys) {
637   auto out_keys = reinterpret_cast<PerFrameMetadataKey *>(int_out_keys);
638   return CallDisplayFunction(display, &HWCDisplay::GetPerFrameMetadataKeys, out_num_keys,
639                              out_keys);
640 }
641 
SetLayerPerFrameMetadata(hwc2_display_t display,hwc2_layer_t layer,uint32_t num_elements,const int32_t * int_keys,const float * metadata)642 int32_t HWCSession::SetLayerPerFrameMetadata(hwc2_display_t display, hwc2_layer_t layer,
643                                              uint32_t num_elements, const int32_t *int_keys,
644                                              const float *metadata) {
645   auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
646   return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadata, num_elements,
647                            keys, metadata);
648 }
649 
SetLayerPerFrameMetadataBlobs(hwc2_display_t display,hwc2_layer_t layer,uint32_t num_elements,const int32_t * int_keys,const uint32_t * sizes,const uint8_t * metadata)650 int32_t HWCSession:: SetLayerPerFrameMetadataBlobs(hwc2_display_t display,
651                                                    hwc2_layer_t layer, uint32_t num_elements,
652                                                    const int32_t *int_keys, const uint32_t *sizes,
653                                                    const uint8_t *metadata) {
654   auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
655   return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadataBlobs,
656                            num_elements, keys, sizes, metadata);
657 }
658 
SetDisplayedContentSamplingEnabled(hwc2_display_t display,int32_t enabled,uint8_t component_mask,uint64_t max_frames)659 int32_t HWCSession::SetDisplayedContentSamplingEnabled(hwc2_display_t display, int32_t enabled,
660                                                        uint8_t component_mask,
661                                                        uint64_t max_frames) {
662   static constexpr int32_t validComponentMask = HWC2_FORMAT_COMPONENT_0 | HWC2_FORMAT_COMPONENT_1 |
663                                                 HWC2_FORMAT_COMPONENT_2 | HWC2_FORMAT_COMPONENT_3;
664   if (component_mask & ~validComponentMask)
665     return HWC2_ERROR_BAD_PARAMETER;
666   return CallDisplayFunction(display, &HWCDisplay::SetDisplayedContentSamplingEnabled, enabled,
667                              component_mask, max_frames);
668 }
669 
GetDisplayedContentSamplingAttributes(hwc2_display_t display,int32_t * format,int32_t * dataspace,uint8_t * supported_components)670 int32_t HWCSession::GetDisplayedContentSamplingAttributes(hwc2_display_t display, int32_t *format,
671                                                           int32_t *dataspace,
672                                                           uint8_t *supported_components) {
673   return CallDisplayFunction(display, &HWCDisplay::GetDisplayedContentSamplingAttributes, format,
674                              dataspace, supported_components);
675 }
676 
GetDisplayedContentSample(hwc2_display_t display,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])677 int32_t HWCSession::GetDisplayedContentSample(hwc2_display_t display, uint64_t max_frames,
678                                               uint64_t timestamp, uint64_t *numFrames,
679                                               int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
680                                               uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
681   return CallDisplayFunction(display, &HWCDisplay::GetDisplayedContentSample, max_frames, timestamp,
682                              numFrames, samples_size, samples);
683 }
684 
GetDisplayAttribute(hwc2_display_t display,hwc2_config_t config,HwcAttribute attribute,int32_t * out_value)685 int32_t HWCSession::GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
686                                         HwcAttribute attribute, int32_t *out_value) {
687   if (out_value == nullptr) {
688     return HWC2_ERROR_BAD_PARAMETER;
689   }
690   return CallDisplayFunction(display, &HWCDisplay::GetDisplayAttribute, config, attribute,
691                              out_value);
692 }
693 
GetDisplayConfigs(hwc2_display_t display,uint32_t * out_num_configs,hwc2_config_t * out_configs)694 int32_t HWCSession::GetDisplayConfigs(hwc2_display_t display, uint32_t *out_num_configs,
695                                       hwc2_config_t *out_configs) {
696   return CallDisplayFunction(display, &HWCDisplay::GetDisplayConfigs, out_num_configs,
697                              out_configs);
698 }
699 
GetDisplayName(hwc2_display_t display,uint32_t * out_size,char * out_name)700 int32_t HWCSession::GetDisplayName(hwc2_display_t display, uint32_t *out_size, char *out_name) {
701   return CallDisplayFunction(display, &HWCDisplay::GetDisplayName, out_size, out_name);
702 }
703 
GetDisplayRequests(hwc2_display_t display,int32_t * out_display_requests,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_layer_requests)704 int32_t HWCSession::GetDisplayRequests(hwc2_display_t display, int32_t *out_display_requests,
705                                        uint32_t *out_num_elements, hwc2_layer_t *out_layers,
706                                        int32_t *out_layer_requests) {
707   return CallDisplayFunction(display, &HWCDisplay::GetDisplayRequests, out_display_requests,
708                              out_num_elements, out_layers, out_layer_requests);
709 }
710 
GetDisplayType(hwc2_display_t display,int32_t * out_type)711 int32_t HWCSession::GetDisplayType(hwc2_display_t display, int32_t *out_type) {
712   return CallDisplayFunction(display, &HWCDisplay::GetDisplayType, out_type);
713 }
714 
715 
GetHdrCapabilities(hwc2_display_t display,uint32_t * out_num_types,int32_t * out_types,float * out_max_luminance,float * out_max_average_luminance,float * out_min_luminance)716 int32_t HWCSession::GetHdrCapabilities(hwc2_display_t display, uint32_t* out_num_types,
717                                        int32_t* out_types, float* out_max_luminance,
718                                        float* out_max_average_luminance,
719                                        float* out_min_luminance) {
720   return CallDisplayFunction(display, &HWCDisplay::GetHdrCapabilities, out_num_types, out_types,
721                              out_max_luminance, out_max_average_luminance, out_min_luminance);
722 }
723 
724 
GetReleaseFences(hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,std::vector<shared_ptr<Fence>> * out_fences)725 int32_t HWCSession::GetReleaseFences(hwc2_display_t display, uint32_t *out_num_elements,
726                                      hwc2_layer_t *out_layers,
727                                      std::vector<shared_ptr<Fence>> *out_fences) {
728   return CallDisplayFunction(display, &HWCDisplay::GetReleaseFences, out_num_elements, out_layers,
729                              out_fences);
730 }
731 
PerformQsyncCallback(hwc2_display_t display)732 void HWCSession::PerformQsyncCallback(hwc2_display_t display) {
733   std::shared_ptr<DisplayConfig::ConfigCallback> callback = qsync_callback_.lock();
734   if (!callback) {
735     return;
736   }
737 
738   bool qsync_enabled = 0;
739   int32_t refresh_rate = 0, qsync_refresh_rate = 0;
740   if (hwc_display_[display]->IsQsyncCallbackNeeded(&qsync_enabled,
741       &refresh_rate, &qsync_refresh_rate)) {
742     callback->NotifyQsyncChange(qsync_enabled, refresh_rate, qsync_refresh_rate);
743   }
744 }
745 
PerformIdleStatusCallback(hwc2_display_t display)746 void HWCSession::PerformIdleStatusCallback(hwc2_display_t display) {
747   std::shared_ptr<DisplayConfig::ConfigCallback> callback = idle_callback_.lock();
748   if (!callback) {
749     return;
750   }
751 
752   if (hwc_display_[display]->IsDisplayIdle()) {
753     DTRACE_SCOPED();
754     callback->NotifyIdleStatus(true);
755   }
756 }
757 
PresentDisplay(hwc2_display_t display,shared_ptr<Fence> * out_retire_fence)758 int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *out_retire_fence) {
759   auto status = HWC2::Error::BadDisplay;
760   DTRACE_SCOPED();
761 
762   SCOPE_LOCK(system_locker_);
763   if (display >= HWCCallbacks::kNumDisplays) {
764     DLOGW("Invalid Display : display = %" PRIu64, display);
765     return HWC2_ERROR_BAD_DISPLAY;
766   }
767 
768   HandleSecureSession();
769 
770 
771   hwc2_display_t target_display = display;
772 
773   {
774     SCOPE_LOCK(power_state_[display]);
775     if (power_state_transition_[display]) {
776       // Route all interactions with client to dummy display.
777       target_display = map_hwc_display_.find(display)->second;
778     }
779   }
780 
781   {
782     SEQUENCE_EXIT_SCOPE_LOCK(locker_[target_display]);
783     if (!hwc_display_[target_display]) {
784       DLOGW("Removed Display : display = %" PRIu64, target_display);
785       return HWC2_ERROR_BAD_DISPLAY;
786     }
787 
788     if (out_retire_fence == nullptr) {
789       return HWC2_ERROR_BAD_PARAMETER;
790     }
791 
792     if (pending_power_mode_[display]) {
793       status = HWC2::Error::None;
794     } else {
795       hwc_display_[target_display]->ProcessActiveConfigChange();
796       status = PresentDisplayInternal(target_display);
797       if (status == HWC2::Error::None) {
798         // Check if hwc's refresh trigger is getting exercised.
799         if (callbacks_.NeedsRefresh(display)) {
800           hwc_display_[target_display]->SetPendingRefresh();
801           callbacks_.ResetRefresh(display);
802         }
803         status = hwc_display_[target_display]->Present(out_retire_fence);
804         if (status == HWC2::Error::None) {
805           PerformQsyncCallback(target_display);
806           PerformIdleStatusCallback(target_display);
807         }
808       }
809     }
810   }
811 
812   if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
813     SEQUENCE_CANCEL_SCOPE_LOCK(locker_[target_display]);
814   }
815 
816   HandlePendingPowerMode(display, *out_retire_fence);
817   HandlePendingHotplug(display, *out_retire_fence);
818   HandlePendingRefresh();
819   if (status != HWC2::Error::NotValidated) {
820     cwb_.PresentDisplayDone(display);
821   }
822   display_ready_.set(UINT32(display));
823   {
824     std::unique_lock<std::mutex> caller_lock(hotplug_mutex_);
825     hotplug_cv_.notify_one();
826   }
827 
828   return INT32(status);
829 }
830 
HandlePendingRefresh()831 void HWCSession::HandlePendingRefresh() {
832   if (pending_refresh_.none()) {
833     return;
834   }
835 
836   for (size_t i = 0; i < pending_refresh_.size(); i++) {
837     if (pending_refresh_.test(i)) {
838       callbacks_.Refresh(i);
839       break;
840     }
841   }
842 
843   pending_refresh_.reset();
844 }
845 
RegisterCallback(int32_t descriptor,hwc2_callback_data_t callback_data,hwc2_function_pointer_t pointer)846 void HWCSession::RegisterCallback(int32_t descriptor, hwc2_callback_data_t callback_data,
847                                   hwc2_function_pointer_t pointer) {
848   auto desc = static_cast<HWC2::Callback>(descriptor);
849 
850   // Detect if client died and now is back
851   bool already_connected = false;
852   vector<hwc2_display_t> pending_hotplugs;
853   if (descriptor == HWC2_CALLBACK_HOTPLUG && pointer) {
854     already_connected = callbacks_.IsClientConnected();
855     if (already_connected) {
856       for (auto& map_info : map_info_builtin_) {
857         SCOPE_LOCK(locker_[map_info.client_id]);
858         if (hwc_display_[map_info.client_id]) {
859           pending_hotplugs.push_back(static_cast<hwc2_display_t>(map_info.client_id));
860         }
861       }
862       for (auto& map_info : map_info_pluggable_) {
863         SCOPE_LOCK(locker_[map_info.client_id]);
864         if (hwc_display_[map_info.client_id]) {
865           pending_hotplugs.push_back(static_cast<hwc2_display_t>(map_info.client_id));
866         }
867       }
868     }
869   }
870 
871   auto error = callbacks_.Register(desc, callback_data, pointer);
872   if (error != HWC2::Error::None) {
873     return;
874   }
875 
876   DLOGI("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
877   if (descriptor == HWC2_CALLBACK_HOTPLUG && pointer) {
878     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
879       DLOGI("Hotplugging primary...");
880       callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
881     }
882     // Create displays since they should now have their final display indices set.
883     DLOGI("Handling built-in displays...");
884     if (HandleBuiltInDisplays()) {
885       DLOGW("Failed handling built-in displays.");
886     }
887     DLOGI("Handling pluggable displays...");
888     int32_t err = HandlePluggableDisplays(false);
889     if (err) {
890       DLOGW("All displays could not be created. Error %d '%s'. Hotplug handling %s.", err,
891             strerror(abs(err)), pending_hotplug_event_ == kHotPlugEvent ? "deferred" :
892             "dropped");
893     }
894 
895     // If previously registered, call hotplug for all connected displays to refresh
896     if (already_connected) {
897       std::vector<hwc2_display_t> updated_pending_hotplugs;
898       for (auto client_id : pending_hotplugs) {
899         SCOPE_LOCK(locker_[client_id]);
900         // check if the display is unregistered
901         if (hwc_display_[client_id]) {
902           updated_pending_hotplugs.push_back(client_id);
903         }
904       }
905       for (auto client_id : updated_pending_hotplugs) {
906         DLOGI("Re-hotplug display connected: client id = %d", UINT32(client_id));
907         callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
908       }
909     }
910   }
911 
912   if (descriptor == HWC2_CALLBACK_HOTPLUG) {
913     client_connected_ = !!pointer;
914     // Notfify all displays.
915     NotifyClientStatus(client_connected_);
916   }
917   need_invalidate_ = false;
918 }
919 
SetActiveConfig(hwc2_display_t display,hwc2_config_t config)920 int32_t HWCSession::SetActiveConfig(hwc2_display_t display, hwc2_config_t config) {
921   return CallDisplayFunction(display, &HWCDisplay::SetActiveConfig, config);
922 }
923 
SetClientTarget(hwc2_display_t display,buffer_handle_t target,const shared_ptr<Fence> acquire_fence,int32_t dataspace,hwc_region_t damage)924 int32_t HWCSession::SetClientTarget(hwc2_display_t display, buffer_handle_t target,
925                                     const shared_ptr<Fence> acquire_fence, int32_t dataspace,
926                                     hwc_region_t damage) {
927   return CallDisplayFunction(display, &HWCDisplay::SetClientTarget, target, acquire_fence,
928                              dataspace, damage);
929 }
930 
SetColorMode(hwc2_display_t display,int32_t int_mode)931 int32_t HWCSession::SetColorMode(hwc2_display_t display, int32_t /*ColorMode*/ int_mode) {
932   auto mode = static_cast<ColorMode>(int_mode);
933   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
934     return HWC2_ERROR_BAD_PARAMETER;
935   }
936   return CallDisplayFunction(display, &HWCDisplay::SetColorMode, mode);
937 }
938 
SetColorModeWithRenderIntent(hwc2_display_t display,int32_t int_mode,int32_t int_render_intent)939 int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_display_t display,
940                                                  int32_t /*ColorMode*/ int_mode,
941                                                  int32_t /*RenderIntent*/ int_render_intent) {
942   auto mode = static_cast<ColorMode>(int_mode);
943   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
944     return HWC2_ERROR_BAD_PARAMETER;
945   }
946 
947   if ((int_render_intent < 0) || (int_render_intent > MAX_EXTENDED_RENDER_INTENT)) {
948     DLOGE("Invalid RenderIntent: %d", int_render_intent);
949     return HWC2_ERROR_BAD_PARAMETER;
950   }
951 
952   auto render_intent = static_cast<RenderIntent>(int_render_intent);
953   return CallDisplayFunction(display, &HWCDisplay::SetColorModeWithRenderIntent, mode,
954                              render_intent);
955 }
956 
SetColorTransform(hwc2_display_t display,const float * matrix,int32_t hint)957 int32_t HWCSession::SetColorTransform(hwc2_display_t display, const float *matrix,
958                                       int32_t /*android_color_transform_t*/ hint) {
959   if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
960        hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
961     return HWC2_ERROR_BAD_PARAMETER;
962   }
963   android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
964   return CallDisplayFunction(display, &HWCDisplay::SetColorTransform, matrix, transform_hint);
965 }
966 
SetCursorPosition(hwc2_display_t display,hwc2_layer_t layer,int32_t x,int32_t y)967 int32_t HWCSession::SetCursorPosition(hwc2_display_t display, hwc2_layer_t layer, int32_t x,
968                                       int32_t y) {
969   auto status = INT32(HWC2::Error::None);
970   status = CallDisplayFunction(display, &HWCDisplay::SetCursorPosition, layer, x, y);
971   if (status == INT32(HWC2::Error::None)) {
972     // Update cursor position
973     CallLayerFunction(display, layer, &HWCLayer::SetCursorPosition, x, y);
974   }
975   return status;
976 }
977 
SetLayerBlendMode(hwc2_display_t display,hwc2_layer_t layer,int32_t int_mode)978 int32_t HWCSession::SetLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
979                                       int32_t int_mode) {
980   if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
981     return HWC2_ERROR_BAD_PARAMETER;
982   }
983   auto mode = static_cast<HWC2::BlendMode>(int_mode);
984   return CallLayerFunction(display, layer, &HWCLayer::SetLayerBlendMode, mode);
985 }
986 
SetLayerBuffer(hwc2_display_t display,hwc2_layer_t layer,buffer_handle_t buffer,const shared_ptr<Fence> & acquire_fence)987 int32_t HWCSession::SetLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
988                                    buffer_handle_t buffer,
989                                    const shared_ptr<Fence> &acquire_fence) {
990   return CallLayerFunction(display, layer, &HWCLayer::SetLayerBuffer, buffer, acquire_fence);
991 }
992 
SetLayerColor(hwc2_display_t display,hwc2_layer_t layer,hwc_color_t color)993 int32_t HWCSession::SetLayerColor(hwc2_display_t display, hwc2_layer_t layer, hwc_color_t color) {
994   return CallLayerFunction(display, layer, &HWCLayer::SetLayerColor, color);
995 }
996 
SetLayerCompositionType(hwc2_display_t display,hwc2_layer_t layer,int32_t int_type)997 int32_t HWCSession::SetLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
998                                             int32_t int_type) {
999   auto type = static_cast<HWC2::Composition>(int_type);
1000   return CallLayerFunction(display, layer, &HWCLayer::SetLayerCompositionType, type);
1001 }
1002 
SetLayerDataspace(hwc2_display_t display,hwc2_layer_t layer,int32_t dataspace)1003 int32_t HWCSession::SetLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
1004                                       int32_t dataspace) {
1005   return CallLayerFunction(display, layer, &HWCLayer::SetLayerDataspace, dataspace);
1006 }
1007 
SetLayerDisplayFrame(hwc2_display_t display,hwc2_layer_t layer,hwc_rect_t frame)1008 int32_t HWCSession::SetLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
1009                                          hwc_rect_t frame) {
1010   return CallLayerFunction(display, layer, &HWCLayer::SetLayerDisplayFrame, frame);
1011 }
1012 
SetLayerPlaneAlpha(hwc2_display_t display,hwc2_layer_t layer,float alpha)1013 int32_t HWCSession::SetLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer, float alpha) {
1014   return CallLayerFunction(display, layer, &HWCLayer::SetLayerPlaneAlpha, alpha);
1015 }
1016 
SetLayerSourceCrop(hwc2_display_t display,hwc2_layer_t layer,hwc_frect_t crop)1017 int32_t HWCSession::SetLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
1018                                        hwc_frect_t crop) {
1019   return HWCSession::CallLayerFunction(display, layer, &HWCLayer::SetLayerSourceCrop, crop);
1020 }
1021 
SetLayerSurfaceDamage(hwc2_display_t display,hwc2_layer_t layer,hwc_region_t damage)1022 int32_t HWCSession::SetLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
1023                                           hwc_region_t damage) {
1024   return CallLayerFunction(display, layer, &HWCLayer::SetLayerSurfaceDamage, damage);
1025 }
1026 
SetLayerTransform(hwc2_display_t display,hwc2_layer_t layer,int32_t int_transform)1027 int32_t HWCSession::SetLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
1028                                       int32_t int_transform) {
1029   auto transform = static_cast<HWC2::Transform>(int_transform);
1030   return CallLayerFunction(display, layer, &HWCLayer::SetLayerTransform, transform);
1031 }
1032 
SetLayerVisibleRegion(hwc2_display_t display,hwc2_layer_t layer,hwc_region_t visible)1033 int32_t HWCSession::SetLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
1034                                           hwc_region_t visible) {
1035   return CallLayerFunction(display, layer, &HWCLayer::SetLayerVisibleRegion, visible);
1036 }
1037 
SetLayerZOrder(hwc2_display_t display,hwc2_layer_t layer,uint32_t z)1038 int32_t HWCSession::SetLayerZOrder(hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
1039   return CallDisplayFunction(display, &HWCDisplay::SetLayerZOrder, layer, z);
1040 }
1041 
SetLayerType(hwc2_display_t display,hwc2_layer_t layer,IQtiComposerClient::LayerType type)1042 int32_t HWCSession::SetLayerType(hwc2_display_t display, hwc2_layer_t layer,
1043                                  IQtiComposerClient::LayerType type) {
1044   return CallDisplayFunction(display, &HWCDisplay::SetLayerType, layer, type);
1045 }
1046 
SetLayerColorTransform(hwc2_display_t display,hwc2_layer_t layer,const float * matrix)1047 int32_t HWCSession::SetLayerColorTransform(hwc2_display_t display, hwc2_layer_t layer,
1048                                            const float *matrix) {
1049   return CallLayerFunction(display, layer, &HWCLayer::SetLayerColorTransform, matrix);
1050 }
1051 
SetDisplayElapseTime(hwc2_display_t display,uint64_t time)1052 int32_t HWCSession::SetDisplayElapseTime(hwc2_display_t display, uint64_t time) {
1053   return CallDisplayFunction(display, &HWCDisplay::SetDisplayElapseTime, time);
1054 }
1055 
SetOutputBuffer(hwc2_display_t display,buffer_handle_t buffer,const shared_ptr<Fence> & release_fence)1056 int32_t HWCSession::SetOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
1057                                     const shared_ptr<Fence> &release_fence) {
1058   if (INT32(display) != GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
1059     return HWC2_ERROR_UNSUPPORTED;
1060   }
1061 
1062   SCOPE_LOCK(locker_[display]);
1063   if (hwc_display_[display]) {
1064     auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_display_[display]);
1065     auto status = vds->SetOutputBuffer(buffer, release_fence);
1066     return INT32(status);
1067   } else {
1068     return HWC2_ERROR_BAD_DISPLAY;
1069   }
1070 }
1071 
SetPowerMode(hwc2_display_t display,int32_t int_mode)1072 int32_t HWCSession::SetPowerMode(hwc2_display_t display, int32_t int_mode) {
1073   if (display >= HWCCallbacks::kNumDisplays) {
1074     return HWC2_ERROR_BAD_DISPLAY;
1075   }
1076 
1077   //  validate device and also avoid undefined behavior in cast to HWC2::PowerMode
1078   if (int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
1079     return HWC2_ERROR_BAD_PARAMETER;
1080   }
1081 
1082   auto mode = static_cast<HWC2::PowerMode>(int_mode);
1083 
1084   // When secure session going on primary, if power request comes on second built-in, cache it and
1085   // process once secure session ends.
1086   // Allow power off transition during secure session.
1087   bool is_builtin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
1088   bool is_power_off = (hwc_display_[display]->GetCurrentPowerMode() == HWC2::PowerMode::Off);
1089   if (secure_session_active_ && is_builtin && is_power_off) {
1090     if (GetActiveBuiltinDisplay() != HWCCallbacks::kNumDisplays) {
1091       DLOGI("Secure session in progress, defer power state change");
1092       hwc_display_[display]->SetPendingPowerMode(mode);
1093       return HWC2_ERROR_NONE;
1094     }
1095   }
1096 
1097   if (pending_power_mode_[display]) {
1098     DLOGW("Set power mode is not allowed during secure display session");
1099     return HWC2_ERROR_UNSUPPORTED;
1100   }
1101 
1102   //  all displays support on/off. Check for doze modes
1103   int support = 0;
1104   auto status = GetDozeSupport(display, &support);
1105   if (status != HWC2_ERROR_NONE) {
1106     DLOGE("Failed to get doze support Error = %d", status);
1107     return INT32(status);
1108   }
1109 
1110   if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
1111     return HWC2_ERROR_UNSUPPORTED;
1112   }
1113 
1114   // async_powermode supported for power on and off
1115   bool override_mode = async_powermode_ && display_ready_.test(UINT32(display)) &&
1116                        async_power_mode_triggered_;
1117   HWC2::PowerMode last_power_mode = hwc_display_[display]->GetCurrentPowerMode();
1118 
1119   if (last_power_mode == mode) {
1120     return HWC2_ERROR_NONE;
1121   }
1122 
1123   if (!((last_power_mode == HWC2::PowerMode::Off && mode == HWC2::PowerMode::On) ||
1124      (last_power_mode == HWC2::PowerMode::On && mode == HWC2::PowerMode::Off))) {
1125     override_mode = false;
1126   }
1127 
1128   if (!override_mode) {
1129     auto error = CallDisplayFunction(display, &HWCDisplay::SetPowerMode, mode,
1130                                      false /* teardown */);
1131     if (INT32(error) != HWC2_ERROR_NONE) {
1132       return INT32(error);
1133     }
1134   } else {
1135     Locker::ScopeLock lock_disp(locker_[display]);
1136     // Update hwc state for now. Actual poweron will handled through DisplayConfig.
1137     hwc_display_[display]->UpdatePowerMode(mode);
1138   }
1139   // Reset idle pc ref count on suspend, as we enable idle pc during suspend.
1140   if (mode == HWC2::PowerMode::Off) {
1141     idle_pc_ref_cnt_ = 0;
1142   }
1143 
1144 
1145   UpdateThrottlingRate();
1146 
1147   if (mode == HWC2::PowerMode::Doze) {
1148     // Trigger one more refresh for PP features to take effect.
1149     pending_refresh_.set(UINT32(display));
1150   }
1151 
1152   return HWC2_ERROR_NONE;
1153 }
1154 
SetVsyncEnabled(hwc2_display_t display,int32_t int_enabled)1155 int32_t HWCSession::SetVsyncEnabled(hwc2_display_t display, int32_t int_enabled) {
1156   //  avoid undefined behavior in cast to HWC2::Vsync
1157   if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
1158     return HWC2_ERROR_BAD_PARAMETER;
1159   }
1160 
1161   auto enabled = static_cast<HWC2::Vsync>(int_enabled);
1162 
1163   if (int_enabled == HWC2_VSYNC_ENABLE) {
1164     callbacks_.UpdateVsyncSource(display);
1165   }
1166 
1167   return CallDisplayFunction(display, &HWCDisplay::SetVsyncEnabled, enabled);
1168 }
1169 
GetDozeSupport(hwc2_display_t display,int32_t * out_support)1170 int32_t HWCSession::GetDozeSupport(hwc2_display_t display, int32_t *out_support) {
1171   if (!out_support) {
1172     return HWC2_ERROR_BAD_PARAMETER;
1173   }
1174 
1175   if (display >= HWCCallbacks::kNumDisplays || (hwc_display_[display] == nullptr)) {
1176     // display may come as -1  from VTS test case
1177     DLOGE("Invalid Display %d ", UINT32(display));
1178     return HWC2_ERROR_BAD_DISPLAY;
1179   }
1180 
1181   *out_support = 0;
1182 
1183   SCOPE_LOCK(locker_[display]);
1184   if (!hwc_display_[display]) {
1185     DLOGE("Display %d is not created yet.", INT32(display));
1186     return HWC2_ERROR_BAD_DISPLAY;
1187   }
1188 
1189   if (hwc_display_[display]->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) {
1190     return HWC2_ERROR_NONE;
1191   }
1192 
1193   *out_support = hwc_display_[display]->HasSmartPanelConfig() ? 1 : 0;
1194 
1195   return HWC2_ERROR_NONE;
1196 }
1197 
isSmartPanelConfig(uint32_t disp_id,uint32_t config_id)1198 bool HWCSession::isSmartPanelConfig(uint32_t disp_id, uint32_t config_id) {
1199   if (disp_id != qdutils::DISPLAY_PRIMARY) {
1200     return false;
1201   }
1202 
1203   SCOPE_LOCK(locker_[disp_id]);
1204   if (!hwc_display_[disp_id]) {
1205     DLOGE("Display %d is not created yet.", disp_id);
1206     return false;
1207   }
1208 
1209   return hwc_display_[disp_id]->IsSmartPanelConfig(config_id);
1210 }
1211 
ValidateDisplay(hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)1212 int32_t HWCSession::ValidateDisplay(hwc2_display_t display, uint32_t *out_num_types,
1213                                     uint32_t *out_num_requests) {
1214   //  out_num_types and out_num_requests will be non-NULL
1215 
1216   if (display >= HWCCallbacks::kNumDisplays) {
1217     return HWC2_ERROR_BAD_DISPLAY;
1218   }
1219 
1220   hwc2_display_t target_display = display;
1221 
1222   {
1223     SCOPE_LOCK(power_state_[display]);
1224     if (power_state_transition_[display]) {
1225       // Route all interactions with client to dummy display.
1226       target_display = map_hwc_display_.find(display)->second;
1227     }
1228   }
1229   DTRACE_SCOPED();
1230   // TODO(user): Handle secure session, handle QDCM solid fill
1231   auto status = HWC2::Error::BadDisplay;
1232   HandleSecureSession();
1233   {
1234     SEQUENCE_ENTRY_SCOPE_LOCK(locker_[target_display]);
1235     if (pending_power_mode_[display]) {
1236       status = HWC2::Error::None;
1237     } else if (hwc_display_[target_display]) {
1238       hwc_display_[target_display]->ProcessActiveConfigChange();
1239       hwc_display_[target_display]->SetFastPathComposition(false);
1240       status = ValidateDisplayInternal(target_display, out_num_types, out_num_requests);
1241     }
1242   }
1243 
1244   // Sequence locking currently begins on Validate, so cancel the sequence lock on failures
1245   if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
1246     SEQUENCE_CANCEL_SCOPE_LOCK(locker_[target_display]);
1247   }
1248 
1249   if (display != target_display) {
1250     // Validate done on a dummy display. Assume present is complete.
1251     SEQUENCE_EXIT_SCOPE_LOCK(locker_[target_display]);
1252   }
1253 
1254   return INT32(status);
1255 }
1256 
CreateVirtualDisplayObj(uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)1257 HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
1258                                                 hwc2_display_t *out_display_id) {
1259   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
1260   hwc2_display_t client_id = HWCCallbacks::kNumDisplays;
1261   if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
1262     SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
1263     std::bitset<kSecureMax> secure_sessions = 0;
1264     if (hwc_display_[active_builtin_disp_id]) {
1265       hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
1266     }
1267     if (secure_sessions.any()) {
1268       DLOGE("Secure session is active, cannot create virtual display.");
1269       return HWC2::Error::Unsupported;
1270     } else if (IsPluggableDisplayConnected()) {
1271       DLOGE("External session is active, cannot create virtual display.");
1272       return HWC2::Error::Unsupported;
1273     }
1274   }
1275 
1276   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1277     DisplayError error = hwc_display_[HWC_DISPLAY_PRIMARY]->TeardownConcurrentWriteback();
1278     if (error) {
1279       return HWC2::Error::NoResources;
1280     }
1281   }
1282 
1283   // Lock confined to this scope
1284   int status = -EINVAL;
1285   for (auto &map_info : map_info_virtual_) {
1286     client_id = map_info.client_id;
1287     {
1288       SCOPE_LOCK(locker_[client_id]);
1289       auto &hwc_display = hwc_display_[client_id];
1290       if (hwc_display) {
1291         continue;
1292       }
1293 
1294       int32_t display_id = GetVirtualDisplayId();
1295       status = virtual_display_factory_.Create(core_intf_, &buffer_allocator_, &callbacks_,
1296                                                client_id, display_id, width, height,
1297                                                format, set_min_lum_, set_max_lum_, &hwc_display);
1298       // TODO(user): validate width and height support
1299       if (status) {
1300         return HWC2::Error::NoResources;
1301       }
1302 
1303       {
1304         SCOPE_LOCK(hdr_locker_[client_id]);
1305         is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
1306       }
1307 
1308       DLOGI("Created virtual display id:%" PRIu64 " with res: %dx%d", client_id, width, height);
1309 
1310       *out_display_id = client_id;
1311       map_info.disp_type = kVirtual;
1312       map_info.sdm_id = display_id;
1313       break;
1314     }
1315   }
1316 
1317   // Active builtin display needs revalidation
1318   if (!async_vds_creation_ && active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
1319     SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
1320     hwc_display_[active_builtin_disp_id]->ResetValidation();
1321   }
1322 
1323   return HWC2::Error::None;
1324 }
1325 
IsPluggableDisplayConnected()1326 bool HWCSession::IsPluggableDisplayConnected() {
1327   for (auto &map_info : map_info_pluggable_) {
1328     if (hwc_display_[map_info.client_id]) {
1329       return true;
1330     }
1331   }
1332   return false;
1333 }
1334 
1335 // Qclient methods
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)1336 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
1337                                              android::Parcel *output_parcel) {
1338   android::status_t status = -EINVAL;
1339 
1340   switch (command) {
1341     case qService::IQService::DYNAMIC_DEBUG:
1342       if (!input_parcel) {
1343         DLOGE("QService command = %d: input_parcel needed.", command);
1344         break;
1345       }
1346       status = 0;
1347       DynamicDebug(input_parcel);
1348       break;
1349 
1350     case qService::IQService::SCREEN_REFRESH:
1351       if (!input_parcel) {
1352         DLOGE("QService command = %d: input_parcel needed.", command);
1353         break;
1354       }
1355       status = RefreshScreen(input_parcel);
1356       break;
1357 
1358     case qService::IQService::SET_IDLE_TIMEOUT:
1359       if (!input_parcel) {
1360         DLOGE("QService command = %d: input_parcel needed.", command);
1361         break;
1362       }
1363       status = SetIdleTimeout(UINT32(input_parcel->readInt32()));
1364       break;
1365 
1366     case qService::IQService::SET_FRAME_DUMP_CONFIG:
1367       if (!input_parcel) {
1368         DLOGE("QService command = %d: input_parcel needed.", command);
1369         break;
1370       }
1371       status = SetFrameDumpConfig(input_parcel);
1372       break;
1373 
1374     case qService::IQService::SET_MAX_PIPES_PER_MIXER:
1375       if (!input_parcel) {
1376         DLOGE("QService command = %d: input_parcel needed.", command);
1377         break;
1378       }
1379       status = SetMaxMixerStages(input_parcel);
1380       break;
1381 
1382     case qService::IQService::SET_DISPLAY_MODE:
1383       if (!input_parcel) {
1384         DLOGE("QService command = %d: input_parcel needed.", command);
1385         break;
1386       }
1387       status = SetDisplayMode(input_parcel);
1388       break;
1389 
1390     case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
1391         if (!input_parcel || !output_parcel) {
1392           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1393           break;
1394         }
1395         int disp_id = INT(input_parcel->readInt32());
1396         HWCDisplay::DisplayStatus disp_status =
1397               static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
1398         status = SetDisplayStatus(disp_id, disp_status);
1399         output_parcel->writeInt32(status);
1400       }
1401       break;
1402 
1403     case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
1404       if (!input_parcel) {
1405         DLOGE("QService command = %d: input_parcel needed.", command);
1406         break;
1407       }
1408       status = ConfigureRefreshRate(input_parcel);
1409       break;
1410 
1411     case qService::IQService::TOGGLE_SCREEN_UPDATES: {
1412         if (!input_parcel || !output_parcel) {
1413           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1414           break;
1415         }
1416         int32_t input = input_parcel->readInt32();
1417         status = ToggleScreenUpdate(input == 1);
1418         output_parcel->writeInt32(status);
1419       }
1420       break;
1421 
1422     case qService::IQService::QDCM_SVC_CMDS:
1423       if (!input_parcel || !output_parcel) {
1424         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1425         break;
1426       }
1427       status = QdcmCMDHandler(input_parcel, output_parcel);
1428       break;
1429 
1430     case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
1431         if (!input_parcel || !output_parcel) {
1432           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1433           break;
1434         }
1435         int disp_id = input_parcel->readInt32();
1436         uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1437         status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
1438         output_parcel->writeInt32(status);
1439       }
1440       break;
1441 
1442     case qService::IQService::CONTROL_PARTIAL_UPDATE: {
1443         if (!input_parcel || !output_parcel) {
1444           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1445           break;
1446         }
1447         int disp_id = input_parcel->readInt32();
1448         uint32_t enable = UINT32(input_parcel->readInt32());
1449         status = ControlPartialUpdate(disp_id, enable == 1);
1450         output_parcel->writeInt32(status);
1451       }
1452       break;
1453 
1454     case qService::IQService::SET_ACTIVE_CONFIG: {
1455         if (!input_parcel) {
1456           DLOGE("QService command = %d: input_parcel needed.", command);
1457           break;
1458         }
1459         uint32_t config = UINT32(input_parcel->readInt32());
1460         int disp_id = input_parcel->readInt32();
1461         status = SetActiveConfigIndex(disp_id, config);
1462       }
1463       break;
1464 
1465     case qService::IQService::GET_ACTIVE_CONFIG: {
1466         if (!input_parcel || !output_parcel) {
1467           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1468           break;
1469         }
1470         int disp_id = input_parcel->readInt32();
1471         uint32_t config = 0;
1472         status = GetActiveConfigIndex(disp_id, &config);
1473         output_parcel->writeInt32(INT(config));
1474       }
1475       break;
1476 
1477     case qService::IQService::GET_CONFIG_COUNT: {
1478         if (!input_parcel || !output_parcel) {
1479           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1480           break;
1481         }
1482         int disp_id = input_parcel->readInt32();
1483         uint32_t count = 0;
1484         status = GetConfigCount(disp_id, &count);
1485         output_parcel->writeInt32(INT(count));
1486       }
1487       break;
1488 
1489     case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
1490       if (!input_parcel || !output_parcel) {
1491         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1492         break;
1493       }
1494       status = GetDisplayAttributesForConfig(input_parcel, output_parcel);
1495       break;
1496 
1497     case qService::IQService::GET_PANEL_BRIGHTNESS: {
1498         if (!output_parcel) {
1499           DLOGE("QService command = %d: output_parcel needed.", command);
1500           break;
1501         }
1502 
1503         uint32_t display = input_parcel->readUint32();
1504         uint32_t max_brightness_level = 0;
1505         status = getDisplayMaxBrightness(display, &max_brightness_level);
1506         if (status || !max_brightness_level) {
1507           output_parcel->writeInt32(max_brightness_level);
1508           DLOGE("Failed to get max brightness %u,  status %d", max_brightness_level, status);
1509           break;
1510         }
1511         DLOGV("Panel Max brightness is %u", max_brightness_level);
1512 
1513         float brightness_precent = -1.0f;
1514         status = getDisplayBrightness(display, &brightness_precent);
1515         if (brightness_precent == -1.0f) {
1516           output_parcel->writeInt32(0);
1517         } else {
1518           output_parcel->writeInt32(INT32(brightness_precent*(max_brightness_level - 1) + 1));
1519         }
1520       }
1521       break;
1522 
1523     case qService::IQService::SET_PANEL_BRIGHTNESS: {
1524         if (!input_parcel || !output_parcel) {
1525           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1526           break;
1527         }
1528 
1529         uint32_t max_brightness_level = 0;
1530         uint32_t display = HWC_DISPLAY_PRIMARY;
1531         status = getDisplayMaxBrightness(display, &max_brightness_level);
1532         if (status || max_brightness_level <= 1) {
1533           output_parcel->writeInt32(max_brightness_level);
1534           DLOGE("Failed to get max brightness %u, status %d", max_brightness_level, status);
1535           break;
1536         }
1537         DLOGV("Panel Max brightness is %u", max_brightness_level);
1538 
1539         int level = input_parcel->readInt32();
1540         if (level == 0) {
1541           status = SetDisplayBrightness(display, -1.0f);
1542         } else {
1543           status = SetDisplayBrightness(display,
1544                     (level - 1)/(static_cast<float>(max_brightness_level - 1)));
1545         }
1546         output_parcel->writeInt32(status);
1547       }
1548       break;
1549 
1550     case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
1551       if (!input_parcel || !output_parcel) {
1552         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1553         break;
1554       }
1555       status = GetVisibleDisplayRect(input_parcel, output_parcel);
1556       break;
1557 
1558     case qService::IQService::SET_CAMERA_STATUS: {
1559         if (!input_parcel) {
1560           DLOGE("QService command = %d: input_parcel needed.", command);
1561           break;
1562         }
1563         uint32_t camera_status = UINT32(input_parcel->readInt32());
1564         status = SetCameraLaunchStatus(camera_status);
1565       }
1566       break;
1567 
1568     case qService::IQService::GET_BW_TRANSACTION_STATUS: {
1569         if (!output_parcel) {
1570           DLOGE("QService command = %d: output_parcel needed.", command);
1571           break;
1572         }
1573         bool state = true;
1574         status = DisplayBWTransactionPending(&state);
1575         output_parcel->writeInt32(state);
1576       }
1577       break;
1578 
1579     case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
1580       if (!input_parcel) {
1581         DLOGE("QService command = %d: input_parcel needed.", command);
1582         break;
1583       }
1584       status = SetMixerResolution(input_parcel);
1585       break;
1586 
1587     case qService::IQService::SET_COLOR_MODE:
1588       if (!input_parcel) {
1589         DLOGE("QService command = %d: input_parcel needed.", command);
1590         break;
1591       }
1592       status = SetColorModeOverride(input_parcel);
1593       break;
1594 
1595     case qService::IQService::SET_COLOR_MODE_WITH_RENDER_INTENT:
1596       if (!input_parcel) {
1597         DLOGE("QService command = %d: input_parcel needed.", command);
1598         break;
1599       }
1600       status = SetColorModeWithRenderIntentOverride(input_parcel);
1601       break;
1602 
1603     case qService::IQService::SET_COLOR_MODE_BY_ID:
1604       if (!input_parcel) {
1605         DLOGE("QService command = %d: input_parcel needed.", command);
1606         break;
1607       }
1608       status = SetColorModeById(input_parcel);
1609       break;
1610 
1611     case qService::IQService::GET_COMPOSER_STATUS:
1612       if (!output_parcel) {
1613         DLOGE("QService command = %d: output_parcel needed.", command);
1614         break;
1615       }
1616       status = 0;
1617       output_parcel->writeInt32(getComposerStatus());
1618       break;
1619 
1620     case qService::IQService::SET_QSYNC_MODE:
1621       if (!input_parcel) {
1622         DLOGE("QService command = %d: input_parcel needed.", command);
1623         break;
1624       }
1625       status = SetQSyncMode(input_parcel);
1626       break;
1627 
1628     case qService::IQService::SET_COLOR_SAMPLING_ENABLED:
1629       if (!input_parcel) {
1630         DLOGE("QService command = %d: input_parcel needed.", command);
1631         break;
1632       }
1633       status = setColorSamplingEnabled(input_parcel);
1634       break;
1635 
1636     case qService::IQService::SET_IDLE_PC:
1637       if (!input_parcel) {
1638         DLOGE("QService command = %d: input_parcel needed.", command);
1639         break;
1640       }
1641       status = SetIdlePC(input_parcel);
1642       break;
1643 
1644     case qService::IQService::SET_DISPLAY_DEVICE_STATUS:
1645       if (!input_parcel) {
1646         DLOGE("QService command = %d: input_parcel needed.", command);
1647         break;
1648       }
1649       status = SetDisplayDeviceStatus(input_parcel);
1650       break;
1651 
1652     case qService::IQService::SET_PANEL_GAMMA_TABLE_SOURCE:
1653       if (!input_parcel || !output_parcel) {
1654         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1655         break;
1656       }
1657       status = SetPanelGammaTableSource(input_parcel);
1658       output_parcel->writeInt32(status);
1659       break;
1660 
1661     case qService::IQService::SET_DPPS_AD4_ROI_CONFIG:
1662       if (!input_parcel) {
1663         DLOGE("QService command = %d: input_parcel needed.", command);
1664         break;
1665       }
1666       status = SetAd4RoiConfig(input_parcel);
1667       break;
1668 
1669     case qService::IQService::SET_DSI_CLK:
1670       if (!input_parcel) {
1671         DLOGE("QService command = %d: input_parcel needed.", command);
1672         break;
1673       }
1674       status = SetDsiClk(input_parcel);
1675       break;
1676 
1677     case qService::IQService::GET_DSI_CLK:
1678       if (!input_parcel || !output_parcel) {
1679         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1680         break;
1681       }
1682       status = GetDsiClk(input_parcel, output_parcel);
1683       break;
1684 
1685     case qService::IQService::GET_SUPPORTED_DSI_CLK:
1686       if (!input_parcel || !output_parcel) {
1687         DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1688         break;
1689       }
1690       status = GetSupportedDsiClk(input_parcel, output_parcel);
1691       break;
1692 
1693     case qService::IQService::SET_PANEL_LUMINANCE:
1694       if (!input_parcel) {
1695         DLOGE("QService command = %d: input_parcel needed.", command);
1696         break;
1697       }
1698       status = SetPanelLuminanceAttributes(input_parcel);
1699       break;
1700 
1701     case qService::IQService::SET_COLOR_MODE_FROM_CLIENT:
1702       if (!input_parcel) {
1703         DLOGE("QService command = %d: input_parcel needed.", command);
1704         break;
1705       }
1706       status = SetColorModeFromClient(input_parcel);
1707       break;
1708 
1709     case qService::IQService::SET_FRAME_TRIGGER_MODE:
1710       if (!input_parcel) {
1711         DLOGE("QService command = %d: input_parcel needed.", command);
1712         break;
1713       }
1714       status = SetFrameTriggerMode(input_parcel);
1715       break;
1716 
1717     case qService::IQService::SET_BRIGHTNESS_SCALE:
1718       if (!input_parcel) {
1719         DLOGE("QService command = %d: input_parcel needed.", command);
1720         break;
1721       }
1722       status = SetDisplayBrightnessScale(input_parcel);
1723       break;
1724 
1725     case qService::IQService::SET_STAND_BY_MODE:
1726       if (!input_parcel) {
1727         DLOGE("QService command = %d: input_parcel needed.", command);
1728         break;
1729       }
1730       status = SetStandByMode(input_parcel);
1731       break;
1732 
1733     default:
1734       DLOGW("QService command = %d is not supported.", command);
1735       break;
1736   }
1737 
1738   return status;
1739 }
1740 
SetDisplayDeviceStatus(const android::Parcel * input_parcel)1741 android::status_t HWCSession::SetDisplayDeviceStatus(const android::Parcel *input_parcel) {
1742   int dpy = input_parcel->readInt32();
1743   int error = android::BAD_VALUE;
1744   auto disp_status = static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
1745 
1746   int disp_idx = GetDisplayIndex(dpy);
1747   if (disp_idx == -1) {
1748     DLOGE("Invalid display = %d", dpy);
1749     return android::BAD_VALUE;
1750   }
1751 
1752   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1753   if (hwc_display_[disp_idx]) {
1754     error = hwc_display_[disp_idx]->SetDisplayStatus(disp_status);
1755     if (error != android::OK)
1756       DLOGW("Set display %d status to %d failed with error %d", dpy, disp_status, error);
1757   } else {
1758     DLOGW("No display %d active", dpy);
1759   }
1760 
1761   return error;
1762 }
1763 
SetPanelGammaTableSource(const android::Parcel * input_parcel)1764 android::status_t HWCSession::SetPanelGammaTableSource(const android::Parcel *input_parcel) {
1765   int dpy = input_parcel->readInt32();
1766   int error = android::BAD_VALUE;
1767   auto source = static_cast<HWCDisplay::PanelGammaSource>(input_parcel->readInt32());
1768 
1769   int disp_idx = GetDisplayIndex(dpy);
1770   if (disp_idx == -1) {
1771     DLOGE("Invalid display = %d", dpy);
1772     return android::BAD_VALUE;
1773   }
1774 
1775   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1776   if (hwc_display_[disp_idx]) {
1777     error = hwc_display_[disp_idx]->SetCurrentPanelGammaSource(source);
1778     if (error != android::OK)
1779       DLOGW("Set display %d gamma source to %d failed with error %d", dpy, source, error);
1780   } else {
1781     DLOGW("No display %d active", dpy);
1782   }
1783 
1784   return error;
1785 }
1786 
getComposerStatus()1787 android::status_t HWCSession::getComposerStatus() {
1788   return is_composer_up_;
1789 }
1790 
GetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)1791 android::status_t HWCSession::GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
1792                                                             android::Parcel *output_parcel) {
1793   int config = input_parcel->readInt32();
1794   int dpy = input_parcel->readInt32();
1795   int error = android::BAD_VALUE;
1796   DisplayConfigVariableInfo display_attributes;
1797 
1798   int disp_idx = GetDisplayIndex(dpy);
1799   if (disp_idx == -1 || config < 0) {
1800     DLOGE("Invalid display = %d, or config = %d", dpy, config);
1801     return android::BAD_VALUE;
1802   }
1803 
1804   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1805   if (hwc_display_[disp_idx]) {
1806     error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(config, &display_attributes);
1807     if (error == 0) {
1808       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1809       output_parcel->writeInt32(INT(display_attributes.x_pixels));
1810       output_parcel->writeInt32(INT(display_attributes.y_pixels));
1811       output_parcel->writeFloat(display_attributes.x_dpi);
1812       output_parcel->writeFloat(display_attributes.y_dpi);
1813       output_parcel->writeInt32(0);  // Panel type, unsupported.
1814     }
1815   }
1816 
1817   return error;
1818 }
1819 
setColorSamplingEnabled(const android::Parcel * input_parcel)1820 android::status_t HWCSession::setColorSamplingEnabled(const android::Parcel *input_parcel) {
1821   int dpy = input_parcel->readInt32();
1822   int enabled_cmd = input_parcel->readInt32();
1823   if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || enabled_cmd < 0 ||
1824       enabled_cmd > 1) {
1825     return android::BAD_VALUE;
1826   }
1827 
1828   SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
1829   if (!hwc_display_[dpy]) {
1830     DLOGW("No display id %i active to enable histogram event", dpy);
1831     return android::BAD_VALUE;
1832   }
1833 
1834   auto error = hwc_display_[dpy]->SetDisplayedContentSamplingEnabledVndService(enabled_cmd);
1835   return (error == HWC2::Error::None) ? android::OK : android::BAD_VALUE;
1836 }
1837 
ConfigureRefreshRate(const android::Parcel * input_parcel)1838 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1839   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1840 
1841   uint32_t operation = UINT32(input_parcel->readInt32());
1842   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1843 
1844   if (!hwc_display) {
1845     DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1846     return -ENODEV;
1847   }
1848 
1849   switch (operation) {
1850     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1851       return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
1852 
1853     case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1854       return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
1855 
1856     case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
1857       uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1858       return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
1859     }
1860 
1861     default:
1862       DLOGW("Invalid operation %d", operation);
1863       return -EINVAL;
1864   }
1865 
1866   return 0;
1867 }
1868 
SetDisplayMode(const android::Parcel * input_parcel)1869 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1870   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1871 
1872   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1873     DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1874     return -ENODEV;
1875   }
1876 
1877   uint32_t mode = UINT32(input_parcel->readInt32());
1878   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayBuiltIn::SET_DISPLAY_MODE, mode);
1879 }
1880 
SetMaxMixerStages(const android::Parcel * input_parcel)1881 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1882   DisplayError error = kErrorNone;
1883   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1884   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1885   android::status_t status = 0;
1886 
1887   for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
1888     int disp_idx = GetDisplayIndex(INT(i));
1889     if (disp_idx == -1) {
1890       continue;
1891     }
1892     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1893     auto &hwc_display = hwc_display_[disp_idx];
1894     if (!hwc_display) {
1895       DLOGW("Display = %d is not connected.", disp_idx);
1896       status = (status)? status : -ENODEV;  // Return higher priority error.
1897       continue;
1898     }
1899 
1900     error = hwc_display->SetMaxMixerStages(max_mixer_stages);
1901     if (error != kErrorNone) {
1902       status = -EINVAL;
1903     }
1904   }
1905 
1906   return status;
1907 }
1908 
SetFrameDumpConfig(const android::Parcel * input_parcel)1909 android::status_t HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1910   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1911   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1912   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1913   int32_t output_format = HAL_PIXEL_FORMAT_RGB_888;
1914   bool post_processed = true;
1915 
1916   // Output buffer dump is not supported, if External or Virtual display is present.
1917   bool output_buffer_dump = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
1918   if (output_buffer_dump) {
1919     int external_dpy_index = GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
1920     int virtual_dpy_index = GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
1921     if (((external_dpy_index != -1) && hwc_display_[external_dpy_index]) ||
1922         ((virtual_dpy_index != -1) && hwc_display_[virtual_dpy_index])) {
1923       DLOGW("Output buffer dump is not supported with External or Virtual display!");
1924       return -EINVAL;
1925     }
1926   }
1927 
1928   // Read optional user preferences: output_format and post_processed.
1929   if (input_parcel->dataPosition() != input_parcel->dataSize()) {
1930     // HAL Pixel Format for output buffer
1931     output_format = input_parcel->readInt32();
1932   }
1933   if (input_parcel->dataPosition() != input_parcel->dataSize()) {
1934     // Option to dump Layer Mixer output (0) or DSPP output (1)
1935     post_processed = (input_parcel->readInt32() != 0);
1936   }
1937 
1938   android::status_t status = 0;
1939 
1940   for (uint32_t i = 0; i < bit_mask_display_type.size(); i++) {
1941     if (!bit_mask_display_type[i]) {
1942       continue;
1943     }
1944     int disp_idx = GetDisplayIndex(INT(i));
1945     if (disp_idx == -1) {
1946       continue;
1947     }
1948     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1949     auto &hwc_display = hwc_display_[disp_idx];
1950     if (!hwc_display) {
1951       DLOGW("Display = %d is not connected.", disp_idx);
1952       status = (status)? status : -ENODEV;  // Return higher priority error.
1953       continue;
1954     }
1955 
1956     HWC2::Error error = hwc_display->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type,
1957                                                         output_format, post_processed);
1958     if (error != HWC2::Error::None) {
1959       status = (HWC2::Error::NoResources == error) ? -ENOMEM : -EINVAL;
1960     }
1961   }
1962 
1963   return status;
1964 }
1965 
SetMixerResolution(const android::Parcel * input_parcel)1966 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1967   DisplayError error = kErrorNone;
1968   uint32_t dpy = UINT32(input_parcel->readInt32());
1969 
1970   if (dpy != HWC_DISPLAY_PRIMARY) {
1971     DLOGW("Resolution change not supported for this display = %d", dpy);
1972     return -EINVAL;
1973   }
1974 
1975   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1976   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1977     DLOGW("Primary display is not initialized");
1978     return -ENODEV;
1979   }
1980 
1981   uint32_t width = UINT32(input_parcel->readInt32());
1982   uint32_t height = UINT32(input_parcel->readInt32());
1983 
1984   error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
1985   if (error != kErrorNone) {
1986     return -EINVAL;
1987   }
1988 
1989   return 0;
1990 }
1991 
SetColorModeOverride(const android::Parcel * input_parcel)1992 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
1993   int display = static_cast<int>(input_parcel->readInt32());
1994   auto mode = static_cast<ColorMode>(input_parcel->readInt32());
1995 
1996   int disp_idx = GetDisplayIndex(display);
1997   if (disp_idx == -1) {
1998     DLOGE("Invalid display = %d", display);
1999     return -EINVAL;
2000   }
2001 
2002   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
2003     DLOGE("Invalid ColorMode: %d", mode);
2004     return HWC2_ERROR_BAD_PARAMETER;
2005   }
2006   auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx), &HWCDisplay::SetColorMode,
2007                                  mode);
2008   if (err != HWC2_ERROR_NONE)
2009     return -EINVAL;
2010 
2011   return 0;
2012 }
2013 
SetAd4RoiConfig(const android::Parcel * input_parcel)2014 android::status_t HWCSession::SetAd4RoiConfig(const android::Parcel *input_parcel) {
2015   auto display_id = static_cast<uint32_t>(input_parcel->readInt32());
2016   auto h_s = static_cast<uint32_t>(input_parcel->readInt32());
2017   auto h_e = static_cast<uint32_t>(input_parcel->readInt32());
2018   auto v_s = static_cast<uint32_t>(input_parcel->readInt32());
2019   auto v_e = static_cast<uint32_t>(input_parcel->readInt32());
2020   auto f_in = static_cast<uint32_t>(input_parcel->readInt32());
2021   auto f_out = static_cast<uint32_t>(input_parcel->readInt32());
2022 
2023   return static_cast<android::status_t>(SetDisplayDppsAdROI(display_id, h_s, h_e, v_s,
2024                                                             v_e, f_in, f_out));
2025 }
2026 
SetFrameTriggerMode(const android::Parcel * input_parcel)2027 android::status_t HWCSession::SetFrameTriggerMode(const android::Parcel *input_parcel) {
2028   auto display_id = static_cast<int>(input_parcel->readInt32());
2029   auto mode = static_cast<uint32_t>(input_parcel->readInt32());
2030 
2031   int disp_idx = GetDisplayIndex(display_id);
2032   if (disp_idx == -1) {
2033     DLOGE("Invalid display = %d", display_id);
2034     return -EINVAL;
2035   }
2036 
2037   auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
2038                                  &HWCDisplay::SetFrameTriggerMode, mode);
2039   if (err != HWC2_ERROR_NONE)
2040     return -EINVAL;
2041 
2042   return 0;
2043 }
2044 
SetColorModeWithRenderIntentOverride(const android::Parcel * input_parcel)2045 android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
2046     const android::Parcel *input_parcel) {
2047   auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
2048   auto mode = static_cast<ColorMode>(input_parcel->readInt32());
2049   auto int_intent = static_cast<int>(input_parcel->readInt32());
2050 
2051   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
2052     DLOGE("Invalid ColorMode: %d", mode);
2053     return HWC2_ERROR_BAD_PARAMETER;
2054   }
2055 
2056   if ((int_intent < 0) || (int_intent > MAX_EXTENDED_RENDER_INTENT)) {
2057     DLOGE("Invalid RenderIntent: %d", int_intent);
2058     return HWC2_ERROR_BAD_PARAMETER;
2059   }
2060 
2061   auto intent = static_cast<RenderIntent>(int_intent);
2062   auto err =
2063       CallDisplayFunction(display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
2064   if (err != HWC2_ERROR_NONE)
2065     return -EINVAL;
2066 
2067   return 0;
2068 }
SetColorModeById(const android::Parcel * input_parcel)2069 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
2070   int display = input_parcel->readInt32();
2071   auto mode = input_parcel->readInt32();
2072 
2073   int disp_idx = GetDisplayIndex(display);
2074   if (disp_idx == -1) {
2075     DLOGE("Invalid display = %d", display);
2076     return -EINVAL;
2077   }
2078 
2079   auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
2080                                  &HWCDisplay::SetColorModeById, mode);
2081   if (err != HWC2_ERROR_NONE)
2082     return -EINVAL;
2083 
2084   return 0;
2085 }
2086 
SetColorModeFromClient(const android::Parcel * input_parcel)2087 android::status_t HWCSession::SetColorModeFromClient(const android::Parcel *input_parcel) {
2088   int display = input_parcel->readInt32();
2089   auto mode = input_parcel->readInt32();
2090 
2091   int disp_idx = GetDisplayIndex(display);
2092   if (disp_idx == -1) {
2093     DLOGE("Invalid display = %d", display);
2094     return -EINVAL;
2095   }
2096 
2097   auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
2098                                  &HWCDisplay::SetColorModeFromClientApi, mode);
2099   if (err != HWC2_ERROR_NONE)
2100     return -EINVAL;
2101 
2102   callbacks_.Refresh(static_cast<hwc2_display_t>(disp_idx));
2103 
2104   return 0;
2105 }
2106 
RefreshScreen(const android::Parcel * input_parcel)2107 android::status_t HWCSession::RefreshScreen(const android::Parcel *input_parcel) {
2108   int display = input_parcel->readInt32();
2109 
2110   int disp_idx = GetDisplayIndex(display);
2111   if (disp_idx == -1) {
2112     DLOGE("Invalid display = %d", display);
2113     return -EINVAL;
2114   }
2115 
2116   callbacks_.Refresh(static_cast<hwc2_display_t>(disp_idx));
2117 
2118   return 0;
2119 }
2120 
DynamicDebug(const android::Parcel * input_parcel)2121 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
2122   int type = input_parcel->readInt32();
2123   bool enable = (input_parcel->readInt32() > 0);
2124   DLOGI("type = %d enable = %d", type, enable);
2125   int verbose_level = input_parcel->readInt32();
2126 
2127   switch (type) {
2128     case qService::IQService::DEBUG_ALL:
2129       HWCDebugHandler::DebugAll(enable, verbose_level);
2130       break;
2131 
2132     case qService::IQService::DEBUG_MDPCOMP:
2133       HWCDebugHandler::DebugStrategy(enable, verbose_level);
2134       HWCDebugHandler::DebugCompManager(enable, verbose_level);
2135       break;
2136 
2137     case qService::IQService::DEBUG_PIPE_LIFECYCLE:
2138       HWCDebugHandler::DebugResources(enable, verbose_level);
2139       HWCDebugHandler::DebugQos(enable, verbose_level);
2140       break;
2141 
2142     case qService::IQService::DEBUG_DRIVER_CONFIG:
2143       HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
2144       break;
2145 
2146     case qService::IQService::DEBUG_ROTATOR:
2147       HWCDebugHandler::DebugResources(enable, verbose_level);
2148       HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
2149       HWCDebugHandler::DebugRotator(enable, verbose_level);
2150       HWCDebugHandler::DebugQos(enable, verbose_level);
2151       break;
2152 
2153     case qService::IQService::DEBUG_QDCM:
2154       HWCDebugHandler::DebugQdcm(enable, verbose_level);
2155       break;
2156 
2157     case qService::IQService::DEBUG_SCALAR:
2158       HWCDebugHandler::DebugScalar(enable, verbose_level);
2159       break;
2160 
2161     case qService::IQService::DEBUG_CLIENT:
2162       HWCDebugHandler::DebugClient(enable, verbose_level);
2163       break;
2164 
2165     case qService::IQService::DEBUG_DISPLAY:
2166       HWCDebugHandler::DebugDisplay(enable, verbose_level);
2167       break;
2168 
2169     default:
2170       DLOGW("type = %d is not supported", type);
2171   }
2172 }
2173 
QdcmCMDDispatch(uint32_t display_id,const PPDisplayAPIPayload & req_payload,PPDisplayAPIPayload * resp_payload,PPPendingParams * pending_action)2174 android::status_t HWCSession::QdcmCMDDispatch(uint32_t display_id,
2175                                               const PPDisplayAPIPayload &req_payload,
2176                                               PPDisplayAPIPayload *resp_payload,
2177                                               PPPendingParams *pending_action) {
2178   int ret = 0;
2179   bool is_physical_display = false;
2180 
2181   if (display_id >= HWCCallbacks::kNumDisplays || !hwc_display_[display_id]) {
2182       DLOGW("Invalid display id or display = %d is not connected.", display_id);
2183       return -ENODEV;
2184   }
2185 
2186   if (display_id == map_info_primary_.client_id) {
2187     is_physical_display = true;
2188   } else {
2189     for (auto &map_info : map_info_builtin_) {
2190       if (map_info.client_id == display_id) {
2191         is_physical_display = true;
2192         break;
2193      }
2194     }
2195   }
2196 
2197   if (!is_physical_display) {
2198     DLOGW("Skipping QDCM command dispatch on display = %d", display_id);
2199     return ret;
2200   }
2201 
2202   ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, resp_payload, pending_action);
2203 
2204   return ret;
2205 }
2206 
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)2207 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
2208                                              android::Parcel *output_parcel) {
2209   int ret = 0;
2210   float *brightness = NULL;
2211   uint32_t display_id(0);
2212   PPPendingParams pending_action;
2213   PPDisplayAPIPayload resp_payload, req_payload;
2214   uint8_t *disp_id = NULL;
2215   int32_t *mode_id = NULL;
2216 
2217   if (!color_mgr_) {
2218     DLOGW("color_mgr_ not initialized.");
2219     return -ENOENT;
2220   }
2221 
2222   pending_action.action = kNoAction;
2223   pending_action.params = NULL;
2224 
2225   // Read display_id, payload_size and payload from in_parcel.
2226   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
2227   if (!ret) {
2228     ret = QdcmCMDDispatch(display_id, req_payload, &resp_payload, &pending_action);
2229   }
2230 
2231   if (ret) {
2232     output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
2233     req_payload.DestroyPayload();
2234     resp_payload.DestroyPayload();
2235     return ret;
2236   }
2237 
2238   if (kNoAction != pending_action.action) {
2239     int32_t action = pending_action.action;
2240     int count = -1;
2241     while (action > 0) {
2242       count++;
2243       int32_t bit = (action & 1);
2244       action = action >> 1;
2245 
2246       if (!bit)
2247         continue;
2248 
2249       DLOGV_IF(kTagQDCM, "pending action = %d, display_id = %d", BITMAP(count), display_id);
2250       switch (BITMAP(count)) {
2251         case kInvalidating:
2252           callbacks_.Refresh(display_id);
2253           break;
2254         case kEnterQDCMMode:
2255           ret = color_mgr_->EnableQDCMMode(true, hwc_display_[display_id]);
2256           break;
2257         case kExitQDCMMode:
2258           ret = color_mgr_->EnableQDCMMode(false, hwc_display_[display_id]);
2259           break;
2260         case kApplySolidFill:
2261           {
2262             SCOPE_LOCK(locker_[display_id]);
2263             ret = color_mgr_->SetSolidFill(pending_action.params,
2264                                            true, hwc_display_[display_id]);
2265           }
2266           callbacks_.Refresh(display_id);
2267           usleep(kSolidFillDelay);
2268           break;
2269         case kDisableSolidFill:
2270           {
2271             SCOPE_LOCK(locker_[display_id]);
2272             ret = color_mgr_->SetSolidFill(pending_action.params,
2273                                            false, hwc_display_[display_id]);
2274           }
2275           callbacks_.Refresh(display_id);
2276           usleep(kSolidFillDelay);
2277           break;
2278         case kSetPanelBrightness:
2279           ret = -EINVAL;
2280           brightness = reinterpret_cast<float *>(resp_payload.payload);
2281           if (brightness == NULL) {
2282             DLOGE("Brightness payload is Null");
2283           } else {
2284             ret = INT(SetDisplayBrightness(static_cast<hwc2_display_t>(display_id), *brightness));
2285           }
2286           break;
2287         case kEnableFrameCapture:
2288           ret = color_mgr_->SetFrameCapture(pending_action.params, true, hwc_display_[display_id]);
2289           callbacks_.Refresh(display_id);
2290           break;
2291         case kDisableFrameCapture:
2292           ret = color_mgr_->SetFrameCapture(pending_action.params, false,
2293                                             hwc_display_[display_id]);
2294           break;
2295         case kConfigureDetailedEnhancer:
2296           ret = color_mgr_->SetDetailedEnhancer(pending_action.params, hwc_display_[display_id]);
2297           callbacks_.Refresh(display_id);
2298           break;
2299         case kModeSet:
2300           ret = static_cast<int>
2301                   (hwc_display_[display_id]->RestoreColorTransform());
2302           callbacks_.Refresh(display_id);
2303           break;
2304         case kNoAction:
2305           break;
2306         case kMultiDispProc:
2307           for (auto &map_info : map_info_builtin_) {
2308             uint32_t id = UINT32(map_info.client_id);
2309             if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
2310               int result = 0;
2311               resp_payload.DestroyPayload();
2312               result = hwc_display_[id]->ColorSVCRequestRoute(req_payload, &resp_payload,
2313                                                               &pending_action);
2314               if (result) {
2315                 DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
2316                 ret = result;
2317               }
2318             }
2319           }
2320           break;
2321         case kMultiDispGetId:
2322           ret = resp_payload.CreatePayloadBytes(HWCCallbacks::kNumDisplays, &disp_id);
2323           if (ret) {
2324             DLOGW("Unable to create response payload!");
2325           } else {
2326             for (int i = 0; i < HWCCallbacks::kNumDisplays; i++) {
2327               disp_id[i] = HWCCallbacks::kNumDisplays;
2328             }
2329             if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
2330               disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
2331             }
2332             for (auto &map_info : map_info_builtin_) {
2333               uint64_t id = map_info.client_id;
2334               if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
2335                 disp_id[id] = (uint8_t)id;
2336               }
2337             }
2338           }
2339           break;
2340         case kSetModeFromClient:
2341           {
2342             SCOPE_LOCK(locker_[display_id]);
2343             mode_id = reinterpret_cast<int32_t *>(resp_payload.payload);
2344             if (mode_id) {
2345               ret = static_cast<int>(hwc_display_[display_id]->SetColorModeFromClientApi(*mode_id));
2346             } else {
2347               DLOGE("mode_id is Null");
2348               ret = -EINVAL;
2349             }
2350           }
2351           if (!ret) {
2352             callbacks_.Refresh(display_id);
2353           }
2354           break;
2355         default:
2356           DLOGW("Invalid pending action = %d!", pending_action.action);
2357           break;
2358       }
2359     }
2360   }
2361   // for display API getter case, marshall returned params into out_parcel.
2362   output_parcel->writeInt32(ret);
2363   HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
2364   req_payload.DestroyPayload();
2365   resp_payload.DestroyPayload();
2366 
2367   SEQUENCE_WAIT_SCOPE_LOCK(locker_[display_id]);
2368   hwc_display_[display_id]->ResetValidation();
2369 
2370   return ret;
2371 }
2372 
GetEventValue(const char * uevent_data,int length,const char * event_info)2373 int GetEventValue(const char *uevent_data, int length, const char *event_info) {
2374   const char *iterator_str = uevent_data;
2375   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
2376     const char *pstr = strstr(iterator_str, event_info);
2377     if (pstr != NULL) {
2378       return (atoi(iterator_str + strlen(event_info)));
2379     }
2380     iterator_str += strlen(iterator_str) + 1;
2381   }
2382 
2383   return -1;
2384 }
2385 
GetTokenValue(const char * uevent_data,int length,const char * token)2386 const char *GetTokenValue(const char *uevent_data, int length, const char *token) {
2387   const char *iterator_str = uevent_data;
2388   const char *pstr = NULL;
2389   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
2390     pstr = strstr(iterator_str, token);
2391     if (pstr) {
2392       break;
2393     }
2394     iterator_str += strlen(iterator_str) + 1;
2395   }
2396 
2397   if (pstr)
2398     pstr = pstr+strlen(token);
2399 
2400   return pstr;
2401 }
2402 
SetDsiClk(const android::Parcel * input_parcel)2403 android::status_t HWCSession::SetDsiClk(const android::Parcel *input_parcel) {
2404   int disp_id = input_parcel->readInt32();
2405   uint64_t clk = UINT64(input_parcel->readInt64());
2406   if (disp_id != HWC_DISPLAY_PRIMARY) {
2407     return -EINVAL;
2408   }
2409 
2410   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
2411   if (!hwc_display_[disp_id]) {
2412     return -EINVAL;
2413   }
2414 
2415   return hwc_display_[disp_id]->SetDynamicDSIClock(clk);
2416 }
2417 
GetDsiClk(const android::Parcel * input_parcel,android::Parcel * output_parcel)2418 android::status_t HWCSession::GetDsiClk(const android::Parcel *input_parcel,
2419                                         android::Parcel *output_parcel) {
2420   int disp_id = input_parcel->readInt32();
2421   if (disp_id != HWC_DISPLAY_PRIMARY) {
2422     return -EINVAL;
2423   }
2424 
2425   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
2426   if (!hwc_display_[disp_id]) {
2427     return -EINVAL;
2428   }
2429 
2430   uint64_t bitrate = 0;
2431   hwc_display_[disp_id]->GetDynamicDSIClock(&bitrate);
2432   output_parcel->writeUint64(bitrate);
2433 
2434   return 0;
2435 }
2436 
GetSupportedDsiClk(const android::Parcel * input_parcel,android::Parcel * output_parcel)2437 android::status_t HWCSession::GetSupportedDsiClk(const android::Parcel *input_parcel,
2438                                                  android::Parcel *output_parcel) {
2439   int disp_id = input_parcel->readInt32();
2440   if (disp_id != HWC_DISPLAY_PRIMARY) {
2441     return -EINVAL;
2442   }
2443 
2444   SCOPE_LOCK(locker_[disp_id]);
2445   if (!hwc_display_[disp_id]) {
2446     return -EINVAL;
2447   }
2448 
2449   std::vector<uint64_t> bit_rates;
2450   hwc_display_[disp_id]->GetSupportedDSIClock(&bit_rates);
2451   output_parcel->writeInt32(INT32(bit_rates.size()));
2452   for (auto &bit_rate : bit_rates) {
2453     output_parcel->writeUint64(bit_rate);
2454   }
2455 
2456   return 0;
2457 }
2458 
SetPanelLuminanceAttributes(const android::Parcel * input_parcel)2459 android::status_t HWCSession::SetPanelLuminanceAttributes(const android::Parcel *input_parcel) {
2460   int disp_id = input_parcel->readInt32();
2461 
2462   // currently doing only for virtual display
2463   if (disp_id != qdutils::DISPLAY_VIRTUAL) {
2464     return -EINVAL;
2465   }
2466 
2467   float min_lum = input_parcel->readFloat();
2468   float max_lum = input_parcel->readFloat();
2469 
2470   // check for out of range luminance values
2471   if (min_lum <= 0.0f || min_lum >= 1.0f || max_lum <= 100.0f || max_lum >= 1000.0f) {
2472     return -EINVAL;
2473   }
2474 
2475   std::lock_guard<std::mutex> obj(mutex_lum_);
2476   set_min_lum_ = min_lum;
2477   set_max_lum_ = max_lum;
2478   DLOGI("set max_lum %f, min_lum %f", set_max_lum_, set_min_lum_);
2479 
2480   return 0;
2481 }
2482 
UEventHandler(const char * uevent_data,int length)2483 void HWCSession::UEventHandler(const char *uevent_data, int length) {
2484   // Drop hotplug uevents until SurfaceFlinger (the client) is connected. The equivalent of hotplug
2485   // uevent handling will be done once when SurfaceFlinger connects, at RegisterCallback(). Since
2486   // HandlePluggableDisplays() reads the latest connection states of all displays, no uevent is
2487   // lost.
2488   if (callbacks_.IsClientConnected() && strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
2489     // MST hotplug will not carry connection status/test pattern etc.
2490     // Pluggable display handler will check all connection status' and take action accordingly.
2491     const char *str_status = GetTokenValue(uevent_data, length, "status=");
2492     const char *str_mst = GetTokenValue(uevent_data, length, "MST_HOTPLUG=");
2493     if (!str_status && !str_mst) {
2494       return;
2495     }
2496 
2497     hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
2498     hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
2499     DLOGI("Uevent = %s, status = %s, MST_HOTPLUG = %s, bpp = %d, pattern = %d", uevent_data,
2500           str_status ? str_status : "NULL", str_mst ? str_mst : "NULL", hpd_bpp_, hpd_pattern_);
2501 
2502     hwc2_display_t virtual_display_index =
2503         (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
2504 
2505     std::bitset<kSecureMax> secure_sessions = 0;
2506     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2507     if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
2508       Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
2509       hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
2510     }
2511     if (secure_sessions[kSecureDisplay] || hwc_display_[virtual_display_index]) {
2512       // Defer hotplug handling.
2513       SCOPE_LOCK(pluggable_handler_lock_);
2514       DLOGI("Marking hotplug pending...");
2515       pending_hotplug_event_ = kHotPlugEvent;
2516     } else {
2517       // Handle hotplug.
2518       int32_t err = HandlePluggableDisplays(true);
2519       if (err) {
2520         DLOGW("Hotplug handling failed. Error %d '%s'. Hotplug handling %s.", err,
2521               strerror(abs(err)), (pending_hotplug_event_ == kHotPlugEvent) ?
2522               "deferred" : "dropped");
2523       }
2524     }
2525 
2526     if (str_status) {
2527       bool connected = (strncmp(str_status, "connected", strlen("connected")) == 0);
2528       DLOGI("Connected = %d", connected);
2529       // Pass on legacy HDMI hot-plug event.
2530       qservice_->onHdmiHotplug(INT(connected));
2531     }
2532   }
2533 }
2534 
GetVsyncPeriod(hwc2_display_t disp,uint32_t * vsync_period)2535 int32_t HWCSession::GetVsyncPeriod(hwc2_display_t disp, uint32_t *vsync_period) {
2536   if (disp >= HWCCallbacks::kNumDisplays) {
2537     DLOGW("Invalid Display : display = %" PRIu64, disp);
2538     return HWC2_ERROR_BAD_DISPLAY;
2539   }
2540 
2541   SCOPE_LOCK(locker_[(int)disp]);
2542   // default value
2543   *vsync_period = 1000000000ul / 60;
2544 
2545   if (hwc_display_[disp]) {
2546     hwc_display_[disp]->GetDisplayAttribute(0, HwcAttribute::VSYNC_PERIOD, (int32_t *)vsync_period);
2547   }
2548 
2549   return HWC2_ERROR_NONE;
2550 }
2551 
Refresh(hwc2_display_t display)2552 void HWCSession::Refresh(hwc2_display_t display) {
2553   callbacks_.Refresh(display);
2554 }
2555 
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)2556 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
2557                                                     android::Parcel *output_parcel) {
2558   int disp_idx = GetDisplayIndex(input_parcel->readInt32());
2559   if (disp_idx == -1) {
2560     DLOGE("Invalid display = %d", disp_idx);
2561     return android::BAD_VALUE;
2562   }
2563 
2564   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
2565   if (!hwc_display_[disp_idx]) {
2566     return android::NO_INIT;
2567   }
2568 
2569   hwc_rect_t visible_rect = {0, 0, 0, 0};
2570   int error = hwc_display_[disp_idx]->GetVisibleDisplayRect(&visible_rect);
2571   if (error < 0) {
2572     return error;
2573   }
2574 
2575   output_parcel->writeInt32(visible_rect.left);
2576   output_parcel->writeInt32(visible_rect.top);
2577   output_parcel->writeInt32(visible_rect.right);
2578   output_parcel->writeInt32(visible_rect.bottom);
2579 
2580   return android::NO_ERROR;
2581 }
2582 
SetStandByMode(const android::Parcel * input_parcel)2583 android::status_t HWCSession::SetStandByMode(const android::Parcel *input_parcel) {
2584   SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
2585 
2586   bool enable = (input_parcel->readInt32() > 0);
2587 
2588   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
2589     DLOGI("Primary display is not initialized");
2590     return -EINVAL;
2591   }
2592 
2593   hwc_display_[HWC_DISPLAY_PRIMARY]->SetStandByMode(enable);
2594 
2595   return android::NO_ERROR;
2596 }
2597 
CreatePrimaryDisplay()2598 int HWCSession::CreatePrimaryDisplay() {
2599   int status = -EINVAL;
2600   HWDisplaysInfo hw_displays_info = {};
2601 
2602   if (null_display_mode_) {
2603     HWDisplayInfo hw_info = {};
2604     hw_info.display_type = kBuiltIn;
2605     hw_info.is_connected = 1;
2606     hw_info.is_primary = 1;
2607     hw_info.is_wb_ubwc_supported = 0;
2608     hw_info.display_id = 1;
2609     hw_displays_info[hw_info.display_id] = hw_info;
2610   } else {
2611     DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2612     if (error != kErrorNone) {
2613       DLOGE("Failed to get connected display list. Error = %d", error);
2614       return status;
2615     }
2616   }
2617 
2618   for (auto &iter : hw_displays_info) {
2619     auto &info = iter.second;
2620     if (!info.is_primary) {
2621       continue;
2622     }
2623 
2624     // todo (user): If primary display is not connected (e.g. hdmi as primary), a NULL display
2625     // need to be created. SF expects primary display hotplug during callback registration unlike
2626     // previous implementation where first hotplug could be notified anytime.
2627     if (!info.is_connected) {
2628       DLOGE("Primary display is not connected. Not supported at present.");
2629       break;
2630     }
2631 
2632     auto hwc_display = &hwc_display_[HWC_DISPLAY_PRIMARY];
2633     hwc2_display_t client_id = map_info_primary_.client_id;
2634 
2635     if (info.display_type == kBuiltIn) {
2636       status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2637                                          qservice_, client_id, info.display_id, hwc_display);
2638     } else if (info.display_type == kPluggable) {
2639       status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2640                                            qservice_, client_id, info.display_id, 0, 0, false,
2641                                            hwc_display);
2642     } else {
2643       DLOGE("Spurious primary display type = %d", info.display_type);
2644       break;
2645     }
2646 
2647     if (!status) {
2648       DLOGI("Created primary display type = %d, sdm id = %d, client id = %d", info.display_type,
2649              info.display_id, UINT32(client_id));
2650       {
2651          SCOPE_LOCK(hdr_locker_[client_id]);
2652          is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
2653       }
2654 
2655       map_info_primary_.disp_type = info.display_type;
2656       map_info_primary_.sdm_id = info.display_id;
2657       CreateDummyDisplay(HWC_DISPLAY_PRIMARY);
2658       color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
2659       if (!color_mgr_) {
2660         DLOGW("Failed to load HWCColorManager.");
2661       }
2662     } else {
2663       DLOGE("Primary display creation has failed! status = %d", status);
2664     }
2665 
2666     // Primary display is found, no need to parse more.
2667     break;
2668   }
2669 
2670   return status;
2671 }
2672 
CreateDummyDisplay(hwc2_display_t client_id)2673 void HWCSession::CreateDummyDisplay(hwc2_display_t client_id) {
2674   if (!async_powermode_) {
2675     return;
2676   }
2677 
2678   hwc2_display_t dummy_disp_id = map_hwc_display_.find(client_id)->second;
2679   auto hwc_display_dummy = &hwc_display_[dummy_disp_id];
2680   HWCDisplayDummy::Create(core_intf_, &buffer_allocator_, &callbacks_, this, qservice_,
2681                     0, 0, hwc_display_dummy);
2682   if (!*hwc_display_dummy) {
2683     DLOGE("Dummy display creation failed for %d display\n", UINT32(client_id));
2684   }
2685 }
2686 
HandleBuiltInDisplays()2687 int HWCSession::HandleBuiltInDisplays() {
2688   if (null_display_mode_) {
2689     DLOGW("Skipped BuiltIn display handling in null-display mode");
2690     return 0;
2691   }
2692 
2693   HWDisplaysInfo hw_displays_info = {};
2694   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2695   if (error != kErrorNone) {
2696     DLOGE("Failed to get connected display list. Error = %d", error);
2697     return -EINVAL;
2698   }
2699 
2700   int status = 0;
2701   for (auto &iter : hw_displays_info) {
2702     auto &info = iter.second;
2703 
2704     // Do not recreate primary display.
2705     if (info.is_primary || info.display_type != kBuiltIn) {
2706       continue;
2707     }
2708 
2709     for (auto &map_info : map_info_builtin_) {
2710       hwc2_display_t client_id = map_info.client_id;
2711 
2712       {
2713         SCOPE_LOCK(locker_[client_id]);
2714         // Lock confined to this scope
2715         if (hwc_display_[client_id]) {
2716           continue;
2717         }
2718 
2719         DLOGI("Create builtin display, sdm id = %d, client id = %d", info.display_id,
2720               UINT32(client_id));
2721         status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2722                                            qservice_, client_id, info.display_id,
2723                                            &hwc_display_[client_id]);
2724         if (status) {
2725           DLOGE("Builtin display creation failed.");
2726           break;
2727         }
2728 
2729         {
2730           SCOPE_LOCK(hdr_locker_[client_id]);
2731           is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
2732         }
2733 
2734         DLOGI("Builtin display created: sdm id = %d, client id = %d", info.display_id,
2735               UINT32(client_id));
2736         map_info.disp_type = info.display_type;
2737         map_info.sdm_id = info.display_id;
2738         CreateDummyDisplay(client_id);
2739       }
2740 
2741       DLOGI("Hotplugging builtin display, sdm id = %d, client id = %d", info.display_id,
2742             UINT32(client_id));
2743       callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
2744       break;
2745     }
2746   }
2747 
2748   return status;
2749 }
2750 
HandlePluggableDisplays(bool delay_hotplug)2751 int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
2752   SCOPE_LOCK(pluggable_handler_lock_);
2753   if (null_display_mode_) {
2754     DLOGW("Skipped pluggable display handling in null-display mode");
2755     return 0;
2756   }
2757 
2758   DLOGI("Handling hotplug...");
2759   HWDisplaysInfo hw_displays_info = {};
2760   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2761   if (error != kErrorNone) {
2762     DLOGE("Failed to get connected display list. Error = %d", error);
2763     return -EINVAL;
2764   }
2765 
2766   int status = HandleDisconnectedDisplays(&hw_displays_info);
2767   if (status) {
2768     DLOGE("All displays could not be disconnected.");
2769     return status;
2770   }
2771 
2772   status = HandleConnectedDisplays(&hw_displays_info, delay_hotplug);
2773   if (status) {
2774     switch (status) {
2775       case -EAGAIN:
2776       case -ENODEV:
2777         // Errors like device removal or deferral for which we want to try another hotplug handling.
2778         pending_hotplug_event_ = kHotPlugEvent;
2779         status = 0;
2780         break;
2781       default:
2782         // Real errors we want to flag and stop hotplug handling.
2783         pending_hotplug_event_ = kHotPlugNone;
2784         DLOGE("All displays could not be connected. Error %d '%s'.", status, strerror(abs(status)));
2785     }
2786     DLOGI("Handling hotplug... %s", (kHotPlugNone == pending_hotplug_event_) ?
2787           "Stopped." : "Done. Hotplug events pending.");
2788     return status;
2789   }
2790 
2791   pending_hotplug_event_ = kHotPlugNone;
2792 
2793   DLOGI("Handling hotplug... Done.");
2794   return 0;
2795 }
2796 
HandleConnectedDisplays(HWDisplaysInfo * hw_displays_info,bool delay_hotplug)2797 int HWCSession::HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug) {
2798   int status = 0;
2799   std::vector<hwc2_display_t> pending_hotplugs = {};
2800   hwc2_display_t client_id = 0;
2801 
2802   for (auto &iter : *hw_displays_info) {
2803     auto &info = iter.second;
2804 
2805     // Do not recreate primary display or if display is not connected.
2806     if (info.is_primary || info.display_type != kPluggable || !info.is_connected) {
2807       continue;
2808     }
2809 
2810     // Check if we are already using the display.
2811     auto display_used = std::find_if(map_info_pluggable_.begin(), map_info_pluggable_.end(),
2812                                      [&](auto &p) {
2813                                        return (p.sdm_id == info.display_id);
2814                                      });
2815     if (display_used != map_info_pluggable_.end()) {
2816       // Display is already used in a slot.
2817       continue;
2818     }
2819 
2820     // Count active pluggable display slots and slots with no commits.
2821     bool first_commit_pending = false;
2822     std::for_each(map_info_pluggable_.begin(), map_info_pluggable_.end(),
2823                    [&](auto &p) {
2824                      SCOPE_LOCK(locker_[p.client_id]);
2825                      if (hwc_display_[p.client_id]) {
2826                        if (!hwc_display_[p.client_id]->IsFirstCommitDone()) {
2827                          DLOGI("Display commit pending on display %d-1", p.sdm_id);
2828                          first_commit_pending = true;
2829                        }
2830                      }
2831                    });
2832 
2833     if (!disable_hotplug_bwcheck_ && first_commit_pending) {
2834       // Hotplug bandwidth check is accomplished by creating and hotplugging a new display after
2835       // a display commit has happened on previous hotplugged displays. This allows the driver to
2836       // return updated modes for the new display based on available link bandwidth.
2837       DLOGI("Pending display commit on one of the displays. Deferring display creation.");
2838       status = -EAGAIN;
2839       if (callbacks_.IsClientConnected()) {
2840         // Trigger a display refresh since we depend on PresentDisplay() to handle pending hotplugs.
2841         hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2842         if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
2843           active_builtin_disp_id = HWC_DISPLAY_PRIMARY;
2844         }
2845         callbacks_.Refresh(active_builtin_disp_id);
2846       }
2847       break;
2848     }
2849 
2850     // find an empty slot to create display.
2851     for (auto &map_info : map_info_pluggable_) {
2852       client_id = map_info.client_id;
2853 
2854       // Lock confined to this scope
2855       {
2856         SCOPE_LOCK(locker_[client_id]);
2857         auto &hwc_display = hwc_display_[client_id];
2858         if (hwc_display) {
2859           // Display slot is already used.
2860           continue;
2861         }
2862 
2863         DLOGI("Create pluggable display, sdm id = %d, client id = %d", info.display_id,
2864               UINT32(client_id));
2865 
2866         // Test pattern generation ?
2867         map_info.test_pattern = (hpd_bpp_ > 0) && (hpd_pattern_ > 0);
2868         int err = 0;
2869         if (!map_info.test_pattern) {
2870           err = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_,
2871                                             &callbacks_, this, qservice_, client_id,
2872                                             info.display_id, 0, 0, false, &hwc_display);
2873         } else {
2874           err = HWCDisplayPluggableTest::Create(core_intf_, &buffer_allocator_,
2875                                                 &callbacks_, this, qservice_, client_id,
2876                                                 info.display_id, UINT32(hpd_bpp_),
2877                                                 UINT32(hpd_pattern_), &hwc_display);
2878         }
2879 
2880         if (err) {
2881           DLOGW("Pluggable display creation failed/aborted. Error %d '%s'.", err,
2882                 strerror(abs(err)));
2883           status = err;
2884           // Attempt creating remaining pluggable displays.
2885           break;
2886         }
2887 
2888         {
2889           SCOPE_LOCK(hdr_locker_[client_id]);
2890           is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
2891         }
2892 
2893         DLOGI("Created pluggable display successfully: sdm id = %d, client id = %d",
2894               info.display_id, UINT32(client_id));
2895         CreateDummyDisplay(client_id);
2896       }
2897 
2898       map_info.disp_type = info.display_type;
2899       map_info.sdm_id = info.display_id;
2900 
2901       pending_hotplugs.push_back((hwc2_display_t)client_id);
2902 
2903       // Display is created for this sdm id, move to next connected display.
2904       break;
2905     }
2906   }
2907 
2908   // No display was created.
2909   if (!pending_hotplugs.size()) {
2910     return status;
2911   }
2912 
2913   // Active builtin display needs revalidation
2914   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2915   if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
2916     WaitForResources(delay_hotplug, active_builtin_disp_id, client_id);
2917   }
2918 
2919   for (auto client_id : pending_hotplugs) {
2920     DLOGI("Notify hotplug display connected: client id = %d", UINT32(client_id));
2921     callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
2922   }
2923 
2924   return status;
2925 }
2926 
HasHDRSupport(HWCDisplay * hwc_display)2927 bool HWCSession::HasHDRSupport(HWCDisplay *hwc_display) {
2928   // query number of hdr types
2929   uint32_t out_num_types = 0;
2930   float out_max_luminance = 0.0f;
2931   float out_max_average_luminance = 0.0f;
2932   float out_min_luminance = 0.0f;
2933   if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
2934                                       &out_max_average_luminance, &out_min_luminance)
2935                                       != HWC2::Error::None) {
2936     return false;
2937   }
2938 
2939   return (out_num_types > 0);
2940 }
2941 
HandleDisconnectedDisplays(HWDisplaysInfo * hw_displays_info)2942 int HWCSession::HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info) {
2943   // Destroy pluggable displays which were connected earlier but got disconnected now.
2944   for (auto &map_info : map_info_pluggable_) {
2945     bool disconnect = true;   // disconnect in case display id is not found in list.
2946 
2947     for (auto &iter : *hw_displays_info) {
2948       auto &info = iter.second;
2949       if (info.display_id != map_info.sdm_id) {
2950         continue;
2951       }
2952       if (info.is_connected) {
2953         disconnect = false;
2954       }
2955       break;
2956     }
2957 
2958     if (disconnect) {
2959       DestroyDisplay(&map_info);
2960     }
2961   }
2962 
2963   return 0;
2964 }
2965 
DestroyDisplay(DisplayMapInfo * map_info)2966 void HWCSession::DestroyDisplay(DisplayMapInfo *map_info) {
2967   switch (map_info->disp_type) {
2968     case kPluggable:
2969       DestroyPluggableDisplay(map_info);
2970       break;
2971     default:
2972       DestroyNonPluggableDisplay(map_info);
2973       break;
2974     }
2975 }
2976 
DestroyPluggableDisplay(DisplayMapInfo * map_info)2977 void HWCSession::DestroyPluggableDisplay(DisplayMapInfo *map_info) {
2978   hwc2_display_t client_id = map_info->client_id;
2979 
2980   DLOGI("Notify hotplug display disconnected: client id = %d", UINT32(client_id));
2981   callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
2982 
2983   SCOPE_LOCK(system_locker_);
2984   {
2985     SEQUENCE_WAIT_SCOPE_LOCK(locker_[client_id]);
2986     auto &hwc_display = hwc_display_[client_id];
2987     if (!hwc_display) {
2988       return;
2989     }
2990     DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
2991          UINT32(client_id));
2992     {
2993       SCOPE_LOCK(hdr_locker_[client_id]);
2994       is_hdr_display_[UINT32(client_id)] = false;
2995     }
2996 
2997     if (!map_info->test_pattern) {
2998       HWCDisplayPluggable::Destroy(hwc_display);
2999     } else {
3000       HWCDisplayPluggableTest::Destroy(hwc_display);
3001     }
3002 
3003     if (async_powermode_) {
3004       hwc2_display_t dummy_disp_id = map_hwc_display_.find(client_id)->second;
3005       auto &hwc_display_dummy = hwc_display_[dummy_disp_id];
3006       display_ready_.reset(UINT32(dummy_disp_id));
3007       if (hwc_display_dummy) {
3008         HWCDisplayDummy::Destroy(hwc_display_dummy);
3009         hwc_display_dummy = nullptr;
3010       }
3011     }
3012     display_ready_.reset(UINT32(client_id));
3013     pending_power_mode_[client_id] = false;
3014     hwc_display = nullptr;
3015     map_info->Reset();
3016   }
3017 }
3018 
DestroyNonPluggableDisplay(DisplayMapInfo * map_info)3019 void HWCSession::DestroyNonPluggableDisplay(DisplayMapInfo *map_info) {
3020   hwc2_display_t client_id = map_info->client_id;
3021 
3022   SCOPE_LOCK(locker_[client_id]);
3023   auto &hwc_display = hwc_display_[client_id];
3024   if (!hwc_display) {
3025     return;
3026   }
3027   DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
3028         UINT32(client_id));
3029   {
3030     SCOPE_LOCK(hdr_locker_[client_id]);
3031     is_hdr_display_[UINT32(client_id)] = false;
3032   }
3033 
3034   switch (map_info->disp_type) {
3035     case kBuiltIn:
3036       HWCDisplayBuiltIn::Destroy(hwc_display);
3037       break;
3038     default:
3039       virtual_display_factory_.Destroy(hwc_display);
3040       break;
3041     }
3042 
3043     if (async_powermode_ && map_info->disp_type == kBuiltIn) {
3044       hwc2_display_t dummy_disp_id = map_hwc_display_.find(client_id)->second;
3045       auto &hwc_display_dummy = hwc_display_[dummy_disp_id];
3046       display_ready_.reset(UINT32(dummy_disp_id));
3047       if (hwc_display_dummy) {
3048         HWCDisplayDummy::Destroy(hwc_display_dummy);
3049         hwc_display_dummy = nullptr;
3050       }
3051     }
3052     pending_power_mode_[client_id] = false;
3053     hwc_display = nullptr;
3054     display_ready_.reset(UINT32(client_id));
3055     map_info->Reset();
3056 }
3057 
ValidateDisplayInternal(hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)3058 HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
3059                                                 uint32_t *out_num_requests) {
3060   HWCDisplay *hwc_display = hwc_display_[display];
3061 
3062   DTRACE_SCOPED();
3063   if (hwc_display->IsInternalValidateState()) {
3064     // Internal Validation has already been done on display, get the Output params.
3065     return hwc_display->GetValidateDisplayOutput(out_num_types, out_num_requests);
3066   }
3067 
3068   if (display == HWC_DISPLAY_PRIMARY) {
3069     // TODO(user): This can be moved to HWCDisplayPrimary
3070     if (need_invalidate_) {
3071       callbacks_.Refresh(display);
3072       need_invalidate_ = false;
3073     }
3074 
3075     if (color_mgr_) {
3076       color_mgr_->SetColorModeDetailEnhancer(hwc_display_[display]);
3077     }
3078   }
3079 
3080   return hwc_display->Validate(out_num_types, out_num_requests);
3081 }
3082 
PresentDisplayInternal(hwc2_display_t display)3083 HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display) {
3084   HWCDisplay *hwc_display = hwc_display_[display];
3085 
3086   DTRACE_SCOPED();
3087   // If display is in Skip-Validate state and Validate cannot be skipped, do Internal
3088   // Validation to optimize for the frames which don't require the Client composition.
3089   if (hwc_display->IsSkipValidateState() && !hwc_display->CanSkipValidate()) {
3090     uint32_t out_num_types = 0, out_num_requests = 0;
3091     hwc_display->SetFastPathComposition(true);
3092     HWC2::Error error = ValidateDisplayInternal(display, &out_num_types, &out_num_requests);
3093     if ((error != HWC2::Error::None) || hwc_display->HWCClientNeedsValidate()) {
3094       hwc_display->SetValidationState(HWCDisplay::kInternalValidate);
3095       hwc_display->SetFastPathComposition(false);
3096       return HWC2::Error::NotValidated;
3097     }
3098   }
3099   return HWC2::Error::None;
3100 }
3101 
DisplayPowerReset()3102 void HWCSession::DisplayPowerReset() {
3103   // Acquire lock on all displays.
3104   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3105     display < HWCCallbacks::kNumDisplays; display++) {
3106     locker_[display].Lock();
3107   }
3108 
3109   HWC2::Error status = HWC2::Error::None;
3110   HWC2::PowerMode last_power_mode[HWCCallbacks::kNumDisplays] = {};
3111 
3112   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3113     display < HWCCallbacks::kNumDisplays; display++) {
3114     if (hwc_display_[display] != NULL) {
3115       last_power_mode[display] = hwc_display_[display]->GetCurrentPowerMode();
3116       DLOGI("Powering off display = %d", INT32(display));
3117       status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off,
3118                                                    true /* teardown */);
3119       if (status != HWC2::Error::None) {
3120         DLOGE("Power off for display = %d failed with error = %d", INT32(display), status);
3121       }
3122     }
3123   }
3124   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3125     display < HWCCallbacks::kNumDisplays; display++) {
3126     if (hwc_display_[display] != NULL) {
3127       HWC2::PowerMode mode = last_power_mode[display];
3128       DLOGI("Setting display %d to mode = %d", INT32(display), mode);
3129       status = hwc_display_[display]->SetPowerMode(mode, false /* teardown */);
3130       if (status != HWC2::Error::None) {
3131         DLOGE("%d mode for display = %d failed with error = %d", mode, INT32(display), status);
3132       }
3133       ColorMode color_mode = hwc_display_[display]->GetCurrentColorMode();
3134       status = hwc_display_[display]->SetColorMode(color_mode);
3135       if (status != HWC2::Error::None) {
3136         DLOGE("SetColorMode failed for display = %d error = %d", INT32(display), status);
3137       }
3138     }
3139   }
3140 
3141   hwc2_display_t vsync_source = callbacks_.GetVsyncSource();
3142   status = hwc_display_[vsync_source]->SetVsyncEnabled(HWC2::Vsync::Enable);
3143   if (status != HWC2::Error::None) {
3144     DLOGE("Enabling vsync failed for disp: %" PRIu64 " with error = %d", vsync_source, status);
3145   }
3146 
3147   // Release lock on all displays.
3148   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3149     display < HWCCallbacks::kNumDisplays; display++) {
3150     locker_[display].Unlock();
3151   }
3152 
3153   callbacks_.Refresh(vsync_source);
3154 }
3155 
HandleSecureSession()3156 void HWCSession::HandleSecureSession() {
3157   std::bitset<kSecureMax> secure_sessions = 0;
3158   {
3159     // TODO(user): Revisit if supporting secure display on non-primary.
3160     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3161     if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3162       return;
3163     }
3164     Locker::ScopeLock lock_pwr(power_state_[active_builtin_disp_id]);
3165     if (power_state_transition_[active_builtin_disp_id]) {
3166       // Route all interactions with client to dummy display.
3167       active_builtin_disp_id = map_hwc_display_.find(active_builtin_disp_id)->second;
3168     }
3169     Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
3170     hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3171   }
3172 
3173   if (secure_sessions.any()) {
3174     secure_session_active_ = true;
3175   } else if (!secure_session_active_) {
3176     // No secure session active. No secure session transition to handle. Skip remaining steps.
3177     return;
3178   }
3179 
3180   // If it is called during primary prepare/commit, we need to pause any ongoing commit on
3181   // external/virtual display.
3182   bool found_active_secure_display = false;
3183   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3184        display < HWCCallbacks::kNumRealDisplays; display++) {
3185     Locker::ScopeLock lock_d(locker_[display]);
3186     HWCDisplay *hwc_display = hwc_display_[display];
3187     if (!hwc_display || hwc_display->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) {
3188       continue;
3189     }
3190 
3191     bool is_active_secure_display = false;
3192     // The first On/Doze/DozeSuspend built-in display is taken as the secure display.
3193     if (!found_active_secure_display &&
3194         hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3195       is_active_secure_display = true;
3196       found_active_secure_display = true;
3197     }
3198     hwc_display->HandleSecureSession(secure_sessions, &pending_power_mode_[display],
3199                                      is_active_secure_display);
3200   }
3201 }
3202 
HandlePendingPowerMode(hwc2_display_t disp_id,const shared_ptr<Fence> & retire_fence)3203 void HWCSession::HandlePendingPowerMode(hwc2_display_t disp_id,
3204                                         const shared_ptr<Fence> &retire_fence) {
3205   if (!secure_session_active_) {
3206     // No secure session active. Skip remaining steps.
3207     return;
3208   }
3209 
3210   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3211   if (disp_id != active_builtin_disp_id) {
3212     return;
3213   }
3214 
3215   Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
3216   bool pending_power_mode = false;
3217   std::bitset<kSecureMax> secure_sessions = 0;
3218   hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3219   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1;
3220     display < HWCCallbacks::kNumDisplays; display++) {
3221     if (display != active_builtin_disp_id) {
3222       Locker::ScopeLock lock_d(locker_[display]);
3223       if (pending_power_mode_[display]) {
3224         pending_power_mode = true;
3225         break;
3226       }
3227     }
3228   }
3229 
3230   if (!pending_power_mode) {
3231     if (!secure_sessions.any()) {
3232       secure_session_active_ = false;
3233     }
3234     return;
3235   }
3236 
3237   // retire fence is set only after successful primary commit, So check for retire fence to know
3238   // non secure commit went through to notify driver to change the CRTC mode to non secure.
3239   // Otherwise any commit to non-primary display would fail.
3240   if (retire_fence == nullptr) {
3241     return;
3242   }
3243 
3244   Fence::Wait(retire_fence);
3245 
3246   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1;
3247     display < HWCCallbacks::kNumDisplays; display++) {
3248     if (display != active_builtin_disp_id) {
3249       Locker::ScopeLock lock_d(locker_[display]);
3250       if (pending_power_mode_[display] && hwc_display_[display]) {
3251         HWC2::Error error =
3252           hwc_display_[display]->SetPowerMode(hwc_display_[display]->GetPendingPowerMode(), false);
3253         if (HWC2::Error::None == error) {
3254           pending_power_mode_[display] = false;
3255           hwc_display_[display]->ClearPendingPowerMode();
3256           pending_refresh_.set(UINT32(HWC_DISPLAY_PRIMARY));
3257         } else {
3258           DLOGE("SetDisplayStatus error = %d (%s)", error, to_string(error).c_str());
3259         }
3260       }
3261     }
3262   }
3263   secure_session_active_ = false;
3264 }
3265 
HandlePendingHotplug(hwc2_display_t disp_id,const shared_ptr<Fence> & retire_fence)3266 void HWCSession::HandlePendingHotplug(hwc2_display_t disp_id,
3267                                       const shared_ptr<Fence> &retire_fence) {
3268   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3269   if (disp_id != active_builtin_disp_id ||
3270       (kHotPlugNone == pending_hotplug_event_ && !destroy_virtual_disp_pending_)) {
3271     return;
3272   }
3273 
3274   std :: bitset < kSecureMax > secure_sessions = 0;
3275   if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
3276     Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
3277     hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3278   }
3279 
3280   if (secure_sessions.any() || active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3281     return;
3282   }
3283 
3284   if (destroy_virtual_disp_pending_ || kHotPlugEvent == pending_hotplug_event_) {
3285     Fence::Wait(retire_fence);
3286 
3287     // Destroy the pending virtual display if secure session not present.
3288     if (destroy_virtual_disp_pending_) {
3289       for (auto &map_info : map_info_virtual_) {
3290         DestroyDisplay(&map_info);
3291         destroy_virtual_disp_pending_ = false;
3292         virtual_id_ = HWCCallbacks::kNumDisplays;
3293       }
3294     }
3295     // Handle connect/disconnect hotplugs if secure session is not present.
3296     hwc2_display_t virtual_display_idx = (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
3297     if (!hwc_display_[virtual_display_idx] && kHotPlugEvent == pending_hotplug_event_) {
3298       // Handle deferred hotplug event.
3299       int32_t err = pluggable_handler_lock_.TryLock();
3300       if (!err) {
3301         // Do hotplug handling in a different thread to avoid blocking PresentDisplay.
3302         std::thread(&HWCSession::HandlePluggableDisplays, this, true).detach();
3303         pluggable_handler_lock_.Unlock();
3304       } else {
3305         // EBUSY means another thread is already handling hotplug. Skip deferred hotplug handling.
3306         if (EBUSY != err) {
3307           DLOGW("Failed to acquire pluggable display handler lock. Error %d '%s'.", err,
3308                 strerror(abs(err)));
3309         }
3310       }
3311     }
3312   }
3313 }
3314 
GetReadbackBufferAttributes(hwc2_display_t display,int32_t * format,int32_t * dataspace)3315 int32_t HWCSession::GetReadbackBufferAttributes(hwc2_display_t display, int32_t *format,
3316                                                 int32_t *dataspace) {
3317   if (display >= HWCCallbacks::kNumDisplays) {
3318     return HWC2_ERROR_BAD_DISPLAY;
3319   }
3320 
3321   if (!format || !dataspace) {
3322     return HWC2_ERROR_BAD_PARAMETER;
3323   }
3324 
3325   if (display != HWC_DISPLAY_PRIMARY) {
3326     return HWC2_ERROR_UNSUPPORTED;
3327   }
3328 
3329   HWCDisplay *hwc_display = hwc_display_[display];
3330   if (hwc_display == nullptr) {
3331     return HWC2_ERROR_BAD_DISPLAY;
3332   } else if (!hwc_display->HasReadBackBufferSupport()) {
3333     return HWC2_ERROR_UNSUPPORTED;
3334   }
3335 
3336   *format = HAL_PIXEL_FORMAT_RGB_888;
3337   *dataspace = GetDataspaceFromColorMode(hwc_display->GetCurrentColorMode());
3338 
3339   return HWC2_ERROR_NONE;
3340 }
3341 
SetReadbackBuffer(hwc2_display_t display,const native_handle_t * buffer,const shared_ptr<Fence> & acquire_fence)3342 int32_t HWCSession::SetReadbackBuffer(hwc2_display_t display, const native_handle_t *buffer,
3343                                       const shared_ptr<Fence> &acquire_fence) {
3344 
3345   if (display >= HWCCallbacks::kNumDisplays) {
3346     return HWC2_ERROR_BAD_DISPLAY;
3347   }
3348 
3349   if (!buffer) {
3350     return HWC2_ERROR_BAD_PARAMETER;
3351   }
3352 
3353   if (display != HWC_DISPLAY_PRIMARY) {
3354     return HWC2_ERROR_UNSUPPORTED;
3355   }
3356 
3357   int external_dpy_index = GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
3358   int virtual_dpy_index = GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
3359   if (((external_dpy_index != -1) && hwc_display_[external_dpy_index]) ||
3360       ((virtual_dpy_index != -1) && hwc_display_[virtual_dpy_index])) {
3361     return HWC2_ERROR_UNSUPPORTED;
3362   }
3363 
3364   return CallDisplayFunction(display, &HWCDisplay::SetReadbackBuffer, buffer, acquire_fence,
3365                              false, kCWBClientComposer);
3366 }
3367 
GetReadbackBufferFence(hwc2_display_t display,shared_ptr<Fence> * release_fence)3368 int32_t HWCSession::GetReadbackBufferFence(hwc2_display_t display,
3369                                            shared_ptr<Fence> *release_fence) {
3370   if (display >= HWCCallbacks::kNumDisplays) {
3371     return HWC2_ERROR_BAD_DISPLAY;
3372   }
3373 
3374   if (!release_fence) {
3375     return HWC2_ERROR_BAD_PARAMETER;
3376   }
3377 
3378   if (display != HWC_DISPLAY_PRIMARY) {
3379     return HWC2_ERROR_UNSUPPORTED;
3380   }
3381 
3382   return CallDisplayFunction(display, &HWCDisplay::GetReadbackBufferFence, release_fence);
3383 }
3384 
GetDisplayIdentificationData(hwc2_display_t display,uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)3385 int32_t HWCSession::GetDisplayIdentificationData(hwc2_display_t display, uint8_t *outPort,
3386                                                  uint32_t *outDataSize, uint8_t *outData) {
3387   if (!outPort || !outDataSize) {
3388     return HWC2_ERROR_BAD_PARAMETER;
3389   }
3390 
3391   if (display >= HWCCallbacks::kNumDisplays) {
3392     return HWC2_ERROR_BAD_DISPLAY;
3393   }
3394 
3395   return CallDisplayFunction(display, &HWCDisplay::GetDisplayIdentificationData, outPort,
3396                              outDataSize, outData);
3397 }
3398 
GetDisplayCapabilities(hwc2_display_t display,uint32_t * outNumCapabilities,uint32_t * outCapabilities)3399 int32_t HWCSession::GetDisplayCapabilities(hwc2_display_t display, uint32_t *outNumCapabilities,
3400                                            uint32_t *outCapabilities) {
3401   if (!outNumCapabilities) {
3402     return HWC2_ERROR_BAD_PARAMETER;
3403   }
3404 
3405   if (display >= HWCCallbacks::kNumDisplays) {
3406     return HWC2_ERROR_BAD_DISPLAY;
3407   }
3408 
3409   if (!hwc_display_[display]) {
3410     DLOGE("Expected valid hwc_display");
3411     return HWC2_ERROR_BAD_PARAMETER;
3412   }
3413 
3414   bool isBuiltin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
3415   *outNumCapabilities = 0;
3416   if (isBuiltin) {
3417     *outNumCapabilities = 3;
3418     if (outCapabilities != nullptr) {
3419       // TODO(user): Handle SKIP_CLIENT_COLOR_TRANSFORM based on DSPP availability
3420       outCapabilities[0] = static_cast<uint32_t>(HwcDisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
3421       outCapabilities[1] = static_cast<uint32_t>(HwcDisplayCapability::DOZE);
3422       outCapabilities[2] = static_cast<uint32_t>(HwcDisplayCapability::BRIGHTNESS);
3423     }
3424   }
3425 
3426   return HWC2_ERROR_NONE;
3427 }
3428 
GetDisplayCapabilities_2_4(hwc2_display_t display,uint32_t * outNumCapabilities,uint32_t * outCapabilities)3429 int32_t HWCSession::GetDisplayCapabilities_2_4(hwc2_display_t display, uint32_t *outNumCapabilities,
3430                                                uint32_t *outCapabilities) {
3431   if (!outNumCapabilities) {
3432     return HWC2_ERROR_BAD_PARAMETER;
3433   }
3434 
3435   if (display >= HWCCallbacks::kNumDisplays) {
3436     return HWC2_ERROR_BAD_DISPLAY;
3437   }
3438 
3439   if (!hwc_display_[display]) {
3440     DLOGE("Expected valid hwc_display");
3441     return HWC2_ERROR_BAD_PARAMETER;
3442   }
3443 
3444   bool isBuiltin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
3445   *outNumCapabilities = 0;
3446   if (isBuiltin) {
3447     *outNumCapabilities = 1;
3448     if (outCapabilities != nullptr) {
3449       outCapabilities[0] = static_cast<uint32_t>(HwcDisplayCapability::PROTECTED_CONTENTS);
3450     }
3451   }
3452 
3453   return HWC2_ERROR_NONE;
3454 }
3455 
GetDisplayConnectionType(hwc2_display_t display,HwcDisplayConnectionType * type)3456 int32_t HWCSession::GetDisplayConnectionType(hwc2_display_t display,
3457                                              HwcDisplayConnectionType *type) {
3458   if (display >= HWCCallbacks::kNumDisplays) {
3459     return HWC2_ERROR_BAD_DISPLAY;
3460   }
3461 
3462   if (!type) {
3463     return HWC2_ERROR_BAD_PARAMETER;
3464   }
3465 
3466   if (!hwc_display_[display]) {
3467     DLOGE("Expected valid hwc_display");
3468     return HWC2_ERROR_BAD_DISPLAY;
3469   }
3470   *type = HwcDisplayConnectionType::EXTERNAL;
3471   if (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
3472     *type = HwcDisplayConnectionType::INTERNAL;
3473   }
3474 
3475   return HWC2_ERROR_NONE;
3476 }
3477 
GetDisplayBrightnessSupport(hwc2_display_t display,bool * outSupport)3478 int32_t HWCSession::GetDisplayBrightnessSupport(hwc2_display_t display, bool *outSupport) {
3479   if (!outSupport) {
3480     return HWC2_ERROR_BAD_PARAMETER;
3481   }
3482 
3483   if (display >= HWCCallbacks::kNumDisplays) {
3484     return HWC2_ERROR_BAD_DISPLAY;
3485   }
3486 
3487   if (!hwc_display_[display]) {
3488     DLOGE("Expected valid hwc_display");
3489     return HWC2_ERROR_BAD_PARAMETER;
3490   }
3491   *outSupport = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
3492   return HWC2_ERROR_NONE;
3493 }
3494 
SetDisplayBrightness(hwc2_display_t display,float brightness)3495 int32_t HWCSession::SetDisplayBrightness(hwc2_display_t display, float brightness) {
3496   if (display >= HWCCallbacks::kNumDisplays) {
3497     return HWC2_ERROR_BAD_DISPLAY;
3498   }
3499 
3500   if (!hwc_display_[display]) {
3501     return HWC2_ERROR_BAD_PARAMETER;
3502   }
3503 
3504   return INT32(hwc_display_[display]->SetPanelBrightness(brightness));
3505 }
3506 
SetQSyncMode(const android::Parcel * input_parcel)3507 android::status_t HWCSession::SetQSyncMode(const android::Parcel *input_parcel) {
3508   auto mode = input_parcel->readInt32();
3509 
3510   QSyncMode qsync_mode = kQSyncModeNone;
3511   switch (mode) {
3512     case qService::IQService::QSYNC_MODE_NONE:
3513       qsync_mode = kQSyncModeNone;
3514       break;
3515     case qService::IQService::QSYNC_MODE_CONTINUOUS:
3516       qsync_mode = kQSyncModeContinuous;
3517       break;
3518     case qService::IQService::QSYNC_MODE_ONESHOT:
3519       qsync_mode = kQsyncModeOneShot;
3520       break;
3521     default:
3522       DLOGE("Qsync mode not supported %d", mode);
3523       return -EINVAL;
3524   }
3525   return CallDisplayFunction(HWC_DISPLAY_PRIMARY, &HWCDisplay::SetQSyncMode, qsync_mode);
3526 }
3527 
UpdateThrottlingRate()3528 void HWCSession::UpdateThrottlingRate() {
3529   uint32_t new_min = 0;
3530 
3531   for (int i=0; i < HWCCallbacks::kNumDisplays; i++) {
3532     auto &display = hwc_display_[i];
3533     if (!display)
3534       continue;
3535     if (display->GetCurrentPowerMode() != HWC2::PowerMode::Off)
3536       new_min = (new_min == 0) ? display->GetMaxRefreshRate() :
3537         std::min(new_min, display->GetMaxRefreshRate());
3538   }
3539 
3540   SetNewThrottlingRate(new_min);
3541 }
3542 
SetNewThrottlingRate(const uint32_t new_rate)3543 void HWCSession::SetNewThrottlingRate(const uint32_t new_rate) {
3544   if (new_rate !=0 && throttling_refresh_rate_ != new_rate) {
3545     HWCDisplay::SetThrottlingRefreshRate(new_rate);
3546     throttling_refresh_rate_ = new_rate;
3547   }
3548 }
3549 
SetIdlePC(const android::Parcel * input_parcel)3550 android::status_t HWCSession::SetIdlePC(const android::Parcel *input_parcel) {
3551   auto enable = input_parcel->readInt32();
3552   auto synchronous = input_parcel->readInt32();
3553 
3554   return static_cast<android::status_t>(ControlIdlePowerCollapse(enable, synchronous));
3555 }
3556 
GetActiveBuiltinDisplay()3557 hwc2_display_t HWCSession::GetActiveBuiltinDisplay() {
3558   hwc2_display_t active_display = HWCCallbacks::kNumDisplays;
3559   // Get first active display among primary and built-in displays.
3560   std::vector<DisplayMapInfo> map_info = {map_info_primary_};
3561   std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
3562 
3563   for (auto &info : map_info) {
3564     hwc2_display_t target_display = info.client_id;
3565     SCOPE_LOCK(power_state_[target_display]);
3566     if (power_state_transition_[target_display]) {
3567       // Route all interactions with client to dummy display.
3568       target_display = map_hwc_display_.find(target_display)->second;
3569     }
3570     Locker::ScopeLock lock_d(locker_[target_display]);
3571     auto &hwc_display = hwc_display_[target_display];
3572     if (hwc_display && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3573       active_display = info.client_id;
3574       break;
3575     }
3576   }
3577 
3578   return active_display;
3579 }
3580 
SetDisplayBrightnessScale(const android::Parcel * input_parcel)3581 int32_t HWCSession::SetDisplayBrightnessScale(const android::Parcel *input_parcel) {
3582   auto display = input_parcel->readInt32();
3583   auto level = input_parcel->readInt32();
3584   if (level < 0 || level > kBrightnessScaleMax) {
3585     DLOGE("Invalid backlight scale level %d", level);
3586     return -EINVAL;
3587   }
3588   auto bl_scale = level * kSvBlScaleMax / kBrightnessScaleMax;
3589   auto error = CallDisplayFunction(display, &HWCDisplay::SetBLScale, (uint32_t)bl_scale);
3590   if (INT32(error) == HWC2_ERROR_NONE) {
3591     callbacks_.Refresh(display);
3592   }
3593 
3594   return INT32(error);
3595 }
3596 
NotifyClientStatus(bool connected)3597 void HWCSession::NotifyClientStatus(bool connected) {
3598   for (uint32_t i = 0; i < HWCCallbacks::kNumDisplays; i++) {
3599     if (!hwc_display_[i]) {
3600       continue;
3601     }
3602     SCOPE_LOCK(locker_[i]);
3603     hwc_display_[i]->NotifyClientStatus(connected);
3604     hwc_display_[i]->SetVsyncEnabled(HWC2::Vsync::Disable);
3605   }
3606   callbacks_.UpdateVsyncSource(HWCCallbacks::kNumDisplays);
3607 }
3608 
WaitForResources(bool wait_for_resources,hwc2_display_t active_builtin_id,hwc2_display_t display_id)3609 void HWCSession::WaitForResources(bool wait_for_resources, hwc2_display_t active_builtin_id,
3610                                   hwc2_display_t display_id) {
3611   std::vector<DisplayMapInfo> map_info = {map_info_primary_};
3612   std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
3613 
3614   for (auto &info : map_info) {
3615     hwc2_display_t target_display = info.client_id;
3616     {
3617       SCOPE_LOCK(power_state_[target_display]);
3618       if (power_state_transition_[target_display]) {
3619         // Route all interactions with client to dummy display.
3620         target_display = map_hwc_display_.find(target_display)->second;
3621       }
3622     }
3623     {
3624       SEQUENCE_WAIT_SCOPE_LOCK(locker_[target_display]);
3625       auto &hwc_display = hwc_display_[target_display];
3626       if (hwc_display && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3627         hwc_display->ResetValidation();
3628       }
3629     }
3630   }
3631 
3632   if (wait_for_resources) {
3633     bool res_wait = true;
3634     do {
3635       if (client_connected_) {
3636         Refresh(active_builtin_id);
3637       }
3638       {
3639         std::unique_lock<std::mutex> caller_lock(hotplug_mutex_);
3640         hotplug_cv_.wait(caller_lock);
3641       }
3642       res_wait = hwc_display_[display_id]->CheckResourceState();
3643     } while (res_wait);
3644   }
3645 }
3646 
GetDisplayVsyncPeriod(hwc2_display_t disp,VsyncPeriodNanos * vsync_period)3647 int32_t HWCSession::GetDisplayVsyncPeriod(hwc2_display_t disp, VsyncPeriodNanos *vsync_period) {
3648   if (vsync_period == nullptr) {
3649     return HWC2_ERROR_BAD_PARAMETER;
3650   }
3651 
3652   return CallDisplayFunction(disp, &HWCDisplay::GetDisplayVsyncPeriod, vsync_period);
3653 }
3654 
SetActiveConfigWithConstraints(hwc2_display_t display,hwc2_config_t config,const VsyncPeriodChangeConstraints * vsync_period_change_constraints,VsyncPeriodChangeTimeline * out_timeline)3655 int32_t HWCSession::SetActiveConfigWithConstraints(
3656     hwc2_display_t display, hwc2_config_t config,
3657     const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
3658     VsyncPeriodChangeTimeline *out_timeline) {
3659   if ((vsync_period_change_constraints == nullptr) || (out_timeline == nullptr)) {
3660     return HWC2_ERROR_BAD_PARAMETER;
3661   }
3662 
3663   return CallDisplayFunction(display, &HWCDisplay::SetActiveConfigWithConstraints, config,
3664                              vsync_period_change_constraints, out_timeline);
3665 }
3666 
SetAutoLowLatencyMode(hwc2_display_t display,bool on)3667 int32_t HWCSession::SetAutoLowLatencyMode(hwc2_display_t display, bool on) {
3668   if (display >= HWCCallbacks::kNumDisplays) {
3669     return HWC2_ERROR_BAD_DISPLAY;
3670   }
3671 
3672   return CallDisplayFunction(display, &HWCDisplay::SetAutoLowLatencyMode, on);
3673 }
3674 
GetSupportedContentTypes(hwc2_display_t display,hidl_vec<HwcContentType> * types)3675 int32_t HWCSession::GetSupportedContentTypes(hwc2_display_t display,
3676                                              hidl_vec<HwcContentType> *types) {
3677   if (display >= HWCCallbacks::kNumDisplays) {
3678     return HWC2_ERROR_BAD_DISPLAY;
3679   }
3680 
3681   return CallDisplayFunction(display, &HWCDisplay::GetSupportedContentTypes, types);
3682 }
3683 
SetContentType(hwc2_display_t display,HwcContentType type)3684 int32_t HWCSession::SetContentType(hwc2_display_t display, HwcContentType type) {
3685   if (display >= HWCCallbacks::kNumDisplays) {
3686     return HWC2_ERROR_BAD_DISPLAY;
3687   }
3688 
3689   return CallDisplayFunction(display, &HWCDisplay::SetContentType, type);
3690 }
3691 
IsHbmSupported()3692 bool HWCSession::IsHbmSupported() {
3693   auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
3694 
3695   if (hwc_display)
3696     return hwc_display->IsHbmSupported();
3697 
3698   return 0;
3699 }
3700 
SetHbmState(HbmState state)3701 void HWCSession::SetHbmState(HbmState state) {
3702   CallDisplayFunction(HWC_DISPLAY_PRIMARY, &HWCDisplay::SetHbm, state, HWCDisplay::APP);
3703 }
3704 
GetHbmState()3705 HbmState HWCSession::GetHbmState() {
3706   auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
3707 
3708   if (hwc_display)
3709     return hwc_display->GetHbm();
3710 
3711   return HbmState::OFF;
3712 }
3713 
IsLbeSupported()3714 bool HWCSession::IsLbeSupported() {
3715   return (is_lbe_supported_ != 0);
3716 }
3717 
SetLbeState(LbeState state)3718 void HWCSession::SetLbeState(LbeState state) {
3719   std::string_view state_cmd;
3720   int ret = 0;
3721 
3722   if (!is_lbe_supported_) {
3723     DLOGE("lbe is not supported");
3724     return;
3725   }
3726 
3727   if (lbe_cur_state_ == state)
3728     return;
3729 
3730   switch (state) {
3731     case LbeState::OFF:
3732       state_cmd = ltm_off_cmd_;
3733       break;
3734     case LbeState::NORMAL:
3735       state_cmd = ltm_default_mode_cmd_;
3736       break;
3737     case LbeState::HIGH_BRIGHTNESS:
3738       state_cmd = ltm_hbm_mode_cmd_;
3739       break;
3740     case LbeState::POWER_SAVE:
3741       state_cmd = ltm_power_save_mode_cmd_;
3742       break;
3743     default:
3744       DLOGE("lbe mode not support");
3745       return;
3746   }
3747 
3748   if (lbe_cur_state_ == LbeState::OFF) {
3749     std::string_view on_cmd = ltm_on_cmd_;
3750     ret = SendLTMCommand(on_cmd.data());
3751     if (ret) {
3752       DLOGE("failed to enable lbe");
3753       return;
3754     }
3755   }
3756 
3757   ret = SendLTMCommand(state_cmd.data());
3758   if (!ret)
3759     lbe_cur_state_ = state;
3760 }
3761 
SetLbeAmbientLight(int value)3762 void HWCSession::SetLbeAmbientLight(int value) {
3763   if (!is_lbe_supported_ || value < 0 || (lbe_cur_state_ == LbeState::OFF))
3764     return;
3765 
3766   std::string cmd = ltm_lux_cmd_;
3767   std::string val = std::to_string(value);
3768 
3769   cmd += val;
3770 
3771   SendLTMCommand(cmd.c_str());
3772 }
3773 
GetLbeState()3774 LbeState HWCSession::GetLbeState() {
3775   return lbe_cur_state_;
3776 }
3777 
SendLTMCommand(const char * cmd)3778 int HWCSession::SendLTMCommand(const char *cmd) {
3779   if (!cmd || !pps_retry)
3780     return -EINVAL;
3781 
3782   while ((pps_retry > 0) && (pps_socket_ < 0)) {
3783     pps_socket_ = socket_local_client("pps", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
3784     if (pps_socket_ < 0) {
3785       pps_retry--;
3786       if (pps_retry == 0) {
3787         DLOGE("Connecting to pps socket failed, error = %s", strerror(errno));
3788         return -ETIMEDOUT;
3789       }
3790     }
3791   }
3792 
3793   int ret = write(pps_socket_, cmd, strlen(cmd));
3794   if (ret < 0) {
3795     DLOGE("Failed to send LTM cmd, error = %s", strerror(errno));
3796     return -EINVAL;
3797   }
3798   usleep(1000);
3799 
3800   return 0;
3801 }
3802 
3803 }  // namespace sdm
3804