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