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