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