• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2014 - 2017, 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_session->AsyncRefresh();
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   locker_.Signal();
424 
425   // This is only indicative of how many times SurfaceFlinger posts
426   // frames to the display.
427   CALC_FPS();
428 
429   // Return 0, else client will go into bad state
430   return 0;
431 }
432 
CloseAcquireFds(hwc_display_contents_1_t * content_list)433 void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
434   if (content_list) {
435     for (size_t i = 0; i < content_list->numHwLayers; i++) {
436       int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
437       if (acquireFenceFd >= 0) {
438         close(acquireFenceFd);
439         acquireFenceFd = -1;
440       }
441     }
442 
443     int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
444     if (outbufAcquireFenceFd >= 0) {
445       close(outbufAcquireFenceFd);
446       outbufAcquireFenceFd = -1;
447     }
448   }
449 }
450 
IsDisplayYUV(int disp)451 bool HWCSession::IsDisplayYUV(int disp) {
452   int error = -EINVAL;
453   bool is_yuv = false;
454   DisplayConfigVariableInfo attributes = {};
455 
456   if (disp < 0 || disp >= HWC_NUM_DISPLAY_TYPES || !hwc_display_[disp]) {
457     DLOGE("Invalid input parameters. Display = %d", disp);
458     return is_yuv;
459   }
460 
461   uint32_t active_config = 0;
462   error = hwc_display_[disp]->GetActiveDisplayConfig(&active_config);
463   if (!error) {
464     error = hwc_display_[disp]->GetDisplayAttributesForConfig(INT(active_config), &attributes);
465     if (error == 0) {
466       is_yuv = attributes.is_yuv;
467     } else {
468       DLOGW("Error querying display attributes. Display = %d, Config = %d", disp, active_config);
469     }
470   }
471 
472   return is_yuv;
473 }
474 
EventControl(hwc_composer_device_1 * device,int disp,int event,int enable)475 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
476   SCOPE_LOCK(locker_);
477 
478   if (!device) {
479     return -EINVAL;
480   }
481 
482   HWCSession *hwc_session = static_cast<HWCSession *>(device);
483   int status = -EINVAL;
484   if (hwc_session->hwc_display_[disp]) {
485     status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
486   }
487 
488   return status;
489 }
490 
SetPowerMode(hwc_composer_device_1 * device,int disp,int mode)491 int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
492   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
493 
494   if (!device) {
495     return -EINVAL;
496   }
497 
498   HWCSession *hwc_session = static_cast<HWCSession *>(device);
499   int status = -EINVAL;
500   if (hwc_session->hwc_display_[disp]) {
501     status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
502   }
503 
504   return status;
505 }
506 
Query(hwc_composer_device_1 * device,int param,int * value)507 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
508   SCOPE_LOCK(locker_);
509 
510   if (!device || !value) {
511     return -EINVAL;
512   }
513 
514   int status = 0;
515 
516   switch (param) {
517   case HWC_BACKGROUND_LAYER_SUPPORTED:
518     value[0] = 1;
519     break;
520 
521   default:
522     status = -EINVAL;
523   }
524 
525   return status;
526 }
527 
RegisterProcs(hwc_composer_device_1 * device,hwc_procs_t const * procs)528 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
529   SCOPE_LOCK(locker_);
530 
531   if (!device || !procs) {
532     return;
533   }
534 
535   HWCSession *hwc_session = static_cast<HWCSession *>(device);
536   hwc_session->hwc_procs_ = procs;
537 }
538 
Dump(hwc_composer_device_1 * device,char * buffer,int length)539 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
540   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
541 
542   if (!device || !buffer || !length) {
543     return;
544   }
545 
546   DumpInterface::GetDump(buffer, UINT32(length));
547 }
548 
GetDisplayConfigs(hwc_composer_device_1 * device,int disp,uint32_t * configs,size_t * num_configs)549 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
550                                   size_t *num_configs) {
551   SCOPE_LOCK(locker_);
552 
553   if (!device || !configs || !num_configs) {
554     return -EINVAL;
555   }
556 
557   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
558     return -EINVAL;
559   }
560 
561   HWCSession *hwc_session = static_cast<HWCSession *>(device);
562   int status = -EINVAL;
563   if (hwc_session->hwc_display_[disp]) {
564     status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
565   }
566 
567   return status;
568 }
569 
GetDisplayAttributes(hwc_composer_device_1 * device,int disp,uint32_t config,const uint32_t * display_attributes,int32_t * values)570 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
571                                      const uint32_t *display_attributes, int32_t *values) {
572   SCOPE_LOCK(locker_);
573 
574   if (!device || !display_attributes || !values) {
575     return -EINVAL;
576   }
577 
578   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
579     return -EINVAL;
580   }
581 
582   HWCSession *hwc_session = static_cast<HWCSession *>(device);
583   int status = -EINVAL;
584   if (hwc_session->hwc_display_[disp]) {
585     status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
586                                                                    values);
587   }
588 
589   return status;
590 }
591 
GetActiveConfig(hwc_composer_device_1 * device,int disp)592 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
593   SCOPE_LOCK(locker_);
594 
595   if (!device) {
596     return -EINVAL;
597   }
598 
599   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
600     return -EINVAL;
601   }
602 
603   HWCSession *hwc_session = static_cast<HWCSession *>(device);
604   int active_config = -1;
605   if (hwc_session->hwc_display_[disp]) {
606     active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
607   }
608 
609   return active_config;
610 }
611 
SetActiveConfig(hwc_composer_device_1 * device,int disp,int index)612 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
613   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
614 
615   if (!device) {
616     return -EINVAL;
617   }
618 
619   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
620     return -EINVAL;
621   }
622 
623   HWCSession *hwc_session = static_cast<HWCSession *>(device);
624   int status = -EINVAL;
625 
626   if (hwc_session->hwc_display_[disp]) {
627     status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
628   }
629 
630   return status;
631 }
632 
SetCursorPositionAsync(hwc_composer_device_1 * device,int disp,int x,int y)633 int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
634   DTRACE_SCOPED();
635 
636   SCOPE_LOCK(locker_);
637 
638   if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
639     return -EINVAL;
640   }
641 
642   int status = -EINVAL;
643   HWCSession *hwc_session = static_cast<HWCSession *>(device);
644   if (hwc_session->hwc_display_[disp]) {
645     status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
646   }
647 
648   return status;
649 }
650 
ConnectDisplay(int disp,hwc_display_contents_1_t * content_list)651 int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
652   DLOGI("Display = %d", disp);
653 
654   int status = 0;
655   uint32_t primary_width = 0;
656   uint32_t primary_height = 0;
657 
658   hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
659 
660   if (disp == HWC_DISPLAY_EXTERNAL) {
661     status = CreateExternalDisplay(disp, primary_width, primary_height, false);
662     connected_displays_[HWC_DISPLAY_EXTERNAL] = 1;
663   } else if (disp == HWC_DISPLAY_VIRTUAL) {
664     status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
665                                        content_list, &hwc_display_[disp]);
666     connected_displays_[HWC_DISPLAY_VIRTUAL] = 1;
667   } else {
668     DLOGE("Invalid display type");
669     return -1;
670   }
671 
672   if (!status) {
673     hwc_display_[disp]->SetSecureDisplay(secure_display_active_, true);
674   }
675 
676   return status;
677 }
678 
DisconnectDisplay(int disp)679 int HWCSession::DisconnectDisplay(int disp) {
680   DLOGI("Display = %d", disp);
681 
682   if (disp == HWC_DISPLAY_EXTERNAL) {
683     HWCDisplayExternal::Destroy(hwc_display_[disp]);
684     connected_displays_[HWC_DISPLAY_EXTERNAL] = 0;
685   } else if (disp == HWC_DISPLAY_VIRTUAL) {
686     HWCDisplayVirtual::Destroy(hwc_display_[disp]);
687     connected_displays_[HWC_DISPLAY_VIRTUAL] = 0;
688   } else {
689     DLOGE("Invalid display type");
690     return -1;
691   }
692 
693   hwc_display_[disp] = NULL;
694 
695   return 0;
696 }
697 
PostRefresh(hwc_procs_t const * hwc_procs)698 static void PostRefresh(hwc_procs_t const *hwc_procs) {
699   hwc_procs->invalidate(hwc_procs);
700 }
701 
AsyncRefresh()702 void HWCSession::AsyncRefresh() {
703   future_ = std::async(PostRefresh, hwc_procs_);
704 }
705 
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)706 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
707                                              android::Parcel *output_parcel) {
708   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
709 
710   android::status_t status = 0;
711 
712   switch (command) {
713   case qService::IQService::DYNAMIC_DEBUG:
714     DynamicDebug(input_parcel);
715     break;
716 
717   case qService::IQService::SCREEN_REFRESH:
718     AsyncRefresh();
719     break;
720 
721   case qService::IQService::SET_IDLE_TIMEOUT:
722     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
723       uint32_t timeout = UINT32(input_parcel->readInt32());
724       hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
725     }
726     break;
727 
728   case qService::IQService::SET_FRAME_DUMP_CONFIG:
729     SetFrameDumpConfig(input_parcel);
730     break;
731 
732   case qService::IQService::SET_MAX_PIPES_PER_MIXER:
733     status = SetMaxMixerStages(input_parcel);
734     break;
735 
736   case qService::IQService::SET_DISPLAY_MODE:
737     status = SetDisplayMode(input_parcel);
738     break;
739 
740   case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
741     status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
742     break;
743 
744   case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
745     status = ConfigureRefreshRate(input_parcel);
746     break;
747 
748   case qService::IQService::SET_VIEW_FRAME:
749     break;
750 
751   case qService::IQService::TOGGLE_SCREEN_UPDATES:
752     status = ToggleScreenUpdates(input_parcel, output_parcel);
753     break;
754 
755   case qService::IQService::QDCM_SVC_CMDS:
756     status = QdcmCMDHandler(input_parcel, output_parcel);
757     break;
758 
759   case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
760     status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
761     break;
762 
763   case qService::IQService::CONTROL_PARTIAL_UPDATE:
764     status = ControlPartialUpdate(input_parcel, output_parcel);
765     break;
766 
767   case qService::IQService::SET_ACTIVE_CONFIG:
768     status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
769     break;
770 
771   case qService::IQService::GET_ACTIVE_CONFIG:
772     status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
773     break;
774 
775   case qService::IQService::GET_CONFIG_COUNT:
776     status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
777     break;
778 
779   case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
780     status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
781     break;
782 
783   case qService::IQService::GET_PANEL_BRIGHTNESS:
784     status = GetPanelBrightness(input_parcel, output_parcel);
785     break;
786 
787   case qService::IQService::SET_PANEL_BRIGHTNESS:
788     status = SetPanelBrightness(input_parcel, output_parcel);
789     break;
790 
791   case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
792     status = GetVisibleDisplayRect(input_parcel, output_parcel);
793     break;
794 
795   case qService::IQService::SET_CAMERA_STATUS:
796     status = SetDynamicBWForCamera(input_parcel, output_parcel);
797     break;
798 
799   case qService::IQService::GET_BW_TRANSACTION_STATUS:
800     status = GetBWTransactionStatus(input_parcel, output_parcel);
801     break;
802 
803   case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
804     status = SetMixerResolution(input_parcel);
805     break;
806 
807   case qService::IQService::GET_HDR_CAPABILITIES:
808     status = GetHdrCapabilities(input_parcel, output_parcel);
809     break;
810 
811   default:
812     DLOGW("QService command = %d is not supported", command);
813     return -EINVAL;
814   }
815 
816   return status;
817 }
818 
ToggleScreenUpdates(const android::Parcel * input_parcel,android::Parcel * output_parcel)819 android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
820                                                   android::Parcel *output_parcel) {
821   int input = input_parcel->readInt32();
822   int error = android::BAD_VALUE;
823 
824   if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
825     error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
826     if (error != 0) {
827       DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
828     }
829   }
830   output_parcel->writeInt32(error);
831 
832   return error;
833 }
834 
SetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)835 android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
836                                                  android::Parcel *output_parcel) {
837   int level = input_parcel->readInt32();
838   int error = android::BAD_VALUE;
839 
840   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
841     error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
842     if (error != 0) {
843       DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
844     }
845   }
846   output_parcel->writeInt32(error);
847 
848   return error;
849 }
850 
GetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)851 android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
852                                                  android::Parcel *output_parcel) {
853   int error = android::BAD_VALUE;
854   int ret = error;
855 
856   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
857     error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
858     if (error != 0) {
859       ret = error;
860       DLOGE("Failed to get the panel brightness. Error = %d", error);
861     }
862   }
863   output_parcel->writeInt32(ret);
864 
865   return error;
866 }
867 
ControlPartialUpdate(const android::Parcel * input_parcel,android::Parcel * output_parcel)868 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
869                                                    android::Parcel *output_parcel) {
870   DisplayError error = kErrorNone;
871   int ret = 0;
872   uint32_t disp_id = UINT32(input_parcel->readInt32());
873   uint32_t enable = UINT32(input_parcel->readInt32());
874 
875   if (disp_id != HWC_DISPLAY_PRIMARY) {
876     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
877     ret = -EINVAL;
878     output_parcel->writeInt32(ret);
879     return ret;
880   }
881 
882   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
883     DLOGE("primary display object is not instantiated");
884     ret = -EINVAL;
885     output_parcel->writeInt32(ret);
886     return ret;
887   }
888 
889   uint32_t pending = 0;
890   error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
891 
892   if (error == kErrorNone) {
893     if (!pending) {
894       output_parcel->writeInt32(ret);
895       return ret;
896     }
897   } else if (error == kErrorNotSupported) {
898     output_parcel->writeInt32(ret);
899     return ret;
900   } else {
901     ret = -EINVAL;
902     output_parcel->writeInt32(ret);
903     return ret;
904   }
905 
906   AsyncRefresh();
907 
908   // Wait until partial update control is complete
909   ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
910 
911   output_parcel->writeInt32(ret);
912 
913   return ret;
914 }
915 
HandleSetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)916 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
917                                                            android::Parcel *output_parcel) {
918   int config = input_parcel->readInt32();
919   int dpy = input_parcel->readInt32();
920   int error = android::BAD_VALUE;
921 
922   if (dpy > HWC_DISPLAY_VIRTUAL) {
923     return android::BAD_VALUE;
924   }
925 
926   if (hwc_display_[dpy]) {
927     error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
928     if (error == 0) {
929       AsyncRefresh();
930     }
931   }
932 
933   return error;
934 }
935 
HandleGetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)936 android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
937                                                            android::Parcel *output_parcel) {
938   int dpy = input_parcel->readInt32();
939   int error = android::BAD_VALUE;
940 
941   if (dpy > HWC_DISPLAY_VIRTUAL) {
942     return android::BAD_VALUE;
943   }
944 
945   if (hwc_display_[dpy]) {
946     uint32_t config = 0;
947     error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
948     if (error == 0) {
949       output_parcel->writeInt32(INT(config));
950     }
951   }
952 
953   return error;
954 }
955 
HandleGetDisplayConfigCount(const android::Parcel * input_parcel,android::Parcel * output_parcel)956 android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
957                                                           android::Parcel *output_parcel) {
958   int dpy = input_parcel->readInt32();
959   int error = android::BAD_VALUE;
960 
961   if (dpy > HWC_DISPLAY_VIRTUAL) {
962     return android::BAD_VALUE;
963   }
964 
965   uint32_t count = 0;
966   if (hwc_display_[dpy]) {
967     error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
968     if (error == 0) {
969       output_parcel->writeInt32(INT(count));
970     }
971   }
972 
973   return error;
974 }
975 
SetDisplayPort(DisplayPort sdm_disp_port,int * hwc_disp_port)976 android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
977   if (!hwc_disp_port) {
978     return -EINVAL;
979   }
980 
981   switch (sdm_disp_port) {
982     case kPortDSI:
983       *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
984       break;
985     case kPortDTV:
986       *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
987       break;
988     case kPortLVDS:
989       *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
990       break;
991     case kPortEDP:
992       *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
993       break;
994     case kPortWriteBack:
995       *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
996       break;
997     case kPortDP:
998       *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
999       break;
1000     case kPortDefault:
1001       *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
1002       break;
1003     default:
1004       DLOGE("Invalid sdm display port %d", sdm_disp_port);
1005       return -EINVAL;
1006   }
1007 
1008   return 0;
1009 }
1010 
HandleGetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)1011 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
1012                                                                   *input_parcel,
1013                                                                   android::Parcel *output_parcel) {
1014   int config = input_parcel->readInt32();
1015   int dpy = input_parcel->readInt32();
1016   int error = android::BAD_VALUE;
1017   DisplayConfigVariableInfo display_attributes;
1018   DisplayPort sdm_disp_port = kPortDefault;
1019   int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
1020 
1021   if (dpy > HWC_DISPLAY_VIRTUAL) {
1022     return android::BAD_VALUE;
1023   }
1024 
1025   if (hwc_display_[dpy]) {
1026     error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
1027     if (error == 0) {
1028       hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
1029 
1030       SetDisplayPort(sdm_disp_port, &hwc_disp_port);
1031 
1032       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1033       output_parcel->writeInt32(INT(display_attributes.x_pixels));
1034       output_parcel->writeInt32(INT(display_attributes.y_pixels));
1035       output_parcel->writeFloat(display_attributes.x_dpi);
1036       output_parcel->writeFloat(display_attributes.y_dpi);
1037       output_parcel->writeInt32(hwc_disp_port);
1038       output_parcel->writeInt32(display_attributes.is_yuv);
1039     }
1040   }
1041 
1042   return error;
1043 }
1044 
SetSecondaryDisplayStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1045 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
1046                                                         android::Parcel *output_parcel) {
1047   int ret = -EINVAL;
1048 
1049   uint32_t display_id = UINT32(input_parcel->readInt32());
1050   uint32_t display_status = UINT32(input_parcel->readInt32());
1051 
1052   DLOGI("Display = %d, Status = %d", display_id, display_status);
1053 
1054   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1055     DLOGE("Invalid display_id");
1056   } else if (display_id == HWC_DISPLAY_PRIMARY) {
1057     DLOGE("Not supported for this display");
1058   } else if (!hwc_display_[display_id]) {
1059     DLOGW("Display is not connected");
1060   } else {
1061     ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
1062   }
1063 
1064   output_parcel->writeInt32(ret);
1065 
1066   return ret;
1067 }
1068 
ConfigureRefreshRate(const android::Parcel * input_parcel)1069 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1070   uint32_t operation = UINT32(input_parcel->readInt32());
1071   switch (operation) {
1072     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1073       return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1074           HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
1075     case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1076       return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1077           HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
1078     case qdutils::SET_BINDER_DYN_REFRESH_RATE:
1079       {
1080         uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1081         return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1082             HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
1083             refresh_rate);
1084       }
1085     default:
1086       DLOGW("Invalid operation %d", operation);
1087       return -EINVAL;
1088   }
1089 
1090   return 0;
1091 }
1092 
SetDisplayMode(const android::Parcel * input_parcel)1093 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1094   uint32_t mode = UINT32(input_parcel->readInt32());
1095   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
1096 }
1097 
SetMaxMixerStages(const android::Parcel * input_parcel)1098 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1099   DisplayError error = kErrorNone;
1100   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1101   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1102 
1103   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1104     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1105       error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
1106       if (error != kErrorNone) {
1107         return -EINVAL;
1108       }
1109     }
1110   }
1111 
1112   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1113     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1114       error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
1115       if (error != kErrorNone) {
1116         return -EINVAL;
1117       }
1118     }
1119   }
1120 
1121   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1122     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1123       error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
1124       if (error != kErrorNone) {
1125         return -EINVAL;
1126       }
1127     }
1128   }
1129 
1130   return 0;
1131 }
1132 
SetDynamicBWForCamera(const android::Parcel * input_parcel,android::Parcel * output_parcel)1133 android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
1134                                                     android::Parcel *output_parcel) {
1135   DisplayError error = kErrorNone;
1136   uint32_t camera_status = UINT32(input_parcel->readInt32());
1137   HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
1138 
1139   // trigger invalidate to apply new bw caps.
1140   AsyncRefresh();
1141 
1142     error = core_intf_->SetMaxBandwidthMode(mode);
1143   if (error != kErrorNone) {
1144       return -EINVAL;
1145   }
1146 
1147   new_bw_mode_ = true;
1148   need_invalidate_ = true;
1149 
1150   return 0;
1151 }
1152 
GetBWTransactionStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1153 android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
1154                                                      android::Parcel *output_parcel)  {
1155   bool state = true;
1156 
1157   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1158     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
1159       DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
1160       state = false;
1161     }
1162     output_parcel->writeInt32(state);
1163   }
1164 
1165   return 0;
1166 }
1167 
SetFrameDumpConfig(const android::Parcel * input_parcel)1168 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1169   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1170   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1171   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1172 
1173   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1174     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1175       hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1176     }
1177   }
1178 
1179   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1180     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1181       hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1182     }
1183   }
1184 
1185   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1186     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1187       hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1188     }
1189   }
1190 }
1191 
SetMixerResolution(const android::Parcel * input_parcel)1192 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1193   DisplayError error = kErrorNone;
1194   uint32_t dpy = UINT32(input_parcel->readInt32());
1195 
1196   if (dpy != HWC_DISPLAY_PRIMARY) {
1197     DLOGI("Resoulution change not supported for this display %d", dpy);
1198     return -EINVAL;
1199   }
1200 
1201   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1202     DLOGI("Primary display is not initialized");
1203     return -EINVAL;
1204   }
1205 
1206   uint32_t width = UINT32(input_parcel->readInt32());
1207   uint32_t height = UINT32(input_parcel->readInt32());
1208 
1209   error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
1210   if (error != kErrorNone) {
1211     return -EINVAL;
1212   }
1213 
1214   return 0;
1215 }
1216 
GetHdrCapabilities(const android::Parcel * input_parcel,android::Parcel * output_parcel)1217 android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel,
1218                                                  android::Parcel *output_parcel) {
1219   uint32_t display_id = UINT32(input_parcel->readInt32());
1220   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1221     DLOGE("Invalid display id = %d", display_id);
1222     return -EINVAL;
1223   }
1224 
1225   if (hwc_display_[display_id] == NULL) {
1226     DLOGW("Display = %d not initialized", display_id);
1227     return -EINVAL;
1228   }
1229 
1230   DisplayConfigFixedInfo fixed_info = {};
1231   int ret = hwc_display_[display_id]->GetDisplayFixedConfig(&fixed_info);
1232   if (ret) {
1233     DLOGE("Failed");
1234     return ret;
1235   }
1236 
1237   if (!fixed_info.hdr_supported) {
1238     DLOGI("HDR is not supported");
1239     return 0;
1240   }
1241 
1242   std::vector<int32_t> supported_hdr_types;
1243   // Only HDR10 supported now, in future add other supported HDR formats(HLG, DolbyVision)
1244   supported_hdr_types.push_back(HAL_HDR_HDR10);
1245 
1246   static const float kLuminanceFactor = 10000.0;
1247   // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
1248   float max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
1249   float max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
1250   float min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
1251 
1252   if (output_parcel != nullptr) {
1253     output_parcel->writeInt32Vector(supported_hdr_types);
1254     output_parcel->writeFloat(max_luminance);
1255     output_parcel->writeFloat(max_average_luminance);
1256     output_parcel->writeFloat(min_luminance);
1257   }
1258 
1259   return 0;
1260 }
1261 
DynamicDebug(const android::Parcel * input_parcel)1262 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
1263   int type = input_parcel->readInt32();
1264   bool enable = (input_parcel->readInt32() > 0);
1265   DLOGI("type = %d enable = %d", type, enable);
1266   int verbose_level = input_parcel->readInt32();
1267 
1268   switch (type) {
1269   case qService::IQService::DEBUG_ALL:
1270     HWCDebugHandler::DebugAll(enable, verbose_level);
1271     break;
1272 
1273   case qService::IQService::DEBUG_MDPCOMP:
1274     HWCDebugHandler::DebugStrategy(enable, verbose_level);
1275     HWCDebugHandler::DebugCompManager(enable, verbose_level);
1276     break;
1277 
1278   case qService::IQService::DEBUG_PIPE_LIFECYCLE:
1279     HWCDebugHandler::DebugResources(enable, verbose_level);
1280     break;
1281 
1282   case qService::IQService::DEBUG_DRIVER_CONFIG:
1283     HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1284     break;
1285 
1286   case qService::IQService::DEBUG_ROTATOR:
1287     HWCDebugHandler::DebugResources(enable, verbose_level);
1288     HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1289     HWCDebugHandler::DebugRotator(enable, verbose_level);
1290     break;
1291 
1292   case qService::IQService::DEBUG_QDCM:
1293     HWCDebugHandler::DebugQdcm(enable, verbose_level);
1294     break;
1295 
1296   default:
1297     DLOGW("type = %d is not supported", type);
1298   }
1299 }
1300 
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)1301 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
1302                                              android::Parcel *output_parcel) {
1303   int ret = 0;
1304   int32_t *brightness_value = NULL;
1305   uint32_t display_id(0);
1306   PPPendingParams pending_action;
1307   PPDisplayAPIPayload resp_payload, req_payload;
1308 
1309   if (!color_mgr_) {
1310     return -1;
1311   }
1312 
1313   pending_action.action = kNoAction;
1314   pending_action.params = NULL;
1315 
1316   // Read display_id, payload_size and payload from in_parcel.
1317   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
1318   if (!ret) {
1319     if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
1320       ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
1321                                                                   &resp_payload, &pending_action);
1322 
1323     if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
1324       ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
1325                                                                   &pending_action);
1326   }
1327 
1328   if (ret) {
1329     output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
1330     req_payload.DestroyPayload();
1331     resp_payload.DestroyPayload();
1332     return ret;
1333   }
1334 
1335   switch (pending_action.action) {
1336     case kInvalidating:
1337       AsyncRefresh();
1338       break;
1339     case kEnterQDCMMode:
1340       ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1341       break;
1342     case kExitQDCMMode:
1343       ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1344       break;
1345     case kApplySolidFill:
1346       ret = color_mgr_->SetSolidFill(pending_action.params,
1347                                      true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1348       AsyncRefresh();
1349       break;
1350     case kDisableSolidFill:
1351       ret = color_mgr_->SetSolidFill(pending_action.params,
1352                                      false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1353       AsyncRefresh();
1354       break;
1355     case kSetPanelBrightness:
1356       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1357       if (brightness_value == NULL) {
1358         DLOGE("Brightness value is Null");
1359         return -EINVAL;
1360       }
1361       if (HWC_DISPLAY_PRIMARY == display_id)
1362         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
1363       break;
1364     case kEnableFrameCapture:
1365       ret = color_mgr_->SetFrameCapture(pending_action.params,
1366                                         true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1367       AsyncRefresh();
1368       break;
1369     case kDisableFrameCapture:
1370       ret = color_mgr_->SetFrameCapture(pending_action.params,
1371                                         false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1372       break;
1373     case kConfigureDetailedEnhancer:
1374       ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
1375                                             hwc_display_[HWC_DISPLAY_PRIMARY]);
1376       AsyncRefresh();
1377       break;
1378     case kInvalidatingAndkSetPanelBrightness:
1379       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1380       if (brightness_value == NULL) {
1381         DLOGE("Brightness value is Null");
1382         return -EINVAL;
1383       }
1384       if (HWC_DISPLAY_PRIMARY == display_id)
1385         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value);
1386       AsyncRefresh();
1387       break;
1388     case kNoAction:
1389       break;
1390     default:
1391       DLOGW("Invalid pending action = %d!", pending_action.action);
1392       break;
1393   }
1394 
1395   // for display API getter case, marshall returned params into out_parcel.
1396   output_parcel->writeInt32(ret);
1397   HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1398   req_payload.DestroyPayload();
1399   resp_payload.DestroyPayload();
1400 
1401   return (ret? -EINVAL : 0);
1402 }
1403 
OnMinHdcpEncryptionLevelChange(const android::Parcel * input_parcel,android::Parcel * output_parcel)1404 android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
1405                                                              android::Parcel *output_parcel) {
1406   int ret = -EINVAL;
1407   uint32_t display_id = UINT32(input_parcel->readInt32());
1408   uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1409 
1410   DLOGI("Display %d", display_id);
1411 
1412   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1413     DLOGE("Invalid display_id");
1414   } else if (display_id != HWC_DISPLAY_EXTERNAL) {
1415     DLOGE("Not supported for display");
1416   } else if (!hwc_display_[display_id]) {
1417     DLOGW("Display is not connected");
1418   } else {
1419     ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
1420   }
1421 
1422   output_parcel->writeInt32(ret);
1423 
1424   return ret;
1425 }
1426 
HWCUeventThread(void * context)1427 void* HWCSession::HWCUeventThread(void *context) {
1428   if (context) {
1429     return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
1430   }
1431 
1432   return NULL;
1433 }
1434 
HWCUeventThreadHandler()1435 void* HWCSession::HWCUeventThreadHandler() {
1436   static char uevent_data[PAGE_SIZE];
1437   int length = 0;
1438 
1439   uevent_locker_.Lock();
1440   prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
1441   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1442   if (!uevent_init()) {
1443     DLOGE("Failed to init uevent");
1444     pthread_exit(0);
1445     uevent_locker_.Signal();
1446     uevent_locker_.Unlock();
1447     return NULL;
1448   }
1449 
1450   uevent_locker_.Signal();
1451   uevent_locker_.Unlock();
1452 
1453   while (!uevent_thread_exit_) {
1454     // keep last 2 zeroes to ensure double 0 termination
1455     length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
1456 
1457     if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
1458       DLOGI("Uevent HDMI = %s", uevent_data);
1459       int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
1460       if (connected >= 0) {
1461         DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
1462         if (HotPlugHandler(connected) == -1) {
1463           DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
1464         }
1465       }
1466     } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
1467       DLOGI("Uevent FB0 = %s", uevent_data);
1468       int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
1469       if (panel_reset == 0) {
1470         if (hwc_procs_) {
1471           reset_panel_ = true;
1472           AsyncRefresh();
1473         } else {
1474           DLOGW("Ignore resetpanel - hwc_proc not registered");
1475         }
1476       }
1477     }
1478   }
1479   pthread_exit(0);
1480 
1481   return NULL;
1482 }
1483 
GetEventValue(const char * uevent_data,int length,const char * event_info)1484 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
1485   const char *iterator_str = uevent_data;
1486   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
1487     const char *pstr = strstr(iterator_str, event_info);
1488     if (pstr != NULL) {
1489       return (atoi(iterator_str + strlen(event_info)));
1490     }
1491     iterator_str += strlen(iterator_str) + 1;
1492   }
1493 
1494   return -1;
1495 }
1496 
ResetPanel()1497 void HWCSession::ResetPanel() {
1498   int status = -EINVAL;
1499 
1500   DLOGI("Powering off primary");
1501   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
1502   if (status) {
1503     DLOGE("power-off on primary failed with error = %d", status);
1504   }
1505 
1506   DLOGI("Restoring power mode on primary");
1507   int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
1508   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
1509   if (status) {
1510     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
1511   }
1512 
1513   status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
1514   if (status) {
1515     DLOGE("enabling vsync failed for primary with error = %d", status);
1516   }
1517 
1518   reset_panel_ = false;
1519 }
1520 
HotPlugHandler(bool connected)1521 int HWCSession::HotPlugHandler(bool connected) {
1522   int status = 0;
1523   bool notify_hotplug = false;
1524   bool refresh_screen = false;
1525 
1526   // To prevent sending events to client while a lock is held, acquire scope locks only within
1527   // below scope so that those get automatically unlocked after the scope ends.
1528   {
1529     SEQUENCE_WAIT_SCOPE_LOCK(locker_);
1530 
1531     if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1532       DLOGE("Primay display is not connected.");
1533       return -1;
1534     }
1535 
1536 
1537     HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1538     HWCDisplay *external_display = NULL;
1539     HWCDisplay *null_display = NULL;
1540 
1541     if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
1542       external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
1543     } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) {
1544       null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
1545     }
1546 
1547     // If primary display connected is a NULL display, then replace it with the external display
1548     if (connected) {
1549       // If we are in HDMI as primary and the primary display just got plugged in
1550       if (is_hdmi_primary_ && null_display) {
1551         uint32_t primary_width, primary_height;
1552         int status = 0;
1553         null_display->GetFrameBufferResolution(&primary_width, &primary_height);
1554         delete null_display;
1555         hwc_display_[HWC_DISPLAY_PRIMARY] = NULL;
1556 
1557         // Create external display with a forced framebuffer resolution to that of what the NULL
1558         // display had. This is necessary because SurfaceFlinger does not dynamically update
1559         // framebuffer resolution once it reads it at bootup. So we always have to have the NULL
1560         // display/external display both at the bootup resolution.
1561         status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, primary_width, primary_height, true);
1562         if (status) {
1563           DLOGE("Could not create external display");
1564           return -1;
1565         }
1566 
1567         status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
1568         if (status) {
1569           DLOGE("power-on on primary failed with error = %d", status);
1570         }
1571 
1572         is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
1573 
1574         // Next, go ahead and enable vsync on external display. This is expliclity required
1575         // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying
1576         // changing display. and thus may not explicitly enable vsync
1577 
1578         status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true);
1579         if (status) {
1580           DLOGE("Error enabling vsync for HDMI as primary case");
1581         }
1582         // Don't do hotplug notification for HDMI as primary case for now
1583         notify_hotplug = false;
1584         refresh_screen = true;
1585       } else {
1586         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1587           DLOGE("HDMI is already connected");
1588           return -1;
1589         }
1590 
1591         // Connect external display if virtual display is not connected.
1592         // Else, defer external display connection and process it when virtual display
1593         // tears down; Do not notify SurfaceFlinger since connection is deferred now.
1594         if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1595           status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
1596           if (status) {
1597             return status;
1598           }
1599           notify_hotplug = true;
1600         } else {
1601           DLOGI("Virtual display is connected, pending connection");
1602           external_pending_connect_ = true;
1603         }
1604       }
1605     } else {
1606       // Do not return error if external display is not in connected status.
1607       // Due to virtual display concurrency, external display connection might be still pending
1608       // but hdmi got disconnected before pending connection could be processed.
1609 
1610       if (is_hdmi_primary_ && external_display) {
1611         uint32_t x_res, y_res;
1612         external_display->GetFrameBufferResolution(&x_res, &y_res);
1613         // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
1614         // for HDMI as primary
1615         external_display->EventControl(HWC_EVENT_VSYNC, false);
1616         HWCDisplayExternal::Destroy(external_display);
1617 
1618         HWCDisplayNull *null_display;
1619 
1620         int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
1621                                             reinterpret_cast<HWCDisplay **>(&null_display));
1622 
1623         if (status) {
1624           DLOGE("Could not create Null display when primary got disconnected");
1625           return -1;
1626         }
1627 
1628         null_display->SetResolution(x_res, y_res);
1629         hwc_display_[HWC_DISPLAY_PRIMARY] = null_display;
1630 
1631         // Don't do hotplug notification for HDMI as primary case for now
1632         notify_hotplug = false;
1633       } else {
1634         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1635           status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
1636           notify_hotplug = true;
1637         }
1638         external_pending_connect_ = false;
1639       }
1640     }
1641   }
1642 
1643   if (connected && (notify_hotplug || refresh_screen)) {
1644     // trigger screen refresh to ensure sufficient resources are available to process new
1645     // new display connection.
1646     hwc_procs_->invalidate(hwc_procs_);
1647     uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
1648     usleep(vsync_period * 2 / 1000);
1649   }
1650   // notify client
1651   if (notify_hotplug) {
1652     hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
1653   }
1654 
1655   qservice_->onHdmiHotplug(INT(connected));
1656 
1657   return 0;
1658 }
1659 
HandleSecureDisplaySession(hwc_display_contents_1_t ** displays)1660 void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
1661   secure_display_active_ = false;
1662   if (!*displays) {
1663     DLOGW("Invalid display contents");
1664     return;
1665   }
1666 
1667   hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
1668   if (!content_list) {
1669     DLOGW("Invalid primary content list");
1670     return;
1671   }
1672   size_t num_hw_layers = content_list->numHwLayers;
1673 
1674   for (size_t i = 0; i < num_hw_layers - 1; i++) {
1675     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
1676     const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
1677     if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
1678       secure_display_active_ = true;
1679     }
1680   }
1681 
1682   // Force flush on primary during transitions(secure<->non secure)
1683   // when external displays are connected.
1684   bool force_flush = false;
1685   if ((connected_displays_[HWC_DISPLAY_PRIMARY] == 1) &&
1686      ((connected_displays_[HWC_DISPLAY_EXTERNAL] == 1) ||
1687       (connected_displays_[HWC_DISPLAY_VIRTUAL] == 1))) {
1688     force_flush = true;
1689   }
1690 
1691   for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
1692     if (hwc_display_[dpy]) {
1693       hwc_display_[dpy]->SetSecureDisplay(secure_display_active_, force_flush);
1694     }
1695   }
1696 }
1697 
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)1698 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
1699                                                     android::Parcel *output_parcel) {
1700   int dpy = input_parcel->readInt32();
1701 
1702   if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
1703     return android::BAD_VALUE;;
1704   }
1705 
1706   if (!hwc_display_[dpy]) {
1707     return android::NO_INIT;
1708   }
1709 
1710   hwc_rect_t visible_rect = {0, 0, 0, 0};
1711   int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
1712   if (error < 0) {
1713     return error;
1714   }
1715 
1716   output_parcel->writeInt32(visible_rect.left);
1717   output_parcel->writeInt32(visible_rect.top);
1718   output_parcel->writeInt32(visible_rect.right);
1719   output_parcel->writeInt32(visible_rect.bottom);
1720 
1721   return android::NO_ERROR;
1722 }
1723 
CreateExternalDisplay(int disp,uint32_t primary_width,uint32_t primary_height,bool use_primary_res)1724 int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
1725                                       bool use_primary_res) {
1726   uint32_t panel_bpp = 0;
1727   uint32_t pattern_type = 0;
1728 
1729   if (qdutils::isDPConnected()) {
1730     qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
1731   }
1732 
1733   if (panel_bpp && pattern_type) {
1734     return HWCDisplayExternalTest::Create(core_intf_, &hwc_procs_, qservice_, panel_bpp,
1735                                           pattern_type, &hwc_display_[disp]);
1736   }
1737 
1738   return HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
1739                                     qservice_, use_primary_res, &hwc_display_[disp]);
1740 }
1741 
1742 }  // namespace sdm
1743 
1744