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_slice_scheduler.h"
17 
18 #include <ability_state.h>
19 #include <log.h>
20 
21 #include "ability_loader.h"
22 #include "ability_slice_manager.h"
23 
24 namespace OHOS {
AbilitySliceScheduler(AbilitySliceManager & abilitySliceManager)25 AbilitySliceScheduler::AbilitySliceScheduler(AbilitySliceManager &abilitySliceManager)
26     : abilitySliceManager_(abilitySliceManager)
27 {
28     abilitySliceRoute_ = new AbilitySliceRoute();
29     abilitySliceStack_ = new AbilitySliceStack();
30 }
31 
~AbilitySliceScheduler()32 AbilitySliceScheduler::~AbilitySliceScheduler()
33 {
34     delete abilitySliceRoute_;
35     abilitySliceRoute_ = nullptr;
36     delete abilitySliceStack_;
37     abilitySliceStack_ = nullptr;
38 }
39 
HandleStartAbilitySlice(const Want & want)40 void AbilitySliceScheduler::HandleStartAbilitySlice(const Want &want)
41 {
42     if (topAbilitySlice_ == nullptr) {
43         topAbilitySlice_ = GetTargetAbilitySlice();
44         if (topAbilitySlice_ == nullptr) {
45             HILOG_ERROR(HILOG_MODULE_APP, "Cannot get slice [%{public}s]", abilitySliceRoute_->GetMainRoute().c_str());
46             return;
47         }
48     }
49     topAbilitySlice_->Init(abilitySliceManager_);
50 
51     topAbilitySlice_->OnStart(want);
52 }
53 
HandleInactiveAbilitySlice()54 void AbilitySliceScheduler::HandleInactiveAbilitySlice()
55 {
56     if (topAbilitySlice_ == nullptr) {
57         return;
58     }
59 
60     topAbilitySlice_->OnInactive();
61 }
62 
HandleActiveAbilitySlice(const Want & want)63 void AbilitySliceScheduler::HandleActiveAbilitySlice(const Want &want)
64 {
65     if (topAbilitySlice_ == nullptr) {
66         HILOG_ERROR(HILOG_MODULE_APP, "top ability slice is null, active slice error");
67         return;
68     }
69 
70     // add want when implicit match, not support jump by want temporary.
71 
72     topAbilitySlice_->OnActive(want);
73 }
74 
HandleMoveAbilitySliceToBackground()75 void AbilitySliceScheduler::HandleMoveAbilitySliceToBackground()
76 {
77     if (topAbilitySlice_ == nullptr) {
78         return;
79     }
80 
81     topAbilitySlice_->OnBackground();
82 }
83 
HandleStopAbilitySlice()84 void AbilitySliceScheduler::HandleStopAbilitySlice()
85 {
86     if (topAbilitySlice_ == nullptr) {
87         return;
88     }
89 
90     topAbilitySlice_->OnStop();
91     while (!abilitySliceStack_->IsEmpty()) {
92         auto abilitySlice = abilitySliceStack_->Pop();
93         if (abilitySlice != nullptr) {
94             abilitySlice->OnStop();
95         }
96     }
97     delete topAbilitySlice_;
98     topAbilitySlice_ = nullptr;
99 }
100 
AddAbilitySlice(const AbilitySlice & caller,AbilitySlice & target,const Want & want)101 void AbilitySliceScheduler::AddAbilitySlice(const AbilitySlice &caller, AbilitySlice &target, const Want &want)
102 {
103     // Check if this jump is legal.
104     if (!CheckLegalForAdd(caller, target, want)) {
105         HILOG_WARN(HILOG_MODULE_APP, "Cannot jump to target AbilitySlice");
106         return;
107     }
108 
109     // Scheduler top slice to inactive.
110     if (topAbilitySlice_->GetState() == STATE_ACTIVE) {
111         topAbilitySlice_->OnInactive();
112     }
113 
114     // Scheduler target slice to Active.
115     if (target.GetState() == STATE_UNINITIALIZED) {
116         target.Init(abilitySliceManager_);
117     }
118     if (target.GetState() == STATE_INITIAL) {
119         target.OnStart(want);
120     }
121     target.OnActive(want);
122 
123     // Scheduler top slice to background.
124     if (topAbilitySlice_->GetState() == STATE_INACTIVE) {
125         topAbilitySlice_->OnBackground();
126     }
127 
128     // Update the topAbilitySlice and stack.
129     abilitySliceStack_->Push(topAbilitySlice_);
130     topAbilitySlice_ = &target;
131 }
132 
RemoveAbilitySlice(AbilitySlice & slice)133 void AbilitySliceScheduler::RemoveAbilitySlice(AbilitySlice &slice)
134 {
135     // Check if this slice is legal.
136     if (!CheckLegalForRemove(slice)) {
137         HILOG_WARN(HILOG_MODULE_APP, "Cannot terminate target AbilitySlice");
138         return;
139     }
140 
141     if (&slice == topAbilitySlice_) {
142         // Scheduler the slice need to exit to inactive.
143         topAbilitySlice_->OnInactive();
144 
145         Want want { nullptr, nullptr, nullptr, 0 };
146         // Scheduler the top slice in the stack to Active.
147         auto next = abilitySliceStack_->Pop();
148         if (next == nullptr) {
149             topAbilitySlice_->OnActive(want);
150             return;
151         }
152         next->OnActive(want);
153 
154         // Scheduler the slice need to exit(State:initial).
155         topAbilitySlice_->OnBackground();
156         topAbilitySlice_->OnStop();
157 
158         // Update the topAbilitySLice and stack.
159         topAbilitySlice_ = next;
160     } else {
161         // Scheduler the background slice to stop
162         slice.OnStop();
163         abilitySliceStack_->Remove(&slice);
164     }
165 }
166 
SetMainRoute(const std::string & entry)167 void AbilitySliceScheduler::SetMainRoute(const std::string &entry)
168 {
169     abilitySliceRoute_->SetMainRoute(entry);
170 }
171 
AddActionRoute(const std::string & action,const std::string & entry)172 void AbilitySliceScheduler::AddActionRoute(const std::string &action, const std::string &entry)
173 {
174     abilitySliceRoute_->AddActionRoute(action, entry);
175 }
176 
GetTargetAbilitySlice() const177 AbilitySlice *AbilitySliceScheduler::GetTargetAbilitySlice() const
178 {
179     std::string mainEntry = abilitySliceRoute_->GetMainRoute();
180 
181     return AbilityLoader::GetInstance().GetAbilitySliceByName(mainEntry);
182 }
183 
CheckLegalForAdd(const AbilitySlice & caller,AbilitySlice & target,const Want & want)184 bool AbilitySliceScheduler::CheckLegalForAdd(const AbilitySlice &caller, AbilitySlice &target, const Want &want)
185 {
186     if (topAbilitySlice_ == nullptr) {
187         return false;
188     }
189     if (abilitySliceManager_.GetAbilityState() != STATE_ACTIVE) {
190         return false;
191     }
192     if (caller.GetState() <= STATE_INITIAL) {
193         return false;
194     }
195     if (target.GetState() == STATE_ACTIVE) {
196         return false;
197     }
198     if (&target == topAbilitySlice_) {
199         return false;
200     }
201 
202     return true;
203 }
204 
CheckLegalForRemove(const AbilitySlice & slice)205 bool AbilitySliceScheduler::CheckLegalForRemove(const AbilitySlice &slice)
206 {
207     if (topAbilitySlice_ == nullptr) {
208         return false;
209     }
210     if (abilitySliceManager_.GetAbilityState() != STATE_ACTIVE) {
211         return false;
212     }
213     if ((!abilitySliceStack_->Exist(&slice)) && (&slice != topAbilitySlice_)) {
214         return false;
215     }
216     if (slice.GetState() <= STATE_INITIAL) {
217         return false;
218     }
219     if (abilitySliceStack_->IsEmpty()) {
220         abilitySliceManager_.TerminateAbility();
221         return false;
222     }
223 
224     return true;
225 }
226 
GetSliceStackInfo() const227 const std::string AbilitySliceScheduler::GetSliceStackInfo() const
228 {
229     if (topAbilitySlice_ == nullptr) {
230         return "    none";
231     }
232     std::string buff;
233     buff += "    [" + std::string(typeid(*topAbilitySlice_).name()) +
234         "] State: [" + std::to_string(topAbilitySlice_->GetState()) + "]\n";
235     auto slices = abilitySliceStack_->GetAllSlices();
236     for (auto slice : slices) {
237         buff += "    [" + std::string(typeid(*slice).name()) + "] State: [" + std::to_string(slice->GetState()) + "]\n";
238     }
239     return buff;
240 }
241 } // namespace OHOS