diff --git a/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp b/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp index 6ab8ecec4..ce4ede8cb 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp @@ -26,8 +26,8 @@ AMS_SF_METHOD_INFO(C, H, 2, Result, SetInitialLaunchSettingsCompletionTime, (const time::SteadyClockTimePoint &time_point), (time_point), hos::Version_3_0_0) \ AMS_SF_METHOD_INFO(C, H, 3, Result, ClearInitialLaunchSettingsCompletionTime, (), (), hos::Version_3_0_0) \ AMS_SF_METHOD_INFO(C, H, 4, Result, UpdatePowerOnTime, (), (), hos::Version_3_0_0) \ - AMS_SF_METHOD_INFO(C, H, 5, Result, UpdateAwakeTime, (), (), hos::Version_3_0_0) \ - AMS_SF_METHOD_INFO(C, H, 6, Result, SubmitMultipleCategoryContext, (const erpt::MultipleCategoryContextEntry &ctx_entry, const ams::sf::InBuffer &str_buffer), (ctx_entry, str_buffer), hos::Version_5_0_0) \ + AMS_SF_METHOD_INFO(C, H, 5, Result, UpdateAwakeTime, (), (), hos::Version_3_0_0, hos::Version_12_0_0) \ + AMS_SF_METHOD_INFO(C, H, 6, Result, SubmitMultipleCategoryContext, (const erpt::MultipleCategoryContextEntry &ctx_entry, const ams::sf::InBuffer &str_buffer), (ctx_entry, str_buffer), hos::Version_5_0_0, hos::Version_12_0_0) \ AMS_SF_METHOD_INFO(C, H, 7, Result, UpdateApplicationLaunchTime, (), (), hos::Version_6_0_0) \ AMS_SF_METHOD_INFO(C, H, 8, Result, ClearApplicationLaunchTime, (), (), hos::Version_6_0_0) \ AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachment, (ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_8_0_0) \ diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp index 08d83d521..764e2b1b7 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp @@ -89,6 +89,11 @@ namespace ams::erpt::srv { Journal::Restore(); + if (hos::GetVersion() >= hos::Version_12_0_0) { + Reporter::UpdatePowerOnTime(); + Reporter::UpdateAwakeTime(); + } + return ResultSuccess(); } diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp index 0ff873e47..8d4b21690 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp @@ -36,6 +36,61 @@ namespace ams::erpt::srv { constinit os::SdkMutex g_limit_mutex; constinit bool g_submitted_limit = false; + class AppletActiveTimeInfoList { + private: + struct AppletActiveTimeInfo { + ncm::ProgramId program_id; + os::Tick register_tick; + TimeSpan suspended_duration; + }; + static constexpr AppletActiveTimeInfo InvalidAppletActiveTimeInfo = { ncm::InvalidProgramId, os::Tick{}, TimeSpan::FromNanoSeconds(0) }; + private: + std::array m_list; + public: + constexpr AppletActiveTimeInfoList() : m_list{InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo, InvalidAppletActiveTimeInfo} { + m_list.fill(InvalidAppletActiveTimeInfo); + } + public: + void Register(ncm::ProgramId program_id) { + /* Find an unused entry. */ + auto entry = util::range::find_if(m_list, [](const AppletActiveTimeInfo &info) { return info.program_id == ncm::InvalidProgramId; }); + AMS_ASSERT(entry != m_list.end()); + + /* Create the entry. */ + *entry = { program_id, os::GetSystemTick(), TimeSpan::FromNanoSeconds(0) }; + } + + void Unregister(ncm::ProgramId program_id) { + /* Find a matching entry. */ + auto entry = util::range::find_if(m_list, [&](const AppletActiveTimeInfo &info) { return info.program_id == program_id; }); + AMS_ASSERT(entry != m_list.end()); + + /* Clear the entry. */ + *entry = InvalidAppletActiveTimeInfo; + } + + void UpdateSuspendedDuration(ncm::ProgramId program_id, TimeSpan suspended_duration) { + /* Find a matching entry. */ + auto entry = util::range::find_if(m_list, [&](const AppletActiveTimeInfo &info) { return info.program_id == program_id; }); + AMS_ASSERT(entry != m_list.end()); + + /* Set the suspended duration. */ + entry->suspended_duration = suspended_duration; + } + + std::optional GetActiveDuration(ncm::ProgramId program_id) const { + /* Try to find a matching entry. */ + const auto entry = util::range::find_if(m_list, [&](const AppletActiveTimeInfo &info) { return info.program_id == program_id; }); + if (entry != m_list.end()) { + return (os::GetSystemTick() - entry->register_tick).ToTimeSpan() - entry->suspended_duration; + } else { + return std::nullopt; + } + } + }; + + constinit AppletActiveTimeInfoList g_applet_active_time_info_list; + Result PullErrorContext(size_t *out_total_size, size_t *out_size, void *dst, size_t dst_size, const err::ContextDescriptor &descriptor, Result result) { s32 unk0; u32 total_size, size; @@ -258,9 +313,9 @@ namespace ams::erpt::srv { SubmitErrorContext(record.get(), this->ctx_result); } - record->Add(FieldId_OsVersion, s_os_version, strnlen(s_os_version, sizeof(s_os_version))); - record->Add(FieldId_PrivateOsVersion, s_private_os_version, strnlen(s_private_os_version, sizeof(s_private_os_version))); - record->Add(FieldId_SerialNumber, s_serial_number, strnlen(s_serial_number, sizeof(s_serial_number))); + record->Add(FieldId_OsVersion, s_os_version, util::Strnlen(s_os_version, sizeof(s_os_version))); + record->Add(FieldId_PrivateOsVersion, s_private_os_version, util::Strnlen(s_private_os_version, sizeof(s_private_os_version))); + record->Add(FieldId_SerialNumber, s_serial_number, util::Strnlen(s_serial_number, sizeof(s_serial_number))); record->Add(FieldId_ReportIdentifier, this->identifier_str, sizeof(this->identifier_str)); record->Add(FieldId_OccurrenceTimestamp, this->timestamp_user.value); record->Add(FieldId_OccurrenceTimestampNet, this->timestamp_network.value); @@ -281,13 +336,15 @@ namespace ams::erpt::srv { } if (s_awake_time) { - record->Add(FieldId_ElapsedTimeSincePowerOn, (this->occurrence_tick - *s_awake_time).ToTimeSpan().GetSeconds()); + record->Add(FieldId_ElapsedTimeSinceLastAwake, (this->occurrence_tick - *s_awake_time).ToTimeSpan().GetSeconds()); } if (s_application_launch_time) { record->Add(FieldId_ApplicationAliveTime, (this->occurrence_tick - *s_application_launch_time).ToTimeSpan().GetSeconds()); } + /* TODO: Add FieldId_AppletTotalActiveTime. */ + R_TRY(Context::SubmitContextRecord(std::move(record))); R_TRY(Context::SubmitContext(this->ctx, this->data, this->data_size));