• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "local_ability_manager.h"
17 
18 #include <chrono>
19 #include <cinttypes>
20 #include <iostream>
21 #include <sys/types.h>
22 #include <thread>
23 
24 #include "datetime_ex.h"
25 #include "errors.h"
26 #include "hitrace_meter.h"
27 #include "ipc_skeleton.h"
28 #include "iservice_registry.h"
29 #include "safwk_log.h"
30 #include "string_ex.h"
31 #include "system_ability_ondemand_reason.h"
32 
33 namespace OHOS {
34 using std::u16string;
35 using std::string;
36 using std::vector;
37 
38 namespace {
39 const string TAG = "LocalAbilityManager";
40 constexpr int32_t RETRY_TIMES_FOR_ONDEMAND = 10;
41 constexpr int32_t RETRY_TIMES_FOR_SAMGR = 50;
42 constexpr int32_t DEFAULT_SAID = -1;
43 constexpr std::chrono::milliseconds MILLISECONDS_WAITING_SAMGR_ONE_TIME(200);
44 constexpr std::chrono::milliseconds MILLISECONDS_WAITING_ONDEMAND_ONE_TIME(100);
45 
46 constexpr int32_t MAX_SA_STARTUP_TIME = 100;
47 constexpr int32_t SUFFIX_LENGTH = 5; // .json length
48 
49 const string PROFILES_DIR = "/system/profile/";
50 const string DEFAULT_DIR = "/system/usr/";
51 const string PREFIX = PROFILES_DIR;
52 const string SUFFIX = "_trust.json";
53 
54 const string ONDEMAND_WORKER = "SaOndemand";
55 const string INIT_POOL = "SaInit";
56 
57 constexpr const char* EVENT_ID = "eventId";
58 constexpr const char* NAME = "name";
59 constexpr const char* VALUE = "value";
60 constexpr const char* EXTRA_DATA_ID = "extraDataId";
61 
62 enum {
63     BOOT_START = 1,
64     CORE_START = 2,
65     OTHER_START = 3,
66 };
67 }
68 
69 IMPLEMENT_SINGLE_INSTANCE(LocalAbilityManager);
70 
LocalAbilityManager()71 LocalAbilityManager::LocalAbilityManager()
72 {
73     profileParser_ = std::make_shared<ParseUtil>();
74     initPool_ = std::make_unique<ThreadPool>(INIT_POOL);
75 }
76 
SetUpdateList(const std::string & updateList)77 void LocalAbilityManager::SetUpdateList(const std::string& updateList)
78 {
79     std::vector<std::string> updateVec;
80     SplitStr(updateList, " ", updateVec);
81     profileParser_->SetUpdateList(updateVec);
82 }
83 
DoStartSAProcess(const std::string & profilePath,int32_t saId)84 void LocalAbilityManager::DoStartSAProcess(const std::string& profilePath, int32_t saId)
85 {
86     startBegin_ = GetTickCount();
87     HILOGI(TAG, "DoStartSAProcess saId : %{public}d", saId);
88     string realProfilePath = "";
89     if (!CheckAndGetProfilePath(profilePath, realProfilePath)) {
90         HILOGE(TAG, "DoStartSAProcess invalid path");
91         return;
92     }
93     {
94         std::string traceTag = GetTraceTag(realProfilePath);
95         HITRACE_METER_NAME(HITRACE_TAG_SAMGR, traceTag);
96         bool ret = InitSystemAbilityProfiles(realProfilePath, saId);
97         if (!ret) {
98             HILOGE(TAG, "InitSystemAbilityProfiles no right profile, will exit");
99             return;
100         }
101         ret = CheckSystemAbilityManagerReady();
102         if (!ret) {
103             HILOGE(TAG, "CheckSystemAbilityManagerReady failed! will exit");
104             return;
105         }
106         ret = Run(saId);
107         if (!ret) {
108             HILOGE(TAG, "Run failed! will exit");
109             return;
110         }
111     }
112 
113     IPCSkeleton::JoinWorkThread();
114     ClearResource();
115     HILOGE(TAG, "JoinWorkThread stop, will exit");
116 }
117 
GetTraceTag(const std::string & profilePath)118 std::string LocalAbilityManager::GetTraceTag(const std::string& profilePath)
119 {
120     std::vector<std::string> libPathVec;
121     string traceTag = "default_proc";
122     SplitStr(profilePath, "/", libPathVec);
123     if ((libPathVec.size() > 0)) {
124         traceTag = libPathVec[libPathVec.size() - 1];
125         auto size = traceTag.length();
126         if (size > SUFFIX_LENGTH) {
127             return traceTag.substr(0, size - SUFFIX_LENGTH);
128         }
129     }
130     return traceTag;
131 }
132 
CheckAndGetProfilePath(const std::string & profilePath,std::string & realProfilePath)133 bool LocalAbilityManager::CheckAndGetProfilePath(const std::string& profilePath, std::string& realProfilePath)
134 {
135     if (profilePath.length() > PATH_MAX) {
136         HILOGE(TAG, "profilePath length too long!");
137         return false;
138     }
139     char realPath[PATH_MAX] = {'\0'};
140     if (realpath(profilePath.c_str(), realPath) == nullptr) {
141         HILOGE(TAG, "file path does not exist!");
142         return false;
143     }
144     // realProfilePath must begin with "/system/profile/" or begin with "/system/usr/"
145     realProfilePath = realPath;
146     if (realProfilePath.find(PROFILES_DIR) != 0 && realProfilePath.find(DEFAULT_DIR) != 0) {
147         HILOGE(TAG, "file path is not matched");
148         return false;
149     }
150     return true;
151 }
152 
CheckSystemAbilityManagerReady()153 bool LocalAbilityManager::CheckSystemAbilityManagerReady()
154 {
155     int32_t timeout = RETRY_TIMES_FOR_SAMGR;
156     constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_SAMGR_ONE_TIME).count();
157     sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
158     while (samgrProxy == nullptr) {
159         HILOGI(TAG, "waiting for samgr...");
160         if (timeout > 0) {
161             usleep(duration);
162             samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
163         } else {
164             HILOGE(TAG, "wait for samgr time out (10s)");
165             return false;
166         }
167         timeout--;
168     }
169     return true;
170 }
171 
InitSystemAbilityProfiles(const std::string & profilePath,int32_t saId)172 bool LocalAbilityManager::InitSystemAbilityProfiles(const std::string& profilePath, int32_t saId)
173 {
174     HILOGD(TAG, "[PerformanceTest] SAFWK parse system ability profiles!");
175     int64_t begin = GetTickCount();
176     bool ret = profileParser_->ParseSaProfiles(profilePath);
177     if (!ret) {
178         HILOGW(TAG, "ParseSaProfiles failed!");
179         return false;
180     }
181 
182     procName_ = profileParser_->GetProcessName();
183     auto saInfos = profileParser_->GetAllSaProfiles();
184     std::string process = Str16ToStr8(procName_);
185     HILOGI(TAG, "[PerformanceTest] SAFWK parse process:%{public}s system ability profiles finished, spend:%{public}"
186         PRId64 " ms", process.c_str(), (GetTickCount() - begin));
187     std::string path = PREFIX + process + SUFFIX;
188     bool isExist = profileParser_->CheckPathExist(path);
189     if (isExist) {
190         CheckTrustSa(path, process, saInfos);
191     }
192     return InitializeSaProfiles(saId);
193 }
194 
InitializeSaProfiles(int32_t saId)195 bool LocalAbilityManager::InitializeSaProfiles(int32_t saId)
196 {
197     if (saId != DEFAULT_SAID) {
198         return InitializeOnDemandSaProfile(saId);
199     } else {
200         return InitializeRunOnCreateSaProfiles(BOOT_START);
201     }
202 }
203 
CheckTrustSa(const std::string & path,const std::string & process,const std::list<SaProfile> & saInfos)204 void LocalAbilityManager::CheckTrustSa(const std::string& path, const std::string& process,
205     const std::list<SaProfile>& saInfos)
206 {
207     HILOGD(TAG, "CheckTrustSa start");
208     std::map<std::u16string, std::set<int32_t>> trustMaps;
209     bool ret = profileParser_->ParseTrustConfig(path, trustMaps);
210     if (ret && !trustMaps.empty()) {
211         // 1.get allowed sa set in the process
212         const auto& saSets = trustMaps[Str8ToStr16(process)];
213         // 2.check to-load sa in the allowed sa set, and if to-load sa not in the allowed, will remove and not load it
214         for (const auto& saInfo : saInfos) {
215             if (saSets.find(saInfo.saId) == saSets.end()) {
216                 HILOGW(TAG, "sa : %{public}d not allow to load in %{public}s", saInfo.saId, process.c_str());
217                 profileParser_->RemoveSaProfile(saInfo.saId);
218             }
219         }
220     }
221 }
222 
ClearResource()223 void LocalAbilityManager::ClearResource()
224 {
225     profileParser_->ClearResource();
226 }
227 
AddAbility(SystemAbility * ability)228 bool LocalAbilityManager::AddAbility(SystemAbility* ability)
229 {
230     if (ability == nullptr) {
231         HILOGW(TAG, "try to add null ability!");
232         return false;
233     }
234 
235     int32_t saId = ability->GetSystemAbilitId();
236     SaProfile saProfile;
237     bool ret = profileParser_->GetProfile(saId, saProfile);
238     if (!ret) {
239         return false;
240     }
241     std::unique_lock<std::shared_mutex> writeLock(abilityMapLock_);
242     auto iter = abilityMap_.find(saId);
243     if (iter != abilityMap_.end()) {
244         HILOGW(TAG, "try to add existed ability:%{public}d!", saId);
245         return false;
246     }
247     HILOGI(TAG, "set profile attributes for SA:%{public}d", saId);
248     ability->SetLibPath(saProfile.libPath);
249     ability->SetRunOnCreate(saProfile.runOnCreate);
250     ability->SetDependSa(saProfile.dependSa);
251     ability->SetDependTimeout(saProfile.dependTimeout);
252     ability->SetDistributed(saProfile.distributed);
253     ability->SetDumpLevel(saProfile.dumpLevel);
254     ability->SetCapability(saProfile.capability);
255     ability->SetPermission(saProfile.permission);
256     abilityMap_.emplace(saId, ability);
257     return true;
258 }
259 
RemoveAbility(int32_t systemAbilityId)260 bool LocalAbilityManager::RemoveAbility(int32_t systemAbilityId)
261 {
262     if (systemAbilityId <= 0) {
263         HILOGW(TAG, "invalid systemAbilityId");
264         return false;
265     }
266     std::unique_lock<std::shared_mutex> writeLock(abilityMapLock_);
267     (void)abilityMap_.erase(systemAbilityId);
268     return true;
269 }
270 
AddSystemAbilityListener(int32_t systemAbilityId,int32_t listenerSaId)271 bool LocalAbilityManager::AddSystemAbilityListener(int32_t systemAbilityId, int32_t listenerSaId)
272 {
273     if (!CheckInputSysAbilityId(systemAbilityId) || !CheckInputSysAbilityId(listenerSaId)) {
274         HILOGW(TAG, "SA:%{public}d or listenerSA:%{public}d invalid!",
275             systemAbilityId, listenerSaId);
276         return false;
277     }
278     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
279     if (samgrProxy == nullptr) {
280         HILOGE(TAG, "failed to get samgrProxy");
281         return false;
282     }
283 
284     {
285         HILOGD(TAG, "SA:%{public}d, listenerSA:%{public}d", systemAbilityId, listenerSaId);
286         std::lock_guard<std::mutex> autoLock(listenerLock_);
287         auto& listenerSaIdList = listenerMap_[systemAbilityId];
288         auto iter = std::find_if(listenerSaIdList.begin(), listenerSaIdList.end(), [listenerSaId](int32_t SaId) {
289             return SaId == listenerSaId;
290         });
291         if (iter == listenerSaIdList.end()) {
292             listenerSaIdList.emplace_back(listenerSaId);
293         }
294         HILOGI(TAG, "AddSystemAbilityListener SA:%{public}d, size:%{public}zu", systemAbilityId,
295             listenerSaIdList.size());
296         if (listenerSaIdList.size() > 1) {
297             sptr<IRemoteObject> object = samgrProxy->CheckSystemAbility(systemAbilityId);
298             if (object != nullptr) {
299                 NotifyAbilityListener(systemAbilityId, listenerSaId, "",
300                     ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY);
301             }
302             return true;
303         }
304     }
305 
306     int32_t ret = samgrProxy->SubscribeSystemAbility(systemAbilityId, GetSystemAbilityStatusChange());
307     if (ret) {
308         HILOGE(TAG, "failed to subscribe sa:%{public}d, process name:%{public}s", systemAbilityId,
309             Str16ToStr8(procName_).c_str());
310         return false;
311     }
312     return true;
313 }
314 
RemoveSystemAbilityListener(int32_t systemAbilityId,int32_t listenerSaId)315 bool LocalAbilityManager::RemoveSystemAbilityListener(int32_t systemAbilityId, int32_t listenerSaId)
316 {
317     if (!CheckInputSysAbilityId(systemAbilityId) || !CheckInputSysAbilityId(listenerSaId)) {
318         HILOGW(TAG, "SA:%{public}d or listenerSA:%{public}d invalid!",
319             systemAbilityId, listenerSaId);
320         return false;
321     }
322 
323     {
324         HILOGD(TAG, "SA:%{public}d, listenerSA:%{public}d", systemAbilityId, listenerSaId);
325         std::lock_guard<std::mutex> autoLock(listenerLock_);
326         if (listenerMap_.count(systemAbilityId) == 0) {
327             return true;
328         }
329         auto& listenerSaIdList = listenerMap_[systemAbilityId];
330         auto iter = std::find_if(listenerSaIdList.begin(), listenerSaIdList.end(), [listenerSaId](int32_t SaId) {
331             return SaId == listenerSaId;
332         });
333         if (iter != listenerSaIdList.end()) {
334             listenerSaIdList.erase(iter);
335         }
336         HILOGI(TAG, "RemoveSystemAbilityListener SA:%{public}d, size:%{public}zu", systemAbilityId,
337             listenerSaIdList.size());
338         if (!listenerSaIdList.empty()) {
339             return true;
340         }
341         listenerMap_.erase(systemAbilityId);
342     }
343 
344     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
345     if (samgrProxy == nullptr) {
346         HILOGE(TAG, "failed to get samgrProxy");
347         return false;
348     }
349     int32_t ret = samgrProxy->UnSubscribeSystemAbility(systemAbilityId, GetSystemAbilityStatusChange());
350     if (ret) {
351         HILOGE(TAG, "failed to unsubscribe SA:%{public}d, process name:%{public}s",
352             systemAbilityId, Str16ToStr8(procName_).c_str());
353         return false;
354     }
355     return true;
356 }
357 
NotifyAbilityListener(int32_t systemAbilityId,int32_t listenerSaId,const std::string & deviceId,int32_t code)358 void LocalAbilityManager::NotifyAbilityListener(int32_t systemAbilityId, int32_t listenerSaId,
359     const std::string& deviceId, int32_t code)
360 {
361     HILOGI(TAG, "SA:%{public}d, listenerSA:%{public}d, code:%{public}d", systemAbilityId, listenerSaId, code);
362     auto ability = GetAbility(listenerSaId);
363     if (ability == nullptr) {
364         HILOGE(TAG, "failed to get listener SA:%{public}d", listenerSaId);
365         return;
366     }
367 
368     switch (code) {
369         case ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY: {
370             HILOGD(TAG, "OnAddSystemAbility, SA:%{public}d", listenerSaId);
371             ability->OnAddSystemAbility(systemAbilityId, deviceId);
372             break;
373         }
374         case ISystemAbilityStatusChange::ON_REMOVE_SYSTEM_ABILITY: {
375             HILOGD(TAG, "OnRemoveSystemAbility, SA:%{public}d", listenerSaId);
376             ability->OnRemoveSystemAbility(systemAbilityId, deviceId);
377             break;
378         }
379         default:
380             break;
381     }
382 }
383 
FindAndNotifyAbilityListeners(int32_t systemAbilityId,const std::string & deviceId,int32_t code)384 void LocalAbilityManager::FindAndNotifyAbilityListeners(int32_t systemAbilityId,
385     const std::string& deviceId, int32_t code)
386 {
387     HILOGD(TAG, "SA:%{public}d, code:%{public}d", systemAbilityId, code);
388     int64_t begin = GetTickCount();
389     std::list<int32_t> listenerSaIdList;
390     {
391         std::lock_guard<std::mutex> autoLock(listenerLock_);
392         auto iter = listenerMap_.find(systemAbilityId);
393         if (iter != listenerMap_.end()) {
394             listenerSaIdList = iter->second;
395         } else {
396             HILOGW(TAG, "SA:%{public}d not found", systemAbilityId);
397         }
398     }
399     for (auto listenerSaId : listenerSaIdList) {
400         NotifyAbilityListener(systemAbilityId, listenerSaId, deviceId, code);
401     }
402     HILOGI(TAG, "SA:%{public}d, code:%{public}d spend:%{public}" PRId64 " ms", systemAbilityId, code,
403         GetTickCount() - begin);
404 }
405 
OnStartAbility(int32_t systemAbilityId)406 bool LocalAbilityManager::OnStartAbility(int32_t systemAbilityId)
407 {
408     HILOGD(TAG, "try to start SA:%{public}d", systemAbilityId);
409     auto ability = GetAbility(systemAbilityId);
410     if (ability == nullptr) {
411         return false;
412     }
413     ability->Start();
414     return true;
415 }
416 
OnStopAbility(int32_t systemAbilityId)417 bool LocalAbilityManager::OnStopAbility(int32_t systemAbilityId)
418 {
419     HILOGD(TAG, "try to stop SA:%{public}d", systemAbilityId);
420     auto ability = GetAbility(systemAbilityId);
421     if (ability == nullptr) {
422         return false;
423     }
424     ability->Stop();
425     return true;
426 }
427 
GetAbility(int32_t systemAbilityId)428 SystemAbility* LocalAbilityManager::GetAbility(int32_t systemAbilityId)
429 {
430     std::shared_lock<std::shared_mutex> readLock(abilityMapLock_);
431     auto it = abilityMap_.find(systemAbilityId);
432     if (it == abilityMap_.end()) {
433         HILOGW(TAG, "SA:%{public}d not register", systemAbilityId);
434         return nullptr;
435     }
436 
437     return it->second;
438 }
439 
GetRunningStatus(int32_t systemAbilityId)440 bool LocalAbilityManager::GetRunningStatus(int32_t systemAbilityId)
441 {
442     auto ability = GetAbility(systemAbilityId);
443     if (ability == nullptr) {
444         return false;
445     }
446 
447     return ability->GetRunningStatus();
448 }
449 
StartOndemandSystemAbility(int32_t systemAbilityId)450 void LocalAbilityManager::StartOndemandSystemAbility(int32_t systemAbilityId)
451 {
452     pthread_setname_np(pthread_self(), ONDEMAND_WORKER.c_str());
453     HILOGD(TAG, "[PerformanceTest] SAFWK ondemand LoadSaLib systemAbilityId:%{public}d library", systemAbilityId);
454     int64_t begin = GetTickCount();
455     bool isExist = profileParser_->LoadSaLib(systemAbilityId);
456     HILOGI(TAG, "[PerformanceTest] SAFWK ondemand LoadSaLib systemAbilityId:%{public}d, spend:%{public}" PRId64 " ms",
457         systemAbilityId, (GetTickCount() - begin));
458     if (isExist) {
459         int32_t timeout = RETRY_TIMES_FOR_ONDEMAND;
460         constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_ONDEMAND_ONE_TIME).count();
461         {
462             std::shared_lock<std::shared_mutex> readLock(abilityMapLock_);
463             auto it = abilityMap_.find(systemAbilityId);
464             while (it == abilityMap_.end()) {
465                 HILOGI(TAG, "waiting for SA:%{public}d...", systemAbilityId);
466                 if (timeout > 0) {
467                     usleep(duration);
468                     it = abilityMap_.find(systemAbilityId);
469                 } else {
470                     HILOGE(TAG, "waiting for SA:%{public}d time out (1s)", systemAbilityId);
471                     return;
472                 }
473                 timeout--;
474             }
475         }
476 
477         if (!OnStartAbility(systemAbilityId)) {
478             HILOGE(TAG, "failed to start ability:%{public}d", systemAbilityId);
479         }
480     } else {
481         HILOGW(TAG, "SA:%{public}d not found", systemAbilityId);
482     }
483 }
484 
StartAbility(int32_t systemAbilityId,const std::string & eventStr)485 bool LocalAbilityManager::StartAbility(int32_t systemAbilityId, const std::string& eventStr)
486 {
487     HILOGI(TAG, "[PerformanceTest] SAFWK received start systemAbilityId:%{public}d request", systemAbilityId);
488     nlohmann::json startReason = ParseUtil::StringToJsonObj(eventStr);
489     SetStartReason(systemAbilityId, startReason);
490     auto task = std::bind(&LocalAbilityManager::StartOndemandSystemAbility, this, systemAbilityId);
491     std::thread thread(task);
492     thread.detach();
493     return true;
494 }
495 
StopOndemandSystemAbility(int32_t systemAbilityId)496 void LocalAbilityManager::StopOndemandSystemAbility(int32_t systemAbilityId)
497 {
498     pthread_setname_np(pthread_self(), ONDEMAND_WORKER.c_str());
499     if (!OnStopAbility(systemAbilityId)) {
500         HILOGE(TAG, "failed to stop ability:%{public}d", systemAbilityId);
501     }
502 }
503 
StopAbility(int32_t systemAbilityId,const std::string & eventStr)504 bool LocalAbilityManager::StopAbility(int32_t systemAbilityId, const std::string& eventStr)
505 {
506     HILOGI(TAG, "[PerformanceTest] SAFWK received stop systemAbilityId:%{public}d request", systemAbilityId);
507     nlohmann::json stopReason = ParseUtil::StringToJsonObj(eventStr);
508     SetStopReason(systemAbilityId, stopReason);
509     auto task = std::bind(&LocalAbilityManager::StopOndemandSystemAbility, this, systemAbilityId);
510     std::thread thread(task);
511     thread.detach();
512     return true;
513 }
514 
ActiveAbility(int32_t systemAbilityId,const nlohmann::json & activeReason)515 bool LocalAbilityManager::ActiveAbility(int32_t systemAbilityId,
516     const nlohmann::json& activeReason)
517 {
518     HILOGD(TAG, "active SA:%{public}d", systemAbilityId);
519     auto ability = GetAbility(systemAbilityId);
520     if (ability == nullptr) {
521         return false;
522     }
523     SystemAbilityOnDemandReason onDemandActiveReason = JsonToOnDemandReason(activeReason);
524     ability->Active(onDemandActiveReason);
525     return true;
526 }
527 
IdleAbility(int32_t systemAbilityId,const nlohmann::json & idleReason,int32_t & delayTime)528 bool LocalAbilityManager::IdleAbility(int32_t systemAbilityId,
529     const nlohmann::json& idleReason, int32_t& delayTime)
530 {
531     HILOGD(TAG, "idle SA:%{public}d", systemAbilityId);
532     auto ability = GetAbility(systemAbilityId);
533     if (ability == nullptr) {
534         return false;
535     }
536     SystemAbilityOnDemandReason onDemandIdleReason = JsonToOnDemandReason(idleReason);
537     ability->Idle(onDemandIdleReason, delayTime);
538     return true;
539 }
540 
JsonToOnDemandReason(const nlohmann::json & reasonJson)541 SystemAbilityOnDemandReason LocalAbilityManager::JsonToOnDemandReason(const nlohmann::json& reasonJson)
542 {
543     SystemAbilityOnDemandReason onDemandStartReason;
544     if (reasonJson.contains(EVENT_ID) && reasonJson[EVENT_ID].is_number()) {
545         onDemandStartReason.SetId(reasonJson[EVENT_ID]);
546     }
547     if (reasonJson.contains(NAME) && reasonJson[NAME].is_string()) {
548         onDemandStartReason.SetName(reasonJson[NAME]);
549     }
550     if (reasonJson.contains(VALUE) && reasonJson[VALUE].is_string()) {
551         onDemandStartReason.SetValue(reasonJson[VALUE]);
552     }
553     if (reasonJson.contains(EXTRA_DATA_ID) && reasonJson[EXTRA_DATA_ID].is_number()) {
554         onDemandStartReason.SetExtraDataId(reasonJson[EXTRA_DATA_ID]);
555     }
556     return onDemandStartReason;
557 }
558 
InitializeOnDemandSaProfile(int32_t saId)559 bool LocalAbilityManager::InitializeOnDemandSaProfile(int32_t saId)
560 {
561     int64_t begin = GetTickCount();
562     HILOGD(TAG, "[PerformanceTest] SAFWK LoadSaLib systemAbilityId:%{public}d", saId);
563     bool result = profileParser_->LoadSaLib(saId);
564     HILOGI(TAG, "[PerformanceTest] SAFWK LoadSaLib systemAbilityId:%{public}d finished, spend:%{public}"
565         PRId64 " ms", saId, (GetTickCount() - begin));
566     if (!result) {
567         HILOGW(TAG, "[PerformanceTest] LoadSaLib failed, Said:{public}%d", saId);
568         return false;
569     }
570     SaProfile saProfile;
571     bool ret = profileParser_->GetProfile(saId, saProfile);
572     if (ret) {
573         return InitializeSaProfilesInnerLocked(saProfile);
574     }
575     return false;
576 }
577 
InitializeSaProfilesInnerLocked(const SaProfile & saProfile)578 bool LocalAbilityManager::InitializeSaProfilesInnerLocked(const SaProfile& saProfile)
579 {
580     std::unique_lock<std::shared_mutex> readLock(abilityMapLock_);
581     auto iterProfile = abilityMap_.find(saProfile.saId);
582     if (iterProfile == abilityMap_.end()) {
583         HILOGW(TAG, "SA:%{public}d not found", saProfile.saId);
584         return false;
585     }
586     auto systemAbility = iterProfile->second;
587     if (systemAbility == nullptr) {
588         HILOGW(TAG, "SA:%{public}d is null", saProfile.saId);
589         return false;
590     }
591     auto& saList = abilityPhaseMap_[saProfile.bootPhase];
592     saList.emplace_back(systemAbility);
593     return true;
594 }
595 
CheckDependencyStatus(const vector<int32_t> & dependSa)596 vector<int32_t> LocalAbilityManager::CheckDependencyStatus(const vector<int32_t>& dependSa)
597 {
598     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
599     if (samgrProxy == nullptr) {
600         HILOGW(TAG, "failed to get samgrProxy");
601         return dependSa;
602     }
603 
604     vector<int32_t> checkSaStatusResult;
605     for (const auto& saId : dependSa) {
606         if (CheckInputSysAbilityId(saId)) {
607             sptr<IRemoteObject> saObject = samgrProxy->CheckSystemAbility(saId);
608             if (saObject == nullptr) {
609                 checkSaStatusResult.emplace_back(saId);
610             }
611         } else {
612             HILOGW(TAG, "dependency's id:%{public}d is invalid", saId);
613         }
614     }
615     return checkSaStatusResult;
616 }
617 
StartDependSaTask(SystemAbility * ability)618 void LocalAbilityManager::StartDependSaTask(SystemAbility* ability)
619 {
620     if (ability == nullptr) {
621         HILOGE(TAG, "ability is null");
622         return;
623     }
624     int64_t start = GetTickCount();
625     int64_t dependTimeout = ability->GetDependTimeout();
626     while (!CheckDependencyStatus(ability->GetDependSa()).empty()) {
627         int64_t end = GetTickCount();
628         int64_t duration = ((end >= start) ? (end - start) : (INT64_MAX - end + start));
629         if (duration < dependTimeout) {
630             usleep(CHECK_DEPENDENT_SA_PERIOD);
631         } else {
632             break;
633         }
634     }
635     vector<int32_t> unpreparedDeps = CheckDependencyStatus(ability->GetDependSa());
636     if (unpreparedDeps.empty()) {
637         ability->Start();
638     } else {
639         for (const auto& unpreparedDep : unpreparedDeps) {
640             HILOGI(TAG, "%{public}d's dependency:%{public}d not started in %{public}d ms",
641                 ability->GetSystemAbilitId(), unpreparedDep, ability->GetDependTimeout());
642         }
643     }
644 }
645 
StartSystemAbilityTask(SystemAbility * ability)646 void LocalAbilityManager::StartSystemAbilityTask(SystemAbility* ability)
647 {
648     if (ability != nullptr) {
649         HILOGD(TAG, "StartSystemAbility is called for %{public}d", ability->GetSystemAbilitId());
650         if (ability->GetDependSa().empty()) {
651             ability->Start();
652         } else {
653             StartDependSaTask(ability);
654         }
655         HILOGI(TAG, "%{public}s SA : %{public}d init finished, %{public}" PRId64 " ms",
656             Str16ToStr8(procName_).c_str(), ability->GetSystemAbilitId(), (GetTickCount() - startBegin_));
657     }
658 
659     std::lock_guard<std::mutex> lock(startPhaseLock_);
660     if (startTaskNum_ > 0) {
661         --startTaskNum_;
662     }
663     startPhaseCV_.notify_one();
664 }
665 
RegisterOnDemandSystemAbility(int32_t saId)666 void LocalAbilityManager::RegisterOnDemandSystemAbility(int32_t saId)
667 {
668     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
669     if (samgrProxy == nullptr) {
670         HILOGI(TAG, "failed to get samgrProxy");
671         return;
672     }
673 
674     auto& saProfileList = profileParser_->GetAllSaProfiles();
675     for (const auto& saProfile : saProfileList) {
676         if (NeedRegisterOnDemand(saProfile, saId)) {
677             HILOGD(TAG, "register ondemand ability:%{public}d to samgr", saProfile.saId);
678             int32_t ret = samgrProxy->AddOnDemandSystemAbilityInfo(saProfile.saId, procName_);
679             if (ret != ERR_OK) {
680                 HILOGI(TAG, "failed to add ability info for on-demand SA:%{public}d", saProfile.saId);
681             }
682         }
683     }
684 }
685 
686 // on default load, not-run-on-create SA will register to OnDemandSystemAbility
687 // on demand load, other SA will register to OnDemandSystemAbility, although some are runOnCreate
NeedRegisterOnDemand(const SaProfile & saProfile,int32_t saId)688 bool LocalAbilityManager::NeedRegisterOnDemand(const SaProfile& saProfile, int32_t saId)
689 {
690     return (saId == DEFAULT_SAID && !saProfile.runOnCreate) ||
691         (saId != DEFAULT_SAID && saProfile.saId != saId);
692 }
693 
StartPhaseTasks(const std::list<SystemAbility * > & systemAbilityList)694 void LocalAbilityManager::StartPhaseTasks(const std::list<SystemAbility*>& systemAbilityList)
695 {
696     if (systemAbilityList.empty()) {
697         return;
698     }
699 
700     for (auto systemAbility : systemAbilityList) {
701         if (systemAbility != nullptr) {
702             HILOGD(TAG, "add phase task for SA:%{public}d", systemAbility->GetSystemAbilitId());
703             std::lock_guard<std::mutex> autoLock(startPhaseLock_);
704             ++startTaskNum_;
705             auto task = std::bind(&LocalAbilityManager::StartSystemAbilityTask, this, systemAbility);
706             initPool_->AddTask(task);
707         }
708     }
709 }
710 
WaitForTasks()711 void LocalAbilityManager::WaitForTasks()
712 {
713     int64_t begin = GetTickCount();
714     HILOGD(TAG, "start waiting for all tasks!");
715     std::unique_lock<std::mutex> lck(startPhaseLock_);
716     if (!startPhaseCV_.wait_for(lck, std::chrono::seconds(MAX_SA_STARTUP_TIME),
717         [this] () { return startTaskNum_ == 0; })) {
718         HILOGW(TAG, "start timeout!");
719     }
720     startTaskNum_ = 0;
721     int64_t end = GetTickCount();
722     HILOGI(TAG, "start tasks finished and spend %{public}" PRId64 " ms", (end - begin));
723 }
724 
FindAndStartPhaseTasks(int32_t saId)725 void LocalAbilityManager::FindAndStartPhaseTasks(int32_t saId)
726 {
727     if (saId == DEFAULT_SAID) {
728         for (uint32_t bootPhase = BOOT_START; bootPhase <= OTHER_START; ++bootPhase) {
729             auto iter = abilityPhaseMap_.find(bootPhase);
730             if (iter != abilityPhaseMap_.end()) {
731                 StartPhaseTasks(iter->second);
732                 InitializeRunOnCreateSaProfiles(bootPhase + 1);
733                 WaitForTasks();
734             } else {
735                 InitializeRunOnCreateSaProfiles(bootPhase + 1);
736             }
737         }
738     } else {
739         for (uint32_t bootPhase = BOOT_START; bootPhase <= OTHER_START; ++bootPhase) {
740             auto iter = abilityPhaseMap_.find(bootPhase);
741             if (iter != abilityPhaseMap_.end()) {
742                 StartPhaseTasks(iter->second);
743                 WaitForTasks();
744             }
745         }
746     }
747 }
748 
InitializeRunOnCreateSaProfiles(uint32_t bootPhase)749 bool LocalAbilityManager::InitializeRunOnCreateSaProfiles(uint32_t bootPhase)
750 {
751     if (bootPhase > OTHER_START) {
752         return false;
753     }
754     int64_t begin = GetTickCount();
755     HILOGD(TAG, "[PerformanceTest] SAFWK load phase %{public}d libraries", bootPhase);
756     profileParser_->OpenSo(bootPhase);
757     HILOGI(TAG, "[PerformanceTest] SAFWK load phase %{public}d libraries finished, spend:%{public}" PRId64 " ms",
758         bootPhase, (GetTickCount() - begin));
759     auto& saProfileList = profileParser_->GetAllSaProfiles();
760     if (saProfileList.empty()) {
761         HILOGW(TAG, "sa profile is empty");
762         return false;
763     }
764     for (const auto& saProfile : saProfileList) {
765         if (saProfile.bootPhase != bootPhase) {
766             continue;
767         }
768         if (!InitializeSaProfilesInnerLocked(saProfile)) {
769             HILOGW(TAG, "SA:%{public}d init fail", saProfile.saId);
770             continue;
771         }
772     }
773     return true;
774 }
775 
Run(int32_t saId)776 bool LocalAbilityManager::Run(int32_t saId)
777 {
778     HILOGD(TAG, "local ability manager is running...");
779     bool addResult = AddLocalAbilityManager();
780     if (!addResult) {
781         HILOGE(TAG, "failed to add local abilitymanager");
782         return false;
783     }
784     HILOGD(TAG, "success to add process name:%{public}s", Str16ToStr8(procName_).c_str());
785     uint32_t concurrentThreads = std::thread::hardware_concurrency();
786     HILOGI(TAG, "concurrentThreads is %{public}d", concurrentThreads);
787     initPool_->Start(concurrentThreads);
788     initPool_->SetMaxTaskNum(MAX_TASK_NUMBER);
789 
790     RegisterOnDemandSystemAbility(saId);
791     FindAndStartPhaseTasks(saId);
792     initPool_->Stop();
793     return true;
794 }
795 
AddLocalAbilityManager()796 bool LocalAbilityManager::AddLocalAbilityManager()
797 {
798     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
799     if (samgrProxy == nullptr) {
800         HILOGE(TAG, "failed to get samgrProxy");
801         return false;
802     }
803 
804     if (localAbilityManager_ == nullptr) {
805         localAbilityManager_ = this;
806     }
807     int32_t ret = samgrProxy->AddSystemProcess(procName_, localAbilityManager_);
808     return ret == ERR_OK;
809 }
810 
SetStartReason(int32_t saId,const nlohmann::json & event)811 void LocalAbilityManager::SetStartReason(int32_t saId, const nlohmann::json& event)
812 {
813     std::lock_guard<std::mutex> autoLock(ReasonLock_);
814     saIdToStartReason_[saId] = event;
815 }
816 
SetStopReason(int32_t saId,const nlohmann::json & event)817 void LocalAbilityManager::SetStopReason(int32_t saId, const nlohmann::json& event)
818 {
819     std::lock_guard<std::mutex> autoLock(ReasonLock_);
820     saIdToStopReason_[saId] = event;
821 }
822 
GetStartReason(int32_t saId)823 nlohmann::json& LocalAbilityManager::GetStartReason(int32_t saId)
824 {
825     std::lock_guard<std::mutex> autoLock(ReasonLock_);
826     return saIdToStartReason_[saId];
827 }
828 
GetStopReason(int32_t saId)829 nlohmann::json& LocalAbilityManager::GetStopReason(int32_t saId)
830 {
831     std::lock_guard<std::mutex> autoLock(ReasonLock_);
832     return saIdToStopReason_[saId];
833 }
834 
GetSystemAbilityStatusChange()835 sptr<ISystemAbilityStatusChange> LocalAbilityManager::GetSystemAbilityStatusChange()
836 {
837     std::lock_guard<std::mutex> autoLock(listenerLock_);
838     if (statusChangeListener_ == nullptr) {
839         statusChangeListener_ = new SystemAbilityListener();
840     }
841     return statusChangeListener_;
842 }
843 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)844 void LocalAbilityManager::SystemAbilityListener::OnAddSystemAbility(int32_t systemAbilityId,
845     const std::string& deviceId)
846 {
847     HILOGD(TAG, "SA:%{public}d added", systemAbilityId);
848     if (!CheckInputSysAbilityId(systemAbilityId)) {
849         HILOGW(TAG, "SA:%{public}d is invalid!", systemAbilityId);
850         return;
851     }
852 
853     GetInstance().FindAndNotifyAbilityListeners(systemAbilityId, deviceId,
854         ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY);
855 }
856 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)857 void LocalAbilityManager::SystemAbilityListener::OnRemoveSystemAbility(int32_t systemAbilityId,
858     const std::string& deviceId)
859 {
860     HILOGD(TAG, "SA:%{public}d removed", systemAbilityId);
861     if (!CheckInputSysAbilityId(systemAbilityId)) {
862         HILOGW(TAG, "SA:%{public}d is invalid!", systemAbilityId);
863         return;
864     }
865 
866     GetInstance().FindAndNotifyAbilityListeners(systemAbilityId, deviceId,
867         ISystemAbilityStatusChange::ON_REMOVE_SYSTEM_ABILITY);
868 }
869 }
870