1*5a923131SAndroid Build Coastguard Worker // 2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2015 The Android Open Source Project 3*5a923131SAndroid Build Coastguard Worker // 4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at 7*5a923131SAndroid Build Coastguard Worker // 8*5a923131SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 9*5a923131SAndroid Build Coastguard Worker // 10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 14*5a923131SAndroid Build Coastguard Worker // limitations under the License. 15*5a923131SAndroid Build Coastguard Worker // 16*5a923131SAndroid Build Coastguard Worker 17*5a923131SAndroid Build Coastguard Worker #ifndef UPDATE_ENGINE_METRICS_UTILS_H_ 18*5a923131SAndroid Build Coastguard Worker #define UPDATE_ENGINE_METRICS_UTILS_H_ 19*5a923131SAndroid Build Coastguard Worker 20*5a923131SAndroid Build Coastguard Worker #include <chrono> 21*5a923131SAndroid Build Coastguard Worker #include <string> 22*5a923131SAndroid Build Coastguard Worker #include <string_view> 23*5a923131SAndroid Build Coastguard Worker #include <type_traits> 24*5a923131SAndroid Build Coastguard Worker #include <utility> 25*5a923131SAndroid Build Coastguard Worker 26*5a923131SAndroid Build Coastguard Worker #include <base/time/time.h> 27*5a923131SAndroid Build Coastguard Worker 28*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/clock_interface.h" 29*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/connection_utils.h" 30*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/error_code.h" 31*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/metrics_constants.h" 32*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/metrics_reporter_interface.h" 33*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/prefs_interface.h" 34*5a923131SAndroid Build Coastguard Worker 35*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine { 36*5a923131SAndroid Build Coastguard Worker 37*5a923131SAndroid Build Coastguard Worker namespace metrics_utils { 38*5a923131SAndroid Build Coastguard Worker 39*5a923131SAndroid Build Coastguard Worker // Transforms a ErrorCode value into a metrics::DownloadErrorCode. 40*5a923131SAndroid Build Coastguard Worker // This obviously only works for errors related to downloading so if |code| 41*5a923131SAndroid Build Coastguard Worker // is e.g. |ErrorCode::kFilesystemCopierError| then 42*5a923131SAndroid Build Coastguard Worker // |kDownloadErrorCodeInputMalformed| is returned. 43*5a923131SAndroid Build Coastguard Worker metrics::DownloadErrorCode GetDownloadErrorCode(ErrorCode code); 44*5a923131SAndroid Build Coastguard Worker 45*5a923131SAndroid Build Coastguard Worker // Transforms a ErrorCode value into a metrics::AttemptResult. 46*5a923131SAndroid Build Coastguard Worker // 47*5a923131SAndroid Build Coastguard Worker // If metrics::AttemptResult::kPayloadDownloadError is returned, you 48*5a923131SAndroid Build Coastguard Worker // can use utils::GetDownloadError() to get more detail. 49*5a923131SAndroid Build Coastguard Worker metrics::AttemptResult GetAttemptResult(ErrorCode code); 50*5a923131SAndroid Build Coastguard Worker 51*5a923131SAndroid Build Coastguard Worker // Calculates the internet connection type given |type| and |tethering|. 52*5a923131SAndroid Build Coastguard Worker metrics::ConnectionType GetConnectionType(ConnectionType type, 53*5a923131SAndroid Build Coastguard Worker ConnectionTethering tethering); 54*5a923131SAndroid Build Coastguard Worker 55*5a923131SAndroid Build Coastguard Worker // Returns the persisted value from prefs for the given key. It also 56*5a923131SAndroid Build Coastguard Worker // validates that the value returned is non-negative. 57*5a923131SAndroid Build Coastguard Worker int64_t GetPersistedValue(std::string_view key, PrefsInterface* prefs); 58*5a923131SAndroid Build Coastguard Worker 59*5a923131SAndroid Build Coastguard Worker // Persists the reboot count of the update attempt to |kPrefsNumReboots|. 60*5a923131SAndroid Build Coastguard Worker void SetNumReboots(int64_t num_reboots, PrefsInterface* prefs); 61*5a923131SAndroid Build Coastguard Worker 62*5a923131SAndroid Build Coastguard Worker // Persists the payload attempt number to |kPrefsPayloadAttemptNumber|. 63*5a923131SAndroid Build Coastguard Worker void SetPayloadAttemptNumber(int64_t payload_attempt_number, 64*5a923131SAndroid Build Coastguard Worker PrefsInterface* prefs); 65*5a923131SAndroid Build Coastguard Worker 66*5a923131SAndroid Build Coastguard Worker // Persists the finished time of an update to the |kPrefsSystemUpdatedMarker|. 67*5a923131SAndroid Build Coastguard Worker void SetSystemUpdatedMarker(ClockInterface* clock, PrefsInterface* prefs); 68*5a923131SAndroid Build Coastguard Worker 69*5a923131SAndroid Build Coastguard Worker // Persists the start monotonic time of an update to 70*5a923131SAndroid Build Coastguard Worker // |kPrefsUpdateTimestampStart|. 71*5a923131SAndroid Build Coastguard Worker void SetUpdateTimestampStart(const base::Time& update_start_time, 72*5a923131SAndroid Build Coastguard Worker PrefsInterface* prefs); 73*5a923131SAndroid Build Coastguard Worker 74*5a923131SAndroid Build Coastguard Worker // Persists the start boot time of an update to 75*5a923131SAndroid Build Coastguard Worker // |kPrefsUpdateBootTimestampStart|. 76*5a923131SAndroid Build Coastguard Worker void SetUpdateBootTimestampStart(const base::Time& update_start_boot_time, 77*5a923131SAndroid Build Coastguard Worker PrefsInterface* prefs); 78*5a923131SAndroid Build Coastguard Worker 79*5a923131SAndroid Build Coastguard Worker // Called at program startup if the device booted into a new update. 80*5a923131SAndroid Build Coastguard Worker // The |time_to_reboot| parameter contains the (monotonic-clock) duration 81*5a923131SAndroid Build Coastguard Worker // from when the update successfully completed (the value in 82*5a923131SAndroid Build Coastguard Worker // |kPrefsSystemUpdatedMarker|) until the device was booted into the update 83*5a923131SAndroid Build Coastguard Worker // (current monotonic-clock time). 84*5a923131SAndroid Build Coastguard Worker bool LoadAndReportTimeToReboot(MetricsReporterInterface* metrics_reporter, 85*5a923131SAndroid Build Coastguard Worker PrefsInterface* prefs, 86*5a923131SAndroid Build Coastguard Worker ClockInterface* clock); 87*5a923131SAndroid Build Coastguard Worker 88*5a923131SAndroid Build Coastguard Worker template <typename T> 89*5a923131SAndroid Build Coastguard Worker class PersistedValue { 90*5a923131SAndroid Build Coastguard Worker public: PersistedValue(std::string_view key,PrefsInterface * prefs)91*5a923131SAndroid Build Coastguard Worker PersistedValue(std::string_view key, PrefsInterface* prefs) 92*5a923131SAndroid Build Coastguard Worker : key_(key), prefs_(prefs) { 93*5a923131SAndroid Build Coastguard Worker val_ = metrics_utils::GetPersistedValue(key, prefs); 94*5a923131SAndroid Build Coastguard Worker } ~PersistedValue()95*5a923131SAndroid Build Coastguard Worker ~PersistedValue() { Flush(true); } Delete()96*5a923131SAndroid Build Coastguard Worker void Delete() { 97*5a923131SAndroid Build Coastguard Worker val_ = {}; 98*5a923131SAndroid Build Coastguard Worker prefs_->Delete(key_); 99*5a923131SAndroid Build Coastguard Worker } get()100*5a923131SAndroid Build Coastguard Worker T get() const { return val_; } 101*5a923131SAndroid Build Coastguard Worker using clock = std::chrono::system_clock; 102*5a923131SAndroid Build Coastguard Worker using time_point = clock::time_point; 103*5a923131SAndroid Build Coastguard Worker // prefix increment 104*5a923131SAndroid Build Coastguard Worker PersistedValue<T>& operator++() { 105*5a923131SAndroid Build Coastguard Worker ++val_; 106*5a923131SAndroid Build Coastguard Worker Flush(); 107*5a923131SAndroid Build Coastguard Worker return *this; 108*5a923131SAndroid Build Coastguard Worker } 109*5a923131SAndroid Build Coastguard Worker PersistedValue<T>& operator--() { 110*5a923131SAndroid Build Coastguard Worker --val_; 111*5a923131SAndroid Build Coastguard Worker Flush(); 112*5a923131SAndroid Build Coastguard Worker return *this; 113*5a923131SAndroid Build Coastguard Worker } 114*5a923131SAndroid Build Coastguard Worker PersistedValue<T>& operator+=(T&& t) { 115*5a923131SAndroid Build Coastguard Worker val_ += std::forward<T>(t); 116*5a923131SAndroid Build Coastguard Worker Flush(); 117*5a923131SAndroid Build Coastguard Worker return *this; 118*5a923131SAndroid Build Coastguard Worker } 119*5a923131SAndroid Build Coastguard Worker PersistedValue<T>& operator-=(T&& t) { 120*5a923131SAndroid Build Coastguard Worker val_ -= std::forward<T>(t); 121*5a923131SAndroid Build Coastguard Worker Flush(); 122*5a923131SAndroid Build Coastguard Worker return *this; 123*5a923131SAndroid Build Coastguard Worker } 124*5a923131SAndroid Build Coastguard Worker PersistedValue<T>& operator=(T&& t) { 125*5a923131SAndroid Build Coastguard Worker val_ = std::forward<T>(t); 126*5a923131SAndroid Build Coastguard Worker Flush(); 127*5a923131SAndroid Build Coastguard Worker return *this; 128*5a923131SAndroid Build Coastguard Worker } 129*5a923131SAndroid Build Coastguard Worker void Flush(bool force = false) { 130*5a923131SAndroid Build Coastguard Worker auto now = clock::now(); 131*5a923131SAndroid Build Coastguard Worker if (now - last_save_ > metrics::kMetricFlushInterval || force) { 132*5a923131SAndroid Build Coastguard Worker last_save_ = now; 133*5a923131SAndroid Build Coastguard Worker if (std::is_integral_v<T>) { 134*5a923131SAndroid Build Coastguard Worker prefs_->SetInt64(key_, val_); 135*5a923131SAndroid Build Coastguard Worker } else if (std::is_same_v<T, bool>) { 136*5a923131SAndroid Build Coastguard Worker prefs_->SetBoolean(key_, val_); 137*5a923131SAndroid Build Coastguard Worker } else { 138*5a923131SAndroid Build Coastguard Worker auto value = std::to_string(val_); 139*5a923131SAndroid Build Coastguard Worker prefs_->SetString(key_, value); 140*5a923131SAndroid Build Coastguard Worker } 141*5a923131SAndroid Build Coastguard Worker } 142*5a923131SAndroid Build Coastguard Worker } 143*5a923131SAndroid Build Coastguard Worker 144*5a923131SAndroid Build Coastguard Worker private: 145*5a923131SAndroid Build Coastguard Worker const std::string_view key_; 146*5a923131SAndroid Build Coastguard Worker PrefsInterface* prefs_; 147*5a923131SAndroid Build Coastguard Worker T val_; 148*5a923131SAndroid Build Coastguard Worker time_point last_save_{}; 149*5a923131SAndroid Build Coastguard Worker }; 150*5a923131SAndroid Build Coastguard Worker 151*5a923131SAndroid Build Coastguard Worker } // namespace metrics_utils 152*5a923131SAndroid Build Coastguard Worker } // namespace chromeos_update_engine 153*5a923131SAndroid Build Coastguard Worker 154*5a923131SAndroid Build Coastguard Worker #endif // UPDATE_ENGINE_METRICS_UTILS_H_ 155