1 /*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "app_startup_scene_rec.h"
17
18 #include "res_sched_log.h"
19 #include "res_sched_mgr.h"
20 #include "res_type.h"
21
22 namespace OHOS {
23 namespace ResourceSchedule {
24 static const int32_t CONTINUOUS_START_TIME_OUT = 15 * 1000 * 1000;
25 static const int32_t MAX_NO_REPEAT_APP_COUNT = 4;
26 static const int32_t MAX_CONTINUOUS_START_NUM = 5;
27 static const int32_t APP_START_UP = 0;
28 static const std::string RUNNER_NAME = "AppStartupSceneRecQueue";
AppStartupSceneRec()29 AppStartupSceneRec::AppStartupSceneRec()
30 {
31 }
~AppStartupSceneRec()32 AppStartupSceneRec::~AppStartupSceneRec()
33 {
34 }
Init()35 void AppStartupSceneRec::Init()
36 {
37 ffrtQueue_ = std::make_shared<ffrt::queue>(RUNNER_NAME.c_str(),
38 ffrt::queue_attr().qos(ffrt::qos_user_initiated));
39 }
Deinit()40 void AppStartupSceneRec::Deinit()
41 {
42 std::lock_guard<ffrt::mutex> lock(mutex_);
43 if (exitContinuousStartupTask != nullptr) {
44 ffrtQueue_->cancel(exitContinuousStartupTask);
45 exitContinuousStartupTask = nullptr;
46 }
47 ffrtQueue_.reset();
48 startPkgs_.clear();
49 startUidSet_.clear();
50 }
GetInstance()51 AppStartupSceneRec& AppStartupSceneRec::GetInstance()
52 {
53 static AppStartupSceneRec instance;
54 return instance;
55 }
56
IsAppStartUp(int32_t abilityState)57 bool AppStartupSceneRec::IsAppStartUp(int32_t abilityState)
58 {
59 return abilityState == APP_START_UP;
60 }
61
RecordIsContinuousStartup(const std::string & uid,const std::string & bundleName)62 void AppStartupSceneRec::RecordIsContinuousStartup(const std::string& uid, const std::string& bundleName)
63 {
64 auto tarEndTimePoint = std::chrono::steady_clock::now();
65 auto tarDuration = std::chrono::duration_cast<std::chrono::microseconds>(tarEndTimePoint.time_since_epoch());
66 int64_t curTime = tarDuration.count();
67 std::lock_guard<ffrt::mutex> lock(mutex_);
68 if (ffrtQueue_ == nullptr) {
69 return;
70 }
71 if (exitContinuousStartupTask != nullptr) {
72 ffrtQueue_->cancel(exitContinuousStartupTask);
73 exitContinuousStartupTask = nullptr;
74 }
75 if (curTime - lastAppStartTime_ >= CONTINUOUS_START_TIME_OUT) {
76 CleanRecordSceneData();
77 }
78 UpdateAppStartupNum(uid, curTime, bundleName);
79 if (IsContinuousStartup() && !isReportContinuousStartup_.load()) {
80 nlohmann::json payload;
81 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_CONTINUOUS_STARTUP,
82 ResType::ContinuousStartupStatus::START_CONTINUOUS_STARTUP, payload);
83 isReportContinuousStartup_ = true;
84 }
85 exitContinuousStartupTask = ffrtQueue_->submit_h([this] {
86 std::lock_guard<ffrt::mutex> lock(mutex_);
87 CleanRecordSceneData();
88 }, ffrt::task_attr().delay(CONTINUOUS_START_TIME_OUT));
89 }
CleanRecordSceneData()90 void AppStartupSceneRec::CleanRecordSceneData()
91 {
92 RESSCHED_LOGI("CleanRecordSceneData");
93 appStartCount_ = 0;
94 startPkgs_.clear();
95 startUidSet_.clear();
96 exitContinuousStartupTask = nullptr;
97 if (isReportContinuousStartup_.load()) {
98 nlohmann::json payload;
99 ResSchedMgr::GetInstance().ReportData(
100 ResType::RES_TYPE_CONTINUOUS_STARTUP, ResType::ContinuousStartupStatus::STOP_CONTINUOUS_STARTUP, payload);
101 isReportContinuousStartup_ = false;
102 }
103 }
UpdateAppStartupNum(std::string uid,int64_t curTime,std::string bundleName)104 void AppStartupSceneRec::UpdateAppStartupNum(std::string uid, int64_t curTime, std::string bundleName)
105 {
106 lastAppStartTime_ = curTime;
107 appStartCount_++;
108 if (isReportContinuousStartup_.load()) {
109 RESSCHED_LOGD("UpdateAppStartupNum appStartCount_:%{public}d", appStartCount_);
110 return;
111 }
112 startPkgs_.emplace_back(bundleName);
113 startUidSet_.insert(uid);
114 }
IsContinuousStartup()115 bool AppStartupSceneRec::IsContinuousStartup()
116 {
117 if (startPkgs_.size() >= MAX_CONTINUOUS_START_NUM && startUidSet_.size() >= MAX_NO_REPEAT_APP_COUNT) {
118 return true;
119 }
120 return false;
121 }
122 }
123 }