1 /*
2 * Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above
10 *       copyright notice, this list of conditions and the following
11 *       disclaimer in the documentation and/or other materials provided
12 *       with the distribution.
13 *     * Neither the name of The Linux Foundation nor the names of its
14 *       contributors may be used to endorse or promote products derived
15 *       from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <core/dump_interface.h>
31 #include <core/buffer_allocator.h>
32 #include <private/color_params.h>
33 #include <utils/constants.h>
34 #include <utils/String16.h>
35 #include <cutils/properties.h>
36 #include <hardware_legacy/uevent.h>
37 #include <sys/resource.h>
38 #include <sys/prctl.h>
39 #include <binder/Parcel.h>
40 #include <QService.h>
41 #include <gr.h>
42 #include <gralloc_priv.h>
43 #include <display_config.h>
44 #include <utils/debug.h>
45 #include <sync/sync.h>
46 #include <profiler.h>
47 #include <bitset>
48 #include <vector>
49 
50 #include "hwc_buffer_allocator.h"
51 #include "hwc_buffer_sync_handler.h"
52 #include "hwc_session.h"
53 #include "hwc_debugger.h"
54 #include "hwc_display_null.h"
55 #include "hwc_display_primary.h"
56 #include "hwc_display_virtual.h"
57 #include "hwc_display_external_test.h"
58 #include "qd_utils.h"
59 
60 #define __CLASS__ "HWCSession"
61 
62 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
63 #define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
64 
65 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
66 
67 hwc_module_t HAL_MODULE_INFO_SYM = {
68   .common = {
69     .tag = HARDWARE_MODULE_TAG,
70     .version_major = 2,
71     .version_minor = 0,
72     .id = HWC_HARDWARE_MODULE_ID,
73     .name = "QTI Hardware Composer Module",
74     .author = "CodeAurora Forum",
75     .methods = &g_hwc_module_methods,
76     .dso = 0,
77     .reserved = {0},
78   }
79 };
80 
81 namespace sdm {
82 
83 Locker HWCSession::locker_;
84 
Invalidate(const struct hwc_procs * procs)85 static void Invalidate(const struct hwc_procs *procs) {
86 }
87 
VSync(const struct hwc_procs * procs,int disp,int64_t timestamp)88 static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) {
89 }
90 
Hotplug(const struct hwc_procs * procs,int disp,int connected)91 static void Hotplug(const struct hwc_procs* procs, int disp, int connected) {
92 }
93 
HWCSession(const hw_module_t * module)94 HWCSession::HWCSession(const hw_module_t *module) {
95   // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs.
96   hwc_procs_default_.invalidate = Invalidate;
97   hwc_procs_default_.vsync = VSync;
98   hwc_procs_default_.hotplug = Hotplug;
99 
100   hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
101   hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
102   hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
103   hwc_composer_device_1_t::common.close = Close;
104   hwc_composer_device_1_t::prepare = Prepare;
105   hwc_composer_device_1_t::set = Set;
106   hwc_composer_device_1_t::eventControl = EventControl;
107   hwc_composer_device_1_t::setPowerMode = SetPowerMode;
108   hwc_composer_device_1_t::query = Query;
109   hwc_composer_device_1_t::registerProcs = RegisterProcs;
110   hwc_composer_device_1_t::dump = Dump;
111   hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
112   hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
113   hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
114   hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
115   hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync;
116 }
117 
Init()118 int HWCSession::Init() {
119   int status = -EINVAL;
120   const char *qservice_name = "display.qservice";
121 
122   // Start QService and connect to it.
123   qService::QService::init();
124   android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
125                 android::defaultServiceManager()->getService(android::String16(qservice_name)));
126 
127   if (iqservice.get()) {
128     iqservice->connect(android::sp<qClient::IQClient>(this));
129     qservice_ = reinterpret_cast<qService::QService* >(iqservice.get());
130   } else {
131     DLOGE("Failed to acquire %s", qservice_name);
132     return -EINVAL;
133   }
134 
135   DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
136                                                  &buffer_sync_handler_, &socket_handler_,
137                                                  &core_intf_);
138   if (error != kErrorNone) {
139     DLOGE("Display core initialization failed. Error = %d", error);
140     return -EINVAL;
141   }
142 
143   SCOPE_LOCK(uevent_locker_);
144 
145   if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
146     DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
147     CoreInterface::DestroyCore();
148     return -errno;
149   }
150 
151   // Wait for uevent_init() to happen and let the uevent thread wait for uevents, so that hdmi
152   // connect/disconnect events won't be missed
153   uevent_locker_.Wait();
154 
155   // Read which display is first, and create it and store it in primary slot
156   HWDisplayInterfaceInfo hw_disp_info;
157   error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
158   if (error == kErrorNone) {
159     if (hw_disp_info.type == kHDMI) {
160       // HDMI is primary display. If already connected, then create it and store in
161       // primary display slot. If not connected, create a NULL display for now.
162       HWCDebugHandler::Get()->SetProperty("persist.sys.is_hdmi_primary", "1");
163       is_hdmi_primary_ = true;
164       if (hw_disp_info.is_connected) {
165         status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
166         is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
167       } else {
168         // NullDisplay simply closes all its fences, and advertizes a standard
169         // resolution to SurfaceFlinger
170         status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
171                                         &hwc_display_[HWC_DISPLAY_PRIMARY]);
172       }
173     } else {
174       // Create and power on primary display
175       status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
176                                          &hwc_display_[HWC_DISPLAY_PRIMARY]);
177     }
178   } else {
179     // Create and power on primary display
180     status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
181                                        &hwc_display_[HWC_DISPLAY_PRIMARY]);
182   }
183 
184   if (status) {
185     CoreInterface::DestroyCore();
186     uevent_thread_exit_ = true;
187     pthread_join(uevent_thread_, NULL);
188     return status;
189   }
190 
191   color_mgr_ = HWCColorManager::CreateColorManager();
192   if (!color_mgr_) {
193     DLOGW("Failed to load HWCColorManager.");
194   }
195 
196   connected_displays_[HWC_DISPLAY_PRIMARY] = 1;
197   struct rlimit fd_limit = {};
198   getrlimit(RLIMIT_NOFILE, &fd_limit);
199   fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
200   auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
201   if (err) {
202     DLOGW("Unable to increase fd limit -  err: %d, %s", errno, strerror(errno));
203   }
204   return 0;
205 }
206 
Deinit()207 int HWCSession::Deinit() {
208   HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
209   hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
210   if (color_mgr_) {
211     color_mgr_->DestroyColorManager();
212   }
213   uevent_thread_exit_ = true;
214   pthread_join(uevent_thread_, NULL);
215 
216   DisplayError error = CoreInterface::DestroyCore();
217   if (error != kErrorNone) {
218     DLOGE("Display core de-initialization failed. Error = %d", error);
219   }
220 
221   connected_displays_[HWC_DISPLAY_PRIMARY] = 0;
222   return 0;
223 }
224 
Open(const hw_module_t * module,const char * name,hw_device_t ** device)225 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
226   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
227 
228   if (!module || !name || !device) {
229     DLOGE("Invalid parameters.");
230     return -EINVAL;
231   }
232 
233   if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
234     HWCSession *hwc_session = new HWCSession(module);
235     if (!hwc_session) {
236       return -ENOMEM;
237     }
238 
239     int status = hwc_session->Init();
240     if (status != 0) {
241       delete hwc_session;
242       return status;
243     }
244 
245     hwc_composer_device_1_t *composer_device = hwc_session;
246     *device = reinterpret_cast<hw_device_t *>(composer_device);
247   }
248 
249   return 0;
250 }
251 
Close(hw_device_t * device)252 int HWCSession::Close(hw_device_t *device) {
253   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
254 
255   if (!device) {
256     return -EINVAL;
257   }
258 
259   hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device);
260   HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
261 
262   hwc_session->Deinit();
263   delete hwc_session;
264 
265   return 0;
266 }
267 
Prepare(hwc_composer_device_1 * device,size_t num_displays,hwc_display_contents_1_t ** displays)268 int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
269                         hwc_display_contents_1_t **displays) {
270   DTRACE_SCOPED();
271 
272   if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
273     return -EINVAL;
274   }
275 
276   HWCSession *hwc_session = static_cast<HWCSession *>(device);
277   hwc_procs_t const *hwc_procs = NULL;
278   bool hotplug_connect = false;
279 
280   // Hold mutex only in this scope.
281   {
282     SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
283 
284     hwc_procs = hwc_session->hwc_procs_;
285 
286     if (hwc_session->reset_panel_) {
287       DLOGW("panel is in bad state, resetting the panel");
288       hwc_session->ResetPanel();
289     }
290 
291     if (hwc_session->need_invalidate_) {
292       hwc_procs->invalidate(hwc_procs);
293       hwc_session->need_invalidate_ = false;
294     }
295 
296     hwc_session->HandleSecureDisplaySession(displays);
297 
298     if (hwc_session->color_mgr_) {
299       HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
300       if (primary_display && !hwc_session->is_hdmi_primary_) {
301         int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
302         if (ret)
303           return 0;
304       }
305     }
306 
307     for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) {
308       hwc_display_contents_1_t *content_list = displays[dpy];
309       // If external display is connected, ignore virtual display content list.
310       // If virtual display content list is valid, connect virtual display if not connected.
311       // If virtual display content list is invalid, disconnect virtual display if connected.
312       // If external display connection is pending, connect external display when virtual
313       // display is destroyed.
314       // If HDMI is primary and the output format is YUV then ignore the virtual display
315       // content list.
316       if (dpy == HWC_DISPLAY_VIRTUAL) {
317         if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL] ||
318                 (hwc_session->is_hdmi_primary_ && hwc_session->is_hdmi_yuv_)) {
319           continue;
320         }
321 
322         bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list);
323         bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
324 
325         if (valid_content && !connected) {
326           hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list);
327         } else if (!valid_content && connected) {
328           hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL);
329 
330           if (hwc_session->external_pending_connect_) {
331             DLOGI("Process pending external display connection");
332             hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
333             hwc_session->external_pending_connect_ = false;
334             hotplug_connect = true;
335           }
336         }
337       }
338 
339       if (hwc_session->hwc_display_[dpy]) {
340         if (!content_list) {
341           DLOGI("Display[%d] connected. content_list is null", dpy);
342         } else if (!content_list->numHwLayers) {
343           DLOGE("Display[%d] connected. numHwLayers is zero", dpy);
344         } else {
345           hwc_session->hwc_display_[dpy]->Prepare(content_list);
346         }
347       }
348     }
349   }
350 
351   if (hotplug_connect) {
352     // notify client
353     hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
354   }
355   // Return 0, else client will go into bad state
356   return 0;
357 }
358 
GetVsyncPeriod(int disp)359 int HWCSession::GetVsyncPeriod(int disp) {
360   SCOPE_LOCK(locker_);
361   // default value
362   int32_t vsync_period = 1000000000l / 60;
363   const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
364 
365   if (hwc_display_[disp]) {
366     hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
367   }
368 
369   return vsync_period;
370 }
371 
Set(hwc_composer_device_1 * device,size_t num_displays,hwc_display_contents_1_t ** displays)372 int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
373                     hwc_display_contents_1_t **displays) {
374   DTRACE_SCOPED();
375 
376   SEQUENCE_EXIT_SCOPE_LOCK(locker_);
377 
378   if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
379     return -EINVAL;
380   }
381 
382   HWCSession *hwc_session = static_cast<HWCSession *>(device);
383 
384   if (hwc_session->color_mgr_) {
385     HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
386     if (primary_display) {
387       int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display);
388       if (ret)
389         return 0;
390       hwc_session->color_mgr_->SetColorModeDetailEnhancer(primary_display);
391     }
392   }
393 
394   for (size_t dpy = 0; dpy < num_displays; dpy++) {
395     hwc_display_contents_1_t *content_list = displays[dpy];
396 
397     // Drop virtual display composition if virtual display object could not be created
398     // due to HDMI concurrency.
399     if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
400       CloseAcquireFds(content_list);
401       if (content_list) {
402         content_list->retireFenceFd = -1;
403       }
404 
405       continue;
406     }
407 
408     if (hwc_session->hwc_display_[dpy]) {
409       hwc_session->hwc_display_[dpy]->Commit(content_list);
410     }
411     CloseAcquireFds(content_list);
412   }
413 
414   if (hwc_session->new_bw_mode_) {
415     hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
416     hwc_session->new_bw_mode_ = false;
417     if (hwc_session->bw_mode_release_fd_ >= 0) {
418       close(hwc_session->bw_mode_release_fd_);
419     }
420     hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
421   }
422 
423   // This is only indicative of how many times SurfaceFlinger posts
424   // frames to the display.
425   CALC_FPS();
426 
427   // Return 0, else client will go into bad state
428   return 0;
429 }
430 
CloseAcquireFds(hwc_display_contents_1_t * content_list)431 void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
432   if (content_list) {
433     for (size_t i = 0; i < content_list->numHwLayers; i++) {
434       int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
435       if (acquireFenceFd >= 0) {
436         close(acquireFenceFd);
437         acquireFenceFd = -1;
438       }
439     }
440 
441     int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
442     if (outbufAcquireFenceFd >= 0) {
443       close(outbufAcquireFenceFd);
444       outbufAcquireFenceFd = -1;
445     }
446   }
447 }
448 
IsDisplayYUV(int disp)449 bool HWCSession::IsDisplayYUV(int disp) {
450   int error = -EINVAL;
451   bool is_yuv = false;
452   DisplayConfigVariableInfo attributes = {};
453 
454   if (disp < 0 || disp >= HWC_NUM_DISPLAY_TYPES || !hwc_display_[disp]) {
455     DLOGE("Invalid input parameters. Display = %d", disp);
456     return is_yuv;
457   }
458 
459   uint32_t active_config = 0;
460   error = hwc_display_[disp]->GetActiveDisplayConfig(&active_config);
461   if (!error) {
462     error = hwc_display_[disp]->GetDisplayAttributesForConfig(INT(active_config), &attributes);
463     if (error == 0) {
464       is_yuv = attributes.is_yuv;
465     } else {
466       DLOGW("Error querying display attributes. Display = %d, Config = %d", disp, active_config);
467     }
468   }
469 
470   return is_yuv;
471 }
472 
EventControl(hwc_composer_device_1 * device,int disp,int event,int enable)473 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
474   SCOPE_LOCK(locker_);
475 
476   if (!device) {
477     return -EINVAL;
478   }
479 
480   HWCSession *hwc_session = static_cast<HWCSession *>(device);
481   int status = -EINVAL;
482   if (hwc_session->hwc_display_[disp]) {
483     status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
484   }
485 
486   return status;
487 }
488 
SetPowerMode(hwc_composer_device_1 * device,int disp,int mode)489 int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
490   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
491 
492   if (!device) {
493     return -EINVAL;
494   }
495 
496   HWCSession *hwc_session = static_cast<HWCSession *>(device);
497   int status = -EINVAL;
498   if (hwc_session->hwc_display_[disp]) {
499     status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
500   }
501 
502   return status;
503 }
504 
Query(hwc_composer_device_1 * device,int param,int * value)505 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
506   SCOPE_LOCK(locker_);
507 
508   if (!device || !value) {
509     return -EINVAL;
510   }
511 
512   int status = 0;
513 
514   switch (param) {
515   case HWC_BACKGROUND_LAYER_SUPPORTED:
516     value[0] = 1;
517     break;
518 
519   default:
520     status = -EINVAL;
521   }
522 
523   return status;
524 }
525 
RegisterProcs(hwc_composer_device_1 * device,hwc_procs_t const * procs)526 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
527   SCOPE_LOCK(locker_);
528 
529   if (!device || !procs) {
530     return;
531   }
532 
533   HWCSession *hwc_session = static_cast<HWCSession *>(device);
534   hwc_session->hwc_procs_ = procs;
535 }
536 
Dump(hwc_composer_device_1 * device,char * buffer,int length)537 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
538   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
539 
540   if (!device || !buffer || !length) {
541     return;
542   }
543 
544   DumpInterface::GetDump(buffer, UINT32(length));
545 }
546 
GetDisplayConfigs(hwc_composer_device_1 * device,int disp,uint32_t * configs,size_t * num_configs)547 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
548                                   size_t *num_configs) {
549   SCOPE_LOCK(locker_);
550 
551   if (!device || !configs || !num_configs) {
552     return -EINVAL;
553   }
554 
555   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
556     return -EINVAL;
557   }
558 
559   HWCSession *hwc_session = static_cast<HWCSession *>(device);
560   int status = -EINVAL;
561   if (hwc_session->hwc_display_[disp]) {
562     status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
563   }
564 
565   return status;
566 }
567 
GetDisplayAttributes(hwc_composer_device_1 * device,int disp,uint32_t config,const uint32_t * display_attributes,int32_t * values)568 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
569                                      const uint32_t *display_attributes, int32_t *values) {
570   SCOPE_LOCK(locker_);
571 
572   if (!device || !display_attributes || !values) {
573     return -EINVAL;
574   }
575 
576   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
577     return -EINVAL;
578   }
579 
580   HWCSession *hwc_session = static_cast<HWCSession *>(device);
581   int status = -EINVAL;
582   if (hwc_session->hwc_display_[disp]) {
583     status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
584                                                                    values);
585   }
586 
587   return status;
588 }
589 
GetActiveConfig(hwc_composer_device_1 * device,int disp)590 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
591   SCOPE_LOCK(locker_);
592 
593   if (!device) {
594     return -EINVAL;
595   }
596 
597   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
598     return -EINVAL;
599   }
600 
601   HWCSession *hwc_session = static_cast<HWCSession *>(device);
602   int active_config = -1;
603   if (hwc_session->hwc_display_[disp]) {
604     active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
605   }
606 
607   return active_config;
608 }
609 
SetActiveConfig(hwc_composer_device_1 * device,int disp,int index)610 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
611   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
612 
613   if (!device) {
614     return -EINVAL;
615   }
616 
617   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
618     return -EINVAL;
619   }
620 
621   HWCSession *hwc_session = static_cast<HWCSession *>(device);
622   int status = -EINVAL;
623 
624   if (hwc_session->hwc_display_[disp]) {
625     status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
626   }
627 
628   return status;
629 }
630 
SetCursorPositionAsync(hwc_composer_device_1 * device,int disp,int x,int y)631 int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
632   DTRACE_SCOPED();
633 
634   SCOPE_LOCK(locker_);
635 
636   if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
637     return -EINVAL;
638   }
639 
640   int status = -EINVAL;
641   HWCSession *hwc_session = static_cast<HWCSession *>(device);
642   if (hwc_session->hwc_display_[disp]) {
643     status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
644   }
645 
646   return status;
647 }
648 
ConnectDisplay(int disp,hwc_display_contents_1_t * content_list)649 int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
650   DLOGI("Display = %d", disp);
651 
652   int status = 0;
653   uint32_t primary_width = 0;
654   uint32_t primary_height = 0;
655 
656   hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
657 
658   if (disp == HWC_DISPLAY_EXTERNAL) {
659     status = CreateExternalDisplay(disp, primary_width, primary_height, false);
660     connected_displays_[HWC_DISPLAY_EXTERNAL] = 1;
661   } else if (disp == HWC_DISPLAY_VIRTUAL) {
662     status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
663                                        content_list, &hwc_display_[disp]);
664     connected_displays_[HWC_DISPLAY_VIRTUAL] = 1;
665   } else {
666     DLOGE("Invalid display type");
667     return -1;
668   }
669 
670   if (!status) {
671     hwc_display_[disp]->SetSecureDisplay(secure_display_active_, true);
672   }
673 
674   return status;
675 }
676 
DisconnectDisplay(int disp)677 int HWCSession::DisconnectDisplay(int disp) {
678   DLOGI("Display = %d", disp);
679 
680   if (disp == HWC_DISPLAY_EXTERNAL) {
681     HWCDisplayExternal::Destroy(hwc_display_[disp]);
682     connected_displays_[HWC_DISPLAY_EXTERNAL] = 0;
683   } else if (disp == HWC_DISPLAY_VIRTUAL) {
684     HWCDisplayVirtual::Destroy(hwc_display_[disp]);
685     connected_displays_[HWC_DISPLAY_VIRTUAL] = 0;
686   } else {
687     DLOGE("Invalid display type");
688     return -1;
689   }
690 
691   hwc_display_[disp] = NULL;
692 
693   return 0;
694 }
695 
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)696 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
697                                              android::Parcel *output_parcel) {
698   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
699 
700   android::status_t status = 0;
701 
702   switch (command) {
703   case qService::IQService::DYNAMIC_DEBUG:
704     DynamicDebug(input_parcel);
705     break;
706 
707   case qService::IQService::SCREEN_REFRESH:
708     hwc_procs_->invalidate(hwc_procs_);
709     break;
710 
711   case qService::IQService::SET_IDLE_TIMEOUT:
712     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
713       uint32_t timeout = UINT32(input_parcel->readInt32());
714       hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
715     }
716     break;
717 
718   case qService::IQService::SET_FRAME_DUMP_CONFIG:
719     SetFrameDumpConfig(input_parcel);
720     break;
721 
722   case qService::IQService::SET_MAX_PIPES_PER_MIXER:
723     status = SetMaxMixerStages(input_parcel);
724     break;
725 
726   case qService::IQService::SET_DISPLAY_MODE:
727     status = SetDisplayMode(input_parcel);
728     break;
729 
730   case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
731     status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
732     break;
733 
734   case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
735     status = ConfigureRefreshRate(input_parcel);
736     break;
737 
738   case qService::IQService::SET_VIEW_FRAME:
739     break;
740 
741   case qService::IQService::TOGGLE_SCREEN_UPDATES:
742     status = ToggleScreenUpdates(input_parcel, output_parcel);
743     break;
744 
745   case qService::IQService::QDCM_SVC_CMDS:
746     status = QdcmCMDHandler(input_parcel, output_parcel);
747     break;
748 
749   case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
750     status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
751     break;
752 
753   case qService::IQService::CONTROL_PARTIAL_UPDATE:
754     status = ControlPartialUpdate(input_parcel, output_parcel);
755     break;
756 
757   case qService::IQService::SET_ACTIVE_CONFIG:
758     status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
759     break;
760 
761   case qService::IQService::GET_ACTIVE_CONFIG:
762     status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
763     break;
764 
765   case qService::IQService::GET_CONFIG_COUNT:
766     status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
767     break;
768 
769   case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
770     status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
771     break;
772 
773   case qService::IQService::GET_PANEL_BRIGHTNESS:
774     status = GetPanelBrightness(input_parcel, output_parcel);
775     break;
776 
777   case qService::IQService::SET_PANEL_BRIGHTNESS:
778     status = SetPanelBrightness(input_parcel, output_parcel);
779     break;
780 
781   case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
782     status = GetVisibleDisplayRect(input_parcel, output_parcel);
783     break;
784 
785   case qService::IQService::SET_CAMERA_STATUS:
786     status = SetDynamicBWForCamera(input_parcel, output_parcel);
787     break;
788 
789   case qService::IQService::GET_BW_TRANSACTION_STATUS:
790     status = GetBWTransactionStatus(input_parcel, output_parcel);
791     break;
792 
793   case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
794     status = SetMixerResolution(input_parcel);
795     break;
796 
797   case qService::IQService::GET_HDR_CAPABILITIES:
798     status = GetHdrCapabilities(input_parcel, output_parcel);
799     break;
800 
801   default:
802     DLOGW("QService command = %d is not supported", command);
803     return -EINVAL;
804   }
805 
806   return status;
807 }
808 
ToggleScreenUpdates(const android::Parcel * input_parcel,android::Parcel * output_parcel)809 android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
810                                                   android::Parcel *output_parcel) {
811   int input = input_parcel->readInt32();
812   int error = android::BAD_VALUE;
813 
814   if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
815     error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
816     if (error != 0) {
817       DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
818     }
819   }
820   output_parcel->writeInt32(error);
821 
822   return error;
823 }
824 
SetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)825 android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
826                                                  android::Parcel *output_parcel) {
827   int level = input_parcel->readInt32();
828   int error = android::BAD_VALUE;
829 
830   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
831     error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
832     if (error != 0) {
833       DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
834     }
835   }
836   output_parcel->writeInt32(error);
837 
838   return error;
839 }
840 
GetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)841 android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
842                                                  android::Parcel *output_parcel) {
843   int error = android::BAD_VALUE;
844   int ret = error;
845 
846   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
847     error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
848     if (error != 0) {
849       ret = error;
850       DLOGE("Failed to get the panel brightness. Error = %d", error);
851     }
852   }
853   output_parcel->writeInt32(ret);
854 
855   return error;
856 }
857 
ControlPartialUpdate(const android::Parcel * input_parcel,android::Parcel * out)858 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
859                                                    android::Parcel *out) {
860   DisplayError error = kErrorNone;
861   int ret = 0;
862   uint32_t disp_id = UINT32(input_parcel->readInt32());
863   uint32_t enable = UINT32(input_parcel->readInt32());
864 
865   if (disp_id != HWC_DISPLAY_PRIMARY) {
866     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
867     ret = -EINVAL;
868     out->writeInt32(ret);
869     return ret;
870   }
871 
872   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
873     DLOGE("primary display object is not instantiated");
874     ret = -EINVAL;
875     out->writeInt32(ret);
876     return ret;
877   }
878 
879   uint32_t pending = 0;
880   error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
881 
882   if (error == kErrorNone) {
883     if (!pending) {
884       out->writeInt32(ret);
885       return ret;
886     }
887   } else if (error == kErrorNotSupported) {
888     out->writeInt32(ret);
889     return ret;
890   } else {
891     ret = -EINVAL;
892     out->writeInt32(ret);
893     return ret;
894   }
895 
896   // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
897   hwc_procs_->invalidate(hwc_procs_);
898 
899   // Wait until partial update control is complete
900   ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
901 
902   out->writeInt32(ret);
903 
904   return ret;
905 }
906 
HandleSetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)907 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
908                                                      android::Parcel *output_parcel) {
909   int config = input_parcel->readInt32();
910   int dpy = input_parcel->readInt32();
911   int error = android::BAD_VALUE;
912 
913   if (dpy > HWC_DISPLAY_VIRTUAL) {
914     return android::BAD_VALUE;
915   }
916 
917   if (hwc_display_[dpy]) {
918     error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
919     if (error == 0) {
920       hwc_procs_->invalidate(hwc_procs_);
921     }
922   }
923 
924   return error;
925 }
926 
HandleGetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)927 android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
928                                                            android::Parcel *output_parcel) {
929   int dpy = input_parcel->readInt32();
930   int error = android::BAD_VALUE;
931 
932   if (dpy > HWC_DISPLAY_VIRTUAL) {
933     return android::BAD_VALUE;
934   }
935 
936   if (hwc_display_[dpy]) {
937     uint32_t config = 0;
938     error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
939     if (error == 0) {
940       output_parcel->writeInt32(INT(config));
941     }
942   }
943 
944   return error;
945 }
946 
HandleGetDisplayConfigCount(const android::Parcel * input_parcel,android::Parcel * output_parcel)947 android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
948                                                           android::Parcel *output_parcel) {
949   int dpy = input_parcel->readInt32();
950   int error = android::BAD_VALUE;
951 
952   if (dpy > HWC_DISPLAY_VIRTUAL) {
953     return android::BAD_VALUE;
954   }
955 
956   uint32_t count = 0;
957   if (hwc_display_[dpy]) {
958     error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
959     if (error == 0) {
960       output_parcel->writeInt32(INT(count));
961     }
962   }
963 
964   return error;
965 }
966 
SetDisplayPort(DisplayPort sdm_disp_port,int * hwc_disp_port)967 android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
968   if (!hwc_disp_port) {
969     return -EINVAL;
970   }
971 
972   switch (sdm_disp_port) {
973     case kPortDSI:
974       *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
975       break;
976     case kPortDTV:
977       *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
978       break;
979     case kPortLVDS:
980       *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
981       break;
982     case kPortEDP:
983       *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
984       break;
985     case kPortWriteBack:
986       *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
987       break;
988     case kPortDP:
989       *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
990       break;
991     case kPortDefault:
992       *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
993       break;
994     default:
995       DLOGE("Invalid sdm display port %d", sdm_disp_port);
996       return -EINVAL;
997   }
998 
999   return 0;
1000 }
1001 
HandleGetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)1002 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
1003                                                                   *input_parcel,
1004                                                                   android::Parcel *output_parcel) {
1005   int config = input_parcel->readInt32();
1006   int dpy = input_parcel->readInt32();
1007   int error = android::BAD_VALUE;
1008   DisplayConfigVariableInfo display_attributes;
1009   DisplayPort sdm_disp_port = kPortDefault;
1010   int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
1011 
1012   if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
1013     return android::BAD_VALUE;
1014   }
1015 
1016   if (hwc_display_[dpy]) {
1017     error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
1018     if (error == 0) {
1019       hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
1020 
1021       SetDisplayPort(sdm_disp_port, &hwc_disp_port);
1022 
1023       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1024       output_parcel->writeInt32(INT(display_attributes.x_pixels));
1025       output_parcel->writeInt32(INT(display_attributes.y_pixels));
1026       output_parcel->writeFloat(display_attributes.x_dpi);
1027       output_parcel->writeFloat(display_attributes.y_dpi);
1028       output_parcel->writeInt32(hwc_disp_port);
1029       output_parcel->writeInt32(display_attributes.is_yuv);
1030     }
1031   }
1032 
1033   return error;
1034 }
1035 
SetSecondaryDisplayStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1036 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
1037                                                         android::Parcel *output_parcel) {
1038   int ret = -EINVAL;
1039 
1040   uint32_t display_id = UINT32(input_parcel->readInt32());
1041   uint32_t display_status = UINT32(input_parcel->readInt32());
1042 
1043   DLOGI("Display = %d, Status = %d", display_id, display_status);
1044 
1045   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1046     DLOGE("Invalid display_id");
1047   } else if (display_id == HWC_DISPLAY_PRIMARY) {
1048     DLOGE("Not supported for this display");
1049   } else if (!hwc_display_[display_id]) {
1050     DLOGW("Display is not connected");
1051   } else {
1052     ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
1053   }
1054 
1055   output_parcel->writeInt32(ret);
1056 
1057   return ret;
1058 }
1059 
ConfigureRefreshRate(const android::Parcel * input_parcel)1060 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1061   uint32_t operation = UINT32(input_parcel->readInt32());
1062   switch (operation) {
1063     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1064       return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1065           HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
1066     case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1067       return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1068           HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
1069     case qdutils::SET_BINDER_DYN_REFRESH_RATE:
1070       {
1071         uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1072         return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1073             HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
1074             refresh_rate);
1075       }
1076     default:
1077       DLOGW("Invalid operation %d", operation);
1078       return -EINVAL;
1079   }
1080 
1081   return 0;
1082 }
1083 
SetDisplayMode(const android::Parcel * input_parcel)1084 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1085   uint32_t mode = UINT32(input_parcel->readInt32());
1086   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
1087 }
1088 
SetMaxMixerStages(const android::Parcel * input_parcel)1089 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1090   DisplayError error = kErrorNone;
1091   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1092   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1093 
1094   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1095     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1096       error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
1097       if (error != kErrorNone) {
1098         return -EINVAL;
1099       }
1100     }
1101   }
1102 
1103   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1104     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1105       error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
1106       if (error != kErrorNone) {
1107         return -EINVAL;
1108       }
1109     }
1110   }
1111 
1112   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1113     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1114       error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
1115       if (error != kErrorNone) {
1116         return -EINVAL;
1117       }
1118     }
1119   }
1120 
1121   return 0;
1122 }
1123 
SetDynamicBWForCamera(const android::Parcel * input_parcel,android::Parcel * output_parcel)1124 android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
1125                                                     android::Parcel *output_parcel) {
1126   DisplayError error = kErrorNone;
1127   uint32_t camera_status = UINT32(input_parcel->readInt32());
1128   HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
1129 
1130   // trigger invalidate to apply new bw caps.
1131   hwc_procs_->invalidate(hwc_procs_);
1132 
1133     error = core_intf_->SetMaxBandwidthMode(mode);
1134   if (error != kErrorNone) {
1135       return -EINVAL;
1136   }
1137 
1138   new_bw_mode_ = true;
1139   need_invalidate_ = true;
1140 
1141   return 0;
1142 }
1143 
GetBWTransactionStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1144 android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
1145                                                      android::Parcel *output_parcel)  {
1146   bool state = true;
1147 
1148   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1149     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
1150       DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
1151       state = false;
1152     }
1153     output_parcel->writeInt32(state);
1154   }
1155 
1156   return 0;
1157 }
1158 
SetFrameDumpConfig(const android::Parcel * input_parcel)1159 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1160   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1161   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1162   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1163 
1164   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1165     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1166       hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1167     }
1168   }
1169 
1170   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1171     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1172       hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1173     }
1174   }
1175 
1176   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1177     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1178       hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1179     }
1180   }
1181 }
1182 
SetMixerResolution(const android::Parcel * input_parcel)1183 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1184   DisplayError error = kErrorNone;
1185   uint32_t dpy = UINT32(input_parcel->readInt32());
1186 
1187   if (dpy != HWC_DISPLAY_PRIMARY) {
1188     DLOGI("Resoulution change not supported for this display %d", dpy);
1189     return -EINVAL;
1190   }
1191 
1192   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1193     DLOGI("Primary display is not initialized");
1194     return -EINVAL;
1195   }
1196 
1197   uint32_t width = UINT32(input_parcel->readInt32());
1198   uint32_t height = UINT32(input_parcel->readInt32());
1199 
1200   error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
1201   if (error != kErrorNone) {
1202     return -EINVAL;
1203   }
1204 
1205   return 0;
1206 }
1207 
GetHdrCapabilities(const android::Parcel * input_parcel,android::Parcel * output_parcel)1208 android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel,
1209                                                  android::Parcel *output_parcel) {
1210   uint32_t display_id = UINT32(input_parcel->readInt32());
1211   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1212     DLOGE("Invalid display id = %d", display_id);
1213     return -EINVAL;
1214   }
1215 
1216   if (hwc_display_[display_id] == NULL) {
1217     DLOGW("Display = %d not initialized", display_id);
1218     return -EINVAL;
1219   }
1220 
1221   DisplayConfigFixedInfo fixed_info = {};
1222   int ret = hwc_display_[display_id]->GetDisplayFixedConfig(&fixed_info);
1223   if (ret) {
1224     DLOGE("Failed");
1225     return ret;
1226   }
1227 
1228   if (!fixed_info.hdr_supported) {
1229     DLOGI("HDR is not supported");
1230     return 0;
1231   }
1232 
1233   std::vector<int32_t> supported_hdr_types;
1234   // Only HDR10 supported now, in future add other supported HDR formats(HLG, DolbyVision)
1235   supported_hdr_types.push_back(HAL_HDR_HDR10);
1236 
1237   static const float kLuminanceFactor = 10000.0;
1238   // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
1239   float max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
1240   float max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
1241   float min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
1242 
1243   if (output_parcel != nullptr) {
1244     output_parcel->writeInt32Vector(supported_hdr_types);
1245     output_parcel->writeFloat(max_luminance);
1246     output_parcel->writeFloat(max_average_luminance);
1247     output_parcel->writeFloat(min_luminance);
1248   }
1249 
1250   return 0;
1251 }
1252 
DynamicDebug(const android::Parcel * input_parcel)1253 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
1254   int type = input_parcel->readInt32();
1255   bool enable = (input_parcel->readInt32() > 0);
1256   DLOGI("type = %d enable = %d", type, enable);
1257   int verbose_level = input_parcel->readInt32();
1258 
1259   switch (type) {
1260   case qService::IQService::DEBUG_ALL:
1261     HWCDebugHandler::DebugAll(enable, verbose_level);
1262     break;
1263 
1264   case qService::IQService::DEBUG_MDPCOMP:
1265     HWCDebugHandler::DebugStrategy(enable, verbose_level);
1266     HWCDebugHandler::DebugCompManager(enable, verbose_level);
1267     break;
1268 
1269   case qService::IQService::DEBUG_PIPE_LIFECYCLE:
1270     HWCDebugHandler::DebugResources(enable, verbose_level);
1271     break;
1272 
1273   case qService::IQService::DEBUG_DRIVER_CONFIG:
1274     HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1275     break;
1276 
1277   case qService::IQService::DEBUG_ROTATOR:
1278     HWCDebugHandler::DebugResources(enable, verbose_level);
1279     HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1280     HWCDebugHandler::DebugRotator(enable, verbose_level);
1281     break;
1282 
1283   case qService::IQService::DEBUG_QDCM:
1284     HWCDebugHandler::DebugQdcm(enable, verbose_level);
1285     break;
1286 
1287   default:
1288     DLOGW("type = %d is not supported", type);
1289   }
1290 }
1291 
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)1292 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
1293                                              android::Parcel *output_parcel) {
1294   int ret = 0;
1295   int32_t *brightness_value = NULL;
1296   uint32_t display_id(0);
1297   PPPendingParams pending_action;
1298   PPDisplayAPIPayload resp_payload, req_payload;
1299 
1300   if (!color_mgr_) {
1301     return -1;
1302   }
1303 
1304   pending_action.action = kNoAction;
1305   pending_action.params = NULL;
1306 
1307   // Read display_id, payload_size and payload from in_parcel.
1308   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
1309   if (!ret) {
1310     if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
1311       ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
1312                                                                   &resp_payload, &pending_action);
1313 
1314     if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
1315       ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
1316                                                                   &pending_action);
1317   }
1318 
1319   if (ret) {
1320     output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
1321     req_payload.DestroyPayload();
1322     resp_payload.DestroyPayload();
1323     return ret;
1324   }
1325 
1326   switch (pending_action.action) {
1327     case kInvalidating:
1328       hwc_procs_->invalidate(hwc_procs_);
1329       break;
1330     case kEnterQDCMMode:
1331       ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1332       break;
1333     case kExitQDCMMode:
1334       ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1335       break;
1336     case kApplySolidFill:
1337       ret = color_mgr_->SetSolidFill(pending_action.params,
1338                                      true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1339       hwc_procs_->invalidate(hwc_procs_);
1340       break;
1341     case kDisableSolidFill:
1342       ret = color_mgr_->SetSolidFill(pending_action.params,
1343                                      false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1344       hwc_procs_->invalidate(hwc_procs_);
1345       break;
1346     case kSetPanelBrightness:
1347       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1348       if (brightness_value == NULL) {
1349         DLOGE("Brightness value is Null");
1350         return -EINVAL;
1351       }
1352       if (HWC_DISPLAY_PRIMARY == display_id)
1353         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
1354       break;
1355     case kEnableFrameCapture:
1356       ret = color_mgr_->SetFrameCapture(pending_action.params,
1357                                         true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1358       hwc_procs_->invalidate(hwc_procs_);
1359       break;
1360     case kDisableFrameCapture:
1361       ret = color_mgr_->SetFrameCapture(pending_action.params,
1362                                         false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1363       break;
1364     case kConfigureDetailedEnhancer:
1365       ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
1366                                             hwc_display_[HWC_DISPLAY_PRIMARY]);
1367       hwc_procs_->invalidate(hwc_procs_);
1368       break;
1369     case kInvalidatingAndkSetPanelBrightness:
1370       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1371       if (brightness_value == NULL) {
1372         DLOGE("Brightness value is Null");
1373         return -EINVAL;
1374       }
1375       if (HWC_DISPLAY_PRIMARY == display_id)
1376         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value);
1377       hwc_procs_->invalidate(hwc_procs_);
1378       break;
1379     case kNoAction:
1380       break;
1381     default:
1382       DLOGW("Invalid pending action = %d!", pending_action.action);
1383       break;
1384   }
1385 
1386   // for display API getter case, marshall returned params into out_parcel.
1387   output_parcel->writeInt32(ret);
1388   HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1389   req_payload.DestroyPayload();
1390   resp_payload.DestroyPayload();
1391 
1392   return (ret? -EINVAL : 0);
1393 }
1394 
OnMinHdcpEncryptionLevelChange(const android::Parcel * input_parcel,android::Parcel * output_parcel)1395 android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
1396                                                              android::Parcel *output_parcel) {
1397   int ret = -EINVAL;
1398   uint32_t display_id = UINT32(input_parcel->readInt32());
1399   uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1400 
1401   DLOGI("Display %d", display_id);
1402 
1403   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1404     DLOGE("Invalid display_id");
1405   } else if (display_id != HWC_DISPLAY_EXTERNAL) {
1406     DLOGE("Not supported for display");
1407   } else if (!hwc_display_[display_id]) {
1408     DLOGW("Display is not connected");
1409   } else {
1410     ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
1411   }
1412 
1413   output_parcel->writeInt32(ret);
1414 
1415   return ret;
1416 }
1417 
HWCUeventThread(void * context)1418 void* HWCSession::HWCUeventThread(void *context) {
1419   if (context) {
1420     return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
1421   }
1422 
1423   return NULL;
1424 }
1425 
HWCUeventThreadHandler()1426 void* HWCSession::HWCUeventThreadHandler() {
1427   static char uevent_data[PAGE_SIZE];
1428   int length = 0;
1429 
1430   uevent_locker_.Lock();
1431   prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
1432   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1433   if (!uevent_init()) {
1434     DLOGE("Failed to init uevent");
1435     pthread_exit(0);
1436     uevent_locker_.Signal();
1437     uevent_locker_.Unlock();
1438     return NULL;
1439   }
1440 
1441   uevent_locker_.Signal();
1442   uevent_locker_.Unlock();
1443 
1444   while (!uevent_thread_exit_) {
1445     // keep last 2 zeroes to ensure double 0 termination
1446     length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
1447 
1448     if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
1449       DLOGI("Uevent HDMI = %s", uevent_data);
1450       int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
1451       if (connected >= 0) {
1452         DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
1453         if (HotPlugHandler(connected) == -1) {
1454           DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
1455         }
1456       }
1457     } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
1458       DLOGI("Uevent FB0 = %s", uevent_data);
1459       int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
1460       if (panel_reset == 0) {
1461         if (hwc_procs_) {
1462           reset_panel_ = true;
1463           hwc_procs_->invalidate(hwc_procs_);
1464         } else {
1465           DLOGW("Ignore resetpanel - hwc_proc not registered");
1466         }
1467       }
1468     }
1469   }
1470   pthread_exit(0);
1471 
1472   return NULL;
1473 }
1474 
GetEventValue(const char * uevent_data,int length,const char * event_info)1475 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
1476   const char *iterator_str = uevent_data;
1477   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
1478     const char *pstr = strstr(iterator_str, event_info);
1479     if (pstr != NULL) {
1480       return (atoi(iterator_str + strlen(event_info)));
1481     }
1482     iterator_str += strlen(iterator_str) + 1;
1483   }
1484 
1485   return -1;
1486 }
1487 
ResetPanel()1488 void HWCSession::ResetPanel() {
1489   int status = -EINVAL;
1490 
1491   DLOGI("Powering off primary");
1492   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
1493   if (status) {
1494     DLOGE("power-off on primary failed with error = %d", status);
1495   }
1496 
1497   DLOGI("Restoring power mode on primary");
1498   int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
1499   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
1500   if (status) {
1501     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
1502   }
1503 
1504   status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
1505   if (status) {
1506     DLOGE("enabling vsync failed for primary with error = %d", status);
1507   }
1508 
1509   reset_panel_ = false;
1510 }
1511 
HotPlugHandler(bool connected)1512 int HWCSession::HotPlugHandler(bool connected) {
1513   int status = 0;
1514   bool notify_hotplug = false;
1515   bool refresh_screen = false;
1516 
1517   // To prevent sending events to client while a lock is held, acquire scope locks only within
1518   // below scope so that those get automatically unlocked after the scope ends.
1519   {
1520     SEQUENCE_WAIT_SCOPE_LOCK(locker_);
1521 
1522     if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1523       DLOGE("Primay display is not connected.");
1524       return -1;
1525     }
1526 
1527 
1528     HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1529     HWCDisplay *external_display = NULL;
1530     HWCDisplay *null_display = NULL;
1531 
1532     if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
1533       external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
1534     } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) {
1535       null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
1536     }
1537 
1538     // If primary display connected is a NULL display, then replace it with the external display
1539     if (connected) {
1540       // If we are in HDMI as primary and the primary display just got plugged in
1541       if (is_hdmi_primary_ && null_display) {
1542         uint32_t primary_width, primary_height;
1543         int status = 0;
1544         null_display->GetFrameBufferResolution(&primary_width, &primary_height);
1545         delete null_display;
1546         hwc_display_[HWC_DISPLAY_PRIMARY] = NULL;
1547 
1548         // Create external display with a forced framebuffer resolution to that of what the NULL
1549         // display had. This is necessary because SurfaceFlinger does not dynamically update
1550         // framebuffer resolution once it reads it at bootup. So we always have to have the NULL
1551         // display/external display both at the bootup resolution.
1552         status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, primary_width, primary_height, true);
1553         if (status) {
1554           DLOGE("Could not create external display");
1555           return -1;
1556         }
1557 
1558         status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
1559         if (status) {
1560           DLOGE("power-on on primary failed with error = %d", status);
1561         }
1562 
1563         is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
1564 
1565         // Next, go ahead and enable vsync on external display. This is expliclity required
1566         // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying
1567         // changing display. and thus may not explicitly enable vsync
1568 
1569         status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true);
1570         if (status) {
1571           DLOGE("Error enabling vsync for HDMI as primary case");
1572         }
1573         // Don't do hotplug notification for HDMI as primary case for now
1574         notify_hotplug = false;
1575         refresh_screen = true;
1576       } else {
1577         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1578           DLOGE("HDMI is already connected");
1579           return -1;
1580         }
1581 
1582         // Connect external display if virtual display is not connected.
1583         // Else, defer external display connection and process it when virtual display
1584         // tears down; Do not notify SurfaceFlinger since connection is deferred now.
1585         if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1586           status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
1587           if (status) {
1588             return status;
1589           }
1590           notify_hotplug = true;
1591         } else {
1592           DLOGI("Virtual display is connected, pending connection");
1593           external_pending_connect_ = true;
1594         }
1595       }
1596     } else {
1597       // Do not return error if external display is not in connected status.
1598       // Due to virtual display concurrency, external display connection might be still pending
1599       // but hdmi got disconnected before pending connection could be processed.
1600 
1601       if (is_hdmi_primary_ && external_display) {
1602         uint32_t x_res, y_res;
1603         external_display->GetFrameBufferResolution(&x_res, &y_res);
1604         // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
1605         // for HDMI as primary
1606         external_display->EventControl(HWC_EVENT_VSYNC, false);
1607         HWCDisplayExternal::Destroy(external_display);
1608 
1609         HWCDisplayNull *null_display;
1610 
1611         int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
1612                                             reinterpret_cast<HWCDisplay **>(&null_display));
1613 
1614         if (status) {
1615           DLOGE("Could not create Null display when primary got disconnected");
1616           return -1;
1617         }
1618 
1619         null_display->SetResolution(x_res, y_res);
1620         hwc_display_[HWC_DISPLAY_PRIMARY] = null_display;
1621 
1622         // Don't do hotplug notification for HDMI as primary case for now
1623         notify_hotplug = false;
1624       } else {
1625         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1626           status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
1627           notify_hotplug = true;
1628         }
1629         external_pending_connect_ = false;
1630       }
1631     }
1632   }
1633 
1634   if (connected && (notify_hotplug || refresh_screen)) {
1635     // trigger screen refresh to ensure sufficient resources are available to process new
1636     // new display connection.
1637     hwc_procs_->invalidate(hwc_procs_);
1638     uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
1639     usleep(vsync_period * 2 / 1000);
1640   }
1641   // notify client
1642   if (notify_hotplug) {
1643     hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
1644   }
1645 
1646   qservice_->onHdmiHotplug(INT(connected));
1647 
1648   return 0;
1649 }
1650 
HandleSecureDisplaySession(hwc_display_contents_1_t ** displays)1651 void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
1652   secure_display_active_ = false;
1653   if (!*displays) {
1654     DLOGW("Invalid display contents");
1655     return;
1656   }
1657 
1658   hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
1659   if (!content_list) {
1660     DLOGW("Invalid primary content list");
1661     return;
1662   }
1663   size_t num_hw_layers = content_list->numHwLayers;
1664 
1665   for (size_t i = 0; i < num_hw_layers - 1; i++) {
1666     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
1667     const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
1668     if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
1669       secure_display_active_ = true;
1670     }
1671   }
1672 
1673   // Force flush on primary during transitions(secure<->non secure)
1674   // when external displays are connected.
1675   bool force_flush = false;
1676   if ((connected_displays_[HWC_DISPLAY_PRIMARY] == 1) &&
1677      ((connected_displays_[HWC_DISPLAY_EXTERNAL] == 1) ||
1678       (connected_displays_[HWC_DISPLAY_VIRTUAL] == 1))) {
1679     force_flush = true;
1680   }
1681 
1682   for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
1683     if (hwc_display_[dpy]) {
1684       hwc_display_[dpy]->SetSecureDisplay(secure_display_active_, force_flush);
1685     }
1686   }
1687 }
1688 
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)1689 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
1690                                                     android::Parcel *output_parcel) {
1691   int dpy = input_parcel->readInt32();
1692 
1693   if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
1694     return android::BAD_VALUE;;
1695   }
1696 
1697   if (!hwc_display_[dpy]) {
1698     return android::NO_INIT;
1699   }
1700 
1701   hwc_rect_t visible_rect = {0, 0, 0, 0};
1702   int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
1703   if (error < 0) {
1704     return error;
1705   }
1706 
1707   output_parcel->writeInt32(visible_rect.left);
1708   output_parcel->writeInt32(visible_rect.top);
1709   output_parcel->writeInt32(visible_rect.right);
1710   output_parcel->writeInt32(visible_rect.bottom);
1711 
1712   return android::NO_ERROR;
1713 }
1714 
CreateExternalDisplay(int disp,uint32_t primary_width,uint32_t primary_height,bool use_primary_res)1715 int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
1716                                       bool use_primary_res) {
1717   uint32_t panel_bpp = 0;
1718   uint32_t pattern_type = 0;
1719 
1720   if (qdutils::isDPConnected()) {
1721     qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
1722   }
1723 
1724   if (panel_bpp && pattern_type) {
1725     return HWCDisplayExternalTest::Create(core_intf_, &hwc_procs_, qservice_, panel_bpp,
1726                                           pattern_type, &hwc_display_[disp]);
1727   }
1728 
1729   return HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
1730                                     qservice_, use_primary_res, &hwc_display_[disp]);
1731 }
1732 
1733 }  // namespace sdm
1734 
1735