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