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