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_record.h"
17 
18 #include "adapter.h"
19 #include "util/abilityms_log.h"
20 #include "utils.h"
21 
22 namespace OHOS {
23 
24 namespace {
25     constexpr static uint16_t PAGE_ABILITY_RECORDS_LIST_CAPACITY = 10240;
26 }
27 
AbilityMissionRecord(AbilityMissionStack * missionStack,const char * bundleName)28 AbilityMissionRecord::AbilityMissionRecord(AbilityMissionStack* missionStack, const char *bundleName)
29     : abilityMissionStack_(missionStack)
30 {
31     if (bundleName != nullptr) {
32         bundleName_ = Utils::Strdup(bundleName);
33     }
34     PRINTD("AbilityMissionRecord", "Constructor");
35 }
36 
~AbilityMissionRecord()37 AbilityMissionRecord::~AbilityMissionRecord()
38 {
39     abilityMissionStack_ = nullptr;
40     ClearPageAbility();
41     AdapterFree(bundleName_);
42     PRINTD("AbilityMissionRecord", "Destructor");
43 }
44 
IsEmpty() const45 bool AbilityMissionRecord::IsEmpty() const
46 {
47     return pageAbilityRecords_.empty();
48 }
49 
IsSameMissionRecord(const char * bundleName) const50 bool AbilityMissionRecord::IsSameMissionRecord(const char *bundleName) const
51 {
52     if (bundleName == nullptr || bundleName_ == nullptr) {
53         return false;
54     }
55     if (strcmp(bundleName, bundleName_) == 0) {
56         return true;
57     }
58     return false;
59 }
60 
SetMissionStack(AbilityMissionStack * missionStack)61 void AbilityMissionRecord::SetMissionStack(AbilityMissionStack *missionStack)
62 {
63     abilityMissionStack_ = missionStack;
64 }
65 
GetMissionStack() const66 const AbilityMissionStack *AbilityMissionRecord::GetMissionStack() const
67 {
68     return abilityMissionStack_;
69 }
70 
GetTopPageAbility() const71 const PageAbilityRecord *AbilityMissionRecord::GetTopPageAbility() const
72 {
73     return pageAbilityRecords_.back();
74 }
75 
GetBottomPageAbility() const76 const PageAbilityRecord *AbilityMissionRecord::GetBottomPageAbility() const
77 {
78     return pageAbilityRecords_.front();
79 }
80 
FindPageAbility(uint64_t token) const81 PageAbilityRecord *AbilityMissionRecord::FindPageAbility(uint64_t token) const
82 {
83     for (auto iterator = pageAbilityRecords_.begin(); iterator != pageAbilityRecords_.end(); ++iterator) {
84         PageAbilityRecord *record = *iterator;
85         if (record != nullptr && record->GetToken() == token) {
86             return record;
87         }
88     }
89     return nullptr;
90 }
91 
FindPageAbility(const Want & want) const92 PageAbilityRecord *AbilityMissionRecord::FindPageAbility(const Want &want) const
93 {
94     for (auto iterator = pageAbilityRecords_.begin(); iterator != pageAbilityRecords_.end(); ++iterator) {
95         PageAbilityRecord *record = *iterator;
96         if (record != nullptr && record->IsSamePageAbility(want)) {
97             return record;
98         }
99     }
100     return nullptr;
101 }
102 
GetPrevPageAbility(const PageAbilityRecord & current) const103 PageAbilityRecord *AbilityMissionRecord::GetPrevPageAbility(const PageAbilityRecord &current) const
104 {
105     for (auto iterator = pageAbilityRecords_.begin(); iterator != pageAbilityRecords_.end(); ++iterator) {
106         PageAbilityRecord *record = *iterator;
107         if (record != nullptr && record->IsSamePageAbility(current)) {
108             if (iterator == pageAbilityRecords_.begin()) {
109                 return nullptr;
110             }
111             return *(--iterator);
112         }
113     }
114     return nullptr;
115 }
116 
PushPageAbility(PageAbilityRecord & abilityRecord)117 void AbilityMissionRecord::PushPageAbility(PageAbilityRecord &abilityRecord)
118 {
119     abilityRecord.SetMissionRecord(this);
120     if (pageAbilityRecords_.size() >= PAGE_ABILITY_RECORDS_LIST_CAPACITY) {
121         return;
122     }
123     pageAbilityRecords_.emplace_back(&abilityRecord);
124 }
125 
RemovePageAbility(const PageAbilityRecord & target)126 void AbilityMissionRecord::RemovePageAbility(const PageAbilityRecord &target)
127 {
128     auto iterator = pageAbilityRecords_.begin();
129     while (iterator != pageAbilityRecords_.end()) {
130         PageAbilityRecord *oldRecord = *iterator;
131         if (oldRecord != nullptr && oldRecord->IsSamePageAbility(target)) {
132             break;
133         }
134         ++iterator;
135     }
136 
137     // remove from current to top of stack
138     while (iterator != pageAbilityRecords_.end()) {
139         PageAbilityRecord* oldRecord = *iterator;
140         iterator = pageAbilityRecords_.erase(iterator);
141         delete oldRecord;
142     }
143 }
144 
ClearPageAbility()145 void AbilityMissionRecord::ClearPageAbility()
146 {
147     for (auto iterator = pageAbilityRecords_.begin(); iterator != pageAbilityRecords_.end();) {
148         PageAbilityRecord *abilityRecord = *iterator;
149         iterator = pageAbilityRecords_.erase(iterator);
150         delete abilityRecord;
151     }
152 }
153 
ClearPageAbility(AbilityConnectMission * connectMission)154 void AbilityMissionRecord::ClearPageAbility(AbilityConnectMission *connectMission)
155 {
156     for (auto iterator = pageAbilityRecords_.begin(); iterator != pageAbilityRecords_.end();) {
157         PageAbilityRecord *abilityRecord = *iterator;
158         iterator = pageAbilityRecords_.erase(iterator);
159         if (connectMission != nullptr) {
160             connectMission->RemoveConnectRecordByPageToken(abilityRecord->GetToken(), bundleName_);
161         }
162         delete abilityRecord;
163     }
164 }
165 
SetPrevMissionRecord(const AbilityMissionRecord * missionRecord)166 void AbilityMissionRecord::SetPrevMissionRecord(const AbilityMissionRecord *missionRecord)
167 {
168     prevMissionRecord_ = missionRecord;
169 }
170 
GetPrevMissionRecord() const171 const AbilityMissionRecord *AbilityMissionRecord::GetPrevMissionRecord() const
172 {
173     return prevMissionRecord_;
174 }
175 
176 #ifdef OHOS_DEBUG
DumpMissionRecord() const177 AbilityMsStatus AbilityMissionRecord::DumpMissionRecord() const
178 {
179     std::string missionInfo = "    MissionRecord: ";
180     if (bundleName_ != nullptr) {
181         missionInfo.append(bundleName_);
182     }
183     missionInfo.append("\n");
184     AbilityMsStatus result = AbilityMsStatus::DumpStatus(missionInfo.c_str());
185     for (auto iterator = pageAbilityRecords_.rbegin(); iterator != pageAbilityRecords_.rend(); ++iterator) {
186         PageAbilityRecord *target = *iterator;
187         if (target != nullptr) {
188             result.DumpAppend(target->DumpAbilityRecord());
189         }
190     }
191     return result;
192 }
193 #endif
194 }  // namespace OHOS
195