• 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 <dlfcn.h>
21 #include <iostream>
22 #include <sys/types.h>
23 #include <thread>
24 
25 #include "datetime_ex.h"
26 #include "errors.h"
27 #include "hitrace_meter.h"
28 #include "ipc_skeleton.h"
29 #include "iservice_registry.h"
30 #include "safwk_log.h"
31 #include "file_ex.h"
32 #include "string_ex.h"
33 #include "hisysevent_adapter.h"
34 #include "system_ability_ondemand_reason.h"
35 #include "local_ability_manager_dumper.h"
36 #include "timer.h"
37 #include "hisysevent_adapter.h"
38 #include "system_ability_definition.h"
39 #include "samgr_xcollie.h"
40 #ifdef SAFWK_ENABLE_RUN_ON_DEMAND_QOS
41 #include <sys/syscall.h>
42 #include <sys/resource.h>
43 #endif
44 
45 namespace OHOS {
46 using std::u16string;
47 using std::string;
48 using std::vector;
49 
50 namespace {
51 constexpr int32_t RETRY_TIMES_FOR_ONDEMAND = 10;
52 constexpr int32_t RETRY_TIMES_FOR_SAMGR = 50;
53 constexpr int32_t DEFAULT_SAID = -1;
54 constexpr int32_t UNUSED_RESIDENT_TIMER_INTERVAL = 1000 * 60 * 10;
55 constexpr int32_t UNUSED_ONDEMAND_TIMER_INTERVAL = 1000 * 60 * 1;
56 constexpr int32_t ONDEMAND_SA_UNUSED_TIMEOUT_LOWLIMIT = UNUSED_ONDEMAND_TIMER_INTERVAL;
57 constexpr int32_t ONDEMAND_SA_UNUSED_TIMEOUT_UPLIMIT = 1000 * 60 * 120;
58 constexpr int32_t RESIDENT_SA_UNUSED_TIMEOUT = 1000 * 60 * 10;
59 constexpr std::chrono::milliseconds MILLISECONDS_WAITING_SAMGR_ONE_TIME(200);
60 constexpr std::chrono::milliseconds MILLISECONDS_WAITING_ONDEMAND_ONE_TIME(100);
61 constexpr int32_t TIME_S_TO_MS = 1000;
62 constexpr int32_t MAX_DEPEND_TIMEOUT = 65;
63 constexpr int32_t MAX_CHECK_TIMEOUT = 10;
64 
65 constexpr int32_t MAX_SA_STARTUP_TIME = 100;
66 constexpr int32_t SUFFIX_LENGTH = 5; // .json length
67 constexpr uint32_t FFRT_DUMP_INFO_ALL = 0;
68 constexpr int FFRT_BUFFER_SIZE = 512 * 1024;
69 
70 #ifdef SAFWK_ENABLE_RUN_ON_DEMAND_QOS
71 constexpr int OPEN_SO_PRIO = -20;
72 constexpr int NORMAL_PRIO = 0;
73 #endif
74 
75 constexpr const char* PROFILES_DIR = "/system/profile/";
76 constexpr const char* DEFAULT_DIR = "/system/usr/";
77 constexpr const char* PREFIX = PROFILES_DIR;
78 constexpr const char* SUFFIX = "_trust.json";
79 
80 constexpr const char* ONDEMAND_WORKER = "SaOndemand";
81 constexpr const char* INIT_POOL = "SaInit";
82 
83 constexpr const char* EVENT_ID = "eventId";
84 constexpr const char* NAME = "name";
85 constexpr const char* VALUE = "value";
86 constexpr const char* EXTRA_DATA_ID = "extraDataId";
87 
88 enum {
89     BOOT_START = 1,
90     CORE_START = 2,
91     OTHER_START = 3,
92 };
93 }
94 
95 IMPLEMENT_SINGLE_INSTANCE(LocalAbilityManager);
96 
97 #ifdef SAFWK_ENABLE_RUN_ON_DEMAND_QOS
SetThreadPrio(int priority)98 static void SetThreadPrio(int priority)
99 {
100     int tid = syscall(SYS_gettid);
101     LOGI("set tid:%{public}d priority:%{public}d.", tid, priority);
102     if (setpriority(PRIO_PROCESS, tid, priority) != 0) {
103         LOGE("set tid:%{public}d priority:%{public}d failed.", tid, priority);
104     }
105 }
106 #endif
107 
LocalAbilityManager()108 LocalAbilityManager::LocalAbilityManager()
109 {
110     profileParser_ = std::make_shared<ParseUtil>();
111     initPool_ = std::make_unique<ThreadPool>(INIT_POOL);
112 }
113 
~LocalAbilityManager()114 LocalAbilityManager::~LocalAbilityManager()
115 {
116     if (idleTimer_ != nullptr) {
117         idleTimer_->Shutdown();
118     }
119 }
120 
DoStartSAProcess(const std::string & profilePath,int32_t saId)121 void LocalAbilityManager::DoStartSAProcess(const std::string& profilePath, int32_t saId)
122 {
123     startBegin_ = GetTickCount();
124     HILOGD(TAG, "SA:%{public}d", saId);
125     string realProfilePath = "";
126     if (!CheckAndGetProfilePath(profilePath, realProfilePath)) {
127         ReportSaMainExit("DoStartSAProcess invalid path");
128         HILOGE(TAG, "DoStartSAProcess invalid path");
129         return;
130     }
131     {
132         std::string traceTag = GetTraceTag(realProfilePath);
133         HITRACE_METER_NAME(HITRACE_TAG_SAMGR, traceTag);
134         bool ret = InitSystemAbilityProfiles(realProfilePath, saId);
135         if (!ret) {
136             ReportSaMainExit("InitSaProfiles no right profile");
137             HILOGE(TAG, "InitSystemAbilityProfiles no right profile, will exit");
138             return;
139         }
140         {
141             SamgrXCollie samgrXCollie("safwk--CheckSamgrReady", MAX_CHECK_TIMEOUT);
142             ret = CheckSystemAbilityManagerReady();
143         }
144         if (!ret) {
145             ReportSaMainExit("CheckSamgrReady failed");
146             HILOGE(TAG, "CheckSystemAbilityManagerReady failed! will exit");
147             return;
148         }
149         ret = Run(saId);
150         if (!ret) {
151             ReportSaMainExit("SA Run failed");
152             HILOGE(TAG, "Run failed! will exit");
153             return;
154         }
155     }
156 
157     StartTimedQuery();
158     IPCSkeleton::JoinWorkThread();
159     HILOGE(TAG, "JoinWorkThread stop, will exit");
160 }
161 
GetTraceTag(const std::string & profilePath)162 std::string LocalAbilityManager::GetTraceTag(const std::string& profilePath)
163 {
164     std::vector<std::string> libPathVec;
165     string traceTag = "default_proc";
166     SplitStr(profilePath, "/", libPathVec);
167     if ((libPathVec.size() > 0)) {
168         traceTag = libPathVec[libPathVec.size() - 1];
169         auto size = traceTag.length();
170         if (size > SUFFIX_LENGTH) {
171             return traceTag.substr(0, size - SUFFIX_LENGTH);
172         }
173     }
174     return traceTag;
175 }
176 
CheckAndGetProfilePath(const std::string & profilePath,std::string & realProfilePath)177 bool LocalAbilityManager::CheckAndGetProfilePath(const std::string& profilePath, std::string& realProfilePath)
178 {
179     if (profilePath.length() > PATH_MAX) {
180         HILOGE(TAG, "profilePath length too long!");
181         return false;
182     }
183     char realPath[PATH_MAX] = {'\0'};
184     if (realpath(profilePath.c_str(), realPath) == nullptr) {
185         HILOGE(TAG, "file path does not exist!");
186         return false;
187     }
188     // realProfilePath must begin with "/system/profile/" or begin with "/system/usr/"
189     realProfilePath = realPath;
190     if (realProfilePath.find(PROFILES_DIR) != 0 && realProfilePath.find(DEFAULT_DIR) != 0) {
191         HILOGE(TAG, "file path is not matched");
192         return false;
193     }
194     return true;
195 }
196 
CheckSystemAbilityManagerReady()197 bool LocalAbilityManager::CheckSystemAbilityManagerReady()
198 {
199     int32_t timeout = RETRY_TIMES_FOR_SAMGR;
200     constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_SAMGR_ONE_TIME).count();
201     sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
202     while (samgrProxy == nullptr) {
203         HILOGI(TAG, "%{public}s waiting for samgr...", Str16ToStr8(procName_).c_str());
204         if (timeout > 0) {
205             usleep(duration);
206             samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
207         } else {
208             HILOGE(TAG, "wait for samgr time out (10s)");
209             return false;
210         }
211         timeout--;
212     }
213     return true;
214 }
215 
InitSystemAbilityProfiles(const std::string & profilePath,int32_t saId)216 bool LocalAbilityManager::InitSystemAbilityProfiles(const std::string& profilePath, int32_t saId)
217 {
218     LOGD("InitProfiles parse sa profiles!");
219     int64_t begin = GetTickCount();
220     bool ret = profileParser_->ParseSaProfiles(profilePath);
221     if (!ret) {
222         HILOGW(TAG, "ParseSaProfiles failed!");
223         return false;
224     }
225 
226     procName_ = profileParser_->GetProcessName();
227     auto saInfos = profileParser_->GetAllSaProfiles();
228     std::string process = Str16ToStr8(procName_);
229     LOGI("InitProfiles proc:%{public}s end,spend:%{public}" PRId64 "ms", process.c_str(), (GetTickCount() - begin));
230     std::string path = PREFIX + process + SUFFIX;
231     bool isExist = profileParser_->CheckPathExist(path);
232     if (isExist) {
233         CheckTrustSa(path, process, saInfos);
234     }
235     return InitializeSaProfiles(saId);
236 }
237 
InitializeSaProfiles(int32_t saId)238 bool LocalAbilityManager::InitializeSaProfiles(int32_t saId)
239 {
240     if (saId != DEFAULT_SAID) {
241         return InitializeOnDemandSaProfile(saId);
242     } else {
243         return InitializeRunOnCreateSaProfiles(BOOT_START);
244     }
245 }
246 
CheckTrustSa(const std::string & path,const std::string & process,const std::list<SaProfile> & saInfos)247 void LocalAbilityManager::CheckTrustSa(const std::string& path, const std::string& process,
248     const std::list<SaProfile>& saInfos)
249 {
250     HILOGD(TAG, "CheckTrustSa start");
251     std::map<std::u16string, std::set<int32_t>> trustMaps;
252     bool ret = profileParser_->ParseTrustConfig(path, trustMaps);
253     if (ret && !trustMaps.empty()) {
254         // 1.get allowed sa set in the process
255         const auto& saSets = trustMaps[Str8ToStr16(process)];
256         // 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
257         for (const auto& saInfo : saInfos) {
258             if (saSets.find(saInfo.saId) == saSets.end()) {
259                 HILOGW(TAG, "SA:%{public}d not allow to load in %{public}s", saInfo.saId, process.c_str());
260                 profileParser_->RemoveSaProfile(saInfo.saId);
261             }
262         }
263     }
264 }
265 
ClearResource()266 void LocalAbilityManager::ClearResource()
267 {
268     profileParser_->ClearResource();
269 }
270 
AddAbility(SystemAbility * ability)271 bool LocalAbilityManager::AddAbility(SystemAbility* ability)
272 {
273     if (ability == nullptr) {
274         HILOGW(TAG, "try to add null ability!");
275         return false;
276     }
277 
278     int32_t saId = ability->GetSystemAbilitId();
279     SaProfile saProfile;
280     bool ret = profileParser_->GetProfile(saId, saProfile);
281     if (!ret) {
282         return false;
283     }
284     std::unique_lock<std::shared_mutex> writeLock(localAbilityMapLock_);
285     auto iter = localAbilityMap_.find(saId);
286     if (iter != localAbilityMap_.end()) {
287         HILOGW(TAG, "try to add existed SA:%{public}d!", saId);
288         return false;
289     }
290     HILOGI(TAG, "set profile attr for SA:%{public}d", saId);
291     ability->SetLibPath(saProfile.libPath);
292     ability->SetRunOnCreate(saProfile.runOnCreate);
293     ability->SetDependSa(saProfile.dependSa);
294     ability->SetDependTimeout(saProfile.dependTimeout);
295     ability->SetDistributed(saProfile.distributed);
296     ability->SetDumpLevel(saProfile.dumpLevel);
297     ability->SetCapability(saProfile.capability);
298     ability->SetPermission(saProfile.permission);
299     localAbilityMap_.emplace(saId, ability);
300     return true;
301 }
302 
RemoveAbility(int32_t systemAbilityId)303 bool LocalAbilityManager::RemoveAbility(int32_t systemAbilityId)
304 {
305     if (systemAbilityId <= 0) {
306         HILOGW(TAG, "invalid systemAbilityId");
307         return false;
308     }
309     std::unique_lock<std::shared_mutex> writeLock(localAbilityMapLock_);
310     (void)localAbilityMap_.erase(systemAbilityId);
311     return true;
312 }
313 
AddSystemAbilityListener(int32_t systemAbilityId,int32_t listenerSaId)314 bool LocalAbilityManager::AddSystemAbilityListener(int32_t systemAbilityId, int32_t listenerSaId)
315 {
316     if (!CheckInputSysAbilityId(systemAbilityId) || !CheckInputSysAbilityId(listenerSaId)) {
317         HILOGW(TAG, "SA:%{public}d or listenerSA:%{public}d invalid!", systemAbilityId, listenerSaId);
318         return false;
319     }
320     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
321     if (samgrProxy == nullptr) {
322         HILOGE(TAG, "failed to get samgrProxy");
323         return false;
324     }
325     bool isNeedNotify = false;
326     size_t listenerListSize = 0;
327     {
328         HILOGD(TAG, "SA:%{public}d, listenerSA:%{public}d", systemAbilityId, listenerSaId);
329         std::lock_guard<std::mutex> autoLock(listenerLock_);
330         auto& listenerList = localListenerMap_[systemAbilityId];
331         auto iter = std::find_if(listenerList.begin(), listenerList.end(),
332             [listenerSaId](const std::pair<int32_t, ListenerState>& listener) {
333             return listener.first == listenerSaId;
334         });
335         if (listenerList.size() > 0) {
336             sptr<IRemoteObject> object = samgrProxy->CheckSystemAbility(systemAbilityId);
337             if (object != nullptr) {
338                 isNeedNotify = true;
339             }
340         }
341         if (iter == listenerList.end()) {
342             listenerList.push_back({listenerSaId,
343                 (isNeedNotify) ? ListenerState::NOTIFIED : ListenerState::INIT});
344         }
345         listenerListSize = listenerList.size();
346         LOGI("AddSaListener SA:%{public}d,listenerSA:%{public}d,size:%{public}zu", systemAbilityId, listenerSaId,
347             listenerList.size());
348     }
349     if (listenerListSize > 1) {
350         if (isNeedNotify) {
351             NotifyAbilityListener(systemAbilityId, listenerSaId, "",
352                 ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY);
353         }
354         return true;
355     }
356     int32_t ret = samgrProxy->SubscribeSystemAbility(systemAbilityId, GetSystemAbilityStatusChange());
357     if (ret) {
358         HILOGE(TAG, "failed to subscribe SA:%{public}d, process name:%{public}s", systemAbilityId,
359             Str16ToStr8(procName_).c_str());
360         return false;
361     }
362     return true;
363 }
364 
RemoveSystemAbilityListener(int32_t systemAbilityId,int32_t listenerSaId)365 bool LocalAbilityManager::RemoveSystemAbilityListener(int32_t systemAbilityId, int32_t listenerSaId)
366 {
367     if (!CheckInputSysAbilityId(systemAbilityId) || !CheckInputSysAbilityId(listenerSaId)) {
368         HILOGW(TAG, "SA:%{public}d or listenerSA:%{public}d invalid!",
369             systemAbilityId, listenerSaId);
370         return false;
371     }
372     {
373         HILOGD(TAG, "SA:%{public}d, listenerSA:%{public}d", systemAbilityId, listenerSaId);
374         std::lock_guard<std::mutex> autoLock(listenerLock_);
375         if (localListenerMap_.count(systemAbilityId) == 0) {
376             return true;
377         }
378         auto& listenerList = localListenerMap_[systemAbilityId];
379         auto iter = std::find_if(listenerList.begin(), listenerList.end(),
380             [listenerSaId](const std::pair<int32_t, ListenerState>& listener) {
381             return listener.first == listenerSaId;
382         });
383         if (iter != listenerList.end()) {
384             listenerList.erase(iter);
385         }
386         HILOGI(TAG, "SA:%{public}d, size:%{public}zu", systemAbilityId,
387             listenerList.size());
388         if (!listenerList.empty()) {
389             return true;
390         }
391         localListenerMap_.erase(systemAbilityId);
392     }
393 
394     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
395     if (samgrProxy == nullptr) {
396         HILOGE(TAG, "failed to get samgrProxy");
397         return false;
398     }
399     int32_t ret = samgrProxy->UnSubscribeSystemAbility(systemAbilityId, GetSystemAbilityStatusChange());
400     if (ret) {
401         HILOGE(TAG, "failed to unsubscribe SA:%{public}d, process name:%{public}s",
402             systemAbilityId, Str16ToStr8(procName_).c_str());
403         return false;
404     }
405     return true;
406 }
407 
NotifyAbilityListener(int32_t systemAbilityId,int32_t listenerSaId,const std::string & deviceId,int32_t code)408 void LocalAbilityManager::NotifyAbilityListener(int32_t systemAbilityId, int32_t listenerSaId,
409     const std::string& deviceId, int32_t code)
410 {
411     LOGI("NotifyListener SA:%{public}d,listenerSA:%{public}d,code:%{public}d", systemAbilityId, listenerSaId, code);
412     auto ability = GetAbility(listenerSaId);
413     if (ability == nullptr) {
414         HILOGE(TAG, "failed to get listener SA:%{public}d", listenerSaId);
415         return;
416     }
417 
418     switch (code) {
419         case ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY: {
420             HILOGD(TAG, "OnAddSystemAbility, SA:%{public}d", listenerSaId);
421             ability->OnAddSystemAbility(systemAbilityId, deviceId);
422             break;
423         }
424         case ISystemAbilityStatusChange::ON_REMOVE_SYSTEM_ABILITY: {
425             HILOGD(TAG, "OnRemoveSystemAbility, SA:%{public}d", listenerSaId);
426             ability->OnRemoveSystemAbility(systemAbilityId, deviceId);
427             break;
428         }
429         default:
430             break;
431     }
432 }
433 
FindAndNotifyAbilityListeners(int32_t systemAbilityId,const std::string & deviceId,int32_t code)434 void LocalAbilityManager::FindAndNotifyAbilityListeners(int32_t systemAbilityId,
435     const std::string& deviceId, int32_t code)
436 {
437     HILOGD(TAG, "SA:%{public}d, code:%{public}d", systemAbilityId, code);
438     int64_t begin = GetTickCount();
439     std::vector<int32_t> listenerSaIdVec;
440     {
441         std::lock_guard<std::mutex> autoLock(listenerLock_);
442         auto iter = localListenerMap_.find(systemAbilityId);
443         if (iter == localListenerMap_.end()) {
444             HILOGW(TAG, "SA:%{public}d not found", systemAbilityId);
445             return;
446         }
447         if (code == ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY) {
448             for (auto& listener : iter->second) {
449                 if (listener.second == ListenerState::INIT) {
450                     listenerSaIdVec.push_back(listener.first);
451                     listener.second = ListenerState::NOTIFIED;
452                 } else {
453                     HILOGW(TAG, "listener SA:%{public}d has been notified add", listener.first);
454                 }
455             }
456         } else if (code == ISystemAbilityStatusChange::ON_REMOVE_SYSTEM_ABILITY) {
457             for (auto& listener : iter->second) {
458                 listenerSaIdVec.push_back(listener.first);
459                 if (listener.second == ListenerState::NOTIFIED) {
460                     listener.second = ListenerState::INIT;
461                 }
462             }
463         }
464     }
465     for (auto listenerSaId : listenerSaIdVec) {
466         NotifyAbilityListener(systemAbilityId, listenerSaId, deviceId, code);
467     }
468     LOGI("FindNotifyListeners SA:%{public}d,size:%{public}zu,code:%{public}d,spend:%{public}" PRId64 "ms",
469         systemAbilityId, listenerSaIdVec.size(), code, GetTickCount() - begin);
470 }
471 
OnStartAbility(int32_t systemAbilityId)472 bool LocalAbilityManager::OnStartAbility(int32_t systemAbilityId)
473 {
474     HILOGD(TAG, "try to start SA:%{public}d", systemAbilityId);
475     auto ability = GetAbility(systemAbilityId);
476     if (ability == nullptr) {
477         return false;
478     }
479     ability->Start();
480     return true;
481 }
482 
OnStopAbility(int32_t systemAbilityId)483 bool LocalAbilityManager::OnStopAbility(int32_t systemAbilityId)
484 {
485     HILOGD(TAG, "try to stop SA:%{public}d", systemAbilityId);
486     auto ability = GetAbility(systemAbilityId);
487     if (ability == nullptr) {
488         return false;
489     }
490     ability->Stop();
491     return true;
492 }
493 
GetAbility(int32_t systemAbilityId)494 SystemAbility* LocalAbilityManager::GetAbility(int32_t systemAbilityId)
495 {
496     std::shared_lock<std::shared_mutex> readLock(localAbilityMapLock_);
497     auto it = localAbilityMap_.find(systemAbilityId);
498     if (it == localAbilityMap_.end()) {
499         HILOGW(TAG, "SA:%{public}d not register", systemAbilityId);
500         return nullptr;
501     }
502 
503     return it->second;
504 }
505 
GetRunningStatus(int32_t systemAbilityId)506 bool LocalAbilityManager::GetRunningStatus(int32_t systemAbilityId)
507 {
508     auto ability = GetAbility(systemAbilityId);
509     if (ability == nullptr) {
510         return false;
511     }
512 
513     return ability->GetRunningStatus();
514 }
515 
StartOndemandSystemAbility(int32_t systemAbilityId)516 void LocalAbilityManager::StartOndemandSystemAbility(int32_t systemAbilityId)
517 {
518     pthread_setname_np(pthread_self(), ONDEMAND_WORKER);
519     LOGD("StartOndemandSa LoadSaLib SA:%{public}d library", systemAbilityId);
520     int64_t begin = GetTickCount();
521     bool isExist = profileParser_->LoadSaLib(systemAbilityId);
522     LOGI("StartOndemandSa LoadSaLib SA:%{public}d,spend:%{public}" PRId64 "ms",
523         systemAbilityId, (GetTickCount() - begin));
524     if (isExist) {
525         int32_t timeout = RETRY_TIMES_FOR_ONDEMAND;
526         constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_ONDEMAND_ONE_TIME).count();
527         {
528             auto it = localAbilityMap_.begin();
529             {
530                 std::shared_lock<std::shared_mutex> readLock(localAbilityMapLock_);
531                 it = localAbilityMap_.find(systemAbilityId);
532             }
533             while (it == localAbilityMap_.end()) {
534                 HILOGI(TAG, "waiting for SA:%{public}d...", systemAbilityId);
535                 if (timeout > 0) {
536                     usleep(duration);
537                     std::shared_lock<std::shared_mutex> readLock(localAbilityMapLock_);
538                     it = localAbilityMap_.find(systemAbilityId);
539                 } else {
540                     HILOGE(TAG, "waiting for SA:%{public}d time out (1s)", systemAbilityId);
541                     return;
542                 }
543                 timeout--;
544             }
545         }
546 
547         if (!OnStartAbility(systemAbilityId)) {
548             HILOGE(TAG, "failed to start SA:%{public}d", systemAbilityId);
549         }
550     } else {
551         HILOGW(TAG, "SA:%{public}d not found", systemAbilityId);
552     }
553 }
554 
StartAbility(int32_t systemAbilityId,const std::string & eventStr)555 bool LocalAbilityManager::StartAbility(int32_t systemAbilityId, const std::string& eventStr)
556 {
557     LOGI("StartSa recv start SA:%{public}d req", systemAbilityId);
558     nlohmann::json startReason = ParseUtil::StringToJsonObj(eventStr);
559     SetStartReason(systemAbilityId, startReason);
560     auto task = [this, systemAbilityId] {this->StartOndemandSystemAbility(systemAbilityId);};
561     std::thread thread(task);
562     thread.detach();
563     return true;
564 }
565 
StopOndemandSystemAbility(int32_t systemAbilityId)566 void LocalAbilityManager::StopOndemandSystemAbility(int32_t systemAbilityId)
567 {
568     pthread_setname_np(pthread_self(), ONDEMAND_WORKER);
569     if (!OnStopAbility(systemAbilityId)) {
570         HILOGE(TAG, "failed to stop SA:%{public}d", systemAbilityId);
571     }
572 }
573 
StopAbility(int32_t systemAbilityId,const std::string & eventStr)574 bool LocalAbilityManager::StopAbility(int32_t systemAbilityId, const std::string& eventStr)
575 {
576     LOGI("StopSa recv stop SA:%{public}d req", systemAbilityId);
577     nlohmann::json stopReason = ParseUtil::StringToJsonObj(eventStr);
578     SetStopReason(systemAbilityId, stopReason);
579     auto task = [this, systemAbilityId] {this->StopOndemandSystemAbility(systemAbilityId);};
580     std::thread thread(task);
581     thread.detach();
582     return true;
583 }
584 
ActiveAbility(int32_t systemAbilityId,const nlohmann::json & activeReason)585 bool LocalAbilityManager::ActiveAbility(int32_t systemAbilityId,
586     const nlohmann::json& activeReason)
587 {
588     LOGD("ActiveSa:%{public}d", systemAbilityId);
589     auto ability = GetAbility(systemAbilityId);
590     if (ability == nullptr) {
591         return false;
592     }
593     SystemAbilityOnDemandReason onDemandActiveReason = JsonToOnDemandReason(activeReason);
594     ability->Active(onDemandActiveReason);
595     return true;
596 }
597 
IdleAbility(int32_t systemAbilityId,const nlohmann::json & idleReason,int32_t & delayTime)598 bool LocalAbilityManager::IdleAbility(int32_t systemAbilityId,
599     const nlohmann::json& idleReason, int32_t& delayTime)
600 {
601     HILOGD(TAG, "idle SA:%{public}d", systemAbilityId);
602     auto ability = GetAbility(systemAbilityId);
603     if (ability == nullptr) {
604         return false;
605     }
606     SystemAbilityOnDemandReason onDemandIdleReason = JsonToOnDemandReason(idleReason);
607     ability->Idle(onDemandIdleReason, delayTime);
608     return true;
609 }
610 
JsonToOnDemandReason(const nlohmann::json & reasonJson)611 SystemAbilityOnDemandReason LocalAbilityManager::JsonToOnDemandReason(const nlohmann::json& reasonJson)
612 {
613     SystemAbilityOnDemandReason onDemandStartReason;
614     if (reasonJson.contains(EVENT_ID) && reasonJson[EVENT_ID].is_number()) {
615         onDemandStartReason.SetId(reasonJson[EVENT_ID]);
616     }
617     if (reasonJson.contains(NAME) && reasonJson[NAME].is_string()) {
618         onDemandStartReason.SetName(reasonJson[NAME]);
619     }
620     if (reasonJson.contains(VALUE) && reasonJson[VALUE].is_string()) {
621         onDemandStartReason.SetValue(reasonJson[VALUE]);
622     }
623     if (reasonJson.contains(EXTRA_DATA_ID) && reasonJson[EXTRA_DATA_ID].is_number()) {
624         onDemandStartReason.SetExtraDataId(reasonJson[EXTRA_DATA_ID]);
625     }
626     return onDemandStartReason;
627 }
628 
InitializeOnDemandSaProfile(int32_t saId)629 bool LocalAbilityManager::InitializeOnDemandSaProfile(int32_t saId)
630 {
631     int64_t begin = GetTickCount();
632     LOGD("InitOnDemandSa LoadSaLib SA:%{public}d", saId);
633 #ifdef SAFWK_ENABLE_RUN_ON_DEMAND_QOS
634     SetThreadPrio(OPEN_SO_PRIO);
635 #endif
636     bool result = profileParser_->LoadSaLib(saId);
637 #ifdef SAFWK_ENABLE_RUN_ON_DEMAND_QOS
638     SetThreadPrio(NORMAL_PRIO);
639 #endif
640     LOGI("InitOnDemandSa LoadSaLib SA:%{public}d finished,spend:%{public}"
641         PRId64 "ms", saId, (GetTickCount() - begin));
642     if (!result) {
643         LOGW("InitOnDemandSa LoadSaLib fail,SA:{public}%d", saId);
644         return false;
645     }
646     SaProfile saProfile;
647     bool ret = profileParser_->GetProfile(saId, saProfile);
648     if (ret) {
649         return InitializeSaProfilesInnerLocked(saProfile);
650     }
651     return false;
652 }
653 
InitializeSaProfilesInnerLocked(const SaProfile & saProfile)654 bool LocalAbilityManager::InitializeSaProfilesInnerLocked(const SaProfile& saProfile)
655 {
656     std::unique_lock<std::shared_mutex> readLock(localAbilityMapLock_);
657     auto iterProfile = localAbilityMap_.find(saProfile.saId);
658     if (iterProfile == localAbilityMap_.end()) {
659         HILOGW(TAG, "SA:%{public}d not found", saProfile.saId);
660         return false;
661     }
662     auto systemAbility = iterProfile->second;
663     if (systemAbility == nullptr) {
664         HILOGW(TAG, "SA:%{public}d is null", saProfile.saId);
665         return false;
666     }
667     if (saProfile.bootPhase > OTHER_START) {
668         HILOGW(TAG, "invalid boot phase: %{public}d", saProfile.bootPhase);
669         return false;
670     }
671     auto& saList = abilityPhaseMap_[saProfile.bootPhase];
672     saList.emplace_back(systemAbility);
673     return true;
674 }
675 
CheckDependencyStatus(const vector<int32_t> & dependSa)676 vector<int32_t> LocalAbilityManager::CheckDependencyStatus(const vector<int32_t>& dependSa)
677 {
678     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
679     if (samgrProxy == nullptr) {
680         HILOGW(TAG, "failed to get samgrProxy");
681         return dependSa;
682     }
683 
684     vector<int32_t> checkSaStatusResult;
685     for (const auto& saId : dependSa) {
686         if (CheckInputSysAbilityId(saId)) {
687             sptr<IRemoteObject> saObject = samgrProxy->CheckSystemAbility(saId);
688             if (saObject == nullptr) {
689                 checkSaStatusResult.emplace_back(saId);
690             }
691         } else {
692             HILOGW(TAG, "dependency's SA:%{public}d is invalid", saId);
693         }
694     }
695     return checkSaStatusResult;
696 }
697 
StartDependSaTask(SystemAbility * ability)698 void LocalAbilityManager::StartDependSaTask(SystemAbility* ability)
699 {
700     if (ability == nullptr) {
701         HILOGE(TAG, "ability is null");
702         return;
703     }
704     int64_t start = GetTickCount();
705     int64_t dependTimeout = ability->GetDependTimeout();
706     size_t lastSize = CheckDependencyStatus(ability->GetDependSa()).size();
707     HILOGI(TAG, "SA:%{public}d's depend timeout:%{public}" PRId64 " ms,depend size:%{public}zu",
708         ability->GetSystemAbilitId(), dependTimeout, lastSize);
709     {
710         SamgrXCollie samgrXCollie("DependSaTimeout_" + ToString(ability->GetSystemAbilitId()), MAX_DEPEND_TIMEOUT);
711         while (lastSize > 0) {
712             int64_t end = GetTickCount();
713             int64_t duration = ((end >= start) ? (end - start) : (INT64_MAX - end + start));
714             if (duration < dependTimeout) {
715                 usleep(CHECK_DEPENDENT_SA_PERIOD);
716             } else {
717                 break;
718             }
719             vector<int32_t> temp = CheckDependencyStatus(ability->GetDependSa());
720             size_t curSize = temp.size();
721             if (curSize != lastSize) {
722                 HILOGI(TAG, "SA:%{public}d's depend left:%{public}zu", ability->GetSystemAbilitId(), curSize);
723             }
724             lastSize = curSize;
725         }
726     }
727     vector<int32_t> unpreparedDeps = CheckDependencyStatus(ability->GetDependSa());
728     if (unpreparedDeps.empty()) {
729         HILOGI(TAG, "SA:%{public}d's depend all start", ability->GetSystemAbilitId());
730         ability->Start();
731     } else {
732         for (const auto& unpreparedDep : unpreparedDeps) {
733             HILOGI(TAG, "%{public}d's dependency:%{public}d not started in %{public}d ms",
734                 ability->GetSystemAbilitId(), unpreparedDep, ability->GetDependTimeout());
735         }
736     }
737 }
738 
StartSystemAbilityTask(SystemAbility * ability)739 void LocalAbilityManager::StartSystemAbilityTask(SystemAbility* ability)
740 {
741     if (ability != nullptr) {
742         HILOGD(TAG, "StartSystemAbility is called for SA:%{public}d", ability->GetSystemAbilitId());
743         if (ability->GetDependSa().empty()) {
744             ability->Start();
745         } else {
746             StartDependSaTask(ability);
747         }
748         KHILOGI(TAG, "%{public}s SA:%{public}d init finished, %{public}" PRId64 " ms",
749             Str16ToStr8(procName_).c_str(), ability->GetSystemAbilitId(), (GetTickCount() - startBegin_));
750     }
751 
752     std::lock_guard<std::mutex> lock(startPhaseLock_);
753     if (startTaskNum_ > 0) {
754         --startTaskNum_;
755     }
756     startPhaseCV_.notify_one();
757 }
758 
RegisterOnDemandSystemAbility(int32_t saId)759 void LocalAbilityManager::RegisterOnDemandSystemAbility(int32_t saId)
760 {
761     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
762     if (samgrProxy == nullptr) {
763         HILOGI(TAG, "failed to get samgrProxy");
764         return;
765     }
766 
767     auto& saProfileList = profileParser_->GetAllSaProfiles();
768     for (const auto& saProfile : saProfileList) {
769         if (NeedRegisterOnDemand(saProfile, saId)) {
770             HILOGD(TAG, "register ondemand SA:%{public}d to samgr", saProfile.saId);
771             int32_t ret = samgrProxy->AddOnDemandSystemAbilityInfo(saProfile.saId, procName_);
772             if (ret != ERR_OK) {
773                 HILOGI(TAG, "failed to add ability info for on-demand SA:%{public}d", saProfile.saId);
774             }
775         }
776     }
777 }
778 
779 // on default load, not-run-on-create SA will register to OnDemandSystemAbility
780 // on demand load, other SA will register to OnDemandSystemAbility, although some are runOnCreate
NeedRegisterOnDemand(const SaProfile & saProfile,int32_t saId)781 bool LocalAbilityManager::NeedRegisterOnDemand(const SaProfile& saProfile, int32_t saId)
782 {
783     return (saId == DEFAULT_SAID && !saProfile.runOnCreate) ||
784         (saId != DEFAULT_SAID && saProfile.saId != saId);
785 }
786 
StartPhaseTasks(const std::list<SystemAbility * > & systemAbilityList)787 void LocalAbilityManager::StartPhaseTasks(const std::list<SystemAbility*>& systemAbilityList)
788 {
789     if (systemAbilityList.empty()) {
790         return;
791     }
792 
793     for (auto systemAbility : systemAbilityList) {
794         if (systemAbility != nullptr) {
795             HILOGD(TAG, "add phase task for SA:%{public}d", systemAbility->GetSystemAbilitId());
796             std::lock_guard<std::mutex> autoLock(startPhaseLock_);
797             ++startTaskNum_;
798             auto task = [this, systemAbility] {this->StartSystemAbilityTask(systemAbility);};
799             initPool_->AddTask(task);
800         }
801     }
802 }
803 
WaitForTasks()804 void LocalAbilityManager::WaitForTasks()
805 {
806     int64_t begin = GetTickCount();
807     HILOGD(TAG, "start waiting for all tasks!");
808     std::unique_lock<std::mutex> lck(startPhaseLock_);
809     if (!startPhaseCV_.wait_for(lck, std::chrono::seconds(MAX_SA_STARTUP_TIME),
810         [this] () { return startTaskNum_ == 0; })) {
811         HILOGW(TAG, "start timeout!");
812     }
813     startTaskNum_ = 0;
814     int64_t end = GetTickCount();
815     LOGI("start tasks proc:%{public}s end,spend %{public}" PRId64 "ms",
816         Str16ToStr8(procName_).c_str(), (end - begin));
817 }
818 
FindAndStartPhaseTasks(int32_t saId)819 void LocalAbilityManager::FindAndStartPhaseTasks(int32_t saId)
820 {
821     if (saId == DEFAULT_SAID) {
822         for (uint32_t bootPhase = BOOT_START; bootPhase <= OTHER_START; ++bootPhase) {
823             auto iter = abilityPhaseMap_.find(bootPhase);
824             if (iter != abilityPhaseMap_.end()) {
825                 StartPhaseTasks(iter->second);
826                 InitializeRunOnCreateSaProfiles(bootPhase + 1);
827                 WaitForTasks();
828             } else {
829                 InitializeRunOnCreateSaProfiles(bootPhase + 1);
830             }
831         }
832     } else {
833         for (uint32_t bootPhase = BOOT_START; bootPhase <= OTHER_START; ++bootPhase) {
834             auto iter = abilityPhaseMap_.find(bootPhase);
835             if (iter != abilityPhaseMap_.end()) {
836                 StartPhaseTasks(iter->second);
837                 WaitForTasks();
838             }
839         }
840     }
841 }
842 
InitializeRunOnCreateSaProfiles(uint32_t bootPhase)843 bool LocalAbilityManager::InitializeRunOnCreateSaProfiles(uint32_t bootPhase)
844 {
845     if (bootPhase > OTHER_START) {
846         return false;
847     }
848     int64_t begin = GetTickCount();
849     LOGD("ROC_InitProfiles load phase %{public}d libraries", bootPhase);
850     profileParser_->OpenSo(bootPhase);
851     LOGI("ROC_InitProfiles proc:%{public}s phase:%{public}d end, spend:%{public}" PRId64 "ms",
852         Str16ToStr8(procName_).c_str(), bootPhase, (GetTickCount() - begin));
853     auto& saProfileList = profileParser_->GetAllSaProfiles();
854     if (saProfileList.empty()) {
855         HILOGW(TAG, "sa profile is empty");
856         return false;
857     }
858     for (const auto& saProfile : saProfileList) {
859         if (saProfile.bootPhase != bootPhase) {
860             continue;
861         }
862         if (!InitializeSaProfilesInnerLocked(saProfile)) {
863             HILOGW(TAG, "SA:%{public}d init fail", saProfile.saId);
864             continue;
865         }
866     }
867     return true;
868 }
869 
Run(int32_t saId)870 bool LocalAbilityManager::Run(int32_t saId)
871 {
872     HILOGD(TAG, "local ability manager is running...");
873     bool addResult = AddLocalAbilityManager();
874     if (!addResult) {
875         HILOGE(TAG, "failed to add local abilitymanager");
876         return false;
877     }
878     LOGD("Run succ to add proc name:%{public}s", Str16ToStr8(procName_).c_str());
879     uint32_t concurrentThreads = std::thread::hardware_concurrency();
880     LOGI("Run curThread is %{public}d,proc:%{public}s,SA:%{public}d",
881         concurrentThreads, Str16ToStr8(procName_).c_str(), saId);
882     initPool_->Start(concurrentThreads);
883     initPool_->SetMaxTaskNum(MAX_TASK_NUMBER);
884 
885     RegisterOnDemandSystemAbility(saId);
886     FindAndStartPhaseTasks(saId);
887     initPool_->Stop();
888     return true;
889 }
890 
AddLocalAbilityManager()891 bool LocalAbilityManager::AddLocalAbilityManager()
892 {
893     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
894     if (samgrProxy == nullptr) {
895         HILOGE(TAG, "failed to get samgrProxy");
896         return false;
897     }
898 
899     if (localAbilityManager_ == nullptr) {
900         localAbilityManager_ = this;
901     }
902     int32_t ret = samgrProxy->AddSystemProcess(procName_, localAbilityManager_);
903     return ret == ERR_OK;
904 }
905 
SetStartReason(int32_t saId,const nlohmann::json & event)906 void LocalAbilityManager::SetStartReason(int32_t saId, const nlohmann::json& event)
907 {
908     std::lock_guard<std::mutex> autoLock(ReasonLock_);
909     saIdToStartReason_[saId] = event;
910 }
911 
SetStopReason(int32_t saId,const nlohmann::json & event)912 void LocalAbilityManager::SetStopReason(int32_t saId, const nlohmann::json& event)
913 {
914     std::lock_guard<std::mutex> autoLock(ReasonLock_);
915     saIdToStopReason_[saId] = event;
916 }
917 
GetStartReason(int32_t saId)918 nlohmann::json LocalAbilityManager::GetStartReason(int32_t saId)
919 {
920     std::lock_guard<std::mutex> autoLock(ReasonLock_);
921     return saIdToStartReason_[saId];
922 }
923 
GetStopReason(int32_t saId)924 nlohmann::json LocalAbilityManager::GetStopReason(int32_t saId)
925 {
926     std::lock_guard<std::mutex> autoLock(ReasonLock_);
927     return saIdToStopReason_[saId];
928 }
929 
GetSystemAbilityStatusChange()930 sptr<ISystemAbilityStatusChange> LocalAbilityManager::GetSystemAbilityStatusChange()
931 {
932     std::lock_guard<std::mutex> autoLock(listenerLock_);
933     if (statusChangeListener_ == nullptr) {
934         statusChangeListener_ = new SystemAbilityListener();
935     }
936     return statusChangeListener_;
937 }
938 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)939 void LocalAbilityManager::SystemAbilityListener::OnAddSystemAbility(int32_t systemAbilityId,
940     const std::string& deviceId)
941 {
942     HILOGD(TAG, "SA:%{public}d added", systemAbilityId);
943     if (!CheckInputSysAbilityId(systemAbilityId)) {
944         HILOGW(TAG, "SA:%{public}d is invalid!", systemAbilityId);
945         return;
946     }
947 
948     GetInstance().FindAndNotifyAbilityListeners(systemAbilityId, deviceId,
949         ISystemAbilityStatusChange::ON_ADD_SYSTEM_ABILITY);
950 }
951 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)952 void LocalAbilityManager::SystemAbilityListener::OnRemoveSystemAbility(int32_t systemAbilityId,
953     const std::string& deviceId)
954 {
955     HILOGD(TAG, "SA:%{public}d removed", systemAbilityId);
956     if (!CheckInputSysAbilityId(systemAbilityId)) {
957         HILOGW(TAG, "SA:%{public}d is invalid!", systemAbilityId);
958         return;
959     }
960 
961     GetInstance().FindAndNotifyAbilityListeners(systemAbilityId, deviceId,
962         ISystemAbilityStatusChange::ON_REMOVE_SYSTEM_ABILITY);
963 }
964 
SendStrategyToSA(int32_t type,int32_t systemAbilityId,int32_t level,std::string & action)965 bool LocalAbilityManager::SendStrategyToSA(int32_t type, int32_t systemAbilityId, int32_t level, std::string& action)
966 {
967     HILOGD(TAG, "SendStrategyTo SA:%{public}d", systemAbilityId);
968     auto ability = GetAbility(systemAbilityId);
969     if (ability == nullptr) {
970         HILOGW(TAG, "failed to get SA:%{public}d", systemAbilityId);
971         return false;
972     }
973     ability->OnDeviceLevelChanged(type, level, action);
974     return true;
975 }
976 
IpcStatCmdProc(int32_t fd,int32_t cmd)977 bool LocalAbilityManager::IpcStatCmdProc(int32_t fd, int32_t cmd)
978 {
979     bool ret = false;
980     std::string result;
981 
982     HILOGI(TAG, "IpcStatCmdProc:fd=%{public}d cmd=%{public}d request", fd, cmd);
983     if (cmd < IPC_STAT_CMD_START || cmd >= IPC_STAT_CMD_MAX) {
984         HILOGW(TAG, "para invalid, fd=%{public}d cmd=%{public}d", fd, cmd);
985         return false;
986     }
987 
988     switch (cmd) {
989         case IPC_STAT_CMD_START: {
990             ret = LocalAbilityManagerDumper::StartIpcStatistics(result);
991             break;
992         }
993         case IPC_STAT_CMD_STOP: {
994             ret = LocalAbilityManagerDumper::StopIpcStatistics(result);
995             break;
996         }
997         case IPC_STAT_CMD_GET: {
998             ret = LocalAbilityManagerDumper::GetIpcStatistics(result);
999             break;
1000         }
1001         default:
1002             return false;
1003     }
1004 
1005     if (!SaveStringToFd(fd, result)) {
1006         HILOGW(TAG, "save to fd failed");
1007         return false;
1008     }
1009     return ret;
1010 }
1011 
1012 typedef void (*PGetSdkName)(uint32_t cmd, char *buf, uint32_t len);
1013 
FfrtDumperProc(std::string & ffrtDumperInfo)1014 bool LocalAbilityManager::FfrtDumperProc(std::string& ffrtDumperInfo)
1015 {
1016     HILOGI(TAG, "FfrtDumperPorc request");
1017     PGetSdkName pFFrtDumpInfo = (PGetSdkName)dlsym(RTLD_DEFAULT, "ffrt_dump");
1018     char* pszErr = dlerror();
1019     if (pszErr != NULL) {
1020         HILOGE(TAG, "dlsym err info: %{public}s", pszErr);
1021     }
1022     if (pFFrtDumpInfo == NULL) {
1023         HILOGE(TAG, "dlsym failed");
1024         ffrtDumperInfo.append("process " + std::to_string(getpid()) + " did not load ffrt\n");
1025         return false;
1026     }
1027     char* buffer = new char[FFRT_BUFFER_SIZE + 1]();
1028     buffer[FFRT_BUFFER_SIZE] = 0;
1029     (*pFFrtDumpInfo)(FFRT_DUMP_INFO_ALL, buffer, FFRT_BUFFER_SIZE);
1030     if (strlen(buffer) == 0) {
1031         HILOGE(TAG, "get samgr FfrtDumperInfo failed");
1032         delete[] buffer;
1033         return false;
1034     }
1035     ffrtDumperInfo += buffer;
1036     delete[] buffer;
1037     return true;
1038 }
1039 
SystemAbilityExtProc(const std::string & extension,int32_t said,SystemAbilityExtensionPara * callback,bool isAsync)1040 int32_t LocalAbilityManager::SystemAbilityExtProc(const std::string& extension, int32_t said,
1041     SystemAbilityExtensionPara* callback, bool isAsync)
1042 {
1043     (void)isAsync;
1044     if (callback == nullptr) {
1045         return INVALID_DATA;
1046     }
1047 
1048     HILOGD(TAG, "SystemAbilityExtProc Extension %{public}s SA:%{public}d", extension.c_str(), said);
1049     auto ability = GetAbility(said);
1050     if (ability == nullptr) {
1051         return INVALID_DATA;
1052     }
1053     return ability->OnExtension(extension, *callback->data_, *callback->reply_);
1054 }
1055 
IsResident()1056 bool LocalAbilityManager::IsResident()
1057 {
1058     std::shared_lock<std::shared_mutex> readLock(localAbilityMapLock_);
1059     for (const auto& it : localAbilityMap_) {
1060         if ((it.second != nullptr) && (it.second->IsRunOnCreate())) {
1061             return true;
1062         }
1063     }
1064     return false;
1065 }
1066 
NoNeedCheckUnused(int32_t saId)1067 bool LocalAbilityManager::NoNeedCheckUnused(int32_t saId)
1068 {
1069     std::set<int32_t> saIdWhiteList = {};
1070     return saIdWhiteList.find(saId) != saIdWhiteList.end();
1071 }
1072 
IsConfigUnused()1073 bool LocalAbilityManager::IsConfigUnused()
1074 {
1075     std::shared_lock<std::shared_mutex> readLock(unusedCfgMapLock_);
1076     HILOGI(TAG, "unusedCfgMap_ size:%{public}zu", unusedCfgMap_.size());
1077     return !unusedCfgMap_.empty();
1078 }
1079 
LimitUnusedTimeout(int32_t saId,int32_t timeout)1080 void LocalAbilityManager::LimitUnusedTimeout(int32_t saId, int32_t timeout)
1081 {
1082     int64_t millisecTimeout = static_cast<int64_t>(timeout * TIME_S_TO_MS);
1083     if (millisecTimeout < ONDEMAND_SA_UNUSED_TIMEOUT_LOWLIMIT) {
1084         unusedCfgMap_[saId] = ONDEMAND_SA_UNUSED_TIMEOUT_LOWLIMIT;
1085     } else if (millisecTimeout > ONDEMAND_SA_UNUSED_TIMEOUT_UPLIMIT) {
1086         unusedCfgMap_[saId] = ONDEMAND_SA_UNUSED_TIMEOUT_UPLIMIT;
1087     } else {
1088         unusedCfgMap_[saId] = millisecTimeout;
1089     }
1090 }
1091 
InitUnusedCfg()1092 void LocalAbilityManager::InitUnusedCfg()
1093 {
1094     auto saProfileList = profileParser_->GetAllSaProfiles();
1095     std::shared_lock<std::shared_mutex> writeLock(unusedCfgMapLock_);
1096     for (const auto& saProfile : saProfileList) {
1097         if (!saProfile.runOnCreate && saProfile.stopOnDemand.unusedTimeout != -1) {
1098             LimitUnusedTimeout(saProfile.saId, saProfile.stopOnDemand.unusedTimeout);
1099         }
1100     }
1101 }
1102 
GetSaLastRequestTime(const sptr<ISystemAbilityManager> & samgr,int32_t saId,uint64_t & lastRequestTime)1103 bool LocalAbilityManager::GetSaLastRequestTime(const sptr<ISystemAbilityManager>& samgr,
1104     int32_t saId, uint64_t& lastRequestTime)
1105 {
1106     sptr<IRemoteObject> object = samgr->CheckSystemAbility(saId);
1107     if (object == nullptr) {
1108         HILOGD(TAG, "SA:%{public}d is not register", saId);
1109         return false;
1110     }
1111     sptr<IPCObjectStub> saStub = reinterpret_cast<IPCObjectStub*>(object.GetRefPtr());
1112     if (saStub == nullptr) {
1113         HILOGE(TAG, "SA:%{public}d stub is nullptr", saId);
1114         return false;
1115     }
1116     lastRequestTime = saStub->GetLastRequestTime();
1117     HILOGI(TAG, "SA:%{public}d last request time %{public}" PRIu64, saId, lastRequestTime);
1118 
1119     return true;
1120 }
1121 
IdentifyUnusedResident()1122 void LocalAbilityManager::IdentifyUnusedResident()
1123 {
1124     auto cur = std::chrono::steady_clock::now();
1125     uint64_t currTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
1126         cur.time_since_epoch()).count());
1127 
1128     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1129     if (samgr == nullptr) {
1130         HILOGE(TAG, "failed to get samgrProxy");
1131         return;
1132     }
1133 
1134     std::shared_lock<std::shared_mutex> readLock(localAbilityMapLock_);
1135     for (const auto& it : localAbilityMap_) {
1136         int32_t saId = it.first;
1137         uint64_t lastRequestTime = 0;
1138         bool ret = GetSaLastRequestTime(samgr, saId, lastRequestTime);
1139         if ((ret != true) || (currTime <= lastRequestTime)) {
1140             continue;
1141         }
1142         uint64_t idleTime = currTime - lastRequestTime;
1143         uint64_t threshold = static_cast<uint64_t>(RESIDENT_SA_UNUSED_TIMEOUT);
1144         HILOGD(TAG, "resident SA:%{public}d, idleTime:%{public}" PRIu64 ", longtime-unused threshold:%{public}" PRIu64,
1145             saId, idleTime, threshold);
1146         if (idleTime > threshold) {
1147             ReportSAIdle(saId, "long time unused:" + ToString(idleTime));
1148             HILOGI(TAG, "resident SA:%{public}d, longtime:%{public}" PRIu64 "unused", saId, idleTime);
1149         }
1150     }
1151 }
1152 
IdentifyUnusedOndemand()1153 void LocalAbilityManager::IdentifyUnusedOndemand()
1154 {
1155     auto cur = std::chrono::steady_clock::now();
1156     uint64_t currTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
1157         cur.time_since_epoch()).count());
1158 
1159     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1160     if (samgr == nullptr) {
1161         HILOGE(TAG, "failed to get samgrProxy");
1162         return;
1163     }
1164 
1165     std::shared_lock<std::shared_mutex> readLock(unusedCfgMapLock_);
1166     for (const auto& it : unusedCfgMap_) {
1167         int32_t saId = it.first;
1168         uint64_t lastRequestTime;
1169         bool ret = GetSaLastRequestTime(samgr, saId, lastRequestTime);
1170         if ((ret != true) || (currTime <= lastRequestTime)) {
1171             continue;
1172         }
1173         uint64_t threshold = it.second;
1174         uint64_t idleTime = currTime - lastRequestTime;
1175         HILOGD(TAG, "ondemand SA:%{public}d, idleTime:%{public}" PRIu64 ", longtime-unused threshold:%{public}" PRIu64,
1176             saId, idleTime, threshold);
1177         if (idleTime > threshold) {
1178             samgr->UnloadSystemAbility(saId);
1179             HILOGI(TAG, "ondemand SA:%{public}d, longtime:%{public}" PRIu64 "unused", saId, idleTime);
1180         }
1181     }
1182 }
1183 
StartTimedQuery()1184 void LocalAbilityManager::StartTimedQuery()
1185 {
1186     int32_t timerInterval = 0;
1187     std::function<void()> timerCallback;
1188 
1189     {
1190         std::shared_lock<std::shared_mutex> readLock(localAbilityMapLock_);
1191         for (const auto& it : localAbilityMap_) {
1192             if (NoNeedCheckUnused(it.first)) {
1193                 HILOGI(TAG, "SA:%{public}d no need check unused", it.first);
1194                 return;
1195             }
1196         }
1197     }
1198 
1199     if (IsResident()) {
1200         timerInterval = UNUSED_RESIDENT_TIMER_INTERVAL;
1201         timerCallback = std::bind(&LocalAbilityManager::IdentifyUnusedResident, this);
1202     } else {
1203         InitUnusedCfg();
1204         if (IsConfigUnused()) {
1205             timerInterval = UNUSED_ONDEMAND_TIMER_INTERVAL;
1206             timerCallback = std::bind(&LocalAbilityManager::IdentifyUnusedOndemand, this);
1207         }
1208     }
1209 
1210     if ((timerInterval != 0) && (timerCallback)) {
1211         idleTimer_ = std::make_unique<Utils::Timer>("OS_IdleSaReport", -1);
1212         idleTimer_->Setup();
1213         auto timerId = idleTimer_->Register(timerCallback, timerInterval);
1214         HILOGI(TAG, "StartIdleTimer timerId:%{public}u, interval:%{public}d", timerId, timerInterval);
1215     }
1216 }
1217 }
1218