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