• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 #include "work_conn_manager.h"
16 
17 #include <hisysevent.h>
18 #include <if_system_ability_manager.h>
19 #include <ipc_skeleton.h>
20 #include <iservice_registry.h>
21 #include <string_ex.h>
22 #include <system_ability_definition.h>
23 
24 #include "ability_manager_client.h"
25 #include "ability_manager_proxy.h"
26 #include "work_sched_hilog.h"
27 #include "work_sched_utils.h"
28 #include "errors.h"
29 #include <cinttypes>
30 #include "work_sched_constants.h"
31 #include "work_sched_hisysevent_report.h"
32 
33 #ifdef DEVICE_STANDBY_ENABLE
34 #include "standby_service_client.h"
35 #endif // DEVICE_STANDBY_ENABLE
36 
37 using namespace std;
38 using namespace OHOS::AAFwk;
39 using namespace OHOS::HiviewDFX;
40 
41 namespace OHOS {
42 namespace WorkScheduler {
43 const std::string PARAM_APP_CLONE_INDEX_KEY = "ohos.extra.param.key.appCloneIndex";
44 
AddConnInfo(const string & workId,sptr<WorkSchedulerConnection> & connection)45 void WorkConnManager::AddConnInfo(const string &workId, sptr<WorkSchedulerConnection> &connection)
46 {
47     std::lock_guard<ffrt::mutex> lock(connMapMutex_);
48     connMap_.emplace(workId, connection);
49 }
50 
RemoveConnInfo(const string & workId)51 void WorkConnManager::RemoveConnInfo(const string &workId)
52 {
53     std::lock_guard<ffrt::mutex> lock(connMapMutex_);
54     connMap_.erase(workId);
55 }
56 
GetConnInfo(const string & workId)57 sptr<WorkSchedulerConnection> WorkConnManager::GetConnInfo(const string &workId)
58 {
59     std::lock_guard<ffrt::mutex> lock(connMapMutex_);
60     if (connMap_.count(workId) > 0) {
61         return connMap_.at(workId);
62     }
63     return nullptr;
64 }
65 
StartWork(shared_ptr<WorkStatus> workStatus)66 bool WorkConnManager::StartWork(shared_ptr<WorkStatus> workStatus)
67 {
68     sptr<WorkSchedulerConnection> conn = GetConnInfo(workStatus->workId_);
69     if (conn) {
70         WS_HILOGE("Work has started with id: %{public}s, bundleName: %{public}s, abilityName: %{public}s",
71             workStatus->workId_.c_str(), workStatus->bundleName_.c_str(), workStatus->abilityName_.c_str());
72         WorkSchedUtil::HiSysEventException(EventErrorCode::CONNECT_ABILITY, "connect info has existed, connect failed");
73         RemoveConnInfo(workStatus->workId_);
74         if (conn->IsConnected()) {
75             conn->StopWork();
76             DisConnect(conn);
77         }
78     }
79 
80     if (!workStatus->workInfo_->GetExtension()) {
81         WS_HILOGE("%{public}s extension's type is not workScheduler, connect failed", workStatus->bundleName_.c_str());
82         WorkSchedUtil::HiSysEventException(EventErrorCode::CONNECT_ABILITY,
83             "app extension's type is not workScheduler");
84         return false;
85     }
86 
87     WS_HILOGI("Begin to connect bundle:%{public}s, abilityName:%{public}s, workId:%{public}s",
88         workStatus->bundleName_.c_str(), workStatus->abilityName_.c_str(), workStatus->workId_.c_str());
89     sptr<AAFwk::IAbilityManager> abilityMgr_ = GetSystemAbilityManager(CONNECT_ABILITY);
90     if (abilityMgr_ == nullptr) {
91         return false;
92     }
93     sptr<WorkSchedulerConnection> connection(new (std::nothrow) WorkSchedulerConnection(workStatus->workInfo_));
94     if (connection == nullptr) {
95         WS_HILOGE("Failed to new connection.");
96         WorkSchedUtil::HiSysEventException(EventErrorCode::CONNECT_ABILITY, "create connection failed");
97         return false;
98     }
99 
100     Want want;
101     want.SetElementName(workStatus->bundleName_, workStatus->abilityName_);
102     want.SetParam(PARAM_APP_CLONE_INDEX_KEY, workStatus->workInfo_->GetAppIndex());
103     int32_t ret = abilityMgr_->ConnectAbility(want, connection, nullptr, workStatus->userId_);
104     if (ret != ERR_OK) {
105         WS_HILOGE("connect failed, ret: %{public}d", ret);
106         WorkSchedUtil::HiSysEventException(EventErrorCode::CONNECT_ABILITY, "connect system ability failed");
107         return false;
108     }
109     AddConnInfo(workStatus->workId_, connection);
110 
111     // Notify work add event to battery statistics
112     WriteStartWorkEvent(workStatus);
113 
114     return true;
115 }
116 
DisConnect(sptr<WorkSchedulerConnection> connect)117 bool WorkConnManager::DisConnect(sptr<WorkSchedulerConnection> connect)
118 {
119     sptr<AAFwk::IAbilityManager> abilityMgr_ = GetSystemAbilityManager(DISCONNECT_ABILITY);
120     if (abilityMgr_ == nullptr) {
121         return false;
122     }
123     int32_t ret = abilityMgr_->DisconnectAbility(connect);
124     if (ret != ERR_OK) {
125         WS_HILOGE("disconnect failed, ret: %{public}d", ret);
126         WorkSchedUtil::HiSysEventException(EventErrorCode::DISCONNECT_ABILITY, "disconnect system ability failed");
127         return false;
128     }
129     return true;
130 }
131 
StopWork(shared_ptr<WorkStatus> workStatus,bool isTimeOut)132 bool WorkConnManager::StopWork(shared_ptr<WorkStatus> workStatus, bool isTimeOut)
133 {
134     bool ret = false;
135     sptr<WorkSchedulerConnection> conn = GetConnInfo(workStatus->workId_);
136     if (!conn) {
137         WS_HILOGE("%{public}s %{public}d connection is null", workStatus->workId_.c_str(), isTimeOut);
138         return false;
139     }
140     if (!conn->IsConnected()) {
141         WS_HILOGE("%{public}s %{public}d is not connected, work will be stopped  by timeout",
142             workStatus->workId_.c_str(), isTimeOut);
143         return false;
144     }
145     conn->StopWork();
146     ret = DisConnect(conn);
147 
148     RemoveConnInfo(workStatus->workId_);
149 
150     // Notify work remove event to battery statistics only work has started
151     if (ret) {
152         int32_t pid = IPCSkeleton::GetCallingPid();
153         workStatus->duration_ += WorkSchedUtils::GetCurrentTimeMs() - workStatus->workStartTime_;
154         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::WORK_SCHEDULER, "WORK_STOP",
155             HiSysEvent::EventType::STATISTIC, "UID",
156             workStatus->uid_, "PID", pid, "NAME", workStatus->bundleName_, "WORKID", workStatus->workId_,
157             "REASON", isTimeOut, "DURATION", workStatus->duration_);
158 #ifdef DEVICE_STANDBY_ENABLE
159         WS_HILOGI("OnWorkStop uid: %{public}d, duration:%{public}" PRIu64 ", startTime:%{public}" PRIu64,
160             workStatus->uid_, workStatus->duration_, workStatus->workStartTime_);
161         DevStandbyMgr::StandbyServiceClient::GetInstance().ReportWorkSchedulerStatus(false,
162             workStatus->uid_, workStatus->bundleName_);
163 #endif // DEVICE_STANDBY_ENABLE
164     }
165     return ret;
166 }
167 
WriteStartWorkEvent(shared_ptr<WorkStatus> workStatus)168 void WorkConnManager::WriteStartWorkEvent(shared_ptr<WorkStatus> workStatus)
169 {
170     int32_t pid = IPCSkeleton::GetCallingPid();
171     string conditions = "";
172     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::NETWORK) > 0) {
173         conditions.append("NETWORK-");
174     }
175 
176     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::CHARGER) > 0) {
177         conditions.append("CHARGER-");
178     }
179 
180     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_STATUS) > 0) {
181         conditions.append("BATTERY_STATUS-");
182     }
183 
184     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::BATTERY_LEVEL) > 0) {
185         conditions.append("BATTERY_LEVEL-");
186     }
187 
188     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::STORAGE) > 0) {
189         conditions.append("STORAGE-");
190     }
191 
192     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
193         conditions.append("TIMER-");
194     }
195 
196     if (workStatus->workInfo_->GetConditionMap()->count(WorkCondition::Type::DEEP_IDLE) > 0) {
197         conditions.append("DEEP_IDLE-");
198     }
199     conditions.pop_back();
200 
201     string type = "Repeat";
202     if (!workStatus->workInfo_->IsRepeat()) {
203         type = "Not Repeat";
204     }
205     if (!workStatus->workInfo_->GetIsInnerApply()) {
206         type = "inner apply" + type;
207     }
208 
209     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::WORK_SCHEDULER, "WORK_START",
210         HiSysEvent::EventType::STATISTIC, "UID",
211         workStatus->uid_, "PID", pid, "NAME", workStatus->bundleName_, "WORKID", workStatus->workId_, "TRIGGER",
212         conditions, "TYPE", type, "INTERVAL", workStatus->workInfo_->GetTimeInterval(),
213         "DELAY_REASON", workStatus->delayReason_);
214 #ifdef DEVICE_STANDBY_ENABLE
215     WS_HILOGI("OnWorkStart uid: %{public}d", workStatus->uid_);
216     DevStandbyMgr::StandbyServiceClient::GetInstance().ReportWorkSchedulerStatus(true,
217         workStatus->uid_, workStatus->bundleName_);
218 #endif // DEVICE_STANDBY_ENABLE
219 }
220 
GetSystemAbilityManager(int32_t errCode)221 sptr<AAFwk::IAbilityManager> WorkConnManager::GetSystemAbilityManager(int32_t errCode)
222 {
223     sptr<ISystemAbilityManager> systemAbilityManager =
224         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
225     if (systemAbilityManager == nullptr) {
226         WS_HILOGE("Failed to get system ability manager service.");
227         WorkSchedUtil::HiSysEventException(errCode, "get system ability manager failed");
228         return nullptr;
229     }
230     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
231     if (remoteObject == nullptr) {
232         WS_HILOGE("Failed to get system ability.");
233         WorkSchedUtil::HiSysEventException(errCode, "get system ability failed");
234         return nullptr;
235     }
236     sptr<AAFwk::IAbilityManager> abilityMgr_ = iface_cast<AAFwk::IAbilityManager>(remoteObject);
237     if ((abilityMgr_ == nullptr) || (abilityMgr_->AsObject() == nullptr)) {
238         WS_HILOGE("Failed to get ability manager services object");
239         WorkSchedUtil::HiSysEventException(errCode, "cast system ability failed");
240         return nullptr;
241     }
242     return abilityMgr_;
243 }
244 } // namespace WorkScheduler
245 } // namespace OHOS
246