1 /*
2  * Copyright (c) 2020 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 "ability_mission_stack.h"
17 
18 #include "util/abilityms_log.h"
19 
20 namespace OHOS {
21 
22 namespace {
23     constexpr static uint16_t MISSION_RECORD_LIST_CAPACITY = 10240;
24 }
25 
AbilityMissionStack(StackType type)26 AbilityMissionStack::AbilityMissionStack(StackType type)
27     : stackType_(type)
28 {
29 }
30 
~AbilityMissionStack()31 AbilityMissionStack::~AbilityMissionStack()
32 {
33     for (auto iterator = missionRecords_.begin(); iterator != missionRecords_.end();) {
34         AbilityMissionRecord *missionRecord = *iterator;
35         iterator = missionRecords_.erase(iterator);
36         delete missionRecord;
37     }
38 }
39 
GetStackType() const40 StackType AbilityMissionStack::GetStackType() const
41 {
42     return stackType_;
43 }
44 
PushTopMissionRecord(AbilityMissionRecord & missionRecord)45 void AbilityMissionStack::PushTopMissionRecord(AbilityMissionRecord &missionRecord)
46 {
47     missionRecord.SetMissionStack(this);
48     if (missionRecords_.size() >= MISSION_RECORD_LIST_CAPACITY) {
49         return;
50     }
51     missionRecords_.emplace_back(&missionRecord);
52 }
53 
MoveMissionRecordToTop(AbilityMissionRecord & missionRecord)54 void AbilityMissionStack::MoveMissionRecordToTop(AbilityMissionRecord &missionRecord)
55 {
56     if (missionRecords_.back() != &missionRecord) {
57         missionRecords_.remove(&missionRecord);
58         missionRecords_.emplace_back(&missionRecord);
59     }
60 }
61 
RemoveMissionRecord(AbilityMissionRecord & missionRecord)62 void AbilityMissionStack::RemoveMissionRecord(AbilityMissionRecord &missionRecord)
63 {
64     missionRecords_.remove(&missionRecord);
65     // clear prev mission record
66     for (const auto currentMission : missionRecords_) {
67         if (currentMission != nullptr && currentMission->GetPrevMissionRecord() == &missionRecord) {
68             currentMission->SetPrevMissionRecord(nullptr);
69         }
70     }
71 }
72 
RemoveMissionRecord(AbilityConnectMission * connectMission,const char * bundleName)73 void AbilityMissionStack::RemoveMissionRecord(AbilityConnectMission *connectMission, const char *bundleName)
74 {
75     AbilityMissionRecord *missionRecord = GetTargetMissionRecord(bundleName);
76     CHECK_NULLPTR_RETURN(missionRecord, "AbilityMissionStack", "missionRecord is null");
77     missionRecord->ClearPageAbility(connectMission);
78     RemoveMissionRecord(*missionRecord);
79     delete missionRecord;
80 }
81 
IsTopMissionRecord(const char * bundleName) const82 bool AbilityMissionStack::IsTopMissionRecord(const char *bundleName) const
83 {
84     if (bundleName == nullptr) {
85         return false;
86     }
87     AbilityMissionRecord *topMissionRecord = missionRecords_.back();
88     if (topMissionRecord != nullptr) {
89         return topMissionRecord->IsSameMissionRecord(bundleName);
90     }
91     return false;
92 }
93 
GetTargetMissionRecord(const char * bundleName) const94 AbilityMissionRecord *AbilityMissionStack::GetTargetMissionRecord(const char *bundleName) const
95 {
96     CHECK_NULLPTR_RETURN_PTR(bundleName, "AbilityMissionStack", "invalid argument");
97     for (const auto missionRecord : missionRecords_) {
98         if (missionRecord != nullptr && missionRecord->IsSameMissionRecord(bundleName)) {
99             return missionRecord;
100         }
101     }
102     return nullptr;
103 }
104 
GetTopMissionRecord() const105 const AbilityMissionRecord *AbilityMissionStack::GetTopMissionRecord() const
106 {
107     return missionRecords_.back();
108 }
109 
FindPageAbility(uint64_t token) const110 PageAbilityRecord *AbilityMissionStack::FindPageAbility(uint64_t token) const
111 {
112     for (const auto missionRecord : missionRecords_) {
113         if (missionRecord == nullptr) {
114             continue;
115         }
116         PageAbilityRecord *record = missionRecord->FindPageAbility(token);
117         if (record != nullptr) {
118             return record;
119         }
120     }
121     return nullptr;
122 }
123 
FindPageAbility(const Want & want) const124 PageAbilityRecord *AbilityMissionStack::FindPageAbility(const Want &want) const
125 {
126     CHECK_NULLPTR_RETURN_PTR(want.element, "AbilityMissionStack", "invalid argument");
127     AbilityMissionRecord *missionRecord = GetTargetMissionRecord(want.element->bundleName);
128     if (missionRecord != nullptr) {
129         return missionRecord->FindPageAbility(want);
130     }
131     return nullptr;
132 }
133 
GetTopPageAbility() const134 const PageAbilityRecord *AbilityMissionStack::GetTopPageAbility() const
135 {
136     if (!missionRecords_.empty()) {
137         return missionRecords_.back()->GetTopPageAbility();
138     }
139     return nullptr;
140 }
141 
142 #ifdef OHOS_DEBUG
DumpMissionStack() const143 AbilityMsStatus AbilityMissionStack::DumpMissionStack() const
144 {
145     if (missionRecords_.size() <= 0) {
146         return AbilityMsStatus::DumpStatus("");
147     }
148     std::string stackType = (stackType_ == LAUNCHER) ? "launcher\n" : "default\n";
149     std::string stackInfo = "MissionStack Type: " + stackType;
150     AbilityMsStatus result = AbilityMsStatus::DumpStatus(stackInfo.c_str());
151     for (const auto missionRecord : missionRecords_) {
152         if (missionRecord != nullptr) {
153             result.DumpAppend(missionRecord->DumpMissionRecord());
154         }
155     }
156     return result;
157 }
158 #endif
159 }  // namespace OHOS
160