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