1/*
2* Copyright (c) 2014 - 2016, 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
48#include "hwc_buffer_allocator.h"
49#include "hwc_buffer_sync_handler.h"
50#include "hwc_session.h"
51#include "hwc_debugger.h"
52#include "hwc_display_primary.h"
53#include "hwc_display_virtual.h"
54
55#define __CLASS__ "HWCSession"
56
57#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
58#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
59
60static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
61
62hwc_module_t HAL_MODULE_INFO_SYM = {
63  .common = {
64    .tag = HARDWARE_MODULE_TAG,
65    .version_major = 2,
66    .version_minor = 0,
67    .id = HWC_HARDWARE_MODULE_ID,
68    .name = "QTI Hardware Composer Module",
69    .author = "CodeAurora Forum",
70    .methods = &g_hwc_module_methods,
71    .dso = 0,
72    .reserved = {0},
73  }
74};
75
76namespace sdm {
77
78Locker HWCSession::locker_;
79
80static void Invalidate(const struct hwc_procs *procs) {
81}
82
83static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) {
84}
85
86static void Hotplug(const struct hwc_procs* procs, int disp, int connected) {
87}
88
89HWCSession::HWCSession(const hw_module_t *module) {
90  // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs.
91  hwc_procs_default_.invalidate = Invalidate;
92  hwc_procs_default_.vsync = VSync;
93  hwc_procs_default_.hotplug = Hotplug;
94
95  hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
96  hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
97  hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
98  hwc_composer_device_1_t::common.close = Close;
99  hwc_composer_device_1_t::prepare = Prepare;
100  hwc_composer_device_1_t::set = Set;
101  hwc_composer_device_1_t::eventControl = EventControl;
102  hwc_composer_device_1_t::setPowerMode = SetPowerMode;
103  hwc_composer_device_1_t::query = Query;
104  hwc_composer_device_1_t::registerProcs = RegisterProcs;
105  hwc_composer_device_1_t::dump = Dump;
106  hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
107  hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
108  hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
109  hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
110  hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync;
111}
112
113int HWCSession::Init() {
114  int status = -EINVAL;
115  const char *qservice_name = "display.qservice";
116
117  // Start QService and connect to it.
118  qService::QService::init();
119  android::sp<qService::IQService> qservice = android::interface_cast<qService::IQService>(
120                android::defaultServiceManager()->getService(android::String16(qservice_name)));
121
122  if (qservice.get()) {
123    qservice->connect(android::sp<qClient::IQClient>(this));
124  } else {
125    DLOGE("Failed to acquire %s", qservice_name);
126    return -EINVAL;
127  }
128
129  buffer_allocator_ = new HWCBufferAllocator();
130  if (buffer_allocator_ == NULL) {
131    DLOGE("Display core initialization failed due to no memory");
132    return -ENOMEM;
133  }
134
135  buffer_sync_handler_ = new HWCBufferSyncHandler();
136  if (buffer_sync_handler_ == NULL) {
137    DLOGE("Display core initialization failed due to no memory");
138    return -ENOMEM;
139  }
140
141  DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_,
142                                                 buffer_sync_handler_, &core_intf_);
143  if (error != kErrorNone) {
144    DLOGE("Display core initialization failed. Error = %d", error);
145    return -EINVAL;
146  }
147
148  // Create and power on primary display
149  status = HWCDisplayPrimary::Create(core_intf_, &hwc_procs_,
150                                     &hwc_display_[HWC_DISPLAY_PRIMARY]);
151  if (status) {
152    CoreInterface::DestroyCore();
153    return status;
154  }
155
156  color_mgr_ = HWCColorManager::CreateColorManager();
157  if (!color_mgr_) {
158    DLOGW("Failed to load HWCColorManager.");
159  }
160
161  if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
162    DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
163    HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
164    hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
165    CoreInterface::DestroyCore();
166    return -errno;
167  }
168
169  return 0;
170}
171
172int HWCSession::Deinit() {
173  HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
174  hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
175  if (color_mgr_) {
176    color_mgr_->DestroyColorManager();
177  }
178  uevent_thread_exit_ = true;
179  pthread_join(uevent_thread_, NULL);
180
181  DisplayError error = CoreInterface::DestroyCore();
182  if (error != kErrorNone) {
183    DLOGE("Display core de-initialization failed. Error = %d", error);
184  }
185
186  return 0;
187}
188
189int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
190  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
191
192  if (!module || !name || !device) {
193    DLOGE("Invalid parameters.");
194    return -EINVAL;
195  }
196
197  if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
198    HWCSession *hwc_session = new HWCSession(module);
199    if (!hwc_session) {
200      return -ENOMEM;
201    }
202
203    int status = hwc_session->Init();
204    if (status != 0) {
205      delete hwc_session;
206      return status;
207    }
208
209    hwc_composer_device_1_t *composer_device = hwc_session;
210    *device = reinterpret_cast<hw_device_t *>(composer_device);
211  }
212
213  return 0;
214}
215
216int HWCSession::Close(hw_device_t *device) {
217  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
218
219  if (!device) {
220    return -EINVAL;
221  }
222
223  hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device);
224  HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
225
226  hwc_session->Deinit();
227  delete hwc_session;
228
229  return 0;
230}
231
232int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
233                        hwc_display_contents_1_t **displays) {
234  DTRACE_SCOPED();
235
236  if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
237    return -EINVAL;
238  }
239
240  HWCSession *hwc_session = static_cast<HWCSession *>(device);
241  hwc_procs_t const *hwc_procs = NULL;
242  bool hotplug_connect = false;
243
244  // Hold mutex only in this scope.
245  {
246    SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
247
248    hwc_procs = hwc_session->hwc_procs_;
249
250    if (hwc_session->reset_panel_) {
251      DLOGW("panel is in bad state, resetting the panel");
252      hwc_session->ResetPanel();
253    }
254
255    if (hwc_session->need_invalidate_) {
256      hwc_procs->invalidate(hwc_procs);
257    }
258
259    hwc_session->HandleSecureDisplaySession(displays);
260
261    if (hwc_session->color_mgr_) {
262      HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
263      if (primary_display) {
264        int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
265        if (ret)
266          return 0;
267      }
268    }
269
270    for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) {
271      hwc_display_contents_1_t *content_list = displays[dpy];
272      // If external display is connected, ignore virtual display content list.
273      // If virtual display content list is valid, connect virtual display if not connected.
274      // If virtual display content list is invalid, disconnect virtual display if connected.
275      // If external display connection is pending, connect external display when virtual
276      // display is destroyed.
277      if (dpy == HWC_DISPLAY_VIRTUAL) {
278        if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL]) {
279          continue;
280        }
281
282        bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list);
283        bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
284
285        if (valid_content && !connected) {
286          hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list);
287        } else if (!valid_content && connected) {
288          hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL);
289
290          if (hwc_session->external_pending_connect_) {
291            DLOGI("Process pending external display connection");
292            hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
293            hwc_session->external_pending_connect_ = false;
294            hotplug_connect = true;
295          }
296        }
297      }
298
299      if (hwc_session->hwc_display_[dpy]) {
300        if (!content_list) {
301          DLOGI("Display[%d] connected. content_list is null", dpy);
302        } else if (!content_list->numHwLayers) {
303          DLOGE("Display[%d] connected. numHwLayers is zero", dpy);
304        } else {
305          hwc_session->hwc_display_[dpy]->Prepare(content_list);
306        }
307      }
308    }
309  }
310
311  if (hotplug_connect) {
312    // notify client
313    hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
314  }
315  // Return 0, else client will go into bad state
316  return 0;
317}
318
319int HWCSession::GetVsyncPeriod(int disp) {
320  SCOPE_LOCK(locker_);
321  // default value
322  int32_t vsync_period = 1000000000l / 60;
323  const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
324
325  if (hwc_display_[disp]) {
326    hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
327  }
328
329  return vsync_period;
330}
331
332int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
333                    hwc_display_contents_1_t **displays) {
334  DTRACE_SCOPED();
335
336  SEQUENCE_EXIT_SCOPE_LOCK(locker_);
337
338  if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
339    return -EINVAL;
340  }
341
342  HWCSession *hwc_session = static_cast<HWCSession *>(device);
343
344  if (hwc_session->color_mgr_) {
345    HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
346    if (primary_display) {
347      int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display);
348      if (ret)
349        return 0;
350    }
351  }
352
353  for (size_t dpy = 0; dpy < num_displays; dpy++) {
354    hwc_display_contents_1_t *content_list = displays[dpy];
355
356    // Drop virtual display composition if virtual display object could not be created
357    // due to HDMI concurrency.
358    if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
359      CloseAcquireFds(content_list);
360      if (content_list) {
361        content_list->retireFenceFd = -1;
362      }
363
364      continue;
365    }
366
367    if (hwc_session->hwc_display_[dpy]) {
368      hwc_session->hwc_display_[dpy]->Commit(content_list);
369    }
370    CloseAcquireFds(content_list);
371  }
372
373  if (hwc_session->new_bw_mode_) {
374    hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
375    hwc_session->new_bw_mode_ = false;
376    if (hwc_session->bw_mode_release_fd_ >= 0) {
377      close(hwc_session->bw_mode_release_fd_);
378    }
379    hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
380  }
381
382  // This is only indicative of how many times SurfaceFlinger posts
383  // frames to the display.
384  CALC_FPS();
385
386  // Return 0, else client will go into bad state
387  return 0;
388}
389
390void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
391  if (content_list) {
392    for (size_t i = 0; i < content_list->numHwLayers; i++) {
393      int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
394      if (acquireFenceFd >= 0) {
395        close(acquireFenceFd);
396        acquireFenceFd = -1;
397      }
398    }
399
400    int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
401    if (outbufAcquireFenceFd >= 0) {
402      close(outbufAcquireFenceFd);
403      outbufAcquireFenceFd = -1;
404    }
405  }
406}
407
408int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
409  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
410
411  if (!device) {
412    return -EINVAL;
413  }
414
415  HWCSession *hwc_session = static_cast<HWCSession *>(device);
416  int status = -EINVAL;
417  if (hwc_session->hwc_display_[disp]) {
418    status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
419  }
420
421  return status;
422}
423
424int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
425  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
426
427  if (!device) {
428    return -EINVAL;
429  }
430
431  HWCSession *hwc_session = static_cast<HWCSession *>(device);
432  int status = -EINVAL;
433  if (hwc_session->hwc_display_[disp]) {
434    status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
435  }
436  if (disp == HWC_DISPLAY_PRIMARY && hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
437    // Set the power mode for virtual display while setting power mode for primary, as SF
438    // does not invoke SetPowerMode() for virtual display.
439    status = hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(mode);
440  }
441
442  return status;
443}
444
445int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
446  SCOPE_LOCK(locker_);
447
448  if (!device || !value) {
449    return -EINVAL;
450  }
451
452  int status = 0;
453
454  switch (param) {
455  case HWC_BACKGROUND_LAYER_SUPPORTED:
456    value[0] = 1;
457    break;
458
459  default:
460    status = -EINVAL;
461  }
462
463  return status;
464}
465
466void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
467  SCOPE_LOCK(locker_);
468
469  if (!device || !procs) {
470    return;
471  }
472
473  HWCSession *hwc_session = static_cast<HWCSession *>(device);
474  hwc_session->hwc_procs_ = procs;
475}
476
477void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
478  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
479
480  if (!device || !buffer || !length) {
481    return;
482  }
483
484  DumpInterface::GetDump(buffer, UINT32(length));
485}
486
487int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
488                                  size_t *num_configs) {
489  SCOPE_LOCK(locker_);
490
491  if (!device || !configs || !num_configs) {
492    return -EINVAL;
493  }
494
495  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
496    return -EINVAL;
497  }
498
499  HWCSession *hwc_session = static_cast<HWCSession *>(device);
500  int status = -EINVAL;
501  if (hwc_session->hwc_display_[disp]) {
502    status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
503  }
504
505  return status;
506}
507
508int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
509                                     const uint32_t *attributes, int32_t *values) {
510  SCOPE_LOCK(locker_);
511
512  if (!device || !attributes || !values) {
513    return -EINVAL;
514  }
515
516  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
517    return -EINVAL;
518  }
519
520  HWCSession *hwc_session = static_cast<HWCSession *>(device);
521  int status = -EINVAL;
522  if (hwc_session->hwc_display_[disp]) {
523    status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, attributes, values);
524  }
525
526  return status;
527}
528
529int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
530  SCOPE_LOCK(locker_);
531
532  if (!device) {
533    return -EINVAL;
534  }
535
536  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
537    return -EINVAL;
538  }
539
540  HWCSession *hwc_session = static_cast<HWCSession *>(device);
541  int active_config = -1;
542  if (hwc_session->hwc_display_[disp]) {
543    active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
544  }
545
546  return active_config;
547}
548
549int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
550  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
551
552  if (!device) {
553    return -EINVAL;
554  }
555
556  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
557    return -EINVAL;
558  }
559
560  HWCSession *hwc_session = static_cast<HWCSession *>(device);
561  int status = -EINVAL;
562
563  if (hwc_session->hwc_display_[disp]) {
564    status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
565  }
566
567  return status;
568}
569
570int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
571  DTRACE_SCOPED();
572
573  SCOPE_LOCK(locker_);
574
575  if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
576    return -EINVAL;
577  }
578
579  int status = -EINVAL;
580  HWCSession *hwc_session = static_cast<HWCSession *>(device);
581  if (hwc_session->hwc_display_[disp]) {
582    status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
583  }
584
585  return status;
586}
587
588int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
589  DLOGI("Display = %d", disp);
590
591  int status = 0;
592  uint32_t primary_width = 0;
593  uint32_t primary_height = 0;
594
595  hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
596
597  if (disp == HWC_DISPLAY_EXTERNAL) {
598    status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
599                                        &hwc_display_[disp]);
600  } else if (disp == HWC_DISPLAY_VIRTUAL) {
601    status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
602                                       content_list, &hwc_display_[disp]);
603  } else {
604    DLOGE("Invalid display type");
605    return -1;
606  }
607
608  if (!status) {
609    hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
610  }
611
612  return status;
613}
614
615int HWCSession::DisconnectDisplay(int disp) {
616  DLOGI("Display = %d", disp);
617
618  if (disp == HWC_DISPLAY_EXTERNAL) {
619    HWCDisplayExternal::Destroy(hwc_display_[disp]);
620  } else if (disp == HWC_DISPLAY_VIRTUAL) {
621    HWCDisplayVirtual::Destroy(hwc_display_[disp]);
622  } else {
623    DLOGE("Invalid display type");
624    return -1;
625  }
626
627  hwc_display_[disp] = NULL;
628
629  return 0;
630}
631
632android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
633                                             android::Parcel *output_parcel) {
634  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
635
636  android::status_t status = 0;
637
638  switch (command) {
639  case qService::IQService::DYNAMIC_DEBUG:
640    DynamicDebug(input_parcel);
641    break;
642
643  case qService::IQService::SCREEN_REFRESH:
644    hwc_procs_->invalidate(hwc_procs_);
645    break;
646
647  case qService::IQService::SET_IDLE_TIMEOUT:
648    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
649      uint32_t timeout = UINT32(input_parcel->readInt32());
650      hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
651    }
652    break;
653
654  case qService::IQService::SET_FRAME_DUMP_CONFIG:
655    SetFrameDumpConfig(input_parcel);
656    break;
657
658  case qService::IQService::SET_MAX_PIPES_PER_MIXER:
659    status = SetMaxMixerStages(input_parcel);
660    break;
661
662  case qService::IQService::SET_DISPLAY_MODE:
663    status = SetDisplayMode(input_parcel);
664    break;
665
666  case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
667    status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
668    break;
669
670  case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
671    status = ConfigureRefreshRate(input_parcel);
672    break;
673
674  case qService::IQService::SET_VIEW_FRAME:
675    break;
676
677  case qService::IQService::TOGGLE_SCREEN_UPDATES:
678    status = ToggleScreenUpdates(input_parcel, output_parcel);
679    break;
680
681  case qService::IQService::QDCM_SVC_CMDS:
682    status = QdcmCMDHandler(input_parcel, output_parcel);
683    break;
684
685  case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
686    status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
687    break;
688
689  case qService::IQService::CONTROL_PARTIAL_UPDATE:
690    status = ControlPartialUpdate(input_parcel, output_parcel);
691    break;
692
693  case qService::IQService::SET_ACTIVE_CONFIG:
694    status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
695    break;
696
697  case qService::IQService::GET_ACTIVE_CONFIG:
698    status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
699    break;
700
701  case qService::IQService::GET_CONFIG_COUNT:
702    status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
703    break;
704
705  case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
706    status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
707    break;
708
709  case qService::IQService::GET_PANEL_BRIGHTNESS:
710    status = GetPanelBrightness(input_parcel, output_parcel);
711    break;
712
713  case qService::IQService::SET_PANEL_BRIGHTNESS:
714    status = SetPanelBrightness(input_parcel, output_parcel);
715    break;
716
717  case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
718    status = GetVisibleDisplayRect(input_parcel, output_parcel);
719    break;
720
721  case qService::IQService::SET_CAMERA_STATUS:
722    status = SetDynamicBWForCamera(input_parcel, output_parcel);
723    break;
724
725  case qService::IQService::GET_BW_TRANSACTION_STATUS:
726    status = GetBWTransactionStatus(input_parcel, output_parcel);
727    break;
728
729  default:
730    DLOGW("QService command = %d is not supported", command);
731    return -EINVAL;
732  }
733
734  return status;
735}
736
737android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
738                                                  android::Parcel *output_parcel) {
739  int input = input_parcel->readInt32();
740  int error = android::BAD_VALUE;
741
742  if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
743    error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
744    if (error != 0) {
745      DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
746    }
747  }
748  output_parcel->writeInt32(error);
749
750  return error;
751}
752
753android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
754                                                 android::Parcel *output_parcel) {
755  int level = input_parcel->readInt32();
756  int error = android::BAD_VALUE;
757
758  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
759    error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
760    if (error != 0) {
761      DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
762    }
763  }
764  output_parcel->writeInt32(error);
765
766  return error;
767}
768
769android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
770                                                 android::Parcel *output_parcel) {
771  int error = android::BAD_VALUE;
772  int ret = error;
773
774  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
775    error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
776    if (error != 0) {
777      ret = error;
778      DLOGE("Failed to get the panel brightness. Error = %d", error);
779    }
780  }
781  output_parcel->writeInt32(ret);
782
783  return error;
784}
785
786android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
787                                                   android::Parcel *out) {
788  DisplayError error = kErrorNone;
789  int ret = 0;
790  uint32_t disp_id = UINT32(input_parcel->readInt32());
791  uint32_t enable = UINT32(input_parcel->readInt32());
792
793  if (disp_id != HWC_DISPLAY_PRIMARY) {
794    DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
795    ret = -EINVAL;
796    out->writeInt32(ret);
797    return ret;
798  }
799
800  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
801    DLOGE("primary display object is not instantiated");
802    ret = -EINVAL;
803    out->writeInt32(ret);
804    return ret;
805  }
806
807  uint32_t pending = 0;
808  error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
809
810  if (error == kErrorNone) {
811    if (!pending) {
812      out->writeInt32(ret);
813      return ret;
814    }
815  } else if (error == kErrorNotSupported) {
816    out->writeInt32(ret);
817    return ret;
818  } else {
819    ret = -EINVAL;
820    out->writeInt32(ret);
821    return ret;
822  }
823
824  // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
825  hwc_procs_->invalidate(hwc_procs_);
826
827  // Wait until partial update control is complete
828  ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
829
830  out->writeInt32(ret);
831
832  return ret;
833}
834
835android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
836                                                     android::Parcel *output_parcel) {
837  int config = input_parcel->readInt32();
838  int dpy = input_parcel->readInt32();
839  int error = android::BAD_VALUE;
840
841  if (dpy > HWC_DISPLAY_VIRTUAL) {
842    return android::BAD_VALUE;
843  }
844
845  if (hwc_display_[dpy]) {
846    error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
847    if (error == 0) {
848      hwc_procs_->invalidate(hwc_procs_);
849    }
850  }
851
852  return error;
853}
854
855android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
856                                                           android::Parcel *output_parcel) {
857  int dpy = input_parcel->readInt32();
858  int error = android::BAD_VALUE;
859
860  if (dpy > HWC_DISPLAY_VIRTUAL) {
861    return android::BAD_VALUE;
862  }
863
864  if (hwc_display_[dpy]) {
865    uint32_t config = 0;
866    error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
867    if (error == 0) {
868      output_parcel->writeInt32(INT(config));
869    }
870  }
871
872  return error;
873}
874
875android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
876                                                          android::Parcel *output_parcel) {
877  int dpy = input_parcel->readInt32();
878  int error = android::BAD_VALUE;
879
880  if (dpy > HWC_DISPLAY_VIRTUAL) {
881    return android::BAD_VALUE;
882  }
883
884  uint32_t count = 0;
885  if (hwc_display_[dpy]) {
886    error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
887    if (error == 0) {
888      output_parcel->writeInt32(INT(count));
889    }
890  }
891
892  return error;
893}
894
895android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
896                                                                  *input_parcel,
897                                                                  android::Parcel *output_parcel) {
898  int config = input_parcel->readInt32();
899  int dpy = input_parcel->readInt32();
900  int error = android::BAD_VALUE;
901  DisplayConfigVariableInfo attributes;
902
903  if (dpy > HWC_DISPLAY_VIRTUAL) {
904    return android::BAD_VALUE;
905  }
906
907  if (hwc_display_[dpy]) {
908    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &attributes);
909    if (error == 0) {
910      output_parcel->writeInt32(INT(attributes.vsync_period_ns));
911      output_parcel->writeInt32(INT(attributes.x_pixels));
912      output_parcel->writeInt32(INT(attributes.y_pixels));
913      output_parcel->writeFloat(attributes.x_dpi);
914      output_parcel->writeFloat(attributes.y_dpi);
915      output_parcel->writeInt32(0);  // Panel type, unsupported.
916    }
917  }
918
919  return error;
920}
921
922android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
923                                                        android::Parcel *output_parcel) {
924  int ret = -EINVAL;
925
926  uint32_t display_id = UINT32(input_parcel->readInt32());
927  uint32_t display_status = UINT32(input_parcel->readInt32());
928
929  DLOGI("Display = %d, Status = %d", display_id, display_status);
930
931  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
932    DLOGE("Invalid display_id");
933  } else if (display_id == HWC_DISPLAY_PRIMARY) {
934    DLOGE("Not supported for this display");
935  } else if (!hwc_display_[display_id]) {
936    DLOGW("Display is not connected");
937  } else {
938    ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
939  }
940
941  output_parcel->writeInt32(ret);
942
943  return ret;
944}
945
946android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
947  uint32_t operation = UINT32(input_parcel->readInt32());
948  switch (operation) {
949    case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
950      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
951          HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
952    case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
953      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
954          HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
955    case qdutils::SET_BINDER_DYN_REFRESH_RATE:
956      {
957        uint32_t refresh_rate = UINT32(input_parcel->readInt32());
958        return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
959            HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
960            refresh_rate);
961      }
962    default:
963      DLOGW("Invalid operation %d", operation);
964      return -EINVAL;
965  }
966
967  return 0;
968}
969
970android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
971  uint32_t mode = UINT32(input_parcel->readInt32());
972  return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
973}
974
975android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
976  DisplayError error = kErrorNone;
977  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
978  uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
979
980  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
981    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
982      error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
983      if (error != kErrorNone) {
984        return -EINVAL;
985      }
986    }
987  }
988
989  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
990    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
991      error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
992      if (error != kErrorNone) {
993        return -EINVAL;
994      }
995    }
996  }
997
998  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
999    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1000      error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
1001      if (error != kErrorNone) {
1002        return -EINVAL;
1003      }
1004    }
1005  }
1006
1007  return 0;
1008}
1009
1010android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
1011                                                    android::Parcel *output_parcel) {
1012  DisplayError error = kErrorNone;
1013  uint32_t camera_status = UINT32(input_parcel->readInt32());
1014  HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
1015
1016  // trigger invalidate to apply new bw caps.
1017  hwc_procs_->invalidate(hwc_procs_);
1018
1019    error = core_intf_->SetMaxBandwidthMode(mode);
1020  if (error != kErrorNone) {
1021      return -EINVAL;
1022  }
1023
1024  new_bw_mode_ = true;
1025  need_invalidate_ = true;
1026
1027  return 0;
1028}
1029
1030android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
1031                                                     android::Parcel *output_parcel)  {
1032  bool state = true;
1033
1034  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1035    if (sync_wait(bw_mode_release_fd_, 0) < 0) {
1036      DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
1037      state = false;
1038    }
1039    output_parcel->writeInt32(state);
1040  }
1041
1042  return 0;
1043}
1044
1045void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1046  uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1047  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
1048  uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1049
1050  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
1051    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1052      hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1053    }
1054  }
1055
1056  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
1057    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1058      hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1059    }
1060  }
1061
1062  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
1063    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1064      hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1065    }
1066  }
1067}
1068
1069void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
1070  int type = input_parcel->readInt32();
1071  bool enable = (input_parcel->readInt32() > 0);
1072  DLOGI("type = %d enable = %d", type, enable);
1073  int verbose_level = input_parcel->readInt32();
1074
1075  switch (type) {
1076  case qService::IQService::DEBUG_ALL:
1077    HWCDebugHandler::DebugAll(enable, verbose_level);
1078    break;
1079
1080  case qService::IQService::DEBUG_MDPCOMP:
1081    HWCDebugHandler::DebugStrategy(enable, verbose_level);
1082    HWCDebugHandler::DebugCompManager(enable, verbose_level);
1083    break;
1084
1085  case qService::IQService::DEBUG_PIPE_LIFECYCLE:
1086    HWCDebugHandler::DebugResources(enable, verbose_level);
1087    break;
1088
1089  case qService::IQService::DEBUG_DRIVER_CONFIG:
1090    HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1091    break;
1092
1093  case qService::IQService::DEBUG_ROTATOR:
1094    HWCDebugHandler::DebugResources(enable, verbose_level);
1095    HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1096    HWCDebugHandler::DebugRotator(enable, verbose_level);
1097    break;
1098
1099  case qService::IQService::DEBUG_QDCM:
1100    HWCDebugHandler::DebugQdcm(enable, verbose_level);
1101    break;
1102
1103  default:
1104    DLOGW("type = %d is not supported", type);
1105  }
1106}
1107
1108android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
1109                                             android::Parcel *output_parcel) {
1110  int ret = 0;
1111  int32_t *brightness_value = NULL;
1112  uint32_t display_id(0);
1113  PPPendingParams pending_action;
1114  PPDisplayAPIPayload resp_payload, req_payload;
1115
1116  if (!color_mgr_) {
1117    return -1;
1118  }
1119
1120  pending_action.action = kNoAction;
1121  pending_action.params = NULL;
1122
1123  // Read display_id, payload_size and payload from in_parcel.
1124  ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
1125  if (!ret) {
1126    if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
1127      ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
1128                                                                  &resp_payload, &pending_action);
1129
1130    if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
1131      ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
1132                                                                  &pending_action);
1133  }
1134
1135  if (ret) {
1136    output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
1137    req_payload.DestroyPayload();
1138    resp_payload.DestroyPayload();
1139    return ret;
1140  }
1141
1142  switch (pending_action.action) {
1143    case kInvalidating:
1144      hwc_procs_->invalidate(hwc_procs_);
1145      break;
1146    case kEnterQDCMMode:
1147      ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1148      break;
1149    case kExitQDCMMode:
1150      ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1151      break;
1152    case kApplySolidFill:
1153      ret = color_mgr_->SetSolidFill(pending_action.params,
1154                                     true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1155      hwc_procs_->invalidate(hwc_procs_);
1156      break;
1157    case kDisableSolidFill:
1158      ret = color_mgr_->SetSolidFill(pending_action.params,
1159                                     false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1160      hwc_procs_->invalidate(hwc_procs_);
1161      break;
1162    case kSetPanelBrightness:
1163      brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1164      if (brightness_value == NULL) {
1165        DLOGE("Brightness value is Null");
1166        return -EINVAL;
1167      }
1168      if (HWC_DISPLAY_PRIMARY == display_id)
1169        ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
1170      break;
1171    case kNoAction:
1172      break;
1173    default:
1174      DLOGW("Invalid pending action = %d!", pending_action.action);
1175      break;
1176  }
1177
1178  // for display API getter case, marshall returned params into out_parcel.
1179  output_parcel->writeInt32(ret);
1180  HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1181  req_payload.DestroyPayload();
1182  resp_payload.DestroyPayload();
1183
1184  return (ret? -EINVAL : 0);
1185}
1186
1187android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
1188                                                             android::Parcel *output_parcel) {
1189  int ret = -EINVAL;
1190  uint32_t display_id = UINT32(input_parcel->readInt32());
1191  uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1192
1193  DLOGI("Display %d", display_id);
1194
1195  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1196    DLOGE("Invalid display_id");
1197  } else if (display_id != HWC_DISPLAY_EXTERNAL) {
1198    DLOGE("Not supported for display");
1199  } else if (!hwc_display_[display_id]) {
1200    DLOGW("Display is not connected");
1201  } else {
1202    ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
1203  }
1204
1205  output_parcel->writeInt32(ret);
1206
1207  return ret;
1208}
1209
1210void* HWCSession::HWCUeventThread(void *context) {
1211  if (context) {
1212    return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
1213  }
1214
1215  return NULL;
1216}
1217
1218void* HWCSession::HWCUeventThreadHandler() {
1219  static char uevent_data[PAGE_SIZE];
1220  int length = 0;
1221  prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
1222  setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1223  if (!uevent_init()) {
1224    DLOGE("Failed to init uevent");
1225    pthread_exit(0);
1226    return NULL;
1227  }
1228
1229  while (!uevent_thread_exit_) {
1230    // keep last 2 zeroes to ensure double 0 termination
1231    length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
1232
1233    if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
1234      DLOGI("Uevent HDMI = %s", uevent_data);
1235      int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
1236      if (connected >= 0) {
1237        DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
1238        if (HotPlugHandler(connected) == -1) {
1239          DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
1240        }
1241      }
1242    } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
1243      DLOGI("Uevent FB0 = %s", uevent_data);
1244      int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
1245      if (panel_reset == 0) {
1246        if (hwc_procs_) {
1247          reset_panel_ = true;
1248          hwc_procs_->invalidate(hwc_procs_);
1249        } else {
1250          DLOGW("Ignore resetpanel - hwc_proc not registered");
1251        }
1252      }
1253    }
1254  }
1255  pthread_exit(0);
1256
1257  return NULL;
1258}
1259
1260int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
1261  const char *iterator_str = uevent_data;
1262  while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
1263    char *pstr = strstr(iterator_str, event_info);
1264    if (pstr != NULL) {
1265      return (atoi(iterator_str + strlen(event_info)));
1266    }
1267    iterator_str += strlen(iterator_str) + 1;
1268  }
1269
1270  return -1;
1271}
1272
1273void HWCSession::ResetPanel() {
1274  int status = -EINVAL;
1275
1276  DLOGI("Powering off primary");
1277  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
1278  if (status) {
1279    DLOGE("power-off on primary failed with error = %d", status);
1280  }
1281
1282  DLOGI("Restoring power mode on primary");
1283  int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
1284  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
1285  if (status) {
1286    DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
1287  }
1288
1289  status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
1290  if (status) {
1291    DLOGE("enabling vsync failed for primary with error = %d", status);
1292  }
1293
1294  reset_panel_ = false;
1295}
1296
1297int HWCSession::HotPlugHandler(bool connected) {
1298  int status = 0;
1299  bool notify_hotplug = false;
1300
1301  // To prevent sending events to client while a lock is held, acquire scope locks only within
1302  // below scope so that those get automatically unlocked after the scope ends.
1303  {
1304    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
1305
1306    if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1307      DLOGE("Primay display is not connected.");
1308      return -1;
1309    }
1310
1311    if (connected) {
1312      if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1313        DLOGE("HDMI is already connected");
1314        return -1;
1315      }
1316
1317      // Connect external display if virtual display is not connected.
1318      // Else, defer external display connection and process it when virtual display
1319      // tears down; Do not notify SurfaceFlinger since connection is deferred now.
1320      if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1321        status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
1322        if (status) {
1323          return status;
1324        }
1325        notify_hotplug = true;
1326      } else {
1327        DLOGI("Virtual display is connected, pending connection");
1328        external_pending_connect_ = true;
1329      }
1330    } else {
1331      // Do not return error if external display is not in connected status.
1332      // Due to virtual display concurrency, external display connection might be still pending
1333      // but hdmi got disconnected before pending connection could be processed.
1334      if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1335        status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
1336        notify_hotplug = true;
1337      }
1338      external_pending_connect_ = false;
1339    }
1340  }
1341  if (connected && notify_hotplug) {
1342    // trigger screen refresh to ensure sufficient resources are available to process new
1343    // new display connection.
1344    hwc_procs_->invalidate(hwc_procs_);
1345    uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
1346    usleep(vsync_period * 2 / 1000);
1347  }
1348  // notify client
1349  if (notify_hotplug) {
1350    hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
1351  }
1352
1353  return 0;
1354}
1355
1356void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
1357  secure_display_active_ = false;
1358  if (!*displays) {
1359    DLOGW("Invalid display contents");
1360    return;
1361  }
1362
1363  hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
1364  if (!content_list) {
1365    DLOGW("Invalid primary content list");
1366    return;
1367  }
1368  size_t num_hw_layers = content_list->numHwLayers;
1369
1370  for (size_t i = 0; i < num_hw_layers - 1; i++) {
1371    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
1372    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
1373    if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
1374      secure_display_active_ = true;
1375    }
1376  }
1377
1378  for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
1379    if (hwc_display_[dpy]) {
1380      hwc_display_[dpy]->SetSecureDisplay(secure_display_active_);
1381    }
1382  }
1383}
1384
1385android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
1386                                                    android::Parcel *output_parcel) {
1387  int dpy = input_parcel->readInt32();
1388
1389  if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
1390    return android::BAD_VALUE;;
1391  }
1392
1393  if (!hwc_display_[dpy]) {
1394    return android::NO_INIT;
1395  }
1396
1397  hwc_rect_t visible_rect = {0, 0, 0, 0};
1398  int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
1399  if (error < 0) {
1400    return error;
1401  }
1402
1403  output_parcel->writeInt32(visible_rect.left);
1404  output_parcel->writeInt32(visible_rect.top);
1405  output_parcel->writeInt32(visible_rect.right);
1406  output_parcel->writeInt32(visible_rect.bottom);
1407
1408  return android::NO_ERROR;
1409}
1410
1411}  // namespace sdm
1412
1413