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