Merge "hwc2: Avoid querying HDR capability for every getHDRCapability call"
diff --git a/composer/Android.mk b/composer/Android.mk
index 62cbca6..7064f1d 100644
--- a/composer/Android.mk
+++ b/composer/Android.mk
@@ -217,6 +217,18 @@
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.8
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.9
 endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_10)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.7
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.8
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.9
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.10
+endif
 
 LOCAL_SRC_FILES               := QtiComposer.cpp QtiComposerClient.cpp service.cpp \
                                  QtiComposerHandleImporter.cpp
diff --git a/composer/display_null.h b/composer/display_null.h
index 1ec6a15..ae3059e 100644
--- a/composer/display_null.h
+++ b/composer/display_null.h
@@ -93,6 +93,7 @@
   MAKE_NO_OP(SetCursorPosition(int, int))
   MAKE_NO_OP(SetRefreshRate(uint32_t, bool))
   MAKE_NO_OP(GetPanelBrightness(float *))
+  MAKE_NO_OP(GetRefreshRate(uint32_t *))
   MAKE_NO_OP(SetVSyncState(bool))
   MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
   MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &))
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 5b90c16..3e219aa 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -739,14 +739,6 @@
       layer_stack_.flags.single_buffered_layer_present = true;
     }
 
-    if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
-      // Currently we support only one HWCursor & only at top most z-order
-      if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
-        layer->flags.cursor = true;
-        layer_stack_.flags.cursor_present = true;
-      }
-    }
-
     bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
                      (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
                      layer->input_buffer.color_metadata.transfer == Transfer_HLG);
@@ -761,6 +753,15 @@
       layer->flags.skip = true;
     }
 
+    if (!layer->flags.skip &&
+        (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor)) {
+      // Currently we support only one HWCursor & only at top most z-order
+      if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
+        layer->flags.cursor = true;
+        layer_stack_.flags.cursor_present = true;
+      }
+    }
+
     if (layer->flags.skip) {
       layer_stack_.flags.skip_present = true;
     }
@@ -1297,6 +1298,10 @@
       // so that previous buffer and fences are released, and override the error.
       flush_ = true;
       validated_ = false;
+      // Prepare cycle can fail on a newly connected display if insufficient pipes
+      // are available at this moment. Trigger refresh so that the other displays
+      // can free up pipes and a valid content can be attached to virtual display.
+      callbacks_->Refresh(id_);
       return HWC2::Error::BadDisplay;
     }
   }
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index e1892da..635fb22 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -179,10 +179,23 @@
   }
 
   uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
-  bool final_rate = force_refresh_rate_ ? true : false;
-  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
+  error = display_intf_->SetRefreshRate(refresh_rate, force_refresh_rate_);
+
+  // Get the refresh rate set.
+  display_intf_->GetRefreshRate(&refresh_rate);
+  bool vsync_source = (callbacks_->GetVsyncSource() == id_);
+
   if (error == kErrorNone) {
-    // On success, set current refresh rate to new refresh rate
+    if (vsync_source && (current_refresh_rate_ < refresh_rate)) {
+      DTRACE_BEGIN("HWC2::Vsync::Enable");
+      // Display is ramping up from idle.
+      // Client realizes need for resync upon change in config.
+      // Since we know config has changed, triggering vsync proactively
+      // can help in reducing pipeline delays to enable events.
+      SetVsyncEnabled(HWC2::Vsync::Enable);
+      DTRACE_END();
+    }
+    // On success, set current refresh rate to new refresh rate.
     current_refresh_rate_ = refresh_rate;
   }
 
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 0aefae1..51820c6 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -477,13 +477,6 @@
 }
 
 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
-  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
-  if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
-    DLOGE("No active displays");
-    return -EINVAL;
-  }
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
-
   if (null_display_mode_) {
     return 0;
   }
@@ -493,23 +486,14 @@
     return -ENOENT;
   }
 
-  if (!hwc_display_[active_builtin_disp_id]) {
-    DLOGW("Display = %d is not connected.", active_builtin_disp_id);
-    return -ENODEV;
-  }
-
-  HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
-
-  // trigger invalidate to apply new bw caps.
-  Refresh(active_builtin_disp_id);
+  HWBwModes mode = on > 0 ? kBwVFEOn : kBwVFEOff;
 
   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
     return -EINVAL;
   }
 
-  new_bw_mode_ = true;
-  need_invalidate_ = true;
-  hwc_display_[active_builtin_disp_id]->ResetValidation();
+  // trigger invalidate to apply new bw caps.
+  Refresh(0);
 
   return 0;
 }
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 1a6ab91..bebc23a 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -541,6 +541,7 @@
   uint32_t max_horizontal_deci;
   uint32_t max_vertical_deci;
   uint64_t max_pipe_bandwidth;
+  uint64_t max_pipe_bandwidth_high;
   uint32_t cache_size;  // cache size in bytes for inline rotation support.
   bool has_excl_rect = false;
   QSEEDStepVersion qseed3_version;
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
index 55802f4..a31abb6 100644
--- a/sde-drm/drm_plane.cpp
+++ b/sde-drm/drm_plane.cpp
@@ -403,6 +403,7 @@
   string max_vertical_deci = "max_vertical_deci=";
   string master_plane_id = "primary_smart_plane_id=";
   string max_pipe_bw = "max_per_pipe_bw=";
+  string max_pipe_bw_high = "max_per_pipe_bw_high=";
   string scaler_version = "scaler_step_ver=";
   string block_sec_ui = "block_sec_ui=";
   string true_inline_rot_rev = "true_inline_rot_rev=";
@@ -435,6 +436,8 @@
       DRM_LOGI("info->master_plane_id: detected master_plane=%d", info->master_plane_id);
     } else if (line.find(max_pipe_bw) != string::npos) {
       info->max_pipe_bandwidth = std::stoull(line.erase(0, max_pipe_bw.length()));
+    } else if (line.find(max_pipe_bw_high) != string::npos) {
+      info->max_pipe_bandwidth_high = std::stoull(line.erase(0, max_pipe_bw_high.length()));
     } else if (line.find(scaler_version) != string::npos) {
       info->qseed3_version =
         PopulateQseedStepVersion(std::stoi(line.erase(0, scaler_version.length())));
diff --git a/sdm/include/core/core_interface.h b/sdm/include/core/core_interface.h
index 2165155..90b496d 100644
--- a/sdm/include/core/core_interface.h
+++ b/sdm/include/core/core_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, 2018 The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 2018 - 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
@@ -80,10 +80,8 @@
   @sa DisplayInterface::SetMaxBandwidthMode
 */
 enum HWBwModes {
-  kBwDefault,      //!< Default state. No change in device bandwidth limit.
-  kBwCamera,       //!< Camera is on. Bandwidth limit should be reduced accordingly.
-  kBwVFlip,        //!< VFlip is required. Reduce bandwidth limit accordingly.
-  kBwHFlip,        //!< HFlip is required.  Reduce bandwidth limit accordingly.
+  kBwVFEOff,       //!< Camera/video front end off. No change in device bandwidth limit.
+  kBwVFEOn,        //!< Camera/video front end is on. Bandwidth limit reduced.
   kBwModeMax,      //!< Limiter for maximum available bandwidth modes.
 };
 
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 5901586..7e385bc 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -532,6 +532,14 @@
   */
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate) = 0;
 
+  /*! @brief Method to get the refresh rate of a display.
+
+    @param[in] refresh_rate refresh rate of the display.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetRefreshRate(uint32_t *refresh_rate) = 0;
+
   /*! @brief Method to query whether scanning is support for the HDMI display.
 
     @return \link DisplayError \endlink
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 1ab6c0b..d197743 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -194,7 +194,7 @@
 };
 
 struct HWDynBwLimitInfo {
-  uint32_t cur_mode = kBwDefault;
+  uint32_t cur_mode = kBwVFEOn;
   uint64_t total_bw_limit[kBwModeMax] = { 0 };
   uint64_t pipe_bw_limit[kBwModeMax] = { 0 };
 };
@@ -270,6 +270,7 @@
   uint32_t max_rotation_pipe_width = 1088;
   uint32_t max_cursor_size = 0;
   uint64_t max_pipe_bw =  0;
+  uint64_t max_pipe_bw_high = 0;
   uint32_t max_sde_clk = 0;
   float clk_fudge_factor = 1.0f;
   uint32_t macrotile_nv12_factor = 0;
@@ -283,7 +284,6 @@
   bool has_decimation = false;
   bool has_non_scalar_rgb = false;
   bool is_src_split = false;
-  bool has_dyn_bw_support = false;
   bool separate_rotator = false;
   bool has_qseed3 = false;
   bool has_concurrent_writeback = false;
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 9ba2df1..a607b1e 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -489,7 +489,8 @@
 }
 
 DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
-  if ((!hw_res_info_.has_dyn_bw_support) || (mode >= kBwModeMax)) {
+  SCOPE_LOCK(locker_);
+  if (mode >= kBwModeMax) {
     return kErrorNotSupported;
   }
 
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index d7e7983..838fc85 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -153,6 +153,7 @@
   virtual DisplayError SetFrameTriggerMode(FrameTriggerMode mode) {
     return kErrorNotSupported;
   }
+  virtual DisplayError GetRefreshRate(uint32_t *refresh_rate) { return kErrorNotSupported; }
 
  protected:
   const char *kBt2020Pq = "bt2020_pq";
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 746fa3b..8d7529a 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -779,4 +779,9 @@
   }
 }
 
+DisplayError DisplayBuiltIn::GetRefreshRate(uint32_t *refresh_rate) {
+  *refresh_rate = current_refresh_rate_;
+  return kErrorNone;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 044c504..6fe7b34 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -71,6 +71,7 @@
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
   virtual DisplayError SetPanelBrightness(float brightness);
   virtual DisplayError GetPanelBrightness(float *brightness);
+  virtual DisplayError GetRefreshRate(uint32_t *refresh_rate);
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event, LayerStack *layer_stack);
   virtual DisplayError SetDisplayDppsAdROI(void *payload);
   virtual DisplayError SetQSyncMode(QSyncMode qsync_mode);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index a75a622..b20386d 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -807,6 +807,18 @@
     return kErrorParameters;
   }
 
+  drmModeModeInfo to_set = connector_info_.modes[index].mode;
+  uint64_t current_bit_clk = connector_info_.modes[current_mode_index_].bit_clk_rate;
+  for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
+    if ((to_set.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
+        (to_set.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+        (to_set.vrefresh == connector_info_.modes[mode_index].mode.vrefresh) &&
+        (current_bit_clk == connector_info_.modes[mode_index].bit_clk_rate)) {
+      index = mode_index;
+      break;
+    }
+  }
+
   current_mode_index_ = index;
   PopulateHWPanelInfo();
   UpdateMixerAttributes();
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index c2a305a..6af7538 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -160,8 +160,13 @@
 DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
   HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
   for (int index = 0; index < kBwModeMax; index++) {
-    bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_low;
-    bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
+    if (index == kBwVFEOn) {
+      bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_low;
+      bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
+    } else if (index == kBwVFEOff) {
+      bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_high;
+      bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw_high;
+    }
   }
 
   return kErrorNone;
@@ -196,7 +201,6 @@
   hw_resource->hw_dest_scalar_info.max_input_width = 0;
   hw_resource->hw_dest_scalar_info.max_output_width = 0;
   hw_resource->is_src_split = true;
-  hw_resource->has_dyn_bw_support = false;
   hw_resource->has_qseed3 = false;
   hw_resource->has_concurrent_writeback = false;
 
@@ -236,9 +240,10 @@
   DLOGI("Has UBWC = %d", hw_resource->has_ubwc);
   DLOGI("Has Concurrent Writeback = %d", hw_resource->has_concurrent_writeback);
   DLOGI("Has Src Tonemap = %d", hw_resource->src_tone_map);
-  DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->max_bandwidth_low);
-  DLOGI("Max High Bw = % " PRIu64 "", hw_resource->max_bandwidth_high);
-  DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->max_pipe_bw);
+  DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->dyn_bw_info.total_bw_limit[kBwVFEOn]);
+  DLOGI("Max High Bw = % " PRIu64 "", hw_resource->dyn_bw_info.total_bw_limit[kBwVFEOff]);
+  DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->dyn_bw_info.pipe_bw_limit[kBwVFEOn]);
+  DLOGI("Max Pipe Bw High= %" PRIu64 " KBps", hw_resource->dyn_bw_info.pipe_bw_limit[kBwVFEOff]);
   DLOGI("MaxSDEClock = % " PRIu64 " Hz", hw_resource->max_sde_clk);
   DLOGI("Clock Fudge Factor = %f", hw_resource->clk_fudge_factor);
   DLOGI("Prefill factors:");
@@ -253,19 +258,11 @@
     GetHWRotatorInfo(hw_resource);
   }
 
-  if (hw_resource->has_dyn_bw_support) {
-    DisplayError ret = GetDynamicBWLimits(hw_resource);
-    if (ret != kErrorNone) {
-      DLOGE("Failed to read dynamic band width info");
-      return ret;
-    }
-
-    DLOGI("Has Support for multiple bw limits shown below");
-    for (int index = 0; index < kBwModeMax; index++) {
-      DLOGI("Mode-index=%d  total_bw_limit=%d and pipe_bw_limit=%d", index,
-            hw_resource->dyn_bw_info.total_bw_limit[index],
-            hw_resource->dyn_bw_info.pipe_bw_limit[index]);
-    }
+  DLOGI("Has Support for multiple bw limits shown below");
+  for (int index = 0; index < kBwModeMax; index++) {
+    DLOGI("Mode-index=%d  total_bw_limit=%d and pipe_bw_limit=%d", index,
+          hw_resource->dyn_bw_info.total_bw_limit[index],
+          hw_resource->dyn_bw_info.pipe_bw_limit[index]);
   }
 
   if (!hw_resource_) {
@@ -296,8 +293,15 @@
   hw_resource->scale_factor = info.downscale_prefill_lines;
   hw_resource->extra_fudge_factor = info.extra_prefill_lines;
   hw_resource->amortizable_threshold = info.amortized_threshold;
-  hw_resource->max_bandwidth_low = info.max_bandwidth_low / kKiloUnit;
-  hw_resource->max_bandwidth_high = info.max_bandwidth_high / kKiloUnit;
+
+  for (int index = 0; index < kBwModeMax; index++) {
+    if (index == kBwVFEOn) {
+      hw_resource->dyn_bw_info.total_bw_limit[index] = info.max_bandwidth_low / kKiloUnit;
+    } else if (index == kBwVFEOff) {
+      hw_resource->dyn_bw_info.total_bw_limit[index] = info.max_bandwidth_high / kKiloUnit;
+    }
+  }
+
   hw_resource->max_sde_clk = info.max_sde_clk;
   hw_resource->hw_version = info.hw_version;
 
@@ -366,6 +370,8 @@
       }
     }
 
+    // TODO(user): Move pipe caps to pipe_caps structure per pipe. Set default for now.
+    // currently copying values to hw_resource!
     HWPipeCaps pipe_caps;
     string name = {};
     switch (pipe_obj.second.type) {
@@ -374,6 +380,7 @@
         pipe_caps.type = kPipeTypeDMA;
         if (!hw_resource->num_dma_pipe) {
           PopulateSupportedFmts(kHWDMAPipe, pipe_obj.second, hw_resource);
+          PopulatePipeBWCaps(pipe_obj.second, hw_resource);
         }
         hw_resource->num_dma_pipe++;
         break;
@@ -451,7 +458,9 @@
   hw_resource->max_scale_down = info.max_downscale;
   hw_resource->max_scale_up = info.max_upscale;
   hw_resource->has_decimation = info.max_horizontal_deci > 0 && info.max_vertical_deci > 0;
-  hw_resource->max_pipe_bw = info.max_pipe_bandwidth / kKiloUnit;
+
+  PopulatePipeBWCaps(info, hw_resource);
+
   hw_resource->cache_size = info.cache_size;
   hw_resource->pipe_qseed3_version = GetQseedStepVersion(info.qseed3_version);
   hw_resource->inline_rot_info.inrot_version = GetInRotVersion(info.inrot_version);
@@ -462,6 +471,17 @@
   }
 }
 
+void HWInfoDRM::PopulatePipeBWCaps(const sde_drm::DRMPlaneTypeInfo &info,
+                                    HWResourceInfo *hw_resource) {
+  for (int index = 0; index < kBwModeMax; index++) {
+    if (index == kBwVFEOn) {
+      hw_resource->dyn_bw_info.pipe_bw_limit[index] = info.max_pipe_bandwidth / kKiloUnit;
+    } else if (index == kBwVFEOff) {
+      hw_resource->dyn_bw_info.pipe_bw_limit[index] = info.max_pipe_bandwidth_high / kKiloUnit;
+    }
+  }
+}
+
 void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
                                       const sde_drm::DRMPlaneTypeInfo  &info,
                                       HWResourceInfo *hw_resource) {
diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h
index 89c02c5..020920b 100644
--- a/sdm/libs/core/drm/hw_info_drm.h
+++ b/sdm/libs/core/drm/hw_info_drm.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-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
@@ -68,6 +68,7 @@
   void PopulateSupportedInlineFmts(const sde_drm::DRMPlaneTypeInfo &info,
                                    HWResourceInfo *hw_resource);
   void PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
+  void PopulatePipeBWCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
 
   sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
   bool default_mode_ = false;