• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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