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