1 /*
2 * Copyright (c) 2021-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
16 #include "mission_info_mgr.h"
17
18 #include "ability_manager_service.h"
19 #include "hilog_wrapper.h"
20 #include "nlohmann/json.hpp"
21 #ifdef SUPPORT_GRAPHICS
22 #include "pixel_map.h"
23 #include "securec.h"
24 #endif
25
26 namespace OHOS {
27 namespace AAFwk {
MissionInfoMgr()28 MissionInfoMgr::MissionInfoMgr()
29 {
30 HILOG_INFO("MissionInfoMgr instance is created");
31 }
32
~MissionInfoMgr()33 MissionInfoMgr::~MissionInfoMgr()
34 {
35 HILOG_INFO("MissionInfoMgr instance is destroyed");
36 }
37
GenerateMissionId(int32_t & missionId)38 bool MissionInfoMgr::GenerateMissionId(int32_t &missionId)
39 {
40 std::lock_guard<std::recursive_mutex> lock(mutex_);
41 if (currentMissionId_ == MAX_MISSION_ID) {
42 currentMissionId_ = MIN_MISSION_ID;
43 }
44
45 for (int32_t index = currentMissionId_; index < MAX_MISSION_ID; index++) {
46 if (missionIdMap_.find(index) == missionIdMap_.end()) {
47 missionId = index;
48 missionIdMap_[missionId] = false;
49 currentMissionId_ = missionId + 1;
50 return true;
51 }
52 }
53
54 HILOG_ERROR("cannot generate mission id");
55 return false;
56 }
57
Init(int userId)58 bool MissionInfoMgr::Init(int userId)
59 {
60 std::lock_guard<std::recursive_mutex> lock(mutex_);
61 if (!taskDataPersistenceMgr_) {
62 taskDataPersistenceMgr_ = DelayedSingleton<TaskDataPersistenceMgr>::GetInstance();
63 if (!taskDataPersistenceMgr_) {
64 HILOG_ERROR("taskDataPersistenceMgr_ is nullptr");
65 return false;
66 }
67 }
68
69 if (!taskDataPersistenceMgr_->Init(userId)) {
70 return false;
71 }
72
73 missionInfoList_.clear();
74 missionIdMap_.clear();
75 if (!LoadAllMissionInfo()) {
76 return false;
77 }
78
79 return true;
80 }
81
AddMissionInfo(const InnerMissionInfo & missionInfo)82 bool MissionInfoMgr::AddMissionInfo(const InnerMissionInfo &missionInfo)
83 {
84 std::lock_guard<std::recursive_mutex> lock(mutex_);
85 auto id = missionInfo.missionInfo.id;
86 if (missionIdMap_.find(id) != missionIdMap_.end() && missionIdMap_[id]) {
87 HILOG_ERROR("add mission info failed, missionId %{public}d already exists", id);
88 return false;
89 }
90
91 auto listIter = missionInfoList_.begin();
92 for (; listIter != missionInfoList_.end(); listIter++) {
93 if (listIter->missionInfo.time < missionInfo.missionInfo.time) {
94 break; // first listIter->time < missionInfo.time
95 }
96 }
97
98 if (!taskDataPersistenceMgr_->SaveMissionInfo(missionInfo)) {
99 HILOG_ERROR("save mission info failed");
100 return false;
101 }
102
103 missionInfoList_.insert(listIter, missionInfo);
104 missionIdMap_[id] = true;
105 return true;
106 }
107
UpdateMissionInfo(const InnerMissionInfo & missionInfo)108 bool MissionInfoMgr::UpdateMissionInfo(const InnerMissionInfo &missionInfo)
109 {
110 std::lock_guard<std::recursive_mutex> lock(mutex_);
111 auto id = missionInfo.missionInfo.id;
112 if (missionIdMap_.find(id) == missionIdMap_.end() || !missionIdMap_[id]) {
113 HILOG_ERROR("update mission info failed, missionId %{public}d not exists", id);
114 return false;
115 }
116
117 auto listIter = missionInfoList_.begin();
118 for (; listIter != missionInfoList_.end(); listIter++) {
119 if (listIter->missionInfo.id == id) {
120 break;
121 }
122 }
123
124 if (listIter == missionInfoList_.end()) {
125 HILOG_ERROR("update mission info failed, missionId %{public}d not exists", id);
126 return false;
127 }
128
129 if (missionInfo.missionInfo.time == listIter->missionInfo.time) {
130 // time not changes, no need sort again
131 *listIter = missionInfo;
132 if (!taskDataPersistenceMgr_->SaveMissionInfo(missionInfo)) {
133 HILOG_ERROR("save mission info failed.");
134 return false;
135 }
136 return true;
137 }
138
139 missionInfoList_.erase(listIter);
140 missionIdMap_.erase(id);
141 return AddMissionInfo(missionInfo);
142 }
143
DeleteMissionInfo(int missionId)144 bool MissionInfoMgr::DeleteMissionInfo(int missionId)
145 {
146 std::lock_guard<std::recursive_mutex> lock(mutex_);
147 if (missionIdMap_.find(missionId) == missionIdMap_.end()) {
148 HILOG_WARN("missionId %{public}d not exists, no need delete", missionId);
149 return true;
150 }
151
152 if (!missionIdMap_[missionId]) {
153 HILOG_WARN("missionId %{public}d distributed but not saved, no need delete", missionId);
154 missionIdMap_.erase(missionId);
155 return true;
156 }
157
158 if (!taskDataPersistenceMgr_) {
159 HILOG_ERROR("taskDataPersistenceMgr_ is nullptr");
160 return false;
161 }
162
163 if (!taskDataPersistenceMgr_->DeleteMissionInfo(missionId)) {
164 HILOG_ERROR("delete mission info failed");
165 return false;
166 }
167
168 for (auto listIter = missionInfoList_.begin(); listIter != missionInfoList_.end(); listIter++) {
169 if (listIter->missionInfo.id == missionId) {
170 missionInfoList_.erase(listIter);
171 break;
172 }
173 }
174
175 missionIdMap_.erase(missionId);
176 return true;
177 }
178
DeleteAllMissionInfos(const std::shared_ptr<MissionListenerController> & listenerController)179 bool MissionInfoMgr::DeleteAllMissionInfos(const std::shared_ptr<MissionListenerController> &listenerController)
180 {
181 std::lock_guard<std::recursive_mutex> lock(mutex_);
182 if (!taskDataPersistenceMgr_) {
183 HILOG_ERROR("taskDataPersistenceMgr_ is nullptr");
184 return false;
185 }
186
187 auto abilityMs_ = OHOS::DelayedSingleton<AbilityManagerService>::GetInstance();
188
189 for (auto listIter = missionInfoList_.begin(); listIter != missionInfoList_.end();) {
190 if (!((listIter->missionInfo.lockedState) || (abilityMs_->IsBackgroundTaskUid(listIter->uid)))) {
191 missionIdMap_.erase(listIter->missionInfo.id);
192 taskDataPersistenceMgr_->DeleteMissionInfo(listIter->missionInfo.id);
193 if (listenerController) {
194 listenerController->NotifyMissionDestroyed(listIter->missionInfo.id);
195 }
196 missionInfoList_.erase(listIter++);
197 } else {
198 ++listIter;
199 }
200 }
201 return true;
202 }
203
DoesNotShowInTheMissionList(const InnerMissionInfo & mission)204 static bool DoesNotShowInTheMissionList(const InnerMissionInfo &mission)
205 {
206 bool isStartByCall = false;
207 switch (static_cast<StartMethod>(mission.startMethod)) {
208 case StartMethod::START_CALL:
209 isStartByCall = true;
210 break;
211 default:
212 isStartByCall = false;
213 }
214 return (isStartByCall && !mission.missionInfo.want.GetBoolParam(Want::PARAM_RESV_CALL_TO_FOREGROUND, false));
215 }
216
GetMissionInfos(int32_t numMax,std::vector<MissionInfo> & missionInfos)217 int MissionInfoMgr::GetMissionInfos(int32_t numMax, std::vector<MissionInfo> &missionInfos)
218 {
219 HILOG_INFO("GetMissionInfos, numMax:%{public}d", numMax);
220 if (numMax < 0) {
221 return -1;
222 }
223
224 std::lock_guard<std::recursive_mutex> lock(mutex_);
225 for (auto &mission : missionInfoList_) {
226 if (static_cast<int>(missionInfos.size()) >= numMax) {
227 break;
228 }
229
230 if (DoesNotShowInTheMissionList(mission)) {
231 HILOG_INFO("MissionId[%{public}d] don't show in mission list", mission.missionInfo.id);
232 continue;
233 }
234 MissionInfo info = mission.missionInfo;
235 missionInfos.emplace_back(info);
236 }
237
238 return 0;
239 }
240
GetMissionInfoById(int32_t missionId,MissionInfo & missionInfo)241 int MissionInfoMgr::GetMissionInfoById(int32_t missionId, MissionInfo &missionInfo)
242 {
243 HILOG_INFO("GetMissionInfoById, missionId:%{public}d", missionId);
244 std::lock_guard<std::recursive_mutex> lock(mutex_);
245 if (missionIdMap_.find(missionId) == missionIdMap_.end()) {
246 HILOG_ERROR("missionId %{public}d not exists, get mission info failed", missionId);
247 return -1;
248 }
249
250 auto it = std::find_if(missionInfoList_.begin(), missionInfoList_.end(),
251 [&missionId](const InnerMissionInfo item) {
252 return item.missionInfo.id == missionId;
253 }
254 );
255 if (it == missionInfoList_.end()) {
256 HILOG_ERROR("no such mission:%{public}d", missionId);
257 return -1;
258 }
259
260 if (DoesNotShowInTheMissionList(*it)) {
261 HILOG_INFO("MissionId[%{public}d] don't show in mission list", (*it).missionInfo.id);
262 return -1;
263 }
264
265 HILOG_INFO("GetMissionInfoById, find missionId missionId:%{public}d", missionId);
266 missionInfo = (*it).missionInfo;
267 return 0;
268 }
269
GetInnerMissionInfoById(int32_t missionId,InnerMissionInfo & innerMissionInfo)270 int MissionInfoMgr::GetInnerMissionInfoById(int32_t missionId, InnerMissionInfo &innerMissionInfo)
271 {
272 std::lock_guard<std::recursive_mutex> lock(mutex_);
273 if (missionIdMap_.find(missionId) == missionIdMap_.end()) {
274 HILOG_ERROR("missionId %{public}d not exists, get inner mission info failed", missionId);
275 return MISSION_NOT_FOUND;
276 }
277
278 auto it = std::find_if(missionInfoList_.begin(), missionInfoList_.end(),
279 [&missionId](const InnerMissionInfo item) {
280 return item.missionInfo.id == missionId;
281 }
282 );
283 if (it == missionInfoList_.end()) {
284 HILOG_ERROR("no such mission:%{public}d", missionId);
285 return MISSION_NOT_FOUND;
286 }
287 innerMissionInfo = *it;
288 return 0;
289 }
290
FindReusedMissionInfo(const std::string & missionName,const std::string & flag,bool isFindRecentStandard,InnerMissionInfo & info)291 bool MissionInfoMgr::FindReusedMissionInfo(const std::string &missionName,
292 const std::string &flag, bool isFindRecentStandard, InnerMissionInfo &info)
293 {
294 if (missionName.empty()) {
295 return false;
296 }
297
298
299
300 std::lock_guard<std::recursive_mutex> lock(mutex_);
301 auto it = std::find_if(missionInfoList_.begin(), missionInfoList_.end(),
302 [&missionName, &flag, &isFindRecentStandard](const InnerMissionInfo item) {
303 if (missionName != item.missionName) {
304 return false;
305 }
306
307 // already sorted, return head of list
308 if (isFindRecentStandard && item.launchMode == static_cast<int32_t>(AppExecFwk::LaunchMode::STANDARD)) {
309 return true;
310 }
311
312 if (item.launchMode == static_cast<int32_t>(AppExecFwk::LaunchMode::SINGLETON)) {
313 return true;
314 }
315
316 if (item.launchMode == static_cast<int32_t>(AppExecFwk::LaunchMode::SPECIFIED)) {
317 return flag == item.specifiedFlag;
318 }
319 return false;
320 }
321 );
322 if (it == missionInfoList_.end()) {
323 HILOG_WARN("can not find target singleton mission:%{public}s", missionName.c_str());
324 return false;
325 }
326 info = *it;
327 return true;
328 }
329
UpdateMissionLabel(int32_t missionId,const std::string & label)330 int MissionInfoMgr::UpdateMissionLabel(int32_t missionId, const std::string& label)
331 {
332 std::lock_guard<std::recursive_mutex> lock(mutex_);
333 if (!taskDataPersistenceMgr_) {
334 HILOG_ERROR("task data persist not init.");
335 return -1;
336 }
337 auto it = find_if(missionInfoList_.begin(), missionInfoList_.end(), [missionId](const InnerMissionInfo &info) {
338 return missionId == info.missionInfo.id;
339 });
340 if (it == missionInfoList_.end()) {
341 HILOG_ERROR("UpdateMissionLabel failed, missionId %{public}d not exists", missionId);
342 return -1;
343 }
344
345 it->missionInfo.label = label;
346 if (!taskDataPersistenceMgr_->SaveMissionInfo(*it)) {
347 HILOG_ERROR("save mission info failed.");
348 return -1;
349 }
350 return 0;
351 }
352
LoadAllMissionInfo()353 bool MissionInfoMgr::LoadAllMissionInfo()
354 {
355 std::lock_guard<std::recursive_mutex> lock(mutex_);
356 if (!taskDataPersistenceMgr_) {
357 HILOG_ERROR("taskDataPersistenceMgr_ is nullptr");
358 return false;
359 }
360
361 if (!taskDataPersistenceMgr_->LoadAllMissionInfo(missionInfoList_)) {
362 HILOG_ERROR("load mission info failed");
363 return false;
364 }
365
366 // sort by time
367 auto cmpFunc = [] (const InnerMissionInfo &infoBase, const InnerMissionInfo &infoCmp) {
368 return infoBase.missionInfo.time > infoCmp.missionInfo.time;
369 };
370 missionInfoList_.sort(cmpFunc);
371
372 for (const auto &info : missionInfoList_) {
373 missionIdMap_[info.missionInfo.id] = true;
374 }
375 return true;
376 }
377
HandleUnInstallApp(const std::string & bundleName,int32_t uid,std::list<int32_t> & missions)378 void MissionInfoMgr::HandleUnInstallApp(const std::string &bundleName, int32_t uid, std::list<int32_t> &missions)
379 {
380 HILOG_INFO("HandleUnInstallApp, bundleName:%{public}s, uid:%{public}d", bundleName.c_str(), uid);
381 GetMatchedMission(bundleName, uid, missions);
382 if (missions.empty()) {
383 return;
384 }
385
386 for (auto missionId : missions) {
387 DeleteMissionInfo(missionId);
388 }
389 }
390
GetMatchedMission(const std::string & bundleName,int32_t uid,std::list<int32_t> & missions)391 void MissionInfoMgr::GetMatchedMission(const std::string &bundleName, int32_t uid, std::list<int32_t> &missions)
392 {
393 std::lock_guard<std::recursive_mutex> lock(mutex_);
394 for (const auto& innerMissionInfo : missionInfoList_) {
395 if (innerMissionInfo.bundleName == bundleName && innerMissionInfo.uid == uid) {
396 missions.push_back(innerMissionInfo.missionInfo.id);
397 }
398 }
399 }
400
Dump(std::vector<std::string> & info)401 void MissionInfoMgr::Dump(std::vector<std::string> &info)
402 {
403 std::lock_guard<std::recursive_mutex> lock(mutex_);
404 for (const auto& innerMissionInfo : missionInfoList_) {
405 innerMissionInfo.Dump(info);
406 }
407 }
408
RegisterSnapshotHandler(const sptr<ISnapshotHandler> & handler)409 void MissionInfoMgr::RegisterSnapshotHandler(const sptr<ISnapshotHandler>& handler)
410 {
411 std::lock_guard<std::recursive_mutex> lock(mutex_);
412 snapshotHandler_ = handler;
413 }
414
UpdateMissionSnapshot(int32_t missionId,const sptr<IRemoteObject> & abilityToken,MissionSnapshot & missionSnapshot,bool isLowResolution)415 bool MissionInfoMgr::UpdateMissionSnapshot(int32_t missionId, const sptr<IRemoteObject>& abilityToken,
416 MissionSnapshot& missionSnapshot, bool isLowResolution)
417 {
418 HILOG_INFO("Update mission snapshot, missionId:%{public}d.", missionId);
419 std::lock_guard<std::recursive_mutex> lock(mutex_);
420 auto it = find_if(missionInfoList_.begin(), missionInfoList_.end(), [missionId](const InnerMissionInfo &info) {
421 return missionId == info.missionInfo.id;
422 });
423 if (it == missionInfoList_.end()) {
424 HILOG_ERROR("snapshot: get mission failed, missionId %{public}d not exists", missionId);
425 return false;
426 }
427 if (!snapshotHandler_) {
428 HILOG_ERROR("snapshot: snapshotHandler_ is nullptr");
429 return false;
430 }
431 Snapshot snapshot;
432 int32_t result = snapshotHandler_->GetSnapshot(abilityToken, snapshot);
433 if (result != 0) {
434 HILOG_ERROR("snapshot: get WMS snapshot failed, result = %{public}d", result);
435 return false;
436 }
437 if (!taskDataPersistenceMgr_) {
438 HILOG_ERROR("snapshot: taskDataPersistenceMgr_ is nullptr");
439 return false;
440 }
441
442 #ifdef SUPPORT_GRAPHICS
443 if (missionSnapshot.isPrivate) {
444 CreateWhitePixelMap(snapshot);
445 }
446 missionSnapshot.snapshot = isLowResolution ?
447 MissionDataStorage::GetReducedPixelMap(snapshot.GetPixelMap()) : snapshot.GetPixelMap();
448 #endif
449 missionSnapshot.topAbility = it->missionInfo.want.GetElement();
450
451 MissionSnapshot savedSnapshot = missionSnapshot;
452 #ifdef SUPPORT_GRAPHICS
453 savedSnapshot.snapshot = snapshot.GetPixelMap();
454 #endif
455 {
456 std::lock_guard<std::mutex> lock(savingSnapshotLock_);
457 auto search = savingSnapshot_.find(missionId);
458 if (search == savingSnapshot_.end()) {
459 savingSnapshot_[missionId] = 1;
460 } else {
461 auto savingCount = search->second + 1;
462 savingSnapshot_.insert_or_assign(missionId, savingCount);
463 }
464 }
465 if (!taskDataPersistenceMgr_->SaveMissionSnapshot(missionId, savedSnapshot)) {
466 HILOG_ERROR("snapshot: save mission snapshot failed");
467 CompleteSaveSnapshot(missionId);
468 return false;
469 }
470 HILOG_INFO("snapshot: update mission snapshot success");
471 return true;
472 }
473
CompleteSaveSnapshot(int32_t missionId)474 void MissionInfoMgr::CompleteSaveSnapshot(int32_t missionId)
475 {
476 std::unique_lock<std::mutex> lock(savingSnapshotLock_);
477 auto search = savingSnapshot_.find(missionId);
478 if (search != savingSnapshot_.end()) {
479 auto savingCount = search->second - 1;
480 if (savingCount == 0) {
481 savingSnapshot_.erase(search);
482 waitSavingCondition_.notify_one();
483 } else {
484 savingSnapshot_.insert_or_assign(missionId, savingCount);
485 }
486 }
487 }
488
489 #ifdef SUPPORT_GRAPHICS
GetSnapshot(int32_t missionId) const490 std::shared_ptr<Media::PixelMap> MissionInfoMgr::GetSnapshot(int32_t missionId) const
491 {
492 HILOG_INFO("mission_list_info GetSnapshot, missionId:%{public}d", missionId);
493 auto it = find_if(missionInfoList_.begin(), missionInfoList_.end(), [missionId](const InnerMissionInfo &info) {
494 return missionId == info.missionInfo.id;
495 });
496 if (it == missionInfoList_.end()) {
497 HILOG_ERROR("snapshot: get mission failed, missionId %{public}d not exists", missionId);
498 return nullptr;
499 }
500 if (!taskDataPersistenceMgr_) {
501 HILOG_ERROR("snapshot: taskDataPersistenceMgr_ is nullptr");
502 return nullptr;
503 }
504
505 return taskDataPersistenceMgr_->GetSnapshot(missionId);
506 }
507 #endif
508
GetMissionSnapshot(int32_t missionId,const sptr<IRemoteObject> & abilityToken,MissionSnapshot & missionSnapshot,bool isLowResolution,bool force)509 bool MissionInfoMgr::GetMissionSnapshot(int32_t missionId, const sptr<IRemoteObject>& abilityToken,
510 MissionSnapshot& missionSnapshot, bool isLowResolution, bool force)
511 {
512 HILOG_INFO("mission_list_info GetMissionSnapshot, missionId:%{public}d, force:%{public}d", missionId, force);
513 std::lock_guard<std::recursive_mutex> lock(mutex_);
514 auto it = find_if(missionInfoList_.begin(), missionInfoList_.end(), [missionId](const InnerMissionInfo &info) {
515 return missionId == info.missionInfo.id;
516 });
517 if (it == missionInfoList_.end()) {
518 HILOG_ERROR("snapshot: get mission failed, missionId %{public}d not exists", missionId);
519 return false;
520 }
521 if (!taskDataPersistenceMgr_) {
522 HILOG_ERROR("snapshot: taskDataPersistenceMgr_ is nullptr");
523 return false;
524 }
525
526 if (force) {
527 HILOG_INFO("force to get snapshot");
528 return UpdateMissionSnapshot(missionId, abilityToken, missionSnapshot, isLowResolution);
529 }
530
531 {
532 std::unique_lock<std::mutex> lock(savingSnapshotLock_);
533 auto search = savingSnapshot_.find(missionId);
534 if (search != savingSnapshot_.end()) {
535 auto savingSnapshotTimeout = 100; // ms
536 std::chrono::milliseconds timeout { savingSnapshotTimeout };
537 auto waitingCount = 5;
538 auto waitingNum = 0;
539 while (waitSavingCondition_.wait_for(lock, timeout) == std::cv_status::no_timeout) {
540 ++waitingNum;
541 auto iter = savingSnapshot_.find(missionId);
542 if (iter == savingSnapshot_.end() || waitingNum == waitingCount) {
543 HILOG_INFO("Saved successfully or waiting failed.");
544 break;
545 }
546 }
547 }
548 }
549
550 if (taskDataPersistenceMgr_->GetMissionSnapshot(missionId, missionSnapshot, isLowResolution)) {
551 missionSnapshot.topAbility = it->missionInfo.want.GetElement();
552 HILOG_ERROR("mission_list_info GetMissionSnapshot, find snapshot OK, missionId:%{public}d", missionId);
553 return true;
554 }
555 HILOG_INFO("snapshot: storage mission snapshot not exists, create new snapshot");
556 return UpdateMissionSnapshot(missionId, abilityToken, missionSnapshot, isLowResolution);
557 }
558
559 #ifdef SUPPORT_GRAPHICS
CreateWhitePixelMap(Snapshot & snapshot) const560 void MissionInfoMgr::CreateWhitePixelMap(Snapshot &snapshot) const
561 {
562 if (snapshot.GetPixelMap() == nullptr) {
563 HILOG_ERROR("CreateWhitePixelMap error.");
564 return;
565 }
566 int32_t dataLength = snapshot.GetPixelMap()->GetByteCount();
567 const uint8_t *pixelData = snapshot.GetPixelMap()->GetPixels();
568 uint8_t *data = const_cast<uint8_t *>(pixelData);
569 if (memset_s(data, dataLength, 0xff, dataLength) != EOK) {
570 HILOG_ERROR("CreateWhitePixelMap memset_s error.");
571 }
572 }
573 #endif
574 } // namespace AAFwk
575 } // namespace OHOS
576