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