Merge cherrypicks of [6161352, 6161353, 6161354, 6161355, 6161236, 6161237, 6161238, 6161759, 6161608, 6161356, 6161760, 6161654, 6161422, 6161423, 6161424, 6161425, 6161426, 6161427, 6161819, 6161357, 6161358, 6161428, 6161429, 6161430, 6159952, 6159858] into pi-b4s4-release

Change-Id: I5c3464c077fc8218ef174834b77e6f8cd52592c5
diff --git a/include/display_properties.h b/include/display_properties.h
index 06f4e64..e59e800 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -94,7 +94,8 @@
 #define ENABLE_DEFAULT_COLOR_MODE            DISPLAY_PROP("enable_default_color_mode")
 #define DISABLE_HDR                          DISPLAY_PROP("disable_hdr")
 #define DATASPACE_SATURATION_MATRIX_PROP     DISPLAY_PROP("dataspace_saturation_matrix")
-#define WHITE_POINT_COMPENSATED_COEFFICIENT_PROP     DISPLAY_PROP("white_point_compensated_coefficient")
+#define ADAPTIVE_WHITE_COEFFICIENT_PROP      DISPLAY_PROP("adaptive_white_coefficient")
+#define ADAPTIVE_SATURATION_PARAMETER_PROP   DISPLAY_PROP("adaptive_saturation_parameter")
 
 #define HDR_CONFIG_PROP                      RO_DISPLAY_PROP("hdr.config")
 #define QDCM_PCC_TRANS_PROP                  DISPLAY_PROP("qdcm.pcc_for_trans")
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 03e4cc3..5940dc2 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -54,8 +54,7 @@
 
 HWC2::Error HWCColorMode::Init() {
   PopulateColorModes();
-  if (GetWhitePointCompensatedCoefficients())
-    white_point_compensated_ = PaserWhitePointCompensatedData();
+  InitColorCompensation();
   return ApplyDefaultColorMode();
 }
 
@@ -145,23 +144,9 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCColorMode::SetWhitePointCompensation(bool enabled) {
-  white_point_compensated_ = enabled;
-  if (white_point_compensated_) {
-    PaserWhitePointCompensatedData();
-    ApplyWhitePointCompensationToMatrix(white_point_compensated_color_matrix_, color_matrix_);
-  }
-
-  RestoreColorTransform();
-
-  DLOGI("Set White Point Compensation: %d", enabled);
-  return HWC2::Error::None;
-}
-
 HWC2::Error HWCColorMode::RestoreColorTransform() {
-
-  DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount,
-                                                        GetTransferMatrix());
+  DisplayError error =
+      display_intf_->SetColorTransform(kColorTransformMatrixCount, PickTransferMatrix());
   if (error != kErrorNone) {
     DLOGE("Failed to set Color Transform");
     return HWC2::Error::BadParameter;
@@ -170,105 +155,227 @@
   return HWC2::Error::None;
 }
 
-bool HWCColorMode::PaserWhitePointCompensatedData() {
-    static constexpr char kWhitePointCalibrationDataPath[] = "/persist/display/calibrated_rgb";
-    FILE *fp = fopen(kWhitePointCalibrationDataPath, "r");
-    int compensated_red = 0;
-    int compensated_green = 0;
-    int compensated_blue = 0;
-
-    if (!fp) {
-      compensated_red_ratio_ = 1.0;
-      compensated_green_ratio_ = 1.0;
-      compensated_blue_ratio_ = 1.0;
-      return false;
-    }
-
-    fscanf(fp, "%d %d %d", &compensated_red, &compensated_green, &compensated_blue);
-
-    fclose(fp);
-
-    // r = r_coeffient2 * R^2 + r_coeffient1 * R + r_coeffient0
-    // g = g_coeffient2 * G^2 + g_coeffient1 * G + g_coeffient0
-    // b = b_coeffient2 * B^2 + b_coeffient1 * B + b_coeffient0
-    // r_ratio = r/kCompensatedMaxRGB
-    // g_ratio = g/kCompensatedMaxRGB
-    // b_ratio = b/kCompensatedMaxRGB
-    auto rgb_ratio = [=](int rgb, float c2, float c1, float c0) {
-                              return ((c2 * rgb * rgb + c1 * rgb + c0) / kCompensatedMaxRGB);};
-
-    compensated_red_ratio_ = rgb_ratio(CheckCompensatedRGB(compensated_red), white_point_compensated_Coefficients_[0],
-                                           white_point_compensated_Coefficients_[1], white_point_compensated_Coefficients_[2]);
-    compensated_green_ratio_ = rgb_ratio(CheckCompensatedRGB(compensated_green), white_point_compensated_Coefficients_[3],
-                                           white_point_compensated_Coefficients_[4], white_point_compensated_Coefficients_[5]);
-    compensated_blue_ratio_ = rgb_ratio(CheckCompensatedRGB(compensated_blue), white_point_compensated_Coefficients_[6],
-                                           white_point_compensated_Coefficients_[7], white_point_compensated_Coefficients_[8]);
-    return true;
+void HWCColorMode::InitColorCompensation() {
+  char value[kPropertyMax] = {0};
+  if (Debug::Get()->GetProperty(ADAPTIVE_WHITE_COEFFICIENT_PROP, value) == kErrorNone) {
+    adaptive_white_ = std::make_unique<WhiteCompensation>(string(value));
+    adaptive_white_->SetEnabled(true);
+  }
+  std::memset(value, 0, sizeof(value));
+  if (Debug::Get()->GetProperty(ADAPTIVE_SATURATION_PARAMETER_PROP, value) == kErrorNone) {
+    adaptive_saturation_ = std::make_unique<SaturationCompensation>(string(value));
+    adaptive_saturation_->SetEnabled(true);
+  }
 }
 
-bool HWCColorMode::GetWhitePointCompensatedCoefficients() {
-  char value[kPropertyMax] = {};
-  if (Debug::Get()->GetProperty(WHITE_POINT_COMPENSATED_COEFFICIENT_PROP, value) != kErrorNone) {
-    DLOGW("Undefined Compensated Coefficients");
-    return false;
+const double *HWCColorMode::PickTransferMatrix() {
+  double matrix[kColorTransformMatrixCount] = {0};
+  if (current_render_intent_ == RenderIntent::ENHANCE) {
+    CopyColorTransformMatrix(color_matrix_, matrix);
+    if (HasSaturationCompensation())
+      adaptive_saturation_->ApplyToMatrix(matrix);
+
+    if (HasWhiteCompensation())
+      adaptive_white_->ApplyToMatrix(matrix);
+
+    CopyColorTransformMatrix(matrix, compensated_color_matrix_);
+    return compensated_color_matrix_;
+  } else {
+    return color_matrix_;
+  }
+}
+
+HWC2::Error HWCColorMode::SetWhiteCompensation(bool enabled) {
+  if (adaptive_white_ == NULL)
+    return HWC2::Error::Unsupported;
+
+  if (adaptive_white_->SetEnabled(enabled) != HWC2::Error::None) {
+    return HWC2::Error::NotValidated;
   }
 
-  std::string value_string(value);
-  std::size_t start = 0, end = 0;
-  int index = 0;
-  // We need 9 coneffients, 3 for red, 3 for green, 3 for blue.
-  float CompensatedCoefficients[kCompensatedCoefficientElements] = { 1.0, 1.0, 1.0, \
-                                                                     1.0, 1.0, 1.0, \
-                                                                     1.0, 1.0, 1.0 };
+  RestoreColorTransform();
 
-  // The property must have kCompensatedCoefficientElements delimited by commas
-  while ((end = value_string.find(",", start)) != std::string::npos) {
-    CompensatedCoefficients[index] = std::stof(value_string.substr(start, end - start));
-    start = end + 1;
+  DLOGI("Set White Point Compensation: %d", enabled);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMatrix::SetEnabled(bool enabled) {
+  enabled_ = enabled;
+  return HWC2::Error::None;
+}
+
+bool HWCColorMatrix::ParseFloatValueByCommas(const string &values, uint32_t length,
+                                             std::vector<float> &elements) const {
+  std::istringstream data_stream(values);
+  string data;
+  uint32_t index = 0;
+  std::vector<float> temp_elements;
+  while (std::getline(data_stream, data, ',')) {
+    temp_elements.push_back(std::move(std::stof(data.c_str())));
     index++;
-    if (index > kCompensatedCoefficientElements - 1) {
-      DLOGW("Over Compensated Coefficients defined");
-      return false;
-    }
   }
+  if (index != length) {
+    DLOGW("Insufficient elements defined");
+    return false;
+  }
+  std::move(temp_elements.begin(), temp_elements.end(), elements.begin());
+  return true;
+}
 
-  if (index < kCompensatedCoefficientElements - 1) {
-    DLOGW("Less Compensated Coefficients defined");
+HWC2::Error WhiteCompensation::SetEnabled(bool enabled) {
+  //re-parse data when set enabled for retry calibration
+  if (enabled) {
+    if (!ConfigCoefficients() || !ParseWhiteCompensatedData()) {
+      enabled_ = false;
+      DLOGE("Failed to WhiteCompensation Set");
+      return HWC2::Error::NotValidated;
+    }
+    CalculateRGBRatio();
+  }
+  enabled_ = enabled;
+  return HWC2::Error::None;
+}
+
+bool WhiteCompensation::ParseWhiteCompensatedData() {
+  static constexpr char kWhitePointCalibrationDataPath[] = "/persist/display/calibrated_rgb";
+  FILE *fp = fopen(kWhitePointCalibrationDataPath, "r");
+  int ret;
+
+  if (!fp) {
+    DLOGW("Failed to open white compensated data file");
     return false;
   }
 
-  CompensatedCoefficients[index] = std::stof(value_string.substr(start, end - start));
+  ret = fscanf(fp, "%d %d %d", &compensated_red_, &compensated_green_, &compensated_blue_);
+  fclose(fp);
 
-  for (int32_t i = 0; i < kCompensatedCoefficientElements; i++) {
-    white_point_compensated_Coefficients_[i] = CompensatedCoefficients[i];
-    DLOGD("CompensatedCoefficients[%d]=%f",i, CompensatedCoefficients[i]);
+  if ((ret == kNumOfCompensationData) && CheckCompensatedRGB(compensated_red_) &&
+      CheckCompensatedRGB(compensated_green_) && CheckCompensatedRGB(compensated_blue_)) {
+    DLOGD("Compensated RGB: %d %d %d", compensated_red_, compensated_green_, compensated_blue_);
+    return true;
+  } else {
+    compensated_red_ = kCompensatedMaxRGB;
+    compensated_green_ = kCompensatedMaxRGB;
+    compensated_blue_ = kCompensatedMaxRGB;
+    DLOGE("Failed to get white compensated data");
+    return false;
+  }
+}
+
+bool WhiteCompensation::ConfigCoefficients() {
+  std::vector<float> CompensatedCoefficients(kCoefficientElements);
+  if (!ParseFloatValueByCommas(key_values_, kCoefficientElements, CompensatedCoefficients))
+    return false;
+  std::move(CompensatedCoefficients.begin(), CompensatedCoefficients.end(),
+            white_compensated_Coefficients_);
+  for (const auto &c : white_compensated_Coefficients_) {
+    DLOGD("white_compensated_Coefficients_=%f", c);
   }
   return true;
 }
 
+void WhiteCompensation::CalculateRGBRatio() {
+  // r = r_coeffient2 * R^2 + r_coeffient1 * R + r_coeffient0
+  // g = g_coeffient2 * G^2 + g_coeffient1 * G + g_coeffient0
+  // b = b_coeffient2 * B^2 + b_coeffient1 * B + b_coeffient0
+  // r_ratio = r/kCompensatedMaxRGB
+  // g_ratio = g/kCompensatedMaxRGB
+  // b_ratio = b/kCompensatedMaxRGB
+  auto rgb_ratio = [=](int rgb, float c2, float c1, float c0) {
+    return ((c2 * rgb * rgb + c1 * rgb + c0) / kCompensatedMaxRGB);
+  };
+
+  compensated_red_ratio_ =
+      rgb_ratio(compensated_red_, white_compensated_Coefficients_[0],
+                white_compensated_Coefficients_[1], white_compensated_Coefficients_[2]);
+  compensated_green_ratio_ =
+      rgb_ratio(compensated_green_, white_compensated_Coefficients_[3],
+                white_compensated_Coefficients_[4], white_compensated_Coefficients_[5]);
+  compensated_blue_ratio_ =
+      rgb_ratio(compensated_blue_, white_compensated_Coefficients_[6],
+                white_compensated_Coefficients_[7], white_compensated_Coefficients_[8]);
+  DLOGI("Compensated ratio %f %f %f", compensated_red_ratio_, compensated_green_ratio_,
+        compensated_blue_ratio_);
+}
+
+void WhiteCompensation::ApplyToMatrix(double *in) {
+  double matrix[kColorTransformMatrixCount] = {0};
+  for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+    if ((i % 4) == 0)
+      matrix[i] = compensated_red_ratio_ * in[i];
+    else if ((i % 4) == 1)
+      matrix[i] = compensated_green_ratio_ * in[i];
+    else if ((i % 4) == 2)
+      matrix[i] = compensated_blue_ratio_ * in[i];
+    else if ((i % 4) == 3)
+      matrix[i] = in[i];
+  }
+  std::move(&matrix[0], &matrix[kColorTransformMatrixCount - 1], in);
+}
+
+HWC2::Error SaturationCompensation::SetEnabled(bool enabled) {
+  if (enabled == enabled_)
+    return HWC2::Error::None;
+
+  if (enabled) {
+    if (!ConfigSaturationParameter()) {
+      enabled_ = false;
+      return HWC2::Error::NotValidated;
+    }
+  }
+  enabled_ = enabled;
+  return HWC2::Error::None;
+}
+
+bool SaturationCompensation::ConfigSaturationParameter() {
+  std::vector<float> SaturationParameter(kSaturationParameters);
+  if (!ParseFloatValueByCommas(key_values_, kSaturationParameters, SaturationParameter))
+    return false;
+
+  int32_t matrix_index = 0;
+  for (uint32_t i = 0; i < SaturationParameter.size(); i++) {
+    saturated_matrix_[matrix_index] = SaturationParameter.at(i);
+    // Put parameters to matrix and keep the last row/column identity
+    if ((i + 1) % 3 == 0) {
+      matrix_index += 2;
+    } else {
+      matrix_index++;
+    }
+    DLOGD("SaturationParameter[%d]=%f", i, SaturationParameter.at(i));
+  }
+  return true;
+}
+
+void SaturationCompensation::ApplyToMatrix(double *in) {
+  double matrix[kColorTransformMatrixCount] = {0};
+  // 4 x 4 matrix multiplication
+  for (uint32_t i = 0; i < kNumOfRows; i++) {
+    for (uint32_t j = 0; j < kColumnsPerRow; j++) {
+      for (uint32_t k = 0; k < kColumnsPerRow; k++) {
+        matrix[j + (i * kColumnsPerRow)] +=
+            saturated_matrix_[k + (i * kColumnsPerRow)] * in[j + (k * kColumnsPerRow)];
+      }
+    }
+  }
+  std::move(&matrix[0], &matrix[kColorTransformMatrixCount - 1], in);
+}
+
 HWC2::Error HWCColorMode::SetColorTransform(const float *matrix,
                                             android_color_transform_t /*hint*/) {
   DTRACE_SCOPED();
   auto status = HWC2::Error::None;
-  double color_matrix[kColorTransformMatrixCount] = {0};
-  double white_point_compensated_color_matrix[kColorTransformMatrixCount] = {0};
-  CopyColorTransformMatrix(matrix, color_matrix);
+  double color_matrix_restore[kColorTransformMatrixCount] = {0};
+  CopyColorTransformMatrix(color_matrix_, color_matrix_restore);
 
-  if (white_point_compensated_)
-    ApplyWhitePointCompensationToMatrix(white_point_compensated_color_matrix, color_matrix);
+  CopyColorTransformMatrix(matrix, color_matrix_);
 
-  DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount,
-                                                        NeedWhitePointCompensated() ?
-                                                        white_point_compensated_color_matrix :
-                                                        color_matrix);
+  DisplayError error =
+      display_intf_->SetColorTransform(kColorTransformMatrixCount, PickTransferMatrix());
   if (error != kErrorNone) {
+    CopyColorTransformMatrix(color_matrix_restore, color_matrix_);
     DLOGE("Failed to set Color Transform Matrix");
     status = HWC2::Error::Unsupported;
   }
-  CopyColorTransformMatrix(matrix, color_matrix_);
-
-  if (white_point_compensated_)
-    CopyColorTransformMatrix(white_point_compensated_color_matrix, white_point_compensated_color_matrix_);
 
   return status;
 }
@@ -418,16 +525,16 @@
   }
   *os << "current mode: " << static_cast<uint32_t>(current_color_mode_) << std::endl;
   *os << "current render_intent: " << static_cast<uint32_t>(current_render_intent_) << std::endl;
-  *os << "Need white point compensated: " <<  NeedWhitePointCompensated() << ",RGB:["
-      << std::fixed << std::setprecision(4)
-      << compensated_red_ratio_ << ","
-      << compensated_green_ratio_ << ","
-      << compensated_blue_ratio_ << "] "<< std::endl;
+  *os << "Need WhiteCompensation: "
+      << (current_render_intent_ == RenderIntent::ENHANCE && HasWhiteCompensation()) << std::endl;
+  *os << "Need SaturationCompensation: "
+      << (current_render_intent_ == RenderIntent::ENHANCE && HasSaturationCompensation())
+      << std::endl;
 
   *os << "current transform: ";
   double color_matrix[kColorTransformMatrixCount] = {0};
 
-  CopyColorTransformMatrix(GetTransferMatrix(), color_matrix);
+  CopyColorTransformMatrix(PickTransferMatrix(), color_matrix);
 
   for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
     if (i % 4 == 0) {
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index ff07217..4523cb5 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -46,6 +46,7 @@
 
 class BlitEngine;
 class HWCToneMapper;
+constexpr uint32_t kColorTransformMatrixCount = 16;
 
 // Subclasses set this to their type. This has to be different from DisplayType.
 // This is to avoid RTTI and dynamic_cast
@@ -56,6 +57,103 @@
   DISPLAY_CLASS_NULL
 };
 
+class HWCColorMatrix {
+ public:
+  HWCColorMatrix(const string &values) : key_values_(values){};
+  virtual ~HWCColorMatrix() = default;
+  virtual HWC2::Error SetEnabled(bool enabled);
+  bool GetEnabled() const { return enabled_; }
+  // Apply effect to input matrix
+  virtual void ApplyToMatrix(double *in) = 0;
+  bool ParseFloatValueByCommas(const string &values, uint32_t length,
+                               std::vector<float> &elements) const;
+
+ protected:
+  bool enabled_ = false;
+  const string key_values_;
+};
+
+class WhiteCompensation : public HWCColorMatrix {
+ public:
+  WhiteCompensation(const string &values) : HWCColorMatrix(values){};
+  int GetCompensatedRed() const { return compensated_red_; }
+  int GetCompensatedGreen() const { return compensated_green_; }
+  int GetCompensatedBlue() const { return compensated_blue_; }
+  HWC2::Error SetEnabled(bool enabled) override;
+  /*
+   * Transform matrix is 4 x 4
+   *  |r.r   r.g   r.b  0|
+   *  |g.r   g.g   g.b  0|
+   *  |b.r   b.g   b.b  0|
+   *  |T.r   T.g   T.b  1|
+   *   R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr
+   *   G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg
+   *   B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb
+   *
+   * Cr, Cg, Cb for white point compensation
+   *  |r.r*Cr   r.g*Cg   r.b*Cb  0|
+   *  |g.r*Cr   g.g*Cg   g.b*Cb  0|
+   *  |b.r*Cr   b.g*Cg   b.b*Cb  0|
+   *  |T.r*Cr   T.g*Cg   T.b*Cb  1|
+   *   R_out = R_in * r.r * Cr + G_in * g.r * Cr + B_in * b.r * Cr + Tr * Cr
+   *   G_out = R_in * r.g * Cg + G_in * g.g * Cg + B_in * b.g * Cg + Tg * Cg
+   *   B_out = R_in * r.b * Cb + G_in * g.b * Cb + B_in * b.b * Cb + Tb * Cb
+   */
+  void ApplyToMatrix(double *in) override;
+
+ private:
+  static constexpr int kCompensatedMaxRGB = 255;
+  static constexpr int kCompensatedMinRGB = 230;
+  static constexpr int kNumOfCompensationData = 3;
+  int compensated_red_ = kCompensatedMaxRGB;
+  int compensated_green_ = kCompensatedMaxRGB;
+  int compensated_blue_ = kCompensatedMaxRGB;
+
+  double compensated_red_ratio_ = 1.0;
+  double compensated_green_ratio_ = 1.0;
+  double compensated_blue_ratio_ = 1.0;
+
+  static constexpr int kCoefficientElements = 9;
+  float white_compensated_Coefficients_[kCoefficientElements] = {0.0, 1.0, 0.0, 0.0, 1.0,
+                                                                 0.0, 0.0, 1.0, 0.0};
+  bool ConfigCoefficients();
+  bool ParseWhiteCompensatedData();
+  inline static constexpr bool CheckCompensatedRGB(int value) {
+    return ((value >= kCompensatedMinRGB) && (value <= kCompensatedMaxRGB));
+  }
+  void CalculateRGBRatio();
+};
+
+class SaturationCompensation : public HWCColorMatrix {
+ public:
+  SaturationCompensation(const string &values) : HWCColorMatrix(values){};
+  HWC2::Error SetEnabled(bool enabled) override;
+  /*  Saturated matrix is 4 x 4
+   *  | s0   s1   s2   s3|
+   *  | s4   s5   s6   s7|
+   *  | s8   s9   s10  s11|
+   *  | s12  s13  s14  s15|
+   * Transform matrix is 4 x 4
+   *  |a0   a1   a2   a3|
+   *  |a4   a5   a6   a7|
+   *  |a8   a9   a10  a11|
+   *  |a12  a13  a14  a15|
+   *
+   *  Saturated matrix[] X Transform matrix[]
+   */
+  void ApplyToMatrix(double *in) override;
+
+ private:
+  static constexpr int kSaturationParameters = 9;
+  static constexpr int kNumOfRows = 4;
+  static constexpr int kColumnsPerRow = 4;
+  static_assert(kNumOfRows * kColumnsPerRow == kColorTransformMatrixCount,
+                "Rows x Columns should be equal to matrix count");
+  float saturated_matrix_[kColorTransformMatrixCount] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
+                                                         0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0};
+  bool ConfigSaturationParameter();
+};
+
 class HWCColorMode {
  public:
   explicit HWCColorMode(DisplayInterface *display_intf);
@@ -73,10 +171,9 @@
   HWC2::Error RestoreColorTransform();
   PrimariesTransfer  GetWorkingColorSpace();
   ColorMode GetCurrentColorMode() { return current_color_mode_; }
-  HWC2::Error SetWhitePointCompensation(bool enabled);
+  HWC2::Error SetWhiteCompensation(bool enabled);
 
  private:
-  static const uint32_t kColorTransformMatrixCount = 16;
   void PopulateColorModes();
   void FindRenderIntent(const ColorMode &mode, const std::string &mode_string);
   template <class T>
@@ -98,65 +195,18 @@
                                                        0.0, 1.0, 0.0, 0.0, \
                                                        0.0, 0.0, 1.0, 0.0, \
                                                        0.0, 0.0, 0.0, 1.0 };
-  /*
-   * Transform matrix is 4 x 4
-   *  |r.r   r.g   r.b  0|
-   *  |g.r   g.g   g.b  0|
-   *  |b.r   b.g   b.b  0|
-   *  |T.r   T.g   T.b  1|
-   *   R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr
-   *   G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg
-   *   B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb
-   *
-   * Cr, Cg, Cb for white point compensation
-   *  |r.r*Cr   r.g*Cg   r.b*Cb  0|
-   *  |g.r*Cr   g.g*Cg   g.b*Cb  0|
-   *  |b.r*Cr   b.g*Cg   b.b*Cb  0|
-   *  |T.r*Cr   T.g*Cg   T.b*Cb  1|
-   *   R_out = R_in * r.r * Cr + G_in * g.r * Cr + B_in * b.r * Cr + Tr * Cr
-   *   G_out = R_in * r.g * Cg + G_in * g.g * Cg + B_in * b.g * Cg + Tg * Cg
-   *   B_out = R_in * r.b * Cb + G_in * g.b * Cb + B_in * b.b * Cb + Tb * Cb
-   */
-  static constexpr int kCompensatedMaxRGB = 255;
-  static constexpr int kCompensatedMinRGB = 230;
-  static constexpr int kCompensatedCoefficientElements = 9;
-  double white_point_compensated_color_matrix_[kColorTransformMatrixCount] = {
-                                                       1.0, 0.0, 0.0, 0.0, \
-                                                       0.0, 1.0, 0.0, 0.0, \
-                                                       0.0, 0.0, 1.0, 0.0, \
-                                                       0.0, 0.0, 0.0, 1.0 };
-  bool PaserWhitePointCompensatedData();
-  float white_point_compensated_Coefficients_[kCompensatedCoefficientElements] = {
-                                                               1.0, 1.0, 1.0, \
-                                                               1.0, 1.0, 1.0, \
-                                                               1.0, 1.0, 1.0 };
-
-  bool GetWhitePointCompensatedCoefficients();
-  bool NeedWhitePointCompensated() { return (current_render_intent_ == RenderIntent::ENHANCE) &&
-                                                                       white_point_compensated_; }
-  double * GetTransferMatrix() { return NeedWhitePointCompensated() ? white_point_compensated_color_matrix_
-                                                                      : color_matrix_;}
-  bool   white_point_compensated_ = false;
-  double compensated_red_ratio_ = 1.0;
-  double compensated_green_ratio_ = 1.0;
-  double compensated_blue_ratio_ = 1.0;
-  inline static constexpr int CheckCompensatedRGB (int value) {
-      return ((value < kCompensatedMinRGB) ? kCompensatedMinRGB :
-              (value > kCompensatedMaxRGB) ? kCompensatedMaxRGB : value);
+  void InitColorCompensation();
+  std::unique_ptr<WhiteCompensation> adaptive_white_;
+  std::unique_ptr<SaturationCompensation> adaptive_saturation_;
+  double compensated_color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
+                                                                   0.0, 1.0, 0.0, 0.0, \
+                                                                   0.0, 0.0, 1.0, 0.0, \
+                                                                   0.0, 0.0, 0.0, 1.0};
+  bool HasWhiteCompensation() { return (adaptive_white_ && adaptive_white_->GetEnabled()); }
+  bool HasSaturationCompensation() {
+    return (adaptive_saturation_ && adaptive_saturation_->GetEnabled());
   }
-
-  void ApplyWhitePointCompensationToMatrix(double *out, double *in) {
-    for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
-       if ((i % 4) == 0)
-         out[i] = compensated_red_ratio_ * in[i];
-       else if ((i % 4) == 1)
-         out[i] = compensated_green_ratio_ * in[i];
-       else if ((i % 4) == 2)
-         out[i] = compensated_blue_ratio_ * in[i];
-       else if ((i % 4) == 3)
-         out[i] = in[i];
-    }
-  }
+  const double *PickTransferMatrix();
 };
 
 class HWCDisplay : public DisplayEventHandler {
@@ -262,7 +312,7 @@
   virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
                                       int32_t dataspace, hwc_region_t damage);
   virtual HWC2::Error SetColorMode(ColorMode mode) { return HWC2::Error::Unsupported; }
-  virtual HWC2::Error SetWhitePointCompensation(bool enabled) { return HWC2::Error::Unsupported; }
+  virtual HWC2::Error SetWhiteCompensation(bool enabled) { return HWC2::Error::Unsupported; }
   virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
     return HWC2::Error::Unsupported;
   }
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 6eaf11d..4d70d7f 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -343,10 +343,10 @@
   return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
 }
 
-HWC2::Error HWCDisplayPrimary::SetWhitePointCompensation(bool enabled) {
-  auto status = color_mode_->SetWhitePointCompensation(enabled);
+HWC2::Error HWCDisplayPrimary::SetWhiteCompensation(bool enabled) {
+  auto status = color_mode_->SetWhiteCompensation(enabled);
   if (status != HWC2::Error::None) {
-    DLOGE("failed for SetWhitePointCompensation to %d", enabled);
+    DLOGE("failed for SetWhiteCompensation to %d", enabled);
     return status;
   }
 
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index d6dcc53..0794b94 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -58,7 +58,7 @@
   virtual HWC2::Error Present(int32_t *out_retire_fence);
   virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes);
   virtual HWC2::Error SetColorMode(ColorMode mode);
-  virtual HWC2::Error SetWhitePointCompensation(bool enabled);
+  virtual HWC2::Error SetWhiteCompensation(bool enabled);
   virtual HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
                                        RenderIntent *out_intents);
   virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 2691a42..570e0fe 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1360,7 +1360,7 @@
         DLOGE("QService command = %d: input_parcel needed.", command);
         break;
       }
-      status = SetWhitePointCompensation(input_parcel);
+      status = SetWhiteCompensation(input_parcel);
       break;
 
     default:
@@ -1559,12 +1559,12 @@
   return 0;
 }
 
-android::status_t HWCSession::SetWhitePointCompensation(const android::Parcel *input_parcel) {
+android::status_t HWCSession::SetWhiteCompensation(const android::Parcel *input_parcel) {
   auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
   auto enabled = static_cast<bool >(input_parcel->readInt32());
   auto device = static_cast<hwc2_device_t *>(this);
 
-  auto err = CallDisplayFunction(device, display, &HWCDisplay::SetWhitePointCompensation, enabled);
+  auto err = CallDisplayFunction(device, display, &HWCDisplay::SetWhiteCompensation, enabled);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
 
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 8eb7016..6271e61 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -271,7 +271,7 @@
   android::status_t SetMixerResolution(const android::Parcel *input_parcel);
   android::status_t SetColorModeOverride(const android::Parcel *input_parcel);
   android::status_t SetColorModeWithRenderIntentOverride(const android::Parcel *input_parcel);
-  android::status_t SetWhitePointCompensation(const android::Parcel *input_parcel);
+  android::status_t SetWhiteCompensation(const android::Parcel *input_parcel);
 
   android::status_t SetColorModeById(const android::Parcel *input_parcel);
   android::status_t getComposerStatus();