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