Merge "sdm: Support dpps AD4 ROI feature"
diff --git a/sdm/include/private/color_interface.h b/sdm/include/private/color_interface.h
index 884df5e..feaea30 100644
--- a/sdm/include/private/color_interface.h
+++ b/sdm/include/private/color_interface.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -45,11 +45,12 @@
 
 class ColorInterface;
 
-typedef DisplayError (*CreateColorInterface)(uint16_t version, DisplayType type,
+typedef DisplayError (*CreateColorInterface)(uint16_t version, int32_t display_id,
+                                             DisplayType type,
                                              const PPHWAttributes &attributes,
                                              ColorInterface **interface);
 
-typedef DisplayError (*DestroyColorInterface)(DisplayType type);
+typedef DisplayError (*DestroyColorInterface)(int32_t display_id);
 
 class ColorModeInterface {
  public:
@@ -63,8 +64,8 @@
   virtual ~ColorModeInterface() {}
 };
 
-extern "C" ColorModeInterface* GetColorModeInterface(DisplayType type);
-extern "C" void ReleaseColorModeInterface(DisplayType type);
+extern "C" ColorModeInterface* GetColorModeInterface(int32_t display_id, DisplayType type);
+extern "C" void ReleaseColorModeInterface(int32_t display_id);
 
 class ColorInterface {
  public:
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 32f0505..7c2846f 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -55,6 +55,8 @@
   kDisableFrameCapture = BITMAP(7),
   kConfigureDetailedEnhancer = BITMAP(8),
   kModeSet = BITMAP(10),
+  kMultiDispProc = BITMAP(11),
+  kMultiDispGetId = BITMAP(12),
   kGetDetailedEnhancerData = BITMAP(21),
   kNoAction = BITMAP(31),
 };
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 694aada..d895bf7 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015 - 2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015 - 2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -99,10 +99,11 @@
   color_lib_.~DynLib();
 }
 
-ColorManagerProxy::ColorManagerProxy(DisplayType type, HWInterface *intf,
+ColorManagerProxy::ColorManagerProxy(int32_t id, DisplayType type, HWInterface *intf,
                                      const HWDisplayAttributes &attr,
                                      const HWPanelInfo &info)
-    : device_type_(type), pp_hw_attributes_(), hw_intf_(intf), color_intf_(NULL), pp_features_() {}
+    : display_id_(id), device_type_(type), pp_hw_attributes_(), hw_intf_(intf),
+      color_intf_(NULL), pp_features_() {}
 
 ColorManagerProxy *ColorManagerProxy::CreateColorManagerProxy(DisplayType type,
                                                               HWInterface *hw_intf,
@@ -110,6 +111,8 @@
                                                               const HWPanelInfo &panel_info) {
   DisplayError error = kErrorNone;
   PPFeatureVersion versions;
+  int32_t display_id = -1;
+  ColorManagerProxy *color_manager_proxy = NULL;
 
   // check if all resources are available before invoking factory method from libsdm-color.so.
   if (!color_lib_ || !create_intf_ || !destroy_intf_) {
@@ -117,8 +120,9 @@
     return NULL;
   }
 
-  ColorManagerProxy *color_manager_proxy =
-      new ColorManagerProxy(type, hw_intf, attribute, panel_info);
+  hw_intf->GetDisplayId(&display_id);
+  color_manager_proxy = new ColorManagerProxy(display_id, type, hw_intf, attribute, panel_info);
+
   if (color_manager_proxy) {
     // 1. need query post-processing feature version from HWInterface.
     error = color_manager_proxy->hw_intf_->GetPPFeaturesVersion(&versions);
@@ -133,7 +137,8 @@
     }
 
     // 2. instantiate concrete ColorInterface from libsdm-color.so, pass all hardware info in.
-    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->device_type_, hw_attr,
+    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->display_id_,
+                         color_manager_proxy->device_type_, hw_attr,
                          &color_manager_proxy->color_intf_);
     if (error != kErrorNone) {
       DLOGW("Unable to instantiate concrete ColorInterface from %s", COLORMGR_LIBRARY_NAME);
@@ -147,7 +152,7 @@
 
 ColorManagerProxy::~ColorManagerProxy() {
   if (destroy_intf_)
-    destroy_intf_(device_type_);
+    destroy_intf_(display_id_);
   color_intf_ = NULL;
 }
 
diff --git a/sdm/libs/core/color_manager.h b/sdm/libs/core/color_manager.h
index db050af..74270e0 100644
--- a/sdm/libs/core/color_manager.h
+++ b/sdm/libs/core/color_manager.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -77,8 +77,8 @@
 
  protected:
   ColorManagerProxy() {}
-  ColorManagerProxy(DisplayType type, HWInterface *intf, const HWDisplayAttributes &attr,
-                    const HWPanelInfo &info);
+  ColorManagerProxy(int32_t id, DisplayType type, HWInterface *intf,
+                    const HWDisplayAttributes &attr, const HWPanelInfo &info);
 
  private:
   static DynLib color_lib_;
@@ -86,6 +86,7 @@
   static DestroyColorInterface destroy_intf_;
   static HWResourceInfo hw_res_info_;
 
+  int32_t display_id_;
   DisplayType device_type_;
   PPHWAttributes pp_hw_attributes_;
   HWInterface *hw_intf_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index a06aa5d..c646668 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -128,17 +128,15 @@
     }
   }
 
-  if (!color_mgr_exists_) {
+  // ColorManager supported for built-in display.
+  if (kBuiltIn == display_type_) {
     color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
                                                             display_attributes_, hw_panel_info_);
 
     if (!color_mgr_) {
-      DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
-    } else {
-      color_mgr_exists_ = true;
-      if (InitializeColorModes() != kErrorNone) {
-        DLOGW("InitColorModes failed for display = %d", display_type_);
-      }
+      DLOGW("Unable to create ColorManagerProxy for display %d-%d", display_id_, display_type_);
+    } else if (InitializeColorModes() != kErrorNone) {
+      DLOGW("InitColorModes failed for display %d-%d", display_id_, display_type_);
     }
   }
 
@@ -1633,8 +1631,6 @@
                                 mixer_height != display_height);
 }
 
-bool DisplayBase::color_mgr_exists_ = false;
-
 void DisplayBase::ClearColorInfo() {
   color_modes_.clear();
   color_mode_map_.clear();
@@ -1644,7 +1640,6 @@
   if (color_mgr_) {
     delete color_mgr_;
     color_mgr_ = NULL;
-    color_mgr_exists_ = false;
   }
 }
 
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 2c626e9..7f8e32d 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -189,8 +189,6 @@
   uint32_t max_mixer_stages_ = 0;
   HWInfoInterface *hw_info_intf_ = NULL;
   ColorManagerProxy *color_mgr_ = NULL;  // each display object owns its ColorManagerProxy
-  // TODO(user): ColorManager supported only on a single built-in display.
-  static bool color_mgr_exists_;
   bool partial_update_control_ = true;
   HWEventsInterface *hw_events_intf_ = NULL;
   bool disable_pu_one_frame_ = false;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index a58c92d..fe608cd 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -943,7 +943,7 @@
   } else {
     *out_size = std::min((UINT32(name.size()) + 1), *out_size);
     if (*out_size > 0) {
-      std::strncpy(out_name, name.c_str(), *out_size);
+      strlcpy(out_name, name.c_str(), *out_size);
       out_name[*out_size - 1] = '\0';
     } else {
       DLOGW("Invalid size requested");
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index 88f21e3..106b147 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -153,7 +153,7 @@
 
   if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
       bootanim_exit) {
-    DLOGI("Applying default mode");
+    DLOGI("Applying default mode for display %d", sdm_id_);
     boot_animation_completed_ = true;
     // Applying default mode after bootanimation is finished And
     // If Data is Encrypted, it is ready for access.
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 4dc8f13..9ba14a9 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -777,6 +777,7 @@
   // in layer_buffer or copy directly to Vector
   if (cr_stats->bDataValid) {
     switch (cr_stats->version) {
+      case UBWC_3_0:
       case UBWC_2_0:
         cr_vec->push_back(std::make_pair(32, cr_stats->ubwc_stats.nCRStatsTile32));
         cr_vec->push_back(std::make_pair(64, cr_stats->ubwc_stats.nCRStatsTile64));
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index e14c0d1..ed72532 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -669,7 +669,7 @@
   if (!hwc_session->primary_ready_ && (display == HWC_DISPLAY_PRIMARY)) {
     hwc_session->primary_ready_ = true;
     hwc_session->CreateBuiltInDisplays();
-    hwc_session->CreatePluggableDisplays(false);
+    hwc_session->HandlePluggableDisplays(false);
   }
 
   return INT32(status);
@@ -1760,6 +1760,41 @@
   }
 }
 
+android::status_t HWCSession::QdcmCMDDispatch(uint32_t display_id,
+                                              const PPDisplayAPIPayload &req_payload,
+                                              PPDisplayAPIPayload *resp_payload,
+                                              PPPendingParams *pending_action) {
+  int ret = 0;
+  bool is_physical_display = false;
+
+  if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
+      DLOGW("Invalid display id or display = %d is not connected.", display_id);
+      return -ENODEV;
+  }
+
+  if (display_id == map_info_primary_.client_id) {
+    is_physical_display = true;
+  } else {
+    for (auto &map_info : map_info_builtin_) {
+      if (map_info.client_id == display_id) {
+        is_physical_display = true;
+        break;
+     }
+    }
+  }
+
+  if (!is_physical_display) {
+    DLOGW("Skipping QDCM command dispatch on display = %d", display_id);
+    return ret;
+  }
+
+  ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload,
+                                                       resp_payload,
+                                                       pending_action);
+
+  return ret;
+}
+
 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
   int ret = 0;
@@ -1767,6 +1802,7 @@
   uint32_t display_id(0);
   PPPendingParams pending_action;
   PPDisplayAPIPayload resp_payload, req_payload;
+  uint8_t *disp_id = NULL;
 
   if (!color_mgr_) {
     DLOGW("color_mgr_ not initialized.");
@@ -1779,21 +1815,7 @@
   // Read display_id, payload_size and payload from in_parcel.
   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   if (!ret) {
-    if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
-      DLOGW("Invalid display id or display = %d is not connected.", display_id);
-      ret = -ENODEV;
-    }
-  }
-
-  if (!ret) {
-    if ((HWC_DISPLAY_PRIMARY == display_id) || (HWC_DISPLAY_EXTERNAL == display_id)) {
-      ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, &resp_payload,
-                                                           &pending_action);
-    } else {
-      // Virtual, Tertiary etc. not supported.
-      DLOGW("Operation not supported on display = %d.", display_id);
-      ret = -EINVAL;
-    }
+    ret = QdcmCMDDispatch(display_id, req_payload, &resp_payload, &pending_action);
   }
 
   if (ret) {
@@ -1804,12 +1826,6 @@
   }
 
   if (kNoAction != pending_action.action) {
-    // Restrict pending actions to primary display.
-    if (HWC_DISPLAY_PRIMARY != display_id) {
-      DLOGW("Skipping pending action %d on display = %d.", pending_action.action, display_id);
-      pending_action.action = kNoAction;
-    }
-
     int32_t action = pending_action.action;
     int count = -1;
     while (action > 0) {
@@ -1820,33 +1836,33 @@
       if (!bit)
         continue;
 
-      DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
+      DLOGV_IF(kTagQDCM, "pending action = %d, display_id = %d", BITMAP(count), display_id);
       switch (BITMAP(count)) {
         case kInvalidating:
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           break;
         case kEnterQDCMMode:
-          ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          ret = color_mgr_->EnableQDCMMode(true, hwc_display_[display_id]);
           break;
         case kExitQDCMMode:
-          ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          ret = color_mgr_->EnableQDCMMode(false, hwc_display_[display_id]);
           break;
         case kApplySolidFill:
           {
-            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            SCOPE_LOCK(locker_[display_id]);
             ret = color_mgr_->SetSolidFill(pending_action.params,
-                                            true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                           true, hwc_display_[display_id]);
           }
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           usleep(kSolidFillDelay);
           break;
         case kDisableSolidFill:
           {
-            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            SCOPE_LOCK(locker_[display_id]);
             ret = color_mgr_->SetSolidFill(pending_action.params,
-                                            false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                           false, hwc_display_[display_id]);
           }
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           usleep(kSolidFillDelay);
           break;
         case kSetPanelBrightness:
@@ -1855,30 +1871,65 @@
             DLOGE("Brightness value is Null");
             ret = -EINVAL;
           } else {
-            ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+            ret = hwc_display_[display_id]->SetPanelBrightness(*brightness_value);
           }
           break;
         case kEnableFrameCapture:
           ret = color_mgr_->SetFrameCapture(pending_action.params, true,
-                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
-          Refresh(HWC_DISPLAY_PRIMARY);
+                                            hwc_display_[display_id]);
+          Refresh(display_id);
           break;
         case kDisableFrameCapture:
           ret = color_mgr_->SetFrameCapture(pending_action.params, false,
-                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                            hwc_display_[display_id]);
           break;
         case kConfigureDetailedEnhancer:
           ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
-                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
-          Refresh(HWC_DISPLAY_PRIMARY);
+                                                hwc_display_[display_id]);
+          Refresh(display_id);
           break;
         case kModeSet:
           ret = static_cast<int>
-                 (hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
-          Refresh(HWC_DISPLAY_PRIMARY);
+                  (hwc_display_[display_id]->RestoreColorTransform());
+          Refresh(display_id);
           break;
         case kNoAction:
           break;
+        case kMultiDispProc:
+          for (auto &map_info : map_info_builtin_) {
+            uint32_t id = UINT32(map_info.client_id);
+            if (id < kNumDisplays && hwc_display_[id]) {
+              int result = 0;
+              resp_payload.DestroyPayload();
+              result = hwc_display_[id]->ColorSVCRequestRoute(req_payload,
+                                                              &resp_payload,
+                                                              &pending_action);
+              if (result) {
+                DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
+                ret = result;
+              }
+            }
+          }
+          break;
+        case kMultiDispGetId:
+          ret = resp_payload.CreatePayloadBytes(HWC_NUM_DISPLAY_TYPES, &disp_id);
+          if (ret) {
+            DLOGW("Unable to create response payload!");
+          } else {
+            for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+              disp_id[i] = HWC_NUM_DISPLAY_TYPES;
+            }
+            if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+              disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
+            }
+            for (auto &map_info : map_info_builtin_) {
+              uint64_t id = map_info.client_id;
+              if (id < kNumDisplays && hwc_display_[id]) {
+                disp_id[id] = (uint8_t)id;
+              }
+            }
+          }
+          break;
         default:
           DLOGW("Invalid pending action = %d!", pending_action.action);
           break;
@@ -1947,8 +1998,9 @@
 
     hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
     hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
-    DLOGI("Uevent = %s, bpp = %d, pattern = %d", uevent_data, hpd_bpp_, hpd_pattern_);
-    if (CreatePluggableDisplays(true)) {
+    DLOGI("Uevent = %s, status = %s, MST_HOTPLUG = %s, bpp = %d, pattern = %d", uevent_data,
+          str_status ? str_status : "NULL", str_mst ? str_mst : "NULL", hpd_bpp_, hpd_pattern_);
+    if (HandlePluggableDisplays(true)) {
       DLOGE("Could not handle hotplug. Event dropped.");
     }
 
@@ -2155,7 +2207,7 @@
   return status;
 }
 
-int HWCSession::CreatePluggableDisplays(bool delay_hotplug) {
+int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
   if (!primary_ready_) {
     DLOGI("Primary display is not ready. Connect displays later if any.");
     return 0;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 1c83a3b..b2a4100 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -246,7 +246,7 @@
   int GetDisplayIndex(int dpy);
   int CreatePrimaryDisplay();
   int CreateBuiltInDisplays();
-  int CreatePluggableDisplays(bool delay_hotplug);
+  int HandlePluggableDisplays(bool delay_hotplug);
   int HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug);
   int HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info);
   void DestroyDisplay(DisplayMapInfo *map_info);
@@ -320,6 +320,10 @@
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
+  android::status_t QdcmCMDDispatch(uint32_t display_id,
+                                    const PPDisplayAPIPayload &req_payload,
+                                    PPDisplayAPIPayload *resp_payload,
+                                    PPPendingParams *pending_action);
   android::status_t GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
                                                   android::Parcel *output_parcel);
   android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,