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