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_stack_manager.h"
17
18 #include "util/abilityms_helper.h"
19
20 namespace OHOS {
GeneratePageAbility(const AbilityInfo & target,const Want & want,const PageAbilityRecord * topAbility,AbilityMgrContext & amsContext) const21 PageAbilityRecord *AbilityStackManager::GeneratePageAbility(const AbilityInfo &target,
22 const Want &want, const PageAbilityRecord *topAbility, AbilityMgrContext &amsContext) const
23 {
24 CHECK_NULLPTR_RETURN_PTR(target.name, "AbilityStackManager", "target ability name is nullptr");
25 auto stack = const_cast<AbilityMissionStack *>(amsContext.GetTargetMissionStack(target.bundleName));
26 CHECK_NULLPTR_RETURN_PTR(stack, "AbilityStackManager", "missionStack is nullptr");
27
28 PageAbilityRecord *targetAbility = nullptr;
29 AbilityMissionRecord *targetMission = stack->GetTargetMissionRecord(target.bundleName);
30 auto topMissionRecord = stack->GetTopMissionRecord();
31 /* launcher -> default or default -> launcher */
32 if (topAbility == nullptr || AbilityMsHelper::IsAceAbility(target.name) ||
33 (!topAbility->IsLauncherAbility() && AbilityMsHelper::IsLauncherAbility(target.bundleName)) ||
34 (topAbility->IsLauncherAbility() && !AbilityMsHelper::IsLauncherAbility(target.bundleName))) {
35 // Get the mission record of the current bundleName
36 PRINTD("AbilityStackManager", "launcher jumps to default or default jumps to launcher");
37 if (targetMission == nullptr) {
38 targetMission = new AbilityMissionRecord(stack, target.bundleName);
39 targetAbility = new PageAbilityRecord(target, want);
40 targetMission->PushPageAbility(*targetAbility);
41 stack->PushTopMissionRecord(*targetMission);
42 } else {
43 targetAbility = const_cast<PageAbilityRecord *>(targetMission->GetTopPageAbility());
44 stack->MoveMissionRecordToTop(*targetMission);
45 }
46 } else {
47 PRINTD("AbilityStackManager", "default application jumps to another default");
48 if (targetMission == nullptr) {
49 targetMission = new AbilityMissionRecord(stack, target.bundleName);
50 stack->PushTopMissionRecord(*targetMission);
51 targetAbility = new PageAbilityRecord(target, want);
52 targetMission->PushPageAbility(*targetAbility);
53 } else {
54 PageAbilityRecord *targetTopAbility = const_cast<PageAbilityRecord *>(targetMission->GetTopPageAbility());
55 if (targetTopAbility != nullptr && targetTopAbility->IsSamePageAbility(want)) {
56 targetAbility = targetTopAbility;
57 } else {
58 targetAbility = new PageAbilityRecord(target, want);
59 targetMission->PushPageAbility(*targetAbility);
60 }
61 stack->MoveMissionRecordToTop(*targetMission);
62 }
63 }
64
65 // default jumps to default, then return to default
66 if (topAbility != nullptr && !topAbility->IsLauncherAbility() &&
67 targetAbility != nullptr && !targetAbility->IsLauncherAbility()) {
68 if (targetMission != nullptr && topMissionRecord != nullptr && targetMission != topMissionRecord) {
69 targetMission->SetPrevMissionRecord(topMissionRecord);
70 }
71 }
72
73 amsContext.SetTopMissionStacks(stack);
74 return targetAbility;
75 }
76
GetTopPageAbility(const AbilityMgrContext & amsContext) const77 const PageAbilityRecord *AbilityStackManager::GetTopPageAbility(const AbilityMgrContext &amsContext) const
78 {
79 const AbilityMissionStack *topMissionStack = amsContext.GetTopMissionStacks();
80 CHECK_NULLPTR_RETURN_PTR(topMissionStack, "AbilityStackManager", "topMissionStack is nullptr");
81 return topMissionStack->GetTopPageAbility();
82 }
83
RemovePageAbility(const PageAbilityRecord & target,AbilityMgrContext & amsContext)84 void AbilityStackManager::RemovePageAbility(const PageAbilityRecord &target, AbilityMgrContext &amsContext)
85 {
86 AbilityMissionRecord *missionRecord = const_cast<AbilityMissionRecord *>(target.GetMissionRecord());
87 CHECK_NULLPTR_RETURN(missionRecord, "AbilityStackManager", "missionRecord is nullptr");
88 missionRecord->RemovePageAbility(target);
89 // Current mission reocrd is empty
90 if (missionRecord->IsEmpty()) {
91 AbilityMissionStack *stack = const_cast<AbilityMissionStack *>(missionRecord->GetMissionStack());
92 if (stack != nullptr) {
93 stack->RemoveMissionRecord(*missionRecord);
94 }
95 auto prevMissionRecord = const_cast<AbilityMissionRecord *>(missionRecord->GetPrevMissionRecord());
96 if (stack != nullptr && prevMissionRecord != nullptr) {
97 stack->MoveMissionRecordToTop(*prevMissionRecord);
98 } else {
99 amsContext.SetTopMissionStacks(amsContext.GetLauncherMissionStacks());
100 }
101 delete missionRecord;
102 }
103 }
104
ClearAbilityStack(const char * bundleName,AbilityMgrContext & amsContext) const105 void AbilityStackManager::ClearAbilityStack(const char *bundleName, AbilityMgrContext &amsContext) const
106 {
107 CHECK_NULLPTR_RETURN(bundleName, "AbilityStackManager", "invalid argument");
108 AbilityConnectMission *connectMission = const_cast<AbilityConnectMission *>(amsContext.GetServiceConnects());
109 if (connectMission != nullptr) {
110 connectMission->RemoveServiceRecord(bundleName);
111 }
112 // get target mission record
113 auto missionStack = const_cast<AbilityMissionStack *>(amsContext.GetTargetMissionStack(bundleName));
114 CHECK_NULLPTR_RETURN(missionStack, "AbilityStackManager", "missionStack is nullptr");
115 AbilityMissionRecord *missionRecord = missionStack->GetTargetMissionRecord(bundleName);
116 if (missionRecord != nullptr) {
117 // if default application jumps to another default, return prev application
118 auto prevMissionRecord = const_cast<AbilityMissionRecord *>(missionRecord->GetPrevMissionRecord());
119 if (prevMissionRecord != nullptr) {
120 missionStack->MoveMissionRecordToTop(*prevMissionRecord);
121 } else {
122 // return launcher application
123 const AbilityMissionStack *topMissionStack = amsContext.GetTopMissionStacks();
124 if (topMissionStack != nullptr && topMissionStack->IsTopMissionRecord(bundleName)) {
125 amsContext.SetTopMissionStacks(amsContext.GetLauncherMissionStacks());
126 }
127 }
128 }
129
130 missionStack->RemoveMissionRecord(connectMission, bundleName);
131 }
132
FindPageAbility(const AbilityMgrContext & amsContext,uint64_t token) const133 PageAbilityRecord *AbilityStackManager::FindPageAbility(const AbilityMgrContext &amsContext, uint64_t token) const
134 {
135 PageAbilityRecord *record = nullptr;
136 const AbilityMissionStack *stack = amsContext.GetDefaultMissionStacks();
137 if (stack != nullptr) {
138 record = stack->FindPageAbility(token);
139 if (record != nullptr) {
140 return record;
141 }
142 }
143 stack = amsContext.GetLauncherMissionStacks();
144 if (stack != nullptr) {
145 record = stack->FindPageAbility(token);
146 }
147
148 // find service ability
149 if (record == nullptr) {
150 auto serviceConnects = amsContext.GetServiceConnects();
151 if (serviceConnects != nullptr) {
152 record = serviceConnects->FindServiceRecord(token);
153 }
154 }
155 return record;
156 }
157
FindPageAbility(const AbilityMgrContext & amsContext,const Want & want) const158 const PageAbilityRecord *AbilityStackManager::FindPageAbility(const AbilityMgrContext &amsContext,
159 const Want &want) const
160 {
161 CHECK_NULLPTR_RETURN_PTR(want.element, "AbilityStackManager", "element is nullptr");
162 auto missionStack = amsContext.GetTargetMissionStack(want.element->bundleName);
163 CHECK_NULLPTR_RETURN_PTR(missionStack, "AbilityStackManager", "target mission stack is nullptr");
164 PageAbilityRecord *record = missionStack->FindPageAbility(want);
165 if (record != nullptr) {
166 return record;
167 }
168 const AbilityConnectMission *connectMission = amsContext.GetServiceConnects();
169 CHECK_NULLPTR_RETURN_PTR(connectMission, "AbilityStackManager", "service connect is nullptr");
170 return connectMission->FindServiceRecord(want.element->bundleName, want.element->abilityName);
171 }
172
GetPrevPageAbility(const AbilityMgrContext & amsContext,const PageAbilityRecord & current) const173 const PageAbilityRecord *AbilityStackManager::GetPrevPageAbility(const AbilityMgrContext &amsContext,
174 const PageAbilityRecord ¤t) const
175 {
176 AbilityMissionRecord *currentMission = const_cast<AbilityMissionRecord *>(current.GetMissionRecord());
177 if (currentMission != nullptr) {
178 PageAbilityRecord *prevAbility = currentMission->GetPrevPageAbility(current);
179 if (prevAbility != nullptr) {
180 return prevAbility;
181 } else {
182 auto prevMission = currentMission->GetPrevMissionRecord();
183 if (prevMission != nullptr) {
184 return prevMission->GetTopPageAbility();
185 }
186 }
187 }
188 auto launcherStack = amsContext.GetLauncherMissionStacks();
189 CHECK_NULLPTR_RETURN_PTR(launcherStack, "AbilityStackManager", "launcherStack is nullptr");
190 return launcherStack->GetTopPageAbility();
191 }
192
ExistAppInStack(const AbilityInfo & target,AbilityMgrContext & amsContext) const193 bool AbilityStackManager::ExistAppInStack(const AbilityInfo &target, AbilityMgrContext &amsContext) const
194 {
195 auto stack = amsContext.GetTargetMissionStack(target.bundleName);
196 if (stack == nullptr) {
197 return false;
198 }
199 AbilityMissionRecord *targetMission = stack->GetTargetMissionRecord(target.bundleName);
200 return targetMission != nullptr;
201 }
202
203 #ifdef OHOS_DEBUG
DumpAllAbilityRecord(const AbilityMgrContext & amsContext) const204 AbilityMsStatus AbilityStackManager::DumpAllAbilityRecord(const AbilityMgrContext &amsContext) const
205 {
206 AbilityMsStatus result = AbilityMsStatus::DumpStatus("");
207 const AbilityMissionStack *stack = amsContext.GetTopMissionStacks();
208 if (stack != nullptr) {
209 result.DumpAppend(stack->DumpMissionStack());
210 if (stack->GetStackType() == LAUNCHER) {
211 stack = amsContext.GetDefaultMissionStacks();
212 if (stack != nullptr) {
213 result.DumpAppend(stack->DumpMissionStack());
214 }
215 } else if (stack->GetStackType() == DEFAULT) {
216 stack = amsContext.GetLauncherMissionStacks();
217 if (stack != nullptr) {
218 result.DumpAppend(stack->DumpMissionStack());
219 }
220 }
221 }
222 const AbilityConnectMission *mission = amsContext.GetServiceConnects();
223 if (mission != nullptr) {
224 result.DumpAppend(mission->DumpConnectMission());
225 }
226 return result;
227 }
228 #endif
229
FindServiceAbility(const AbilityMgrContext & amsContext,uint64_t token) const230 PageAbilityRecord *AbilityStackManager::FindServiceAbility(const AbilityMgrContext &amsContext, uint64_t token) const
231 {
232 auto serviceConnects = amsContext.GetServiceConnects();
233 CHECK_NULLPTR_RETURN_PTR(serviceConnects, "AbilityStackManager", "serviceConnects is nullptr");
234 return serviceConnects->FindServiceRecord(token);
235 }
236
FindServiceAbility(const AbilityMgrContext & amsContext,const char * bundleName,const char * abilityName) const237 PageAbilityRecord *AbilityStackManager::FindServiceAbility(const AbilityMgrContext &amsContext,
238 const char *bundleName, const char *abilityName) const
239 {
240 auto serviceConnects = amsContext.GetServiceConnects();
241 CHECK_NULLPTR_RETURN_PTR(serviceConnects, "AbilityStackManager", "serviceConnects is nullptr");
242 return serviceConnects->FindServiceRecord(bundleName, abilityName);
243 }
244 }
245