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