Home | History | Annotate | Download | only in hwc2
      1 /*
      2  * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
      3  * Not a Contribution.
      4  *
      5  * Copyright 2015 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  */
     19 
     20 #include <core/buffer_allocator.h>
     21 #include <private/color_params.h>
     22 #include <utils/constants.h>
     23 #include <utils/String16.h>
     24 #include <cutils/properties.h>
     25 #include <hardware_legacy/uevent.h>
     26 #include <sys/resource.h>
     27 #include <sys/prctl.h>
     28 #include <binder/Parcel.h>
     29 #include <QService.h>
     30 #include <display_config.h>
     31 #include <utils/debug.h>
     32 #include <sync/sync.h>
     33 #include <profiler.h>
     34 #include <algorithm>
     35 #include <string>
     36 #include <bitset>
     37 #include <thread>
     38 #include <memory>
     39 
     40 #include "hwc_buffer_allocator.h"
     41 #include "hwc_buffer_sync_handler.h"
     42 #include "hwc_session.h"
     43 #include "hwc_debugger.h"
     44 #include "hwc_display_primary.h"
     45 #include "hwc_display_virtual.h"
     46 #include "hwc_display_external_test.h"
     47 #include "qd_utils.h"
     48 
     49 #define __CLASS__ "HWCSession"
     50 
     51 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
     52 #define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
     53 
     54 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
     55 
     56 hwc_module_t HAL_MODULE_INFO_SYM = {
     57   .common = {
     58     .tag = HARDWARE_MODULE_TAG,
     59     .version_major = 3,
     60     .version_minor = 0,
     61     .id = HWC_HARDWARE_MODULE_ID,
     62     .name = "QTI Hardware Composer Module",
     63     .author = "CodeAurora Forum",
     64     .methods = &g_hwc_module_methods,
     65     .dso = 0,
     66     .reserved = {0},
     67   }
     68 };
     69 
     70 namespace sdm {
     71 
     72 static HWCUEvent g_hwc_uevent_;
     73 Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
     74 bool HWCSession::disable_skip_validate_ = false;
     75 
     76 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
     77   const char *uevent_thread_name = "HWC_UeventThread";
     78 
     79   prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
     80   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
     81 
     82   int status = uevent_init();
     83   if (!status) {
     84     std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
     85     hwc_uevent->caller_cv_.notify_one();
     86     DLOGE("Failed to init uevent with err %d", status);
     87     return;
     88   }
     89 
     90   {
     91     // Signal caller thread that worker thread is ready to listen to events.
     92     std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
     93     hwc_uevent->init_done_ = true;
     94     hwc_uevent->caller_cv_.notify_one();
     95   }
     96 
     97   while (1) {
     98     char uevent_data[PAGE_SIZE] = {};
     99 
    100     // keep last 2 zeroes to ensure double 0 termination
    101     int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
    102 
    103     // scope of lock to this block only, so that caller is free to set event handler to nullptr;
    104     {
    105       std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
    106       if (hwc_uevent->uevent_listener_) {
    107         hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
    108       } else {
    109         DLOGW("UEvent dropped. No uevent listener.");
    110       }
    111     }
    112   }
    113 }
    114 
    115 HWCUEvent::HWCUEvent() {
    116   std::unique_lock<std::mutex> caller_lock(mutex_);
    117   std::thread thread(HWCUEvent::UEventThread, this);
    118   thread.detach();
    119   caller_cv_.wait(caller_lock);
    120 }
    121 
    122 void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
    123   DLOGI("Set uevent listener = %p", uevent_listener);
    124 
    125   std::lock_guard<std::mutex> obj(mutex_);
    126   uevent_listener_ = uevent_listener;
    127 }
    128 
    129 HWCSession::HWCSession(const hw_module_t *module) {
    130   hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
    131   hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
    132   hwc2_device_t::common.module = const_cast<hw_module_t *>(module);
    133   hwc2_device_t::common.close = Close;
    134   hwc2_device_t::getCapabilities = GetCapabilities;
    135   hwc2_device_t::getFunction = GetFunction;
    136 }
    137 
    138 int HWCSession::Init() {
    139   SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
    140 
    141   int status = -EINVAL;
    142   const char *qservice_name = "display.qservice";
    143 
    144   if (!g_hwc_uevent_.InitDone()) {
    145     return status;
    146   }
    147 
    148   // Start QService and connect to it.
    149   qService::QService::init();
    150   android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
    151       android::defaultServiceManager()->getService(android::String16(qservice_name)));
    152 
    153   if (iqservice.get()) {
    154     iqservice->connect(android::sp<qClient::IQClient>(this));
    155     qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
    156   } else {
    157     ALOGE("%s::%s: Failed to acquire %s", __CLASS__, __FUNCTION__, qservice_name);
    158     return -EINVAL;
    159   }
    160 
    161   StartServices();
    162 
    163   DisplayError error = buffer_allocator_.Init();
    164   if (error != kErrorNone) {
    165     ALOGE("%s::%s: Buffer allocaor initialization failed. Error = %d",
    166           __CLASS__, __FUNCTION__, error);
    167     return -EINVAL;
    168   }
    169 
    170   error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
    171                                     &buffer_sync_handler_, &socket_handler_, &core_intf_);
    172   if (error != kErrorNone) {
    173     buffer_allocator_.Deinit();
    174     ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__, error);
    175     return -EINVAL;
    176   }
    177 
    178   g_hwc_uevent_.Register(this);
    179 
    180   // If HDMI display is primary display, defer display creation until hotplug event is received.
    181   HWDisplayInterfaceInfo hw_disp_info = {};
    182   error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
    183   if (error != kErrorNone) {
    184     g_hwc_uevent_.Register(nullptr);
    185     CoreInterface::DestroyCore();
    186     buffer_allocator_.Deinit();
    187     DLOGE("Primary display type not recognized. Error = %d", error);
    188     return -EINVAL;
    189   }
    190 
    191   if (hw_disp_info.type == kHDMI) {
    192     status = 0;
    193     hdmi_is_primary_ = true;
    194     // Create display if it is connected, else wait for hotplug connect event.
    195     if (hw_disp_info.is_connected) {
    196       status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
    197     }
    198   } else {
    199     // Create and power on primary display
    200     status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_,
    201                                        &hwc_display_[HWC_DISPLAY_PRIMARY]);
    202     color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
    203     if (!color_mgr_) {
    204       DLOGW("Failed to load HWCColorManager.");
    205     }
    206   }
    207 
    208   if (status) {
    209     g_hwc_uevent_.Register(nullptr);
    210     CoreInterface::DestroyCore();
    211     buffer_allocator_.Deinit();
    212     return status;
    213   }
    214 
    215   struct rlimit fd_limit = {};
    216   getrlimit(RLIMIT_NOFILE, &fd_limit);
    217   fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
    218   if (fd_limit.rlim_cur < fd_limit.rlim_max) {
    219     auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
    220     if (err) {
    221       DLOGW("Unable to increase fd limit -  err:%d, %s", errno, strerror(errno));
    222     }
    223   }
    224 
    225   return 0;
    226 }
    227 
    228 int HWCSession::Deinit() {
    229   Locker::SequenceCancelScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
    230   Locker::SequenceCancelScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
    231   Locker::SequenceCancelScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
    232 
    233   HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
    234   if (primary_display) {
    235     if (hdmi_is_primary_) {
    236       HWCDisplayExternal::Destroy(primary_display);
    237     } else {
    238       HWCDisplayPrimary::Destroy(primary_display);
    239     }
    240   }
    241   hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr;
    242 
    243   if (color_mgr_) {
    244     color_mgr_->DestroyColorManager();
    245   }
    246 
    247   g_hwc_uevent_.Register(nullptr);
    248 
    249   DisplayError error = CoreInterface::DestroyCore();
    250   if (error != kErrorNone) {
    251     ALOGE("Display core de-initialization failed. Error = %d", error);
    252   }
    253 
    254   return 0;
    255 }
    256 
    257 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
    258   if (!module || !name || !device) {
    259     ALOGE("%s::%s: Invalid parameters.", __CLASS__, __FUNCTION__);
    260     return -EINVAL;
    261   }
    262 
    263   if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
    264     HWCSession *hwc_session = new HWCSession(module);
    265     if (!hwc_session) {
    266       return -ENOMEM;
    267     }
    268 
    269     int status = hwc_session->Init();
    270     if (status != 0) {
    271       return status;
    272     }
    273 
    274     hwc2_device_t *composer_device = hwc_session;
    275     *device = reinterpret_cast<hw_device_t *>(composer_device);
    276   }
    277 
    278   return 0;
    279 }
    280 
    281 int HWCSession::Close(hw_device_t *device) {
    282   if (!device) {
    283     return -EINVAL;
    284   }
    285 
    286   hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device);
    287   HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
    288 
    289   hwc_session->Deinit();
    290 
    291   return 0;
    292 }
    293 
    294 void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
    295                                  int32_t *outCapabilities) {
    296   if (!outCount) {
    297     return;
    298   }
    299 
    300   int value = 0;
    301   uint32_t count = 0;
    302   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    303   bool color_transform_supported = hwc_session->core_intf_->IsColorTransformSupported();
    304 
    305   if (Debug::Get()->GetProperty(DISABLE_SKIP_VALIDATE_PROP, &value) == kErrorNone) {
    306     disable_skip_validate_ = (value == 1);
    307   }
    308 
    309   count += (color_transform_supported) ? 1 : 0;
    310   count += (!disable_skip_validate_) ? 1 : 0;
    311 
    312   if (outCapabilities != nullptr && (*outCount >= count)) {
    313     int i = 0;
    314     if (color_transform_supported) {
    315       outCapabilities[i++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
    316     }
    317     if (!disable_skip_validate_) {
    318       outCapabilities[i++] = HWC2_CAPABILITY_SKIP_VALIDATE;
    319     }
    320   }
    321   *outCount = count;
    322 }
    323 
    324 template <typename PFN, typename T>
    325 static hwc2_function_pointer_t AsFP(T function) {
    326   static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
    327   return reinterpret_cast<hwc2_function_pointer_t>(function);
    328 }
    329 
    330 // HWC2 functions returned in GetFunction
    331 // Defined in the same order as in the HWC2 header
    332 
    333 int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
    334   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
    335 }
    336 
    337 int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
    338                                 hwc2_layer_t *out_layer_id) {
    339   if (!out_layer_id) {
    340     return  HWC2_ERROR_BAD_PARAMETER;
    341   }
    342 
    343   return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
    344 }
    345 
    346 int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
    347                                          int32_t *format, hwc2_display_t *out_display_id) {
    348   // TODO(user): Handle concurrency with HDMI
    349   SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
    350   if (!device) {
    351     return HWC2_ERROR_BAD_DISPLAY;
    352   }
    353 
    354   if (!out_display_id || !width || !height || !format) {
    355     return  HWC2_ERROR_BAD_PARAMETER;
    356   }
    357 
    358   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    359   auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
    360   if (status == HWC2::Error::None) {
    361     *out_display_id = HWC_DISPLAY_VIRTUAL;
    362     DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d",
    363           *out_display_id, width, height);
    364   } else {
    365     DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
    366   }
    367   return INT32(status);
    368 }
    369 
    370 int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
    371                                  hwc2_layer_t layer) {
    372   return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
    373 }
    374 
    375 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
    376   if (!device || display != HWC_DISPLAY_VIRTUAL) {
    377     return HWC2_ERROR_BAD_DISPLAY;
    378   }
    379 
    380   SCOPE_LOCK(locker_[display]);
    381   DLOGI("Destroying virtual display id:%" PRIu64, display);
    382   auto *hwc_session = static_cast<HWCSession *>(device);
    383 
    384   if (hwc_session->hwc_display_[display]) {
    385     HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]);
    386     hwc_session->hwc_display_[display] = nullptr;
    387     return HWC2_ERROR_NONE;
    388   } else {
    389     return HWC2_ERROR_BAD_DISPLAY;
    390   }
    391 }
    392 
    393 void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
    394   if (!device || !out_size) {
    395     return;
    396   }
    397 
    398   auto *hwc_session = static_cast<HWCSession *>(device);
    399   const size_t max_dump_size = 8192;
    400 
    401   if (out_buffer == nullptr) {
    402     *out_size = max_dump_size;
    403   } else {
    404     std::string s {};
    405     for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
    406       SCOPE_LOCK(locker_[id]);
    407       if (hwc_session->hwc_display_[id]) {
    408         s += hwc_session->hwc_display_[id]->Dump();
    409       }
    410     }
    411     auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
    412     *out_size = UINT32(copied);
    413   }
    414 }
    415 
    416 static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
    417                                hwc2_config_t *out_config) {
    418   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
    419 }
    420 
    421 static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
    422                                           uint32_t *out_num_elements, hwc2_layer_t *out_layers,
    423                                           int32_t *out_types) {
    424   // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
    425   if (!out_num_elements) {
    426     return  HWC2_ERROR_BAD_PARAMETER;
    427   }
    428   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
    429                                          out_num_elements, out_layers, out_types);
    430 }
    431 
    432 static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width,
    433                                       uint32_t height, int32_t format, int32_t dataspace) {
    434   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport,
    435                                          width, height, format, dataspace);
    436 }
    437 
    438 static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
    439                              int32_t /*android_color_mode_t*/ *int_out_modes) {
    440   auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
    441   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
    442                                          out_modes);
    443 }
    444 
    445 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
    446                                    hwc2_config_t config, int32_t int_attribute,
    447                                    int32_t *out_value) {
    448   auto attribute = static_cast<HWC2::Attribute>(int_attribute);
    449   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
    450                                          attribute, out_value);
    451 }
    452 
    453 static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display,
    454                                  uint32_t *out_num_configs, hwc2_config_t *out_configs) {
    455   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs,
    456                                          out_num_configs, out_configs);
    457 }
    458 
    459 static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size,
    460                               char *out_name) {
    461   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size,
    462                                          out_name);
    463 }
    464 
    465 static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display,
    466                                   int32_t *out_display_requests, uint32_t *out_num_elements,
    467                                   hwc2_layer_t *out_layers, int32_t *out_layer_requests) {
    468   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests,
    469                                          out_display_requests, out_num_elements, out_layers,
    470                                          out_layer_requests);
    471 }
    472 
    473 static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) {
    474   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
    475 }
    476 
    477 static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
    478   if (display == HWC_DISPLAY_PRIMARY) {
    479     *out_support = 1;
    480   } else {
    481     // TODO(user): Port over connect_display_ from HWC1
    482     // Return no error for connected displays
    483     *out_support = 0;
    484     return HWC2_ERROR_BAD_DISPLAY;
    485   }
    486   return HWC2_ERROR_NONE;
    487 }
    488 
    489 static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
    490                                   uint32_t* out_num_types, int32_t* out_types,
    491                                   float* out_max_luminance, float* out_max_average_luminance,
    492                                   float* out_min_luminance) {
    493   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities,
    494                                          out_num_types, out_types, out_max_luminance,
    495                                          out_max_average_luminance, out_min_luminance);
    496 }
    497 
    498 static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
    499   char property[PROPERTY_VALUE_MAX];
    500   property_get(WRITEBACK_SUPPORTED, property, "1");
    501   return (uint32_t) atoi(property);
    502 }
    503 
    504 static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
    505                                 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
    506                                 int32_t *out_fences) {
    507   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences,
    508                                          out_num_elements, out_layers, out_fences);
    509 }
    510 
    511 int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
    512                                    int32_t *out_retire_fence) {
    513   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    514   bool notify_hotplug = false;
    515   auto status = HWC2::Error::BadDisplay;
    516   DTRACE_SCOPED();
    517 
    518   if (display >= HWC_NUM_DISPLAY_TYPES) {
    519     return HWC2_ERROR_BAD_DISPLAY;
    520   }
    521 
    522   {
    523     SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
    524     if (!device) {
    525       return HWC2_ERROR_BAD_DISPLAY;
    526     }
    527 
    528     // TODO(user): Handle virtual display/HDMI concurrency
    529     if (hwc_session->hwc_display_[display]) {
    530       status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
    531       // This is only indicative of how many times SurfaceFlinger posts
    532       // frames to the display.
    533       CALC_FPS();
    534     }
    535   }
    536 
    537   if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
    538     SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
    539   }
    540 
    541   // Handle Pending external display connection
    542   if (hwc_session->external_pending_connect_ && (display == HWC_DISPLAY_PRIMARY)) {
    543     Locker::ScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
    544     Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
    545 
    546     if (!hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
    547       DLOGD("Process pending external display connection");
    548       hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL);
    549       hwc_session->external_pending_connect_ = false;
    550       notify_hotplug = true;
    551     }
    552   }
    553 
    554   if (notify_hotplug) {
    555     hwc_session->HotPlug(HWC_DISPLAY_EXTERNAL, HWC2::Connection::Connected);
    556   }
    557 
    558   return INT32(status);
    559 }
    560 
    561 int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
    562                                      hwc2_callback_data_t callback_data,
    563                                      hwc2_function_pointer_t pointer) {
    564   if (!device || pointer == nullptr) {
    565     return HWC2_ERROR_BAD_PARAMETER;
    566   }
    567   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    568   SCOPE_LOCK(hwc_session->callbacks_lock_);
    569   auto desc = static_cast<HWC2::Callback>(descriptor);
    570   auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
    571   DLOGD("Registering callback: %s", to_string(desc).c_str());
    572   if (descriptor == HWC2_CALLBACK_HOTPLUG) {
    573     if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
    574       hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
    575     }
    576   }
    577   hwc_session->need_invalidate_ = false;
    578   hwc_session->callbacks_lock_.Broadcast();
    579   return INT32(error);
    580 }
    581 
    582 static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
    583                                hwc2_config_t config) {
    584   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config);
    585 }
    586 
    587 static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
    588                                buffer_handle_t target, int32_t acquire_fence,
    589                                int32_t dataspace, hwc_region_t damage) {
    590   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target,
    591                                          acquire_fence, dataspace, damage);
    592 }
    593 
    594 int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
    595                                  int32_t /*android_color_mode_t*/ int_mode) {
    596   if (int_mode < HAL_COLOR_MODE_NATIVE || int_mode > HAL_COLOR_MODE_DISPLAY_P3) {
    597     return HWC2_ERROR_BAD_PARAMETER;
    598   }
    599   auto mode = static_cast<android_color_mode_t>(int_mode);
    600   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
    601 }
    602 
    603 int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
    604                                       const float *matrix,
    605                                       int32_t /*android_color_transform_t*/ hint) {
    606   if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
    607        hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
    608     return HWC2_ERROR_BAD_PARAMETER;
    609   }
    610   android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
    611   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
    612                                          transform_hint);
    613 }
    614 
    615 static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    616                                  int32_t x, int32_t y) {
    617   auto status = INT32(HWC2::Error::None);
    618   status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition,
    619                                            layer, x, y);
    620   if (status == INT32(HWC2::Error::None)) {
    621     // Update cursor position
    622     HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y);
    623   }
    624   return status;
    625 }
    626 
    627 static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    628                                  int32_t int_mode) {
    629   if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
    630     return HWC2_ERROR_BAD_PARAMETER;
    631   }
    632   auto mode = static_cast<HWC2::BlendMode>(int_mode);
    633   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
    634 }
    635 
    636 static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    637                               buffer_handle_t buffer, int32_t acquire_fence) {
    638   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer,
    639                                        acquire_fence);
    640 }
    641 
    642 static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    643                              hwc_color_t color) {
    644   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color);
    645 }
    646 
    647 static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display,
    648                                        hwc2_layer_t layer, int32_t int_type) {
    649   auto type = static_cast<HWC2::Composition>(int_type);
    650   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType,
    651                                        type);
    652 }
    653 
    654 static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    655                                  int32_t dataspace) {
    656   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace,
    657                                        dataspace);
    658 }
    659 
    660 static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display,
    661                                     hwc2_layer_t layer, hwc_rect_t frame) {
    662   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame,
    663                                        frame);
    664 }
    665 
    666 static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    667                                   float alpha) {
    668   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha,
    669                                        alpha);
    670 }
    671 
    672 static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    673                                   hwc_frect_t crop) {
    674   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop);
    675 }
    676 
    677 static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display,
    678                                      hwc2_layer_t layer, hwc_region_t damage) {
    679   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage,
    680                                        damage);
    681 }
    682 
    683 static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    684                                  int32_t int_transform) {
    685   auto transform = static_cast<HWC2::Transform>(int_transform);
    686   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform,
    687                                        transform);
    688 }
    689 
    690 static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display,
    691                                      hwc2_layer_t layer, hwc_region_t visible) {
    692   return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion,
    693                                        visible);
    694 }
    695 
    696 static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
    697                               uint32_t z) {
    698   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
    699 }
    700 
    701 int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
    702                                     buffer_handle_t buffer, int32_t releaseFence) {
    703   if (!device) {
    704     return HWC2_ERROR_BAD_DISPLAY;
    705   }
    706 
    707   if (display != HWC_DISPLAY_VIRTUAL) {
    708     return HWC2_ERROR_UNSUPPORTED;
    709   }
    710 
    711   SCOPE_LOCK(locker_[display]);
    712   auto *hwc_session = static_cast<HWCSession *>(device);
    713   if (hwc_session->hwc_display_[display]) {
    714     auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
    715     auto status = vds->SetOutputBuffer(buffer, releaseFence);
    716     return INT32(status);
    717   } else {
    718     return HWC2_ERROR_BAD_DISPLAY;
    719   }
    720 }
    721 
    722 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
    723   auto mode = static_cast<HWC2::PowerMode>(int_mode);
    724   return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
    725 }
    726 
    727 static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
    728   auto enabled = static_cast<HWC2::Vsync>(int_enabled);
    729   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
    730 }
    731 
    732 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
    733                                     uint32_t *out_num_types, uint32_t *out_num_requests) {
    734   DTRACE_SCOPED();
    735   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    736   if (!device) {
    737     return HWC2_ERROR_BAD_DISPLAY;
    738   }
    739 
    740   // TODO(user): Handle secure session, handle QDCM solid fill
    741   // Handle external_pending_connect_ in CreateVirtualDisplay
    742   auto status = HWC2::Error::BadDisplay;
    743   {
    744     SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
    745     if (hwc_session->hwc_display_[display]) {
    746       if (display == HWC_DISPLAY_PRIMARY) {
    747         // TODO(user): This can be moved to HWCDisplayPrimary
    748         if (hwc_session->reset_panel_) {
    749           DLOGW("panel is in bad state, resetting the panel");
    750           hwc_session->ResetPanel();
    751         }
    752 
    753         if (hwc_session->need_invalidate_) {
    754           hwc_session->Refresh(display);
    755           hwc_session->need_invalidate_ = false;
    756         }
    757 
    758         if (hwc_session->color_mgr_) {
    759           hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
    760         }
    761       }
    762 
    763       status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
    764     }
    765   }
    766 
    767   // Sequence locking currently begins on Validate, so cancel the sequence lock on failures
    768   if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
    769     SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
    770   }
    771 
    772   return INT32(status);
    773 }
    774 
    775 hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
    776                                                 int32_t int_descriptor) {
    777   auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor);
    778 
    779   switch (descriptor) {
    780     case HWC2::FunctionDescriptor::AcceptDisplayChanges:
    781       return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
    782     case HWC2::FunctionDescriptor::CreateLayer:
    783       return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
    784     case HWC2::FunctionDescriptor::CreateVirtualDisplay:
    785       return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay);
    786     case HWC2::FunctionDescriptor::DestroyLayer:
    787       return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
    788     case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
    789       return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay);
    790     case HWC2::FunctionDescriptor::Dump:
    791       return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump);
    792     case HWC2::FunctionDescriptor::GetActiveConfig:
    793       return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
    794     case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
    795       return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
    796     case HWC2::FunctionDescriptor::GetClientTargetSupport:
    797       return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
    798     case HWC2::FunctionDescriptor::GetColorModes:
    799       return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
    800     case HWC2::FunctionDescriptor::GetDisplayAttribute:
    801       return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
    802     case HWC2::FunctionDescriptor::GetDisplayConfigs:
    803       return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
    804     case HWC2::FunctionDescriptor::GetDisplayName:
    805       return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
    806     case HWC2::FunctionDescriptor::GetDisplayRequests:
    807       return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
    808     case HWC2::FunctionDescriptor::GetDisplayType:
    809       return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
    810     case HWC2::FunctionDescriptor::GetHdrCapabilities:
    811       return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
    812     case HWC2::FunctionDescriptor::GetDozeSupport:
    813       return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
    814     case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
    815       return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount);
    816     case HWC2::FunctionDescriptor::GetReleaseFences:
    817       return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
    818     case HWC2::FunctionDescriptor::PresentDisplay:
    819       return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
    820     case HWC2::FunctionDescriptor::RegisterCallback:
    821       return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback);
    822     case HWC2::FunctionDescriptor::SetActiveConfig:
    823       return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
    824     case HWC2::FunctionDescriptor::SetClientTarget:
    825       return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
    826     case HWC2::FunctionDescriptor::SetColorMode:
    827       return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
    828     case HWC2::FunctionDescriptor::SetColorTransform:
    829       return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
    830     case HWC2::FunctionDescriptor::SetCursorPosition:
    831       return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
    832     case HWC2::FunctionDescriptor::SetLayerBlendMode:
    833       return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
    834     case HWC2::FunctionDescriptor::SetLayerBuffer:
    835       return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
    836     case HWC2::FunctionDescriptor::SetLayerColor:
    837       return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
    838     case HWC2::FunctionDescriptor::SetLayerCompositionType:
    839       return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
    840     case HWC2::FunctionDescriptor::SetLayerDataspace:
    841       return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
    842     case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
    843       return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
    844     case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
    845       return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
    846     // Sideband stream is not supported
    847     // case HWC2::FunctionDescriptor::SetLayerSidebandStream:
    848     case HWC2::FunctionDescriptor::SetLayerSourceCrop:
    849       return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
    850     case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
    851       return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
    852     case HWC2::FunctionDescriptor::SetLayerTransform:
    853       return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
    854     case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
    855       return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
    856     case HWC2::FunctionDescriptor::SetLayerZOrder:
    857       return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
    858     case HWC2::FunctionDescriptor::SetOutputBuffer:
    859       return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
    860     case HWC2::FunctionDescriptor::SetPowerMode:
    861       return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
    862     case HWC2::FunctionDescriptor::SetVsyncEnabled:
    863       return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
    864     case HWC2::FunctionDescriptor::ValidateDisplay:
    865       return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
    866     default:
    867       DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
    868             to_string(descriptor).c_str());
    869       return nullptr;
    870   }
    871   return nullptr;
    872 }
    873 
    874 // TODO(user): handle locking
    875 
    876 HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height,
    877                                                    int32_t *format) {
    878   if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
    879     return HWC2::Error::NoResources;
    880   }
    881   auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, width,
    882                                           height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
    883   // TODO(user): validate width and height support
    884   if (status)
    885     return HWC2::Error::Unsupported;
    886 
    887   return HWC2::Error::None;
    888 }
    889 
    890 int32_t HWCSession::ConnectDisplay(int disp) {
    891   DLOGI("Display = %d", disp);
    892 
    893   int status = 0;
    894   uint32_t primary_width = 0;
    895   uint32_t primary_height = 0;
    896 
    897   hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
    898 
    899   if (disp == HWC_DISPLAY_EXTERNAL) {
    900     status = CreateExternalDisplay(disp, primary_width, primary_height);
    901   } else {
    902     DLOGE("Invalid display type");
    903     return -1;
    904   }
    905 
    906   if (!status) {
    907     hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
    908   }
    909 
    910   return status;
    911 }
    912 
    913 int HWCSession::DisconnectDisplay(int disp) {
    914   DLOGI("Display = %d", disp);
    915 
    916   if (disp == HWC_DISPLAY_EXTERNAL) {
    917     HWCDisplayExternal::Destroy(hwc_display_[disp]);
    918   } else if (disp == HWC_DISPLAY_VIRTUAL) {
    919     HWCDisplayVirtual::Destroy(hwc_display_[disp]);
    920   } else {
    921     DLOGE("Invalid display type");
    922     return -1;
    923   }
    924 
    925   hwc_display_[disp] = NULL;
    926 
    927   return 0;
    928 }
    929 
    930 // Qclient methods
    931 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
    932                                              android::Parcel *output_parcel) {
    933   android::status_t status = 0;
    934 
    935   switch (command) {
    936     case qService::IQService::DYNAMIC_DEBUG:
    937       DynamicDebug(input_parcel);
    938       break;
    939 
    940     case qService::IQService::SCREEN_REFRESH:
    941       refreshScreen();
    942       break;
    943 
    944     case qService::IQService::SET_IDLE_TIMEOUT:
    945       setIdleTimeout(UINT32(input_parcel->readInt32()));
    946       break;
    947 
    948     case qService::IQService::SET_FRAME_DUMP_CONFIG:
    949       SetFrameDumpConfig(input_parcel);
    950       break;
    951 
    952     case qService::IQService::SET_MAX_PIPES_PER_MIXER:
    953       status = SetMaxMixerStages(input_parcel);
    954       break;
    955 
    956     case qService::IQService::SET_DISPLAY_MODE:
    957       status = SetDisplayMode(input_parcel);
    958       break;
    959 
    960     case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
    961         int disp_id = INT(input_parcel->readInt32());
    962         HWCDisplay::DisplayStatus disp_status =
    963               static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
    964         status = SetSecondaryDisplayStatus(disp_id, disp_status);
    965         output_parcel->writeInt32(status);
    966       }
    967       break;
    968 
    969     case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
    970       status = ConfigureRefreshRate(input_parcel);
    971       break;
    972 
    973     case qService::IQService::SET_VIEW_FRAME:
    974       break;
    975 
    976     case qService::IQService::TOGGLE_SCREEN_UPDATES: {
    977         int32_t input = input_parcel->readInt32();
    978         status = toggleScreenUpdate(input == 1);
    979         output_parcel->writeInt32(status);
    980       }
    981       break;
    982 
    983     case qService::IQService::QDCM_SVC_CMDS:
    984       status = QdcmCMDHandler(input_parcel, output_parcel);
    985       break;
    986 
    987     case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
    988         int disp_id = input_parcel->readInt32();
    989         uint32_t min_enc_level = UINT32(input_parcel->readInt32());
    990         status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
    991         output_parcel->writeInt32(status);
    992       }
    993       break;
    994 
    995     case qService::IQService::CONTROL_PARTIAL_UPDATE: {
    996         int disp_id = input_parcel->readInt32();
    997         uint32_t enable = UINT32(input_parcel->readInt32());
    998         status = ControlPartialUpdate(disp_id, enable == 1);
    999         output_parcel->writeInt32(status);
   1000       }
   1001       break;
   1002 
   1003     case qService::IQService::SET_ACTIVE_CONFIG: {
   1004         uint32_t config = UINT32(input_parcel->readInt32());
   1005         int disp_id = input_parcel->readInt32();
   1006         status = SetActiveConfigIndex(disp_id, config);
   1007       }
   1008       break;
   1009 
   1010     case qService::IQService::GET_ACTIVE_CONFIG: {
   1011         int disp_id = input_parcel->readInt32();
   1012         uint32_t config = 0;
   1013         status = GetActiveConfigIndex(disp_id, &config);
   1014         output_parcel->writeInt32(INT(config));
   1015       }
   1016       break;
   1017 
   1018     case qService::IQService::GET_CONFIG_COUNT: {
   1019         int disp_id = input_parcel->readInt32();
   1020         uint32_t count = 0;
   1021         status = GetConfigCount(disp_id, &count);
   1022         output_parcel->writeInt32(INT(count));
   1023       }
   1024       break;
   1025 
   1026     case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
   1027       status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
   1028       break;
   1029 
   1030     case qService::IQService::GET_PANEL_BRIGHTNESS: {
   1031         int level = 0;
   1032         status = GetPanelBrightness(&level);
   1033         output_parcel->writeInt32(level);
   1034       }
   1035       break;
   1036 
   1037     case qService::IQService::SET_PANEL_BRIGHTNESS: {
   1038         uint32_t level = UINT32(input_parcel->readInt32());
   1039         status = setPanelBrightness(level);
   1040         output_parcel->writeInt32(status);
   1041       }
   1042       break;
   1043 
   1044     case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
   1045       status = GetVisibleDisplayRect(input_parcel, output_parcel);
   1046       break;
   1047 
   1048     case qService::IQService::SET_CAMERA_STATUS: {
   1049         uint32_t camera_status = UINT32(input_parcel->readInt32());
   1050         status = setCameraLaunchStatus(camera_status);
   1051       }
   1052       break;
   1053 
   1054     case qService::IQService::GET_BW_TRANSACTION_STATUS: {
   1055         bool state = true;
   1056         status = DisplayBWTransactionPending(&state);
   1057         output_parcel->writeInt32(state);
   1058       }
   1059       break;
   1060 
   1061     case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
   1062       status = SetMixerResolution(input_parcel);
   1063       break;
   1064 
   1065     case qService::IQService::SET_COLOR_MODE:
   1066       status = SetColorModeOverride(input_parcel);
   1067       break;
   1068 
   1069     default:
   1070       DLOGW("QService command = %d is not supported", command);
   1071       return -EINVAL;
   1072   }
   1073 
   1074   return status;
   1075 }
   1076 
   1077 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
   1078                                                                   *input_parcel,
   1079                                                                   android::Parcel *output_parcel) {
   1080   int config = input_parcel->readInt32();
   1081   int dpy = input_parcel->readInt32();
   1082   int error = android::BAD_VALUE;
   1083   DisplayConfigVariableInfo display_attributes;
   1084 
   1085   if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
   1086     return android::BAD_VALUE;
   1087   }
   1088 
   1089   SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
   1090   if (hwc_display_[dpy]) {
   1091     error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
   1092     if (error == 0) {
   1093       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
   1094       output_parcel->writeInt32(INT(display_attributes.x_pixels));
   1095       output_parcel->writeInt32(INT(display_attributes.y_pixels));
   1096       output_parcel->writeFloat(display_attributes.x_dpi);
   1097       output_parcel->writeFloat(display_attributes.y_dpi);
   1098       output_parcel->writeInt32(0);  // Panel type, unsupported.
   1099     }
   1100   }
   1101 
   1102   return error;
   1103 }
   1104 
   1105 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
   1106   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1107 
   1108   uint32_t operation = UINT32(input_parcel->readInt32());
   1109   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
   1110 
   1111   switch (operation) {
   1112     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
   1113       return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
   1114 
   1115     case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
   1116       return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
   1117 
   1118     case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
   1119       uint32_t refresh_rate = UINT32(input_parcel->readInt32());
   1120       return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
   1121     }
   1122 
   1123     default:
   1124       DLOGW("Invalid operation %d", operation);
   1125       return -EINVAL;
   1126   }
   1127 
   1128   return 0;
   1129 }
   1130 
   1131 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
   1132   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1133 
   1134   uint32_t mode = UINT32(input_parcel->readInt32());
   1135   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
   1136 }
   1137 
   1138 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
   1139   DisplayError error = kErrorNone;
   1140   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   1141   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
   1142 
   1143   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
   1144     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1145     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1146       error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
   1147       if (error != kErrorNone) {
   1148         return -EINVAL;
   1149       }
   1150     }
   1151   }
   1152 
   1153   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
   1154     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
   1155     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1156       error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
   1157       if (error != kErrorNone) {
   1158         return -EINVAL;
   1159       }
   1160     }
   1161   }
   1162 
   1163   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
   1164     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
   1165     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
   1166       error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
   1167       if (error != kErrorNone) {
   1168         return -EINVAL;
   1169       }
   1170     }
   1171   }
   1172 
   1173   return 0;
   1174 }
   1175 
   1176 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
   1177   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
   1178   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   1179   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
   1180 
   1181   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
   1182     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1183     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1184       hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
   1185     }
   1186   }
   1187 
   1188   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
   1189     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
   1190     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1191       hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
   1192     }
   1193   }
   1194 
   1195   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
   1196     SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
   1197     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
   1198       hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
   1199     }
   1200   }
   1201 }
   1202 
   1203 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
   1204   DisplayError error = kErrorNone;
   1205   uint32_t dpy = UINT32(input_parcel->readInt32());
   1206 
   1207   if (dpy != HWC_DISPLAY_PRIMARY) {
   1208     DLOGI("Resoulution change not supported for this display %d", dpy);
   1209     return -EINVAL;
   1210   }
   1211 
   1212   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1213   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1214     DLOGI("Primary display is not initialized");
   1215     return -EINVAL;
   1216   }
   1217 
   1218   uint32_t width = UINT32(input_parcel->readInt32());
   1219   uint32_t height = UINT32(input_parcel->readInt32());
   1220 
   1221   error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
   1222   if (error != kErrorNone) {
   1223     return -EINVAL;
   1224   }
   1225 
   1226   return 0;
   1227 }
   1228 
   1229 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
   1230   auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
   1231   auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
   1232   auto device = static_cast<hwc2_device_t *>(this);
   1233 
   1234   if (display >= HWC_NUM_DISPLAY_TYPES) {
   1235     return -EINVAL;
   1236   }
   1237   auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
   1238   if (err != HWC2_ERROR_NONE)
   1239     return -EINVAL;
   1240 
   1241   return 0;
   1242 }
   1243 
   1244 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   1245   // TODO(user): Do we really need a lock here?
   1246 
   1247   int type = input_parcel->readInt32();
   1248   bool enable = (input_parcel->readInt32() > 0);
   1249   DLOGI("type = %d enable = %d", type, enable);
   1250   int verbose_level = input_parcel->readInt32();
   1251 
   1252   switch (type) {
   1253     case qService::IQService::DEBUG_ALL:
   1254       HWCDebugHandler::DebugAll(enable, verbose_level);
   1255       break;
   1256 
   1257     case qService::IQService::DEBUG_MDPCOMP:
   1258       HWCDebugHandler::DebugStrategy(enable, verbose_level);
   1259       HWCDebugHandler::DebugCompManager(enable, verbose_level);
   1260       break;
   1261 
   1262     case qService::IQService::DEBUG_PIPE_LIFECYCLE:
   1263       HWCDebugHandler::DebugResources(enable, verbose_level);
   1264       break;
   1265 
   1266     case qService::IQService::DEBUG_DRIVER_CONFIG:
   1267       HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
   1268       break;
   1269 
   1270     case qService::IQService::DEBUG_ROTATOR:
   1271       HWCDebugHandler::DebugResources(enable, verbose_level);
   1272       HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
   1273       HWCDebugHandler::DebugRotator(enable, verbose_level);
   1274       break;
   1275 
   1276     case qService::IQService::DEBUG_QDCM:
   1277       HWCDebugHandler::DebugQdcm(enable, verbose_level);
   1278       break;
   1279 
   1280     case qService::IQService::DEBUG_SCALAR:
   1281       HWCDebugHandler::DebugScalar(enable, verbose_level);
   1282       break;
   1283 
   1284     case qService::IQService::DEBUG_CLIENT:
   1285       HWCDebugHandler::DebugClient(enable, verbose_level);
   1286       break;
   1287 
   1288     case qService::IQService::DEBUG_DISPLAY:
   1289       HWCDebugHandler::DebugDisplay(enable, verbose_level);
   1290       break;
   1291 
   1292     default:
   1293       DLOGW("type = %d is not supported", type);
   1294   }
   1295 }
   1296 
   1297 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
   1298                                              android::Parcel *output_parcel) {
   1299   int ret = 0;
   1300   int32_t *brightness_value = NULL;
   1301   uint32_t display_id(0);
   1302   PPPendingParams pending_action;
   1303   PPDisplayAPIPayload resp_payload, req_payload;
   1304 
   1305   if (!color_mgr_) {
   1306     return -1;
   1307   }
   1308 
   1309   pending_action.action = kNoAction;
   1310   pending_action.params = NULL;
   1311 
   1312   // Read display_id, payload_size and payload from in_parcel.
   1313   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   1314   if (!ret) {
   1315     if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
   1316       ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, &resp_payload,
   1317                                                                     &pending_action);
   1318 
   1319     if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
   1320       ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
   1321                                                                      &pending_action);
   1322   }
   1323 
   1324   if (ret) {
   1325     output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
   1326     req_payload.DestroyPayload();
   1327     resp_payload.DestroyPayload();
   1328     return ret;
   1329   }
   1330 
   1331 
   1332   int32_t action = pending_action.action;
   1333   int count = -1;
   1334   bool reset_validate = true;
   1335   while (action > 0) {
   1336     count++;
   1337     int32_t bit = (action & 1);
   1338     action = action >> 1;
   1339 
   1340     if (!bit)
   1341       continue;
   1342 
   1343     DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
   1344     switch (BITMAP(count)) {
   1345       case kInvalidating:
   1346         Refresh(HWC_DISPLAY_PRIMARY);
   1347         reset_validate = !disable_skip_validate_;
   1348         break;
   1349       case kEnterQDCMMode:
   1350         ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1351         break;
   1352       case kExitQDCMMode:
   1353         ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1354         break;
   1355       case kApplySolidFill:
   1356         ret = color_mgr_->SetSolidFill(pending_action.params,
   1357                                             true, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1358         Refresh(HWC_DISPLAY_PRIMARY);
   1359         break;
   1360       case kDisableSolidFill:
   1361         ret = color_mgr_->SetSolidFill(pending_action.params,
   1362                                             false, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1363         Refresh(HWC_DISPLAY_PRIMARY);
   1364         break;
   1365       case kSetPanelBrightness:
   1366         brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
   1367         if (brightness_value == NULL) {
   1368           DLOGE("Brightness value is Null");
   1369           return -EINVAL;
   1370         }
   1371         if (HWC_DISPLAY_PRIMARY == display_id)
   1372           ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
   1373         break;
   1374       case kEnableFrameCapture:
   1375         ret = color_mgr_->SetFrameCapture(pending_action.params, true,
   1376                                         hwc_display_[HWC_DISPLAY_PRIMARY]);
   1377         Refresh(HWC_DISPLAY_PRIMARY);
   1378         break;
   1379       case kDisableFrameCapture:
   1380         ret = color_mgr_->SetFrameCapture(pending_action.params, false,
   1381                                         hwc_display_[HWC_DISPLAY_PRIMARY]);
   1382         break;
   1383       case kConfigureDetailedEnhancer:
   1384         ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
   1385                                               hwc_display_[HWC_DISPLAY_PRIMARY]);
   1386         Refresh(HWC_DISPLAY_PRIMARY);
   1387         break;
   1388       case kModeSet:
   1389         ret = static_cast<int>
   1390                  (hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
   1391         Refresh(HWC_DISPLAY_PRIMARY);
   1392         break;
   1393       case kNoAction:
   1394         break;
   1395       default:
   1396         DLOGW("Invalid pending action = %d!", pending_action.action);
   1397         break;
   1398     }
   1399   }
   1400   // for display API getter case, marshall returned params into out_parcel.
   1401   output_parcel->writeInt32(ret);
   1402   HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
   1403   req_payload.DestroyPayload();
   1404   resp_payload.DestroyPayload();
   1405   if (reset_validate) {
   1406     hwc_display_[display_id]->ResetValidation();
   1407   }
   1408 
   1409   return (ret ? -EINVAL : 0);
   1410 }
   1411 
   1412 void HWCSession::UEventHandler(const char *uevent_data, int length) {
   1413   if (!strcasecmp(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
   1414     DLOGI("Uevent HDMI = %s", uevent_data);
   1415     int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
   1416     if (connected >= 0) {
   1417       DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
   1418       if (HotPlugHandler(connected) == -1) {
   1419         DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
   1420       }
   1421     }
   1422   } else if (!strcasecmp(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
   1423     DLOGI("Uevent FB0 = %s", uevent_data);
   1424     int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
   1425     if (panel_reset == 0) {
   1426       Refresh(0);
   1427       reset_panel_ = true;
   1428     }
   1429   }
   1430 }
   1431 
   1432 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
   1433   const char *iterator_str = uevent_data;
   1434   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
   1435     const char *pstr = strstr(iterator_str, event_info);
   1436     if (pstr != NULL) {
   1437       return (atoi(iterator_str + strlen(event_info)));
   1438     }
   1439     iterator_str += strlen(iterator_str) + 1;
   1440   }
   1441 
   1442   return -1;
   1443 }
   1444 
   1445 void HWCSession::ResetPanel() {
   1446   HWC2::Error status;
   1447 
   1448   DLOGI("Powering off primary");
   1449   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off);
   1450   if (status != HWC2::Error::None) {
   1451     DLOGE("power-off on primary failed with error = %d", status);
   1452   }
   1453 
   1454   DLOGI("Restoring power mode on primary");
   1455   HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode();
   1456   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
   1457   if (status != HWC2::Error::None) {
   1458     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
   1459   }
   1460 
   1461   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
   1462   if (status != HWC2::Error::None) {
   1463     DLOGE("enabling vsync failed for primary with error = %d", status);
   1464   }
   1465 
   1466   reset_panel_ = false;
   1467 }
   1468 
   1469 int HWCSession::HotPlugHandler(bool connected) {
   1470   int status = 0;
   1471   bool notify_hotplug = false;
   1472 
   1473   // To prevent sending events to client while a lock is held, acquire scope locks only within
   1474   // below scope so that those get automatically unlocked after the scope ends.
   1475   do {
   1476     // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger.
   1477     //    if it is already created, but got disconnected/connected again,
   1478     //    just toggle display status and do not notify surfaceflinger.
   1479     // If HDMI is not primary, create/destroy external display normally.
   1480     if (hdmi_is_primary_) {
   1481       SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1482       if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1483         status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
   1484       } else {
   1485         status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
   1486         notify_hotplug = true;
   1487       }
   1488 
   1489       break;
   1490     }
   1491 
   1492     {
   1493       SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   1494       // Primary display must be connected for HDMI as secondary cases.
   1495       if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1496         DLOGE("Primary display is not connected.");
   1497         return -1;
   1498       }
   1499     }
   1500 
   1501     if (connected) {
   1502       SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
   1503       Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
   1504       // Connect external display if virtual display is not connected.
   1505       // Else, defer external display connection and process it when virtual display
   1506       // tears down; Do not notify SurfaceFlinger since connection is deferred now.
   1507       if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
   1508         status = ConnectDisplay(HWC_DISPLAY_EXTERNAL);
   1509         if (status) {
   1510           return status;
   1511         }
   1512         notify_hotplug = true;
   1513       } else {
   1514         DLOGI("Virtual display is connected, pending connection");
   1515         external_pending_connect_ = true;
   1516       }
   1517     } else {
   1518       SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
   1519       // Do not return error if external display is not in connected status.
   1520       // Due to virtual display concurrency, external display connection might be still pending
   1521       // but hdmi got disconnected before pending connection could be processed.
   1522       if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1523         status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
   1524         notify_hotplug = true;
   1525       }
   1526       external_pending_connect_ = false;
   1527     }
   1528   } while (0);
   1529 
   1530   if (connected) {
   1531     Refresh(0);
   1532 
   1533     if (!hdmi_is_primary_) {
   1534       // wait for sufficient time to ensure sufficient resources are available to process new
   1535       // new display connection.
   1536       uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
   1537       usleep(vsync_period * 2 / 1000);
   1538     }
   1539   }
   1540 
   1541   // notify client
   1542   if (notify_hotplug) {
   1543     HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
   1544             connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
   1545   }
   1546 
   1547   qservice_->onHdmiHotplug(INT(connected));
   1548 
   1549   return 0;
   1550 }
   1551 
   1552 int HWCSession::GetVsyncPeriod(int disp) {
   1553   SCOPE_LOCK(locker_[disp]);
   1554   // default value
   1555   int32_t vsync_period = 1000000000l / 60;
   1556   auto attribute = HWC2::Attribute::VsyncPeriod;
   1557 
   1558   if (hwc_display_[disp]) {
   1559     hwc_display_[disp]->GetDisplayAttribute(0, attribute, &vsync_period);
   1560   }
   1561 
   1562   return vsync_period;
   1563 }
   1564 
   1565 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
   1566                                                     android::Parcel *output_parcel) {
   1567   int dpy = input_parcel->readInt32();
   1568   if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
   1569     return android::BAD_VALUE;
   1570   }
   1571 
   1572   SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
   1573   if (!hwc_display_[dpy]) {
   1574     return android::NO_INIT;
   1575   }
   1576 
   1577   hwc_rect_t visible_rect = {0, 0, 0, 0};
   1578   int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
   1579   if (error < 0) {
   1580     return error;
   1581   }
   1582 
   1583   output_parcel->writeInt32(visible_rect.left);
   1584   output_parcel->writeInt32(visible_rect.top);
   1585   output_parcel->writeInt32(visible_rect.right);
   1586   output_parcel->writeInt32(visible_rect.bottom);
   1587 
   1588   return android::NO_ERROR;
   1589 }
   1590 
   1591 void HWCSession::Refresh(hwc2_display_t display) {
   1592   SCOPE_LOCK(callbacks_lock_);
   1593   HWC2::Error err = callbacks_.Refresh(display);
   1594   while (err != HWC2::Error::None) {
   1595     callbacks_lock_.Wait();
   1596     err = callbacks_.Refresh(display);
   1597   }
   1598 }
   1599 
   1600 void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
   1601   SCOPE_LOCK(callbacks_lock_);
   1602   HWC2::Error err = callbacks_.Hotplug(display, state);
   1603   while (err != HWC2::Error::None) {
   1604     callbacks_lock_.Wait();
   1605     err = callbacks_.Hotplug(display, state);
   1606   }
   1607 }
   1608 
   1609 int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width,
   1610                                       uint32_t primary_height, bool use_primary_res) {
   1611     uint32_t panel_bpp = 0;
   1612     uint32_t pattern_type = 0;
   1613     if (qdutils::isDPConnected()) {
   1614         qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
   1615     }
   1616     if (panel_bpp && pattern_type) {
   1617         return HWCDisplayExternalTest::Create(core_intf_, &buffer_allocator_, &callbacks_,
   1618                                               qservice_, panel_bpp,
   1619                                               pattern_type, &hwc_display_[disp]);
   1620     }
   1621     if (use_primary_res) {
   1622       return  HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
   1623                                          primary_width, primary_height, qservice_,
   1624                                          use_primary_res, &hwc_display_[disp]);
   1625     } else {
   1626       return  HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
   1627                                          qservice_, &hwc_display_[disp]);
   1628     }
   1629 }
   1630 
   1631 }  // namespace sdm
   1632