RDK-56073: initial support for user settings
Change-Id: I9bd3333d46a07969424a3f952684a01059f47afc
diff --git a/src/third_party/starboard/rdk/shared/application_rdk.cc b/src/third_party/starboard/rdk/shared/application_rdk.cc
index cbfa0f7..daebcb9 100644
--- a/src/third_party/starboard/rdk/shared/application_rdk.cc
+++ b/src/third_party/starboard/rdk/shared/application_rdk.cc
@@ -433,6 +433,18 @@
return kSbTimeSecond;
}
+void Application::InjectAccessibilitySettingsChanged() {
+ Inject(new Event(kSbEventTypeAccessibilitySettingsChanged, NULL, NULL));
+}
+
+void Application::InjectAccessibilityCaptionSettingsChanged() {
+ Inject(new Event(kSbEventTypeAccessibilityCaptionSettingsChanged, NULL, NULL));
+}
+
+void Application::InjectAccessibilityTextToSpeechSettingsChanged() {
+ Inject(new Event(kSbEventTypeAccessibilityTextToSpeechSettingsChanged, NULL, NULL));
+}
+
} // namespace shared
} // namespace rdk
} // namespace starboard
diff --git a/src/third_party/starboard/rdk/shared/application_rdk.h b/src/third_party/starboard/rdk/shared/application_rdk.h
index 1bd3dda..b61c8c8 100644
--- a/src/third_party/starboard/rdk/shared/application_rdk.h
+++ b/src/third_party/starboard/rdk/shared/application_rdk.h
@@ -78,6 +78,10 @@
bool IsStartImmediate() override { return !HasPreloadSwitch(); }
bool IsPreloadImmediate() override { return HasPreloadSwitch(); }
+ void InjectAccessibilitySettingsChanged();
+ void InjectAccessibilityCaptionSettingsChanged();
+ void InjectAccessibilityTextToSpeechSettingsChanged();
+
protected:
// --- Application overrides ---
void Initialize() override;
diff --git a/src/third_party/starboard/rdk/shared/rdkservices.cc b/src/third_party/starboard/rdk/shared/rdkservices.cc
index 215ef9f..8d86260 100644
--- a/src/third_party/starboard/rdk/shared/rdkservices.cc
+++ b/src/third_party/starboard/rdk/shared/rdkservices.cc
@@ -72,7 +72,7 @@
const char kNetworkCallsign[] = "org.rdk.Network.1";
const char kTTSCallsign[] = "org.rdk.TextToSpeech.1";
const char kAuthServiceCallsign[] = "org.rdk.AuthService.1";
-
+const char kUserSetingsCallsign[] = "org.rdk.UserSettings.1";
const char kDeviceInfoCallsign[] = "DeviceInfo.1";
const char kBluetoothCallsign[] = "org.rdk.Bluetooth.1";
@@ -241,191 +241,12 @@
SB_ONCE_INITIALIZE_FUNCTION(DeviceIdImpl, GetDeviceIdImpl);
-struct TextToSpeechImpl {
-private:
- ::starboard::atomic_bool is_enabled_ { false };
- ::starboard::atomic_bool needs_refresh_ { true };
- ::starboard::atomic_bool did_subscribe_ { false };
- int64_t speech_id_ { -1 };
- int32_t speech_request_num_ { 0 };
- ServiceLink tts_link_ { kTTSCallsign };
- ::starboard::Mutex mutex_;
- ::starboard::ConditionVariable condition_ { mutex_ };
-
- std::string client_id_;
- struct IsTTSEnabledInfo : public Core::JSON::Container {
- IsTTSEnabledInfo()
- : Core::JSON::Container() {
- Add(_T("isenabled"), &IsEnabled);
- }
- IsTTSEnabledInfo(const IsTTSEnabledInfo&) = delete;
- IsTTSEnabledInfo& operator=(const IsTTSEnabledInfo&) = delete;
-
- Core::JSON::Boolean IsEnabled;
- };
-
- struct SpeakResult : public Core::JSON::Container {
- SpeakResult()
- : Core::JSON::Container()
- , SpeechId(-1) {
- Add(_T("speechid"), &SpeechId);
- }
- SpeakResult(const SpeakResult&) = delete;
- SpeakResult& operator=(const SpeakResult&) = delete;
-
- Core::JSON::DecSInt64 SpeechId;
- };
-
- struct StateInfo : public Core::JSON::Container {
- StateInfo()
- : Core::JSON::Container()
- , State(false) {
- Add(_T("state"), &State);
- }
- StateInfo(const StateInfo& other)
- : Core::JSON::Container()
- , State(other.State) {
- Add(_T("state"), &State);
- }
- StateInfo& operator=(const StateInfo&) = delete;
-
- Core::JSON::Boolean State;
- };
-
- void OnCancelResult(const Core::JSON::String&, const Core::JSONRPC::Error*) {
- }
-
- void OnStateChanged(const StateInfo& info) {
- is_enabled_.store( info.State.Value() );
- }
-
- void OnSpeakResult(const SpeakResult& result, const Core::JSONRPC::Error* err) {
- ::starboard::ScopedLock lock(mutex_);
- if (err) {
- SB_LOG(ERROR)
- << "TTS speak request failed. Error code: "
- << err->Code.Value()
- << " message: "
- << err->Text.Value();
- speech_id_ = -1;
- }
- else {
- speech_id_ = result.SpeechId;
- }
- --speech_request_num_;
- condition_.Broadcast();
- }
-
-public:
- TextToSpeechImpl() = default;
-
- void Speak(const std::string &text) {
- Refresh();
- if (!is_enabled_.load())
- return;
-
- JsonObject params;
- params.Set(_T("text"), text);
- params.Set(_T("callsign"), client_id_ );
-
- uint64_t rc = tts_link_.Dispatch(kDefaultTimeoutMs, "speak", params, &TextToSpeechImpl::OnSpeakResult, this);
- if (Core::ERROR_NONE == rc) {
- ::starboard::ScopedLock lock(mutex_);
- ++speech_request_num_;
- }
- }
-
- void Cancel() {
- Refresh();
- if (!is_enabled_.load())
- return;
-
- int64_t speechId = -1;
-
- {
- ::starboard::ScopedLock lock(mutex_);
- if (speech_request_num_ != 0) {
- if (!condition_.WaitTimed(kSbTimeMillisecond) || speech_request_num_ != 0)
- return;
- }
- speechId = speech_id_;
- }
-
- if (speechId < 0)
- return;
-
- JsonObject params;
- params.Set(_T("speechid"), speechId);
-
- tts_link_.Dispatch(kDefaultTimeoutMs, "cancel", params, &TextToSpeechImpl::OnCancelResult, this);
- }
-
- bool IsEnabled() {
- Refresh();
- return is_enabled_.load();
- }
-
- void Refresh() {
- if (!needs_refresh_.load())
- return;
-
- uint32_t rc;
- if (!did_subscribe_.load()) {
- bool old_val = did_subscribe_.exchange(true);
- if (old_val == false) {
- rc = tts_link_.Subscribe<StateInfo>(kDefaultTimeoutMs, "onttsstatechanged", &TextToSpeechImpl::OnStateChanged, this);
- if (Core::ERROR_UNAVAILABLE == rc || kPriviligedRequestErrorCode == rc) {
- needs_refresh_.store(false);
- SB_LOG(ERROR) << "Failed to subscribe to '" << kTTSCallsign
- << ".onstatechanged' event, rc=" << rc
- << " ( " << Core::ErrorToString(rc) << " )";
- return;
- }
- if (Core::ERROR_NONE != rc && Core::ERROR_DUPLICATE_KEY != rc) {
- did_subscribe_.store(false);
- SB_LOG(ERROR) << "Failed to subscribe to '" << kTTSCallsign
- << ".onstatechanged' event, rc=" << rc
- << " ( " << Core::ErrorToString(rc) << " )."
- << " Going to try again next time.";
- return;
- }
- }
- }
-
- IsTTSEnabledInfo info;
- rc = tts_link_.Get(kDefaultTimeoutMs, "isttsenabled", info);
- if (Core::ERROR_NONE == rc) {
- is_enabled_.store( info.IsEnabled.Value() );
- }
- if (Core::SystemInfo::GetEnvironment(_T("CLIENT_IDENTIFIER"), client_id_) == true) {
- std::string::size_type pos = client_id_.find(',');
- if (pos != std::string::npos)
- client_id_.erase(pos, std::string::npos);
- } else {
- client_id_ = "Cobalt";
- }
-
- needs_refresh_.store(false);
- }
-
- void Teardown() {
- if (did_subscribe_.load()) {
- tts_link_.Unsubscribe(kDefaultTimeoutMs, "onttsstatechanged");
- did_subscribe_.store(false);
- }
- tts_link_.Teardown();
- needs_refresh_.store(true);
- is_enabled_.store(false);
- }
-};
-
-SB_ONCE_INITIALIZE_FUNCTION(TextToSpeechImpl, GetTextToSpeech);
-
struct AccessibilityImpl {
private:
::starboard::Mutex mutex_;
SbAccessibilityDisplaySettings display_settings_ { };
SbAccessibilityCaptionSettings caption_settings_ { };
+ bool is_voice_guidance_enabled_ { false };
public:
AccessibilityImpl() {
@@ -448,7 +269,6 @@
}
void SetSettings(const std::string& json) {
-
SB_LOG(INFO) << "Updating accessibility settings: " << json;
JsonData::Accessibility::AccessibilityData settings;
@@ -461,6 +281,9 @@
::starboard::ScopedLock lock(mutex_);
+ bool was_cc_enabled = caption_settings_.is_enabled;
+ bool was_highcontrast_enabled = display_settings_.is_high_contrast_text_enabled;
+
memset(&display_settings_, 0, sizeof(display_settings_));
memset(&caption_settings_, 0, sizeof(caption_settings_));
@@ -512,6 +335,14 @@
display_settings_.is_high_contrast_text_enabled =
settings.TextDisplay.IsHighContrastTextEnabled.Value();
}
+
+ if (auto* app = Application::Get(); app != nullptr) {
+ if (was_cc_enabled != caption_settings_.is_enabled)
+ app->InjectAccessibilityCaptionSettingsChanged();
+
+ if (was_highcontrast_enabled != display_settings_.is_high_contrast_text_enabled)
+ app->InjectAccessibilitySettingsChanged();
+ }
}
bool GetSettings(std::string& out_json) {
@@ -567,10 +398,226 @@
return false;
}
+ void SetCaptionEnabled(bool enabled, bool notify_on_change = true) {
+ {
+ ::starboard::ScopedLock lock(mutex_);
+ notify_on_change &= (caption_settings_.is_enabled != enabled);
+ caption_settings_.is_enabled = enabled;
+ }
+ if (notify_on_change && Application::Get()) {
+ SB_LOG(INFO) << "Accessibility closed caption setting changed, enabled = " << enabled;
+ Application::Get()->InjectAccessibilityCaptionSettingsChanged();
+ }
+ }
+
+ void SetHighContrastEnabled(bool enabled, bool notify_on_change = true) {
+ {
+ ::starboard::ScopedLock lock(mutex_);
+ notify_on_change &= (display_settings_.is_high_contrast_text_enabled != enabled);
+ display_settings_.is_high_contrast_text_enabled = enabled;
+ }
+ if (notify_on_change && Application::Get()) {
+ SB_LOG(INFO) << "Accessibility high contrast text setting changed, enabled = " << enabled;
+ Application::Get()->InjectAccessibilitySettingsChanged();
+ }
+ }
+
+ void SetVoiceGuidanceEnabled(bool enabled, bool notify_on_change = true) {
+ {
+ ::starboard::ScopedLock lock(mutex_);
+ notify_on_change &= (is_voice_guidance_enabled_ != enabled);
+ is_voice_guidance_enabled_ = enabled;
+ }
+ if (notify_on_change && Application::Get()) {
+ SB_LOG(INFO) << "Accessibility voice guidance setting changed, enabled = " << enabled;
+ Application::Get()->InjectAccessibilityTextToSpeechSettingsChanged();
+ }
+ }
+
+ bool GetVoiceGuidanceEnabled() const {
+ ::starboard::ScopedLock lock(mutex_);
+ return is_voice_guidance_enabled_;
+ }
};
SB_ONCE_INITIALIZE_FUNCTION(AccessibilityImpl, GetAccessibility);
+struct TextToSpeechImpl {
+private:
+ ::starboard::atomic_bool is_enabled_ { false };
+ ::starboard::atomic_bool needs_refresh_ { true };
+ ::starboard::atomic_bool did_subscribe_ { false };
+ int64_t speech_id_ { -1 };
+ int32_t speech_request_num_ { 0 };
+ ServiceLink tts_link_ { kTTSCallsign };
+ ::starboard::Mutex mutex_;
+ ::starboard::ConditionVariable condition_ { mutex_ };
+ std::string client_id_;
+
+ struct IsTTSEnabledInfo : public Core::JSON::Container {
+ IsTTSEnabledInfo()
+ : Core::JSON::Container() {
+ Add(_T("isenabled"), &IsEnabled);
+ }
+ IsTTSEnabledInfo(const IsTTSEnabledInfo&) = delete;
+ IsTTSEnabledInfo& operator=(const IsTTSEnabledInfo&) = delete;
+
+ Core::JSON::Boolean IsEnabled;
+ };
+
+ struct SpeakResult : public Core::JSON::Container {
+ SpeakResult()
+ : Core::JSON::Container()
+ , SpeechId(-1) {
+ Add(_T("speechid"), &SpeechId);
+ }
+ SpeakResult(const SpeakResult&) = delete;
+ SpeakResult& operator=(const SpeakResult&) = delete;
+
+ Core::JSON::DecSInt64 SpeechId;
+ };
+
+ struct StateInfo : public Core::JSON::Container {
+ StateInfo()
+ : Core::JSON::Container()
+ , State(false) {
+ Add(_T("state"), &State);
+ }
+ StateInfo(const StateInfo& other)
+ : Core::JSON::Container()
+ , State(other.State) {
+ Add(_T("state"), &State);
+ }
+ StateInfo& operator=(const StateInfo&) = delete;
+
+ Core::JSON::Boolean State;
+ };
+
+ void OnCancelResult(const Core::JSON::String&, const Core::JSONRPC::Error*) {
+ }
+
+ void OnStateChanged(const StateInfo& info) {
+ is_enabled_.store( info.State.Value() );
+ GetAccessibility()->SetVoiceGuidanceEnabled( info.State.Value() );
+ }
+
+ void OnSpeakResult(const SpeakResult& result, const Core::JSONRPC::Error* err) {
+ ::starboard::ScopedLock lock(mutex_);
+ if (err) {
+ SB_LOG(ERROR)
+ << "TTS speak request failed. Error code: "
+ << err->Code.Value()
+ << " message: "
+ << err->Text.Value();
+ speech_id_ = -1;
+ }
+ else {
+ speech_id_ = result.SpeechId;
+ }
+ --speech_request_num_;
+ condition_.Broadcast();
+ }
+
+public:
+ TextToSpeechImpl() = default;
+
+ void Speak(const std::string &text) {
+ if (!IsEnabled())
+ return;
+
+ JsonObject params;
+ params.Set(_T("text"), text);
+ params.Set(_T("callsign"), client_id_ );
+
+ uint64_t rc = tts_link_.Dispatch(kDefaultTimeoutMs, "speak", params, &TextToSpeechImpl::OnSpeakResult, this);
+ if (Core::ERROR_NONE == rc) {
+ ::starboard::ScopedLock lock(mutex_);
+ ++speech_request_num_;
+ }
+ }
+
+ void Cancel() {
+ int64_t speechId = -1;
+
+ {
+ ::starboard::ScopedLock lock(mutex_);
+ if (speech_request_num_ != 0) {
+ if (!condition_.WaitTimed(kSbTimeMillisecond) || speech_request_num_ != 0)
+ return;
+ }
+ speechId = std::exchange(speech_id_, -1);
+ }
+
+ if (speechId < 0)
+ return;
+
+ JsonObject params;
+ params.Set(_T("speechid"), speechId);
+
+ tts_link_.Dispatch(kDefaultTimeoutMs, "cancel", params, &TextToSpeechImpl::OnCancelResult, this);
+ }
+
+ bool IsEnabled() {
+ Refresh();
+ return is_enabled_.load() || GetAccessibility()->GetVoiceGuidanceEnabled();
+ }
+
+ void Refresh() {
+ if (!needs_refresh_.load())
+ return;
+
+ uint32_t rc;
+ if (!did_subscribe_.load()) {
+ bool old_val = did_subscribe_.exchange(true);
+ if (old_val == false) {
+ rc = tts_link_.Subscribe<StateInfo>(kDefaultTimeoutMs, "onttsstatechanged", &TextToSpeechImpl::OnStateChanged, this);
+ if (Core::ERROR_UNAVAILABLE == rc || kPriviligedRequestErrorCode == rc) {
+ needs_refresh_.store(false);
+ SB_LOG(ERROR) << "Failed to subscribe to '" << kTTSCallsign
+ << ".onstatechanged' event, rc=" << rc
+ << " ( " << Core::ErrorToString(rc) << " )";
+ return;
+ }
+ if (Core::ERROR_NONE != rc && Core::ERROR_DUPLICATE_KEY != rc) {
+ did_subscribe_.store(false);
+ SB_LOG(ERROR) << "Failed to subscribe to '" << kTTSCallsign
+ << ".onstatechanged' event, rc=" << rc
+ << " ( " << Core::ErrorToString(rc) << " )."
+ << " Going to try again next time.";
+ return;
+ }
+ }
+ }
+
+ IsTTSEnabledInfo info;
+ rc = tts_link_.Get(kDefaultTimeoutMs, "isttsenabled", info);
+ if (Core::ERROR_NONE == rc) {
+ is_enabled_.store( info.IsEnabled.Value() );
+ }
+ if (Core::SystemInfo::GetEnvironment(_T("CLIENT_IDENTIFIER"), client_id_) == true) {
+ std::string::size_type pos = client_id_.find(',');
+ if (pos != std::string::npos)
+ client_id_.erase(pos, std::string::npos);
+ } else {
+ client_id_ = "Cobalt";
+ }
+
+ needs_refresh_.store(false);
+ }
+
+ void Teardown() {
+ if (did_subscribe_.load()) {
+ tts_link_.Unsubscribe(kDefaultTimeoutMs, "onttsstatechanged");
+ did_subscribe_.store(false);
+ }
+ tts_link_.Teardown();
+ needs_refresh_.store(true);
+ is_enabled_.store(false);
+ }
+};
+
+SB_ONCE_INITIALIZE_FUNCTION(TextToSpeechImpl, GetTextToSpeech);
+
struct SystemPropertiesImpl {
struct SystemPropertiesData : public Core::JSON::Container {
SystemPropertiesData()
@@ -1462,6 +1509,148 @@
return !out.empty();
}
+struct UserSettingsImpl {
+private:
+ ::starboard::Mutex mutex_;
+ std::vector<std::string> subscriptions_ { };
+ bool needs_refresh_ { true };
+ ServiceLink link_ { kUserSetingsCallsign };
+
+ struct StateChangedInfo : public Core::JSON::Container {
+ StateChangedInfo()
+ : Core::JSON::Container()
+ , Enabled(false) {
+ Add(_T("enabled"), &Enabled);
+ }
+ StateChangedInfo(const StateChangedInfo& other)
+ : Core::JSON::Container()
+ , Enabled(other.Enabled) {
+ Add(_T("enabled"), &Enabled);
+ }
+ StateChangedInfo& operator=(const StateChangedInfo&) = delete;
+
+ Core::JSON::Boolean Enabled;
+ };
+
+ void OnVoiceGuidanceChanged(const StateChangedInfo& info) {
+ bool is_voice_guidance_enabled = info.Enabled.Value();
+ SB_LOG(INFO) << "User setting changed. voice guidance enabled = " << is_voice_guidance_enabled;
+ GetAccessibility()->SetVoiceGuidanceEnabled(is_voice_guidance_enabled);
+ };
+
+ void OnHighContrastChanged(const StateChangedInfo& info) {
+ bool is_highcontrast_enabled = info.Enabled.Value();
+ SB_LOG(INFO) << "User setting changed. highcontrast enabled = " << is_highcontrast_enabled;
+ GetAccessibility()->SetHighContrastEnabled(is_highcontrast_enabled);
+ };
+
+ void OnCaptionsChanged(const StateChangedInfo& info) {
+ bool is_cc_enabled = info.Enabled.Value();
+ SB_LOG(INFO) << "User setting changed. cc enabled = " << is_cc_enabled;
+ GetAccessibility()->SetCaptionEnabled(is_cc_enabled);
+ };
+
+ bool RefreshSubscriptions() {
+ using NotificationHandlerCb = void(UserSettingsImpl::*)(const StateChangedInfo&);
+
+ const std::map<std::string, NotificationHandlerCb> kNotificationHandlers = {
+ {"onVoiceGuidanceChanged", &UserSettingsImpl::OnVoiceGuidanceChanged },
+ {"onHighContrastChanged", &UserSettingsImpl::OnHighContrastChanged },
+ {"onCaptionsChanged", &UserSettingsImpl::OnCaptionsChanged },
+ };
+
+ uint32_t rc;
+
+ mutex_.DCheckAcquired();
+
+ for (const auto& kv : kNotificationHandlers) {
+ const auto& name = kv.first;
+ const auto& callback = kv.second;
+
+ if (std::find(subscriptions_.begin(), subscriptions_.end(), name)
+ != subscriptions_.end())
+ continue;
+
+ rc = link_.Subscribe<StateChangedInfo>(
+ kDefaultTimeoutMs, name, callback, this);
+
+ if (Core::ERROR_UNAVAILABLE == rc || kPriviligedRequestErrorCode == rc) {
+ needs_refresh_ = false;
+ SB_LOG(ERROR) << "Failed to subscribe to '" << kUserSetingsCallsign
+ << "." << name << "' event, rc = " << rc
+ << " ( " << Core::ErrorToString(rc) << " )";
+ return false;
+ }
+
+ if (Core::ERROR_NONE != rc && Core::ERROR_DUPLICATE_KEY != rc) {
+ SB_LOG(ERROR) << "Failed to subscribe to '" << kUserSetingsCallsign
+ << "." << name << "' event, rc = " << rc
+ << " ( " << Core::ErrorToString(rc) << " ).";
+ continue;
+ }
+
+ subscriptions_.push_back(name);
+ }
+
+ return true;
+ }
+
+public:
+ UserSettingsImpl() = default;
+
+ void Refresh() {
+ ::starboard::ScopedLock lock(mutex_);
+ if (!needs_refresh_)
+ return;
+
+ if (!RefreshSubscriptions())
+ return;
+
+ bool is_voice_guidance_enabled = false;
+ bool is_cc_enabled = false;
+ bool is_highcontrast_enabled = false;
+
+ const std::map<std::string, bool*> kSettings = {
+ {"getVoiceGuidance", &is_voice_guidance_enabled},
+ {"getHighContrast", &is_highcontrast_enabled},
+ {"getCaptions", &is_cc_enabled},
+ };
+
+ for (const auto& kv: kSettings) {
+ uint32_t rc;
+ Core::JSON::Boolean result;
+
+ rc = link_.Get(kDefaultTimeoutMs, kv.first, result);
+
+ if (Core::ERROR_NONE == rc) {
+ SB_LOG(INFO) << "User setting: " << kv.first << " = " << result.Value();
+ (*kv.second) = result.Value();
+ } else {
+ SB_LOG(ERROR) << "Failed to get user setting '" << kv.first<< ", rc=" << rc
+ << " ( " << Core::ErrorToString(rc) << " ).";
+ }
+ }
+
+ needs_refresh_ = false;
+
+ auto *accessibility = GetAccessibility();
+ accessibility->SetVoiceGuidanceEnabled(is_voice_guidance_enabled, false);
+ accessibility->SetCaptionEnabled(is_cc_enabled, false);
+ accessibility->SetHighContrastEnabled(is_highcontrast_enabled, false);
+ }
+
+ void Teardown() {
+ ::starboard::ScopedLock lock(mutex_);
+ for (const auto& subscription : subscriptions_)
+ link_.Unsubscribe(kDefaultTimeoutMs, subscription.c_str());
+ link_.Teardown();
+ needs_refresh_ = true;
+ subscriptions_.clear();
+ }
+};
+
+SB_ONCE_INITIALIZE_FUNCTION(UserSettingsImpl, GetUserSettings);
+
} // namespace
ResolutionInfo DisplayInfo::GetResolution() {
@@ -1497,6 +1686,7 @@
}
bool TextToSpeech::IsEnabled() {
+ GetUserSettings()->Refresh();
return GetTextToSpeech()->IsEnabled();
}
@@ -1505,10 +1695,12 @@
}
bool Accessibility::GetCaptionSettings(SbAccessibilityCaptionSettings* out) {
+ GetUserSettings()->Refresh();
return GetAccessibility()->GetCaptionSettings(out);
}
bool Accessibility::GetDisplaySettings(SbAccessibilityDisplaySettings* out) {
+ GetUserSettings()->Refresh();
return GetAccessibility()->GetDisplaySettings(out);
}
@@ -1601,6 +1793,7 @@
GetTextToSpeech()->Teardown();
GetNetworkInfo()->Teardown();
GetDeviceInfo()->Teardown();
+ GetUserSettings()->Teardown();
}
} // namespace shared