/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "applib/preferred_content_size.h" #include "apps/system_app_ids.h" #include "board/board.h" #include "os/mutex.h" #include "process_management/app_install_manager.h" #include "process_management/process_manager.h" #include "services/normal/activity/activity.h" #include "services/normal/activity/activity_insights.h" #include "services/normal/activity/insights_settings.h" #include "services/normal/settings/settings_file.h" #include "shell/prefs.h" #include "shell/prefs_private.h" static PebbleMutex *s_mutex; #define PREF_KEY_CLOCK_24H "clock24h" static bool s_is_24h_style; #define PREF_KEY_DEFAULT_WATCHFACE "watchface" static Uuid s_default_watchface = UUID_INVALID_INIT; #define PREF_KEY_CONTENT_SIZE "contentSize" static uint8_t s_content_size; #if !UNITTEST _Static_assert(sizeof(PreferredContentSize) == sizeof(s_content_size), "sizeof(PreferredContentSize) grew, pref needs to be migrated!"); #endif void shell_prefs_init(void) { s_mutex = mutex_create(); mutex_lock(s_mutex); SettingsFile file = {}; if (settings_file_open(&file, SHELL_PREFS_FILE_NAME, SHELL_PREFS_FILE_LEN) != S_SUCCESS) { goto cleanup; } if (settings_file_get(&file, PREF_KEY_CLOCK_24H, sizeof(PREF_KEY_CLOCK_24H), &s_is_24h_style, sizeof(s_is_24h_style)) != S_SUCCESS) { // The setting likely doesn't exist yet so set it to the default (true) s_is_24h_style = true; } if (settings_file_get(&file, PREF_KEY_DEFAULT_WATCHFACE, sizeof(PREF_KEY_DEFAULT_WATCHFACE), &s_default_watchface, sizeof(s_default_watchface)) != S_SUCCESS) { s_default_watchface = UUID_INVALID; } if (settings_file_get(&file, PREF_KEY_CONTENT_SIZE, sizeof(PREF_KEY_CONTENT_SIZE), &s_content_size, sizeof(s_content_size)) != S_SUCCESS) { s_content_size = PreferredContentSizeDefault; } settings_file_close(&file); cleanup: mutex_unlock(s_mutex); } static bool prv_pref_set(const char *key, const void *val, size_t val_len) { SettingsFile file = {}; status_t rv; if ((rv = settings_file_open(&file, SHELL_PREFS_FILE_NAME, SHELL_PREFS_FILE_LEN)) != S_SUCCESS) { goto cleanup; } rv = settings_file_set(&file, key, strnlen(key, SETTINGS_KEY_MAX_LEN) + 1, val, val_len); settings_file_close(&file); cleanup: return (rv == S_SUCCESS); } bool shell_prefs_get_clock_24h_style(void) { return s_is_24h_style; } void shell_prefs_set_clock_24h_style(bool is_24h_style) { mutex_lock(s_mutex); if (prv_pref_set(PREF_KEY_CLOCK_24H, &s_is_24h_style, sizeof(s_is_24h_style))) { s_is_24h_style = is_24h_style; } mutex_unlock(s_mutex); } bool shell_prefs_is_timezone_source_manual(void) { // Force things to automatic return false; } void shell_prefs_set_timezone_source_manual(bool manual) { } int16_t shell_prefs_get_automatic_timezone_id(void) { // Invalid return -1; } void shell_prefs_set_automatic_timezone_id(int16_t timezone_id) { } // Exported function used by blob_db API to set the backing store for a specific key. // Not used by the SDK shell bool prefs_private_write_backing(const uint8_t *key, size_t key_len, const void *value, int value_len) { return false; } // Exported function used by blob_db API to get the length of a value in our backing store // Not used by the SDK shell int prefs_private_get_backing_len(const uint8_t *key, size_t key_len) { return 0; } // Exported function used by blob_db API to read our backing store // Not used by the SDK shell bool prefs_private_read_backing(const uint8_t *key, size_t key_len, void *value, int value_len) { return false; } #if CAPABILITY_HAS_SDK_SHELL4 void watchface_set_default_install_id(AppInstallId app_id) { mutex_lock(s_mutex); Uuid uuid; app_install_get_uuid_for_install_id(app_id, &uuid); if (prv_pref_set(PREF_KEY_DEFAULT_WATCHFACE, &uuid, sizeof(uuid))) { s_default_watchface = uuid; } mutex_unlock(s_mutex); } static bool prv_set_default_any_watchface_enumerate_callback(AppInstallEntry *entry, void *data) { if (!app_install_entry_is_watchface(entry) || app_install_entry_is_hidden(entry)) { return true; // continue search } watchface_set_default_install_id(entry->install_id); return false; } AppInstallId watchface_get_default_install_id(void) { AppInstallId app_id = app_install_get_id_for_uuid(&s_default_watchface); AppInstallEntry entry; if ((app_id == INSTALL_ID_INVALID) || !app_install_get_entry_for_install_id(app_id, &entry) || !app_install_entry_is_watchface(&entry)) { app_install_enumerate_entries(prv_set_default_any_watchface_enumerate_callback, NULL); app_id = app_install_get_id_for_uuid(&s_default_watchface); } return app_id; } #else AppInstallId watchface_get_default_install_id(void) { return APP_ID_SDK; } void watchface_set_default_install_id(AppInstallId id) { } #endif void system_theme_set_content_size(PreferredContentSize content_size) { mutex_lock(s_mutex); const uint8_t content_size_uint = content_size; if (content_size >= NumPreferredContentSizes) { PBL_LOG(LOG_LEVEL_WARNING, "Ignoring attempt to set content size to invalid size %d", content_size); } else if (prv_pref_set(PREF_KEY_CONTENT_SIZE, &content_size_uint, sizeof(content_size_uint))) { s_content_size = content_size; } mutex_unlock(s_mutex); } PreferredContentSize system_theme_get_content_size(void) { return system_theme_convert_host_content_size_to_runtime_platform( (PreferredContentSize)s_content_size); } bool activity_prefs_tracking_is_enabled(void) { #if CAPABILITY_HAS_HEALTH_TRACKING return true; #else return false; #endif } #if CAPABILITY_HAS_HEALTH_TRACKING void activity_prefs_tracking_set_enabled(bool enable) { } bool activity_prefs_activity_insights_are_enabled(void) { return false; } void activity_prefs_activity_insights_set_enabled(bool enable) { } bool activity_prefs_sleep_insights_are_enabled(void) { return false; } void activity_prefs_sleep_insights_set_enabled(bool enable) { } uint8_t activity_prefs_get_health_app_opened_version(void) { return 0; } void activity_prefs_set_height_mm(uint16_t height_mm) { } uint16_t activity_prefs_get_height_mm(void) { return 0; } void activity_prefs_set_weight_dag(uint16_t weight_dag) { } uint16_t activity_prefs_get_weight_dag(void) { return 0; } void activity_prefs_set_gender(ActivityGender gender) { } ActivityGender activity_prefs_get_gender(void) { return ActivityGenderOther; } void activity_prefs_set_age_years(uint8_t age_years) { } uint8_t activity_prefs_get_age_years(void) { return 0; } bool activity_prefs_heart_rate_is_enabled(void) { return true; } ActivityInsightSettings *activity_prefs_get_sleep_reward_settings(void) { static ActivityInsightSettings s_settings = { 0 }; return &s_settings; } void activity_prefs_set_activation_delay_insight_fired(ActivationDelayInsightType type) { } bool activity_prefs_has_activation_delay_insight_fired(ActivationDelayInsightType type) { return false; } bool activity_prefs_get_health_app_opened(void) { return false; } void activity_prefs_set_activated(void) { } time_t activity_prefs_get_activation_time(void) { return 0; } UnitsDistance shell_prefs_get_units_distance(void) { return UnitsDistance_Miles; } #endif