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 && !hwc_session->is_hdmi_primary_) {
    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 
    480   return status;
    481 }
    482 
    483 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
    484   SCOPE_LOCK(locker_);
    485 
    486   if (!device || !value) {
    487     return -EINVAL;
    488   }
    489 
    490   int status = 0;
    491 
    492   switch (param) {
    493   case HWC_BACKGROUND_LAYER_SUPPORTED:
    494     value[0] = 1;
    495     break;
    496 
    497   default:
    498     status = -EINVAL;
    499   }
    500 
    501   return status;
    502 }
    503 
    504 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
    505   SCOPE_LOCK(locker_);
    506 
    507   if (!device || !procs) {
    508     return;
    509   }
    510 
    511   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    512   hwc_session->hwc_procs_ = procs;
    513 }
    514 
    515 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
    516   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
    517 
    518   if (!device || !buffer || !length) {
    519     return;
    520   }
    521 
    522   DumpInterface::GetDump(buffer, UINT32(length));
    523 }
    524 
    525 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
    526                                   size_t *num_configs) {
    527   SCOPE_LOCK(locker_);
    528 
    529   if (!device || !configs || !num_configs) {
    530     return -EINVAL;
    531   }
    532 
    533   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
    534     return -EINVAL;
    535   }
    536 
    537   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    538   int status = -EINVAL;
    539   if (hwc_session->hwc_display_[disp]) {
    540     status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
    541   }
    542 
    543   return status;
    544 }
    545 
    546 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
    547                                      const uint32_t *display_attributes, int32_t *values) {
    548   SCOPE_LOCK(locker_);
    549 
    550   if (!device || !display_attributes || !values) {
    551     return -EINVAL;
    552   }
    553 
    554   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
    555     return -EINVAL;
    556   }
    557 
    558   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    559   int status = -EINVAL;
    560   if (hwc_session->hwc_display_[disp]) {
    561     status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
    562                                                                    values);
    563   }
    564 
    565   return status;
    566 }
    567 
    568 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
    569   SCOPE_LOCK(locker_);
    570 
    571   if (!device) {
    572     return -EINVAL;
    573   }
    574 
    575   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
    576     return -EINVAL;
    577   }
    578 
    579   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    580   int active_config = -1;
    581   if (hwc_session->hwc_display_[disp]) {
    582     active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
    583   }
    584 
    585   return active_config;
    586 }
    587 
    588 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
    589   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
    590 
    591   if (!device) {
    592     return -EINVAL;
    593   }
    594 
    595   if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
    596     return -EINVAL;
    597   }
    598 
    599   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    600   int status = -EINVAL;
    601 
    602   if (hwc_session->hwc_display_[disp]) {
    603     status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
    604   }
    605 
    606   return status;
    607 }
    608 
    609 int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
    610   DTRACE_SCOPED();
    611 
    612   SCOPE_LOCK(locker_);
    613 
    614   if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
    615     return -EINVAL;
    616   }
    617 
    618   int status = -EINVAL;
    619   HWCSession *hwc_session = static_cast<HWCSession *>(device);
    620   if (hwc_session->hwc_display_[disp]) {
    621     status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
    622   }
    623 
    624   return status;
    625 }
    626 
    627 int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
    628   DLOGI("Display = %d", disp);
    629 
    630   int status = 0;
    631   uint32_t primary_width = 0;
    632   uint32_t primary_height = 0;
    633 
    634   hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
    635 
    636   if (disp == HWC_DISPLAY_EXTERNAL) {
    637     status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
    638                                         qservice_, false, &hwc_display_[disp]);
    639   } else if (disp == HWC_DISPLAY_VIRTUAL) {
    640     status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
    641                                        content_list, &hwc_display_[disp]);
    642   } else {
    643     DLOGE("Invalid display type");
    644     return -1;
    645   }
    646 
    647   if (!status) {
    648     hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
    649   }
    650 
    651   return status;
    652 }
    653 
    654 int HWCSession::DisconnectDisplay(int disp) {
    655   DLOGI("Display = %d", disp);
    656 
    657   if (disp == HWC_DISPLAY_EXTERNAL) {
    658     HWCDisplayExternal::Destroy(hwc_display_[disp]);
    659   } else if (disp == HWC_DISPLAY_VIRTUAL) {
    660     HWCDisplayVirtual::Destroy(hwc_display_[disp]);
    661   } else {
    662     DLOGE("Invalid display type");
    663     return -1;
    664   }
    665 
    666   hwc_display_[disp] = NULL;
    667 
    668   return 0;
    669 }
    670 
    671 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
    672                                              android::Parcel *output_parcel) {
    673   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
    674 
    675   android::status_t status = 0;
    676 
    677   switch (command) {
    678   case qService::IQService::DYNAMIC_DEBUG:
    679     DynamicDebug(input_parcel);
    680     break;
    681 
    682   case qService::IQService::SCREEN_REFRESH:
    683     hwc_procs_->invalidate(hwc_procs_);
    684     break;
    685 
    686   case qService::IQService::SET_IDLE_TIMEOUT:
    687     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
    688       uint32_t timeout = UINT32(input_parcel->readInt32());
    689       hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
    690     }
    691     break;
    692 
    693   case qService::IQService::SET_FRAME_DUMP_CONFIG:
    694     SetFrameDumpConfig(input_parcel);
    695     break;
    696 
    697   case qService::IQService::SET_MAX_PIPES_PER_MIXER:
    698     status = SetMaxMixerStages(input_parcel);
    699     break;
    700 
    701   case qService::IQService::SET_DISPLAY_MODE:
    702     status = SetDisplayMode(input_parcel);
    703     break;
    704 
    705   case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
    706     status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
    707     break;
    708 
    709   case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
    710     status = ConfigureRefreshRate(input_parcel);
    711     break;
    712 
    713   case qService::IQService::SET_VIEW_FRAME:
    714     break;
    715 
    716   case qService::IQService::TOGGLE_SCREEN_UPDATES:
    717     status = ToggleScreenUpdates(input_parcel, output_parcel);
    718     break;
    719 
    720   case qService::IQService::QDCM_SVC_CMDS:
    721     status = QdcmCMDHandler(input_parcel, output_parcel);
    722     break;
    723 
    724   case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
    725     status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
    726     break;
    727 
    728   case qService::IQService::CONTROL_PARTIAL_UPDATE:
    729     status = ControlPartialUpdate(input_parcel, output_parcel);
    730     break;
    731 
    732   case qService::IQService::SET_ACTIVE_CONFIG:
    733     status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
    734     break;
    735 
    736   case qService::IQService::GET_ACTIVE_CONFIG:
    737     status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
    738     break;
    739 
    740   case qService::IQService::GET_CONFIG_COUNT:
    741     status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
    742     break;
    743 
    744   case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
    745     status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
    746     break;
    747 
    748   case qService::IQService::GET_PANEL_BRIGHTNESS:
    749     status = GetPanelBrightness(input_parcel, output_parcel);
    750     break;
    751 
    752   case qService::IQService::SET_PANEL_BRIGHTNESS:
    753     status = SetPanelBrightness(input_parcel, output_parcel);
    754     break;
    755 
    756   case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
    757     status = GetVisibleDisplayRect(input_parcel, output_parcel);
    758     break;
    759 
    760   case qService::IQService::SET_CAMERA_STATUS:
    761     status = SetDynamicBWForCamera(input_parcel, output_parcel);
    762     break;
    763 
    764   case qService::IQService::GET_BW_TRANSACTION_STATUS:
    765     status = GetBWTransactionStatus(input_parcel, output_parcel);
    766     break;
    767 
    768   case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
    769     status = SetMixerResolution(input_parcel);
    770     break;
    771 
    772   default:
    773     DLOGW("QService command = %d is not supported", command);
    774     return -EINVAL;
    775   }
    776 
    777   return status;
    778 }
    779 
    780 android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
    781                                                   android::Parcel *output_parcel) {
    782   int input = input_parcel->readInt32();
    783   int error = android::BAD_VALUE;
    784 
    785   if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
    786     error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
    787     if (error != 0) {
    788       DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
    789     }
    790   }
    791   output_parcel->writeInt32(error);
    792 
    793   return error;
    794 }
    795 
    796 android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
    797                                                  android::Parcel *output_parcel) {
    798   int level = input_parcel->readInt32();
    799   int error = android::BAD_VALUE;
    800 
    801   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
    802     error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
    803     if (error != 0) {
    804       DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
    805     }
    806   }
    807   output_parcel->writeInt32(error);
    808 
    809   return error;
    810 }
    811 
    812 android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
    813                                                  android::Parcel *output_parcel) {
    814   int error = android::BAD_VALUE;
    815   int ret = error;
    816 
    817   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
    818     error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
    819     if (error != 0) {
    820       ret = error;
    821       DLOGE("Failed to get the panel brightness. Error = %d", error);
    822     }
    823   }
    824   output_parcel->writeInt32(ret);
    825 
    826   return error;
    827 }
    828 
    829 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
    830                                                    android::Parcel *out) {
    831   DisplayError error = kErrorNone;
    832   int ret = 0;
    833   uint32_t disp_id = UINT32(input_parcel->readInt32());
    834   uint32_t enable = UINT32(input_parcel->readInt32());
    835 
    836   if (disp_id != HWC_DISPLAY_PRIMARY) {
    837     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
    838     ret = -EINVAL;
    839     out->writeInt32(ret);
    840     return ret;
    841   }
    842 
    843   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
    844     DLOGE("primary display object is not instantiated");
    845     ret = -EINVAL;
    846     out->writeInt32(ret);
    847     return ret;
    848   }
    849 
    850   uint32_t pending = 0;
    851   error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
    852 
    853   if (error == kErrorNone) {
    854     if (!pending) {
    855       out->writeInt32(ret);
    856       return ret;
    857     }
    858   } else if (error == kErrorNotSupported) {
    859     out->writeInt32(ret);
    860     return ret;
    861   } else {
    862     ret = -EINVAL;
    863     out->writeInt32(ret);
    864     return ret;
    865   }
    866 
    867   // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
    868   hwc_procs_->invalidate(hwc_procs_);
    869 
    870   // Wait until partial update control is complete
    871   ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
    872 
    873   out->writeInt32(ret);
    874 
    875   return ret;
    876 }
    877 
    878 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
    879                                                      android::Parcel *output_parcel) {
    880   int config = input_parcel->readInt32();
    881   int dpy = input_parcel->readInt32();
    882   int error = android::BAD_VALUE;
    883 
    884   if (dpy > HWC_DISPLAY_VIRTUAL) {
    885     return android::BAD_VALUE;
    886   }
    887 
    888   if (hwc_display_[dpy]) {
    889     error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
    890     if (error == 0) {
    891       hwc_procs_->invalidate(hwc_procs_);
    892     }
    893   }
    894 
    895   return error;
    896 }
    897 
    898 android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
    899                                                            android::Parcel *output_parcel) {
    900   int dpy = input_parcel->readInt32();
    901   int error = android::BAD_VALUE;
    902 
    903   if (dpy > HWC_DISPLAY_VIRTUAL) {
    904     return android::BAD_VALUE;
    905   }
    906 
    907   if (hwc_display_[dpy]) {
    908     uint32_t config = 0;
    909     error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
    910     if (error == 0) {
    911       output_parcel->writeInt32(INT(config));
    912     }
    913   }
    914 
    915   return error;
    916 }
    917 
    918 android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
    919                                                           android::Parcel *output_parcel) {
    920   int dpy = input_parcel->readInt32();
    921   int error = android::BAD_VALUE;
    922 
    923   if (dpy > HWC_DISPLAY_VIRTUAL) {
    924     return android::BAD_VALUE;
    925   }
    926 
    927   uint32_t count = 0;
    928   if (hwc_display_[dpy]) {
    929     error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
    930     if (error == 0) {
    931       output_parcel->writeInt32(INT(count));
    932     }
    933   }
    934 
    935   return error;
    936 }
    937 
    938 android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
    939   if (!hwc_disp_port) {
    940     return -EINVAL;
    941   }
    942 
    943   switch (sdm_disp_port) {
    944     case kPortDSI:
    945       *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
    946       break;
    947     case kPortDTV:
    948       *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
    949       break;
    950     case kPortLVDS:
    951       *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
    952       break;
    953     case kPortEDP:
    954       *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
    955       break;
    956     case kPortWriteBack:
    957       *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
    958       break;
    959     case kPortDP:
    960       *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
    961       break;
    962     case kPortDefault:
    963       *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
    964       break;
    965     default:
    966       DLOGE("Invalid sdm display port %d", sdm_disp_port);
    967       return -EINVAL;
    968   }
    969 
    970   return 0;
    971 }
    972 
    973 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
    974                                                                   *input_parcel,
    975                                                                   android::Parcel *output_parcel) {
    976   int config = input_parcel->readInt32();
    977   int dpy = input_parcel->readInt32();
    978   int error = android::BAD_VALUE;
    979   DisplayConfigVariableInfo display_attributes;
    980   DisplayPort sdm_disp_port = kPortDefault;
    981   int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
    982 
    983   if (dpy > HWC_DISPLAY_VIRTUAL) {
    984     return android::BAD_VALUE;
    985   }
    986 
    987   if (hwc_display_[dpy]) {
    988     error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
    989     if (error == 0) {
    990       hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
    991 
    992       SetDisplayPort(sdm_disp_port, &hwc_disp_port);
    993 
    994       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
    995       output_parcel->writeInt32(INT(display_attributes.x_pixels));
    996       output_parcel->writeInt32(INT(display_attributes.y_pixels));
    997       output_parcel->writeFloat(display_attributes.x_dpi);
    998       output_parcel->writeFloat(display_attributes.y_dpi);
    999       output_parcel->writeInt32(hwc_disp_port);
   1000       output_parcel->writeInt32(display_attributes.is_yuv);
   1001     }
   1002   }
   1003 
   1004   return error;
   1005 }
   1006 
   1007 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
   1008                                                         android::Parcel *output_parcel) {
   1009   int ret = -EINVAL;
   1010 
   1011   uint32_t display_id = UINT32(input_parcel->readInt32());
   1012   uint32_t display_status = UINT32(input_parcel->readInt32());
   1013 
   1014   DLOGI("Display = %d, Status = %d", display_id, display_status);
   1015 
   1016   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
   1017     DLOGE("Invalid display_id");
   1018   } else if (display_id == HWC_DISPLAY_PRIMARY) {
   1019     DLOGE("Not supported for this display");
   1020   } else if (!hwc_display_[display_id]) {
   1021     DLOGW("Display is not connected");
   1022   } else {
   1023     ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
   1024   }
   1025 
   1026   output_parcel->writeInt32(ret);
   1027 
   1028   return ret;
   1029 }
   1030 
   1031 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
   1032   uint32_t operation = UINT32(input_parcel->readInt32());
   1033   switch (operation) {
   1034     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
   1035       return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
   1036           HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
   1037     case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
   1038       return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
   1039           HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
   1040     case qdutils::SET_BINDER_DYN_REFRESH_RATE:
   1041       {
   1042         uint32_t refresh_rate = UINT32(input_parcel->readInt32());
   1043         return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
   1044             HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
   1045             refresh_rate);
   1046       }
   1047     default:
   1048       DLOGW("Invalid operation %d", operation);
   1049       return -EINVAL;
   1050   }
   1051 
   1052   return 0;
   1053 }
   1054 
   1055 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
   1056   uint32_t mode = UINT32(input_parcel->readInt32());
   1057   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
   1058 }
   1059 
   1060 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
   1061   DisplayError error = kErrorNone;
   1062   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   1063   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
   1064 
   1065   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
   1066     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1067       error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
   1068       if (error != kErrorNone) {
   1069         return -EINVAL;
   1070       }
   1071     }
   1072   }
   1073 
   1074   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
   1075     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1076       error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
   1077       if (error != kErrorNone) {
   1078         return -EINVAL;
   1079       }
   1080     }
   1081   }
   1082 
   1083   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
   1084     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
   1085       error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
   1086       if (error != kErrorNone) {
   1087         return -EINVAL;
   1088       }
   1089     }
   1090   }
   1091 
   1092   return 0;
   1093 }
   1094 
   1095 android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
   1096                                                     android::Parcel *output_parcel) {
   1097   DisplayError error = kErrorNone;
   1098   uint32_t camera_status = UINT32(input_parcel->readInt32());
   1099   HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
   1100 
   1101   // trigger invalidate to apply new bw caps.
   1102   hwc_procs_->invalidate(hwc_procs_);
   1103 
   1104     error = core_intf_->SetMaxBandwidthMode(mode);
   1105   if (error != kErrorNone) {
   1106       return -EINVAL;
   1107   }
   1108 
   1109   new_bw_mode_ = true;
   1110   need_invalidate_ = true;
   1111 
   1112   return 0;
   1113 }
   1114 
   1115 android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
   1116                                                      android::Parcel *output_parcel)  {
   1117   bool state = true;
   1118 
   1119   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1120     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
   1121       DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
   1122       state = false;
   1123     }
   1124     output_parcel->writeInt32(state);
   1125   }
   1126 
   1127   return 0;
   1128 }
   1129 
   1130 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
   1131   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
   1132   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   1133   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
   1134 
   1135   if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
   1136     if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1137       hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
   1138     }
   1139   }
   1140 
   1141   if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
   1142     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1143       hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
   1144     }
   1145   }
   1146 
   1147   if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
   1148     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
   1149       hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
   1150     }
   1151   }
   1152 }
   1153 
   1154 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
   1155   DisplayError error = kErrorNone;
   1156   uint32_t dpy = UINT32(input_parcel->readInt32());
   1157 
   1158   if (dpy != HWC_DISPLAY_PRIMARY) {
   1159     DLOGI("Resoulution change not supported for this display %d", dpy);
   1160     return -EINVAL;
   1161   }
   1162 
   1163   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1164     DLOGI("Primary display is not initialized");
   1165     return -EINVAL;
   1166   }
   1167 
   1168   uint32_t width = UINT32(input_parcel->readInt32());
   1169   uint32_t height = UINT32(input_parcel->readInt32());
   1170 
   1171   error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
   1172   if (error != kErrorNone) {
   1173     return -EINVAL;
   1174   }
   1175 
   1176   return 0;
   1177 }
   1178 
   1179 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   1180   int type = input_parcel->readInt32();
   1181   bool enable = (input_parcel->readInt32() > 0);
   1182   DLOGI("type = %d enable = %d", type, enable);
   1183   int verbose_level = input_parcel->readInt32();
   1184 
   1185   switch (type) {
   1186   case qService::IQService::DEBUG_ALL:
   1187     HWCDebugHandler::DebugAll(enable, verbose_level);
   1188     break;
   1189 
   1190   case qService::IQService::DEBUG_MDPCOMP:
   1191     HWCDebugHandler::DebugStrategy(enable, verbose_level);
   1192     HWCDebugHandler::DebugCompManager(enable, verbose_level);
   1193     break;
   1194 
   1195   case qService::IQService::DEBUG_PIPE_LIFECYCLE:
   1196     HWCDebugHandler::DebugResources(enable, verbose_level);
   1197     break;
   1198 
   1199   case qService::IQService::DEBUG_DRIVER_CONFIG:
   1200     HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
   1201     break;
   1202 
   1203   case qService::IQService::DEBUG_ROTATOR:
   1204     HWCDebugHandler::DebugResources(enable, verbose_level);
   1205     HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
   1206     HWCDebugHandler::DebugRotator(enable, verbose_level);
   1207     break;
   1208 
   1209   case qService::IQService::DEBUG_QDCM:
   1210     HWCDebugHandler::DebugQdcm(enable, verbose_level);
   1211     break;
   1212 
   1213   default:
   1214     DLOGW("type = %d is not supported", type);
   1215   }
   1216 }
   1217 
   1218 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
   1219                                              android::Parcel *output_parcel) {
   1220   int ret = 0;
   1221   int32_t *brightness_value = NULL;
   1222   uint32_t display_id(0);
   1223   PPPendingParams pending_action;
   1224   PPDisplayAPIPayload resp_payload, req_payload;
   1225 
   1226   if (!color_mgr_) {
   1227     return -1;
   1228   }
   1229 
   1230   pending_action.action = kNoAction;
   1231   pending_action.params = NULL;
   1232 
   1233   // Read display_id, payload_size and payload from in_parcel.
   1234   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   1235   if (!ret) {
   1236     if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
   1237       ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
   1238                                                                   &resp_payload, &pending_action);
   1239 
   1240     if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
   1241       ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
   1242                                                                   &pending_action);
   1243   }
   1244 
   1245   if (ret) {
   1246     output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
   1247     req_payload.DestroyPayload();
   1248     resp_payload.DestroyPayload();
   1249     return ret;
   1250   }
   1251 
   1252   switch (pending_action.action) {
   1253     case kInvalidating:
   1254       hwc_procs_->invalidate(hwc_procs_);
   1255       break;
   1256     case kEnterQDCMMode:
   1257       ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1258       break;
   1259     case kExitQDCMMode:
   1260       ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1261       break;
   1262     case kApplySolidFill:
   1263       ret = color_mgr_->SetSolidFill(pending_action.params,
   1264                                      true, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1265       hwc_procs_->invalidate(hwc_procs_);
   1266       break;
   1267     case kDisableSolidFill:
   1268       ret = color_mgr_->SetSolidFill(pending_action.params,
   1269                                      false, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1270       hwc_procs_->invalidate(hwc_procs_);
   1271       break;
   1272     case kSetPanelBrightness:
   1273       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
   1274       if (brightness_value == NULL) {
   1275         DLOGE("Brightness value is Null");
   1276         return -EINVAL;
   1277       }
   1278       if (HWC_DISPLAY_PRIMARY == display_id)
   1279         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
   1280       break;
   1281     case kEnableFrameCapture:
   1282       ret = color_mgr_->SetFrameCapture(pending_action.params,
   1283                                         true, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1284       hwc_procs_->invalidate(hwc_procs_);
   1285       break;
   1286     case kDisableFrameCapture:
   1287       ret = color_mgr_->SetFrameCapture(pending_action.params,
   1288                                         false, hwc_display_[HWC_DISPLAY_PRIMARY]);
   1289       break;
   1290     case kConfigureDetailedEnhancer:
   1291       ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
   1292                                             hwc_display_[HWC_DISPLAY_PRIMARY]);
   1293       hwc_procs_->invalidate(hwc_procs_);
   1294       break;
   1295     case kNoAction:
   1296       break;
   1297     default:
   1298       DLOGW("Invalid pending action = %d!", pending_action.action);
   1299       break;
   1300   }
   1301 
   1302   // for display API getter case, marshall returned params into out_parcel.
   1303   output_parcel->writeInt32(ret);
   1304   HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
   1305   req_payload.DestroyPayload();
   1306   resp_payload.DestroyPayload();
   1307 
   1308   return (ret? -EINVAL : 0);
   1309 }
   1310 
   1311 android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
   1312                                                              android::Parcel *output_parcel) {
   1313   int ret = -EINVAL;
   1314   uint32_t display_id = UINT32(input_parcel->readInt32());
   1315   uint32_t min_enc_level = UINT32(input_parcel->readInt32());
   1316 
   1317   DLOGI("Display %d", display_id);
   1318 
   1319   if (display_id >= HWC_NUM_DISPLAY_TYPES) {
   1320     DLOGE("Invalid display_id");
   1321   } else if (display_id != HWC_DISPLAY_EXTERNAL) {
   1322     DLOGE("Not supported for display");
   1323   } else if (!hwc_display_[display_id]) {
   1324     DLOGW("Display is not connected");
   1325   } else {
   1326     ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
   1327   }
   1328 
   1329   output_parcel->writeInt32(ret);
   1330 
   1331   return ret;
   1332 }
   1333 
   1334 void* HWCSession::HWCUeventThread(void *context) {
   1335   if (context) {
   1336     return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
   1337   }
   1338 
   1339   return NULL;
   1340 }
   1341 
   1342 void* HWCSession::HWCUeventThreadHandler() {
   1343   static char uevent_data[PAGE_SIZE];
   1344   int length = 0;
   1345   prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
   1346   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
   1347   if (!uevent_init()) {
   1348     DLOGE("Failed to init uevent");
   1349     pthread_exit(0);
   1350     return NULL;
   1351   }
   1352 
   1353   while (!uevent_thread_exit_) {
   1354     // keep last 2 zeroes to ensure double 0 termination
   1355     length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
   1356 
   1357     if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
   1358       DLOGI("Uevent HDMI = %s", uevent_data);
   1359       int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
   1360       if (connected >= 0) {
   1361         DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
   1362         if (HotPlugHandler(connected) == -1) {
   1363           DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
   1364         }
   1365       }
   1366     } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
   1367       DLOGI("Uevent FB0 = %s", uevent_data);
   1368       int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
   1369       if (panel_reset == 0) {
   1370         if (hwc_procs_) {
   1371           reset_panel_ = true;
   1372           hwc_procs_->invalidate(hwc_procs_);
   1373         } else {
   1374           DLOGW("Ignore resetpanel - hwc_proc not registered");
   1375         }
   1376       }
   1377     }
   1378   }
   1379   pthread_exit(0);
   1380 
   1381   return NULL;
   1382 }
   1383 
   1384 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
   1385   const char *iterator_str = uevent_data;
   1386   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
   1387     const char *pstr = strstr(iterator_str, event_info);
   1388     if (pstr != NULL) {
   1389       return (atoi(iterator_str + strlen(event_info)));
   1390     }
   1391     iterator_str += strlen(iterator_str) + 1;
   1392   }
   1393 
   1394   return -1;
   1395 }
   1396 
   1397 void HWCSession::ResetPanel() {
   1398   int status = -EINVAL;
   1399 
   1400   DLOGI("Powering off primary");
   1401   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
   1402   if (status) {
   1403     DLOGE("power-off on primary failed with error = %d", status);
   1404   }
   1405 
   1406   DLOGI("Restoring power mode on primary");
   1407   int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
   1408   status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
   1409   if (status) {
   1410     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
   1411   }
   1412 
   1413   status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
   1414   if (status) {
   1415     DLOGE("enabling vsync failed for primary with error = %d", status);
   1416   }
   1417 
   1418   reset_panel_ = false;
   1419 }
   1420 
   1421 int HWCSession::HotPlugHandler(bool connected) {
   1422   int status = 0;
   1423   bool notify_hotplug = false;
   1424   bool refresh_screen = false;
   1425 
   1426   // To prevent sending events to client while a lock is held, acquire scope locks only within
   1427   // below scope so that those get automatically unlocked after the scope ends.
   1428   {
   1429     SEQUENCE_WAIT_SCOPE_LOCK(locker_);
   1430 
   1431     if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
   1432       DLOGE("Primay display is not connected.");
   1433       return -1;
   1434     }
   1435 
   1436 
   1437     HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
   1438     HWCDisplay *external_display = NULL;
   1439     HWCDisplay *null_display = NULL;
   1440 
   1441     if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
   1442       external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
   1443     } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) {
   1444       null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
   1445     }
   1446 
   1447     // If primary display connected is a NULL display, then replace it with the external display
   1448     if (connected) {
   1449       // If we are in HDMI as primary and the primary display just got plugged in
   1450       if (is_hdmi_primary_ && null_display) {
   1451         uint32_t primary_width, primary_height;
   1452         null_display->GetFrameBufferResolution(&primary_width, &primary_height);
   1453         delete null_display;
   1454         hwc_display_[HWC_DISPLAY_PRIMARY] = NULL;
   1455 
   1456         // Create external display with a forced framebuffer resolution to that of what the NULL
   1457         // display had. This is necessary because SurfaceFlinger does not dynamically update
   1458         // framebuffer resolution once it reads it at bootup. So we always have to have the NULL
   1459         // display/external display both at the bootup resolution.
   1460         int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width,
   1461                                                 primary_height, qservice_, true,
   1462                                                 &hwc_display_[HWC_DISPLAY_PRIMARY]);
   1463         if (status) {
   1464           DLOGE("Could not create external display");
   1465           return -1;
   1466         }
   1467 
   1468         status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
   1469         if (status) {
   1470           DLOGE("power-on on primary failed with error = %d", status);
   1471         }
   1472 
   1473         is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
   1474 
   1475         // Next, go ahead and enable vsync on external display. This is expliclity required
   1476         // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying
   1477         // changing display. and thus may not explicitly enable vsync
   1478 
   1479         status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true);
   1480         if (status) {
   1481           DLOGE("Error enabling vsync for HDMI as primary case");
   1482         }
   1483         // Don't do hotplug notification for HDMI as primary case for now
   1484         notify_hotplug = false;
   1485         refresh_screen = true;
   1486       } else {
   1487         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1488           DLOGE("HDMI is already connected");
   1489           return -1;
   1490         }
   1491 
   1492         // Connect external display if virtual display is not connected.
   1493         // Else, defer external display connection and process it when virtual display
   1494         // tears down; Do not notify SurfaceFlinger since connection is deferred now.
   1495         if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
   1496           status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
   1497           if (status) {
   1498             return status;
   1499           }
   1500           notify_hotplug = true;
   1501         } else {
   1502           DLOGI("Virtual display is connected, pending connection");
   1503           external_pending_connect_ = true;
   1504         }
   1505       }
   1506     } else {
   1507       // Do not return error if external display is not in connected status.
   1508       // Due to virtual display concurrency, external display connection might be still pending
   1509       // but hdmi got disconnected before pending connection could be processed.
   1510 
   1511       if (is_hdmi_primary_ && external_display) {
   1512         uint32_t x_res, y_res;
   1513         external_display->GetFrameBufferResolution(&x_res, &y_res);
   1514         // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
   1515         // for HDMI as primary
   1516         external_display->EventControl(HWC_EVENT_VSYNC, false);
   1517         HWCDisplayExternal::Destroy(external_display);
   1518 
   1519         HWCDisplayNull *null_display;
   1520 
   1521         int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
   1522                                             reinterpret_cast<HWCDisplay **>(&null_display));
   1523 
   1524         if (status) {
   1525           DLOGE("Could not create Null display when primary got disconnected");
   1526           return -1;
   1527         }
   1528 
   1529         null_display->SetResolution(x_res, y_res);
   1530         hwc_display_[HWC_DISPLAY_PRIMARY] = null_display;
   1531 
   1532         // Don't do hotplug notification for HDMI as primary case for now
   1533         notify_hotplug = false;
   1534       } else {
   1535         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
   1536           status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
   1537           notify_hotplug = true;
   1538         }
   1539         external_pending_connect_ = false;
   1540       }
   1541     }
   1542   }
   1543 
   1544   if (connected && (notify_hotplug || refresh_screen)) {
   1545     // trigger screen refresh to ensure sufficient resources are available to process new
   1546     // new display connection.
   1547     hwc_procs_->invalidate(hwc_procs_);
   1548     uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
   1549     usleep(vsync_period * 2 / 1000);
   1550   }
   1551   // notify client
   1552   if (notify_hotplug) {
   1553     hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
   1554   }
   1555 
   1556   qservice_->onHdmiHotplug(INT(connected));
   1557 
   1558   return 0;
   1559 }
   1560 
   1561 void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
   1562   secure_display_active_ = false;
   1563   if (!*displays) {
   1564     DLOGW("Invalid display contents");
   1565     return;
   1566   }
   1567 
   1568   hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
   1569   if (!content_list) {
   1570     DLOGW("Invalid primary content list");
   1571     return;
   1572   }
   1573   size_t num_hw_layers = content_list->numHwLayers;
   1574 
   1575   for (size_t i = 0; i < num_hw_layers - 1; i++) {
   1576     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
   1577     const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
   1578     if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
   1579       secure_display_active_ = true;
   1580     }
   1581   }
   1582 
   1583   for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
   1584     if (hwc_display_[dpy]) {
   1585       hwc_display_[dpy]->SetSecureDisplay(secure_display_active_);
   1586     }
   1587   }
   1588 }
   1589 
   1590 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
   1591                                                     android::Parcel *output_parcel) {
   1592   int dpy = input_parcel->readInt32();
   1593 
   1594   if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
   1595     return android::BAD_VALUE;;
   1596   }
   1597 
   1598   if (!hwc_display_[dpy]) {
   1599     return android::NO_INIT;
   1600   }
   1601 
   1602   hwc_rect_t visible_rect = {0, 0, 0, 0};
   1603   int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
   1604   if (error < 0) {
   1605     return error;
   1606   }
   1607 
   1608   output_parcel->writeInt32(visible_rect.left);
   1609   output_parcel->writeInt32(visible_rect.top);
   1610   output_parcel->writeInt32(visible_rect.right);
   1611   output_parcel->writeInt32(visible_rect.bottom);
   1612 
   1613   return android::NO_ERROR;
   1614 }
   1615 
   1616 }  // namespace sdm
   1617 
   1618