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