Merge "hwc2: Teardown CWB in Create Virtual Display"
diff --git a/gralloc/gr_priv_handle.h b/gralloc/gr_priv_handle.h
index ace762e..0968c5c 100644
--- a/gralloc/gr_priv_handle.h
+++ b/gralloc/gr_priv_handle.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution
  *
  * Copyright (C) 2008 The Android Open Source Project
@@ -23,7 +23,9 @@
 #include <log/log.h>
 #include <hardware/gralloc.h>
 #include <hardware/gralloc1.h>
+#ifdef __cplusplus
 #include <cinttypes>
+#endif
 
 #define GRALLOC1_FUNCTION_PERFORM 0x00001000
 
@@ -34,7 +36,12 @@
 #define PRIV_HANDLE_CONST(exp) static_cast<const private_handle_t *>(exp)
 
 #pragma pack(push, 4)
+#ifdef __cplusplus
 struct private_handle_t : public native_handle_t {
+#else
+struct private_handle_t {
+        native_handle_t nativeHandle;
+#endif
   enum {
     PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
     PRIV_FLAGS_USES_ION = 0x00000008,
@@ -85,7 +92,7 @@
   uint64_t base;
   uint64_t base_metadata;
   uint64_t gpuaddr;
-
+#ifdef __cplusplus
   static const int kNumFds = 2;
   static const int kMagic = 'gmsm';
 
@@ -175,6 +182,7 @@
   uint64_t GetUsage() const { return usage; }
 
   uint64_t GetBackingstore() const { return id; }
+#endif
 };
 #pragma pack(pop)
 
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 569c4ea..e19eccc 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, 2016-2019 The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -84,6 +84,7 @@
         SET_DSI_CLK = 42, // Set DSI Clk.
         GET_DSI_CLK = 43, // Get DSI Clk.
         GET_SUPPORTED_DSI_CLK = 44, // Get supported DSI Clk.
+        SET_COLOR_MODE_FROM_CLIENT = 45, // Overrides the QDCM mode using the given mode ID
         COMMAND_LIST_END = 400,
     };
 
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 14f156b..fa4efb6 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -36,6 +36,7 @@
     kCmdResetLUT,
     kCmdGetDefaultClk,
     kCmdDisableRotatorOneFrame,
+    kCmdSetDisplayState,
     kCmdMax,
   };
 
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index e07aae1..0f92d62 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -545,6 +545,9 @@
   DisplayCompositionContext *display_comp_ctx =
       reinterpret_cast<DisplayCompositionContext *>(display_ctx);
 
+  resource_intf_->Perform(ResourceInterface::kCmdSetDisplayState,
+                          display_comp_ctx->display_resource_ctx, state);
+
   switch (state) {
   case kStateOff:
     Purge(display_ctx);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index f219726..97eb72b 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1410,7 +1410,8 @@
   uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
 
   for (uint32_t i = 0; i < hw_layers_count; i++) {
-    Layer *sdm_layer = layer_stack->layers.at(hw_layers_.info.index.at(i));
+    uint32_t sdm_layer_index = hw_layers_.info.index.at(i);
+    Layer *sdm_layer = layer_stack->layers.at(sdm_layer_index);
     Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
 
     hw_layer.input_buffer.planes[0].fd = sdm_layer->input_buffer.planes[0].fd;
@@ -1419,6 +1420,12 @@
     hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
     hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
     hw_layer.input_buffer.handle_id = sdm_layer->input_buffer.handle_id;
+    // TODO(user): Other FBT layer attributes like surface damage, dataspace, secure camera and
+    // secure display flags are also updated during SetClientTarget() called between validate and
+    // commit. Need to revist this and update it accordingly for FBT layer.
+    if (hw_layers_.info.gpu_target_index == sdm_layer_index) {
+      hw_layer.input_buffer.flags.secure = sdm_layer->input_buffer.flags.secure;
+    }
   }
 
   return;
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 21a7890..bf53c66 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -131,16 +131,16 @@
     fb_config = display_attributes;
   }
 
-  // if display is already connected, unregister display from composition manager and register
-  // the display with new configuration.
-  if (display_comp_ctx_) {
-    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  // if display is already connected, reconfigure the display with new configuration.
+  if (!display_comp_ctx_) {
+    error = comp_manager_->RegisterDisplay(display_id_, display_type_, display_attributes,
+                                           hw_panel_info, mixer_attributes, fb_config,
+                                           &display_comp_ctx_, &(default_qos_data_.clock_hz));
+  } else {
+    error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+                                              mixer_attributes, fb_config,
+                                              &(default_qos_data_.clock_hz));
   }
-
-  error =
-      comp_manager_->RegisterDisplay(display_id_, display_type_, display_attributes, hw_panel_info,
-                                     mixer_attributes, fb_config, &display_comp_ctx_,
-                                     &(default_qos_data_.clock_hz));
   if (error != kErrorNone) {
     return error;
   }
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 7988405..51a47c8 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1940,6 +1940,11 @@
     AddSolidfillStage(sf, 0xFF);
     SetSolidfillStages();
   }
+
+  if (!secure_display_active_) {
+    DRMSecurityLevel crtc_security_level = DRMSecurityLevel::SECURE_NON_SECURE;
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
+  }
 }
 
 DisplayError HWDeviceDRM::NullCommit(bool synchronous, bool retain_planes) {
diff --git a/sdm/libs/hwc2/hwc_debugger.cpp b/sdm/libs/hwc2/hwc_debugger.cpp
index 82f0e47..7f116d5 100644
--- a/sdm/libs/hwc2/hwc_debugger.cpp
+++ b/sdm/libs/hwc2/hwc_debugger.cpp
@@ -165,6 +165,20 @@
   DebugHandler::SetLogMask(debug_handler_.log_mask_);
 }
 
+void HWCDebugHandler::DebugQos(bool enable, int verbose_level) {
+  if (enable) {
+    debug_handler_.log_mask_[kTagQOSClient] = 1;
+    // TODO(user): add qos impl log mask when logging available
+    debug_handler_.verbose_level_ = verbose_level;
+  } else {
+    debug_handler_.log_mask_[kTagQOSClient] = 0;
+    // TODO(user): add qos impl log mask when logging available
+    debug_handler_.verbose_level_ = 0;
+  }
+
+  DebugHandler::SetLogMask(debug_handler_.log_mask_);
+}
+
 void HWCDebugHandler::Error(const char *format, ...) {
   va_list list;
   va_start(list, format);
diff --git a/sdm/libs/hwc2/hwc_debugger.h b/sdm/libs/hwc2/hwc_debugger.h
index 7ebca8a..db8c2a6 100644
--- a/sdm/libs/hwc2/hwc_debugger.h
+++ b/sdm/libs/hwc2/hwc_debugger.h
@@ -57,6 +57,7 @@
   static void DebugScalar(bool enable, int verbose_level);
   static void DebugQdcm(bool enable, int verbose_level);
   static void DebugClient(bool enable, int verbose_level);
+  static void DebugQos(bool enable, int verbose_level);
   static void DebugDisplay(bool enable, int verbose_level);
   static int  GetIdleTimeoutMs();
 
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index f6051bd..cee0b8b 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -50,6 +50,8 @@
 
 namespace sdm {
 
+uint32_t HWCDisplay::throttling_refresh_rate_ = 60;
+
 bool NeedsToneMap(const LayerStack &layer_stack) {
   for (Layer *layer : layer_stack.layers) {
     if (layer->request.flags.tone_map) {
@@ -795,6 +797,9 @@
   // Append client target to the layer stack
   Layer *sdm_client_target = client_target_->GetSDMLayer();
   sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
+  // Derive client target dataspace based on the color mode - bug/115482728
+  int32_t client_target_dataspace = GetDataspaceFromColorMode(GetCurrentColorMode());
+  SetClientTargetDataSpace(client_target_dataspace);
   layer_stack_.layers.push_back(sdm_client_target);
 
   // fall back frame composition to GPU when client target is 10bit
@@ -819,7 +824,7 @@
 HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
   const auto map_layer = layer_map_.find(layer_id);
   if (map_layer == layer_map_.end()) {
-    DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
+    DLOGW("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
     return HWC2::Error::BadLayer;
   }
 
@@ -1145,14 +1150,13 @@
   }
 
   Layer *sdm_layer = client_target_->GetSDMLayer();
-  sdm_layer->frame_rate = current_refresh_rate_;
+  sdm_layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
   client_target_->SetLayerSurfaceDamage(damage);
-  if (client_target_->GetLayerDataspace() != dataspace) {
-    client_target_->SetLayerDataspace(dataspace);
-    Layer *sdm_layer = client_target_->GetSDMLayer();
-    // Data space would be validated at GetClientTargetSupport, so just use here.
-    sdm::GetSDMColorSpace(client_target_->GetLayerDataspace(),
-                          &sdm_layer->input_buffer.color_metadata);
+  int translated_dataspace = TranslateFromLegacyDataspace(dataspace);
+  if (client_target_->GetLayerDataspace() != translated_dataspace) {
+    DLOGW("New Dataspace = %d not matching Dataspace from color mode = %d",
+           translated_dataspace, client_target_->GetLayerDataspace());
+    return HWC2::Error::BadParameter;
   }
   client_target_->SetLayerBuffer(target, acquire_fence);
 
@@ -2294,8 +2298,20 @@
       continue;
     }
     auto layer = hwc_layer->GetSDMLayer();
-    layer->frame_rate = current_refresh_rate_;
+    layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
   }
 }
 
+int32_t HWCDisplay::SetClientTargetDataSpace(int32_t dataspace) {
+  if (client_target_->GetLayerDataspace() != dataspace) {
+    client_target_->SetLayerDataspace(dataspace);
+    Layer *sdm_layer = client_target_->GetSDMLayer();
+    // Data space would be validated at GetClientTargetSupport, so just use here.
+    sdm::GetSDMColorSpace(client_target_->GetLayerDataspace(),
+                          &sdm_layer->input_buffer.color_metadata);
+  }
+
+  return 0;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 3ee1551..ed0696a 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -34,7 +34,7 @@
 #include <utility>
 #include <vector>
 #include <bitset>
-
+#include <algorithm>
 #include "hwc_buffer_allocator.h"
 #include "hwc_callbacks.h"
 #include "hwc_layers.h"
@@ -191,6 +191,9 @@
   }
 
   // Display Configurations
+  static uint32_t GetThrottlingRefreshRate() { return HWCDisplay::throttling_refresh_rate_; }
+  static void SetThrottlingRefreshRate(uint32_t newRefreshRate)
+              { HWCDisplay::throttling_refresh_rate_ = newRefreshRate; }
   virtual int SetActiveDisplayConfig(uint32_t config);
   virtual int GetActiveDisplayConfig(uint32_t *config);
   virtual int GetDisplayConfigCount(uint32_t *count);
@@ -203,6 +206,7 @@
     return kErrorNotSupported;
   }
 
+  uint32_t GetMaxRefreshRate() { return max_refresh_rate_; }
   int SetPanelBrightness(int level);
   int GetPanelBrightness(int *level);
   int ToggleScreenUpdates(bool enable);
@@ -309,9 +313,9 @@
   }
 
  protected:
+  static uint32_t throttling_refresh_rate_;
   // Maximum number of layers supported by display manager.
   static const uint32_t kMaxLayerCount = 32;
-
   HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator, HWCCallbacks *callbacks,
              HWCDisplayEventHandler *event_handler, qService::QService *qservice, DisplayType type,
              hwc2_display_t id, int32_t sdm_id, bool needs_blit, DisplayClass display_class);
@@ -337,6 +341,7 @@
   bool IsLayerUpdating(HWCLayer *layer);
   uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
   virtual void GetUnderScanConfig() { }
+  int32_t SetClientTargetDataSpace(int32_t dataspace);
 
   enum {
     INPUT_LAYER_DUMP,
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 45cfb16..4caad2a 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -182,6 +182,10 @@
     }
   }
 
+  if (dataspace == HAL_DATASPACE_UNKNOWN) {
+    dataspace = HAL_DATASPACE_V0_SRGB;
+  }
+
   return dataspace;
 }
 
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 9eba741..9c33e7b 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -34,6 +34,7 @@
 #include <QService.h>
 #include <utils/utils.h>
 #include <algorithm>
+#include <utility>
 #include <bitset>
 #include <iterator>
 #include <memory>
@@ -76,7 +77,7 @@
 int HWCSession::null_display_mode_ = 0;
 
 // Map the known color modes to dataspace.
-static int32_t GetDataspace(ColorMode mode) {
+int32_t GetDataspaceFromColorMode(ColorMode mode) {
   switch (mode) {
     case ColorMode::SRGB:
     case ColorMode::NATIVE:
@@ -182,7 +183,6 @@
   }
 
   StartServices();
-
   HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
   DisplayError error = kErrorNone;
 
@@ -945,7 +945,7 @@
   }
 
   hwc_session->UpdateVsyncSource();
-
+  hwc_session->UpdateThrottlingRate();
   return HWC2_ERROR_NONE;
 }
 
@@ -1551,6 +1551,14 @@
       status = GetSupportedDsiClk(input_parcel, output_parcel);
       break;
 
+    case qService::IQService::SET_COLOR_MODE_FROM_CLIENT:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetColorModeFromClient(input_parcel);
+      break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -1823,6 +1831,27 @@
   return 0;
 }
 
+android::status_t HWCSession::SetColorModeFromClient(const android::Parcel *input_parcel) {
+  int display = input_parcel->readInt32();
+  auto mode = input_parcel->readInt32();
+  auto device = static_cast<hwc2_device_t *>(this);
+
+  int disp_idx = GetDisplayIndex(display);
+  if (disp_idx == -1) {
+    DLOGE("Invalid display = %d", display);
+    return -EINVAL;
+  }
+
+  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+                                 &HWCDisplay::SetColorModeFromClientApi, mode);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+
+  Refresh(static_cast<hwc2_display_t>(disp_idx));
+
+  return 0;
+}
+
 android::status_t HWCSession::RefreshScreen(const android::Parcel *input_parcel) {
   int display = input_parcel->readInt32();
 
@@ -1855,6 +1884,7 @@
 
     case qService::IQService::DEBUG_PIPE_LIFECYCLE:
       HWCDebugHandler::DebugResources(enable, verbose_level);
+      HWCDebugHandler::DebugQos(enable, verbose_level);
       break;
 
     case qService::IQService::DEBUG_DRIVER_CONFIG:
@@ -1865,6 +1895,7 @@
       HWCDebugHandler::DebugResources(enable, verbose_level);
       HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
       HWCDebugHandler::DebugRotator(enable, verbose_level);
+      HWCDebugHandler::DebugQos(enable, verbose_level);
       break;
 
     case qService::IQService::DEBUG_QDCM:
@@ -2840,7 +2871,7 @@
 
   if (hwc_display) {
     *format = HAL_PIXEL_FORMAT_RGB_888;
-    *dataspace = GetDataspace(hwc_display->GetCurrentColorMode());
+    *dataspace = GetDataspaceFromColorMode(hwc_display->GetCurrentColorMode());
     return HWC2_ERROR_NONE;
   }
 
@@ -2947,6 +2978,28 @@
   return HWC_DISPLAY_PRIMARY;
 }
 
+void HWCSession::UpdateThrottlingRate() {
+  uint32_t new_min = 0;
+
+  for (int i=0; i < kNumDisplays; i++) {
+    auto &display = hwc_display_[i];
+    if (!display)
+      continue;
+    if (display->GetCurrentPowerMode() != HWC2::PowerMode::Off)
+      new_min = (new_min == 0) ? display->GetMaxRefreshRate() :
+        std::min(new_min, display->GetMaxRefreshRate());
+  }
+
+  SetNewThrottlingRate(new_min);
+}
+
+void HWCSession::SetNewThrottlingRate(const uint32_t new_rate) {
+  if (new_rate !=0 && throttling_refresh_rate_ != new_rate) {
+    HWCDisplay::SetThrottlingRefreshRate(new_rate);
+    throttling_refresh_rate_ = new_rate;
+  }
+}
+
 android::status_t HWCSession::SetIdlePC(const android::Parcel *input_parcel) {
   auto enable = input_parcel->readInt32();
   auto synchronous = input_parcel->readInt32();
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 5dd803d..48aa5eb 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -43,6 +43,7 @@
 #include <qd_utils.h>
 #include <display_config.h>
 #include <vector>
+#include <utility>
 
 #include "hwc_callbacks.h"
 #include "hwc_layers.h"
@@ -78,6 +79,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::hidl_string;
 
+int32_t GetDataspaceFromColorMode(ColorMode mode);
+
 // Create a singleton uevent listener thread valid for life of hardware composer process.
 // This thread blocks on uevents poll inside uevent library implementation. This poll exits
 // only when there is a valid uevent, it can not be interrupted otherwise. Tieing life cycle
@@ -241,7 +244,9 @@
 
   static const int kExternalConnectionTimeoutMs = 500;
   static const int kCommitDoneTimeoutMs = 100;
-
+  uint32_t throttling_refresh_rate_ = 60;
+  void UpdateThrottlingRate();
+  void SetNewThrottlingRate(uint32_t new_rate);
   // hwc methods
   static int Open(const hw_module_t *module, const char *name, hw_device_t **device);
   static int Close(hw_device_t *device);
@@ -359,6 +364,7 @@
   android::status_t SetColorModeWithRenderIntentOverride(const android::Parcel *input_parcel);
 
   android::status_t SetColorModeById(const android::Parcel *input_parcel);
+  android::status_t SetColorModeFromClient(const android::Parcel *input_parcel);
   android::status_t getComposerStatus();
   android::status_t SetQSyncMode(const android::Parcel *input_parcel);
   android::status_t SetIdlePC(const android::Parcel *input_parcel);