• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "os_account_static_subscriber_manager.h"
17 
18 #include <dlfcn.h>
19 #include <thread>
20 #include <pthread.h>
21 #include "account_constants.h"
22 #include "account_log_wrapper.h"
23 #include "account_hisysevent_adapter.h"
24 #ifdef HICOLLIE_ENABLE
25 #include "account_timer.h"
26 #include "xcollie/xcollie.h"
27 #endif // HICOLLIE_ENABLE
28 
29 namespace OHOS {
30 namespace AccountSA {
31 namespace {
32 #ifdef _ARM64_
33 static const std::string ROOT_LIB_PATH = "/system/lib64/";
34 #else
35 static const std::string ROOT_LIB_PATH = "/system/lib/";
36 #endif
37 }
38 
~StaticSubscriber()39 StaticSubscriber::~StaticSubscriber()
40 {
41     callback = nullptr;
42     if (handle != nullptr) {
43         dlclose(handle);
44         handle = nullptr;
45     }
46 }
47 
OsAccountStaticSubscriberManager()48 OsAccountStaticSubscriberManager::OsAccountStaticSubscriberManager()
49 {
50     std::map<OsAccountState, std::set<std::string>> defaultConfig;
51     defaultConfig[OsAccountState::CREATING] = { ROOT_LIB_PATH + "libtheme_manager_client.z.so" };
52     Init(defaultConfig);
53 }
54 
GetInstance()55 OsAccountStaticSubscriberManager &OsAccountStaticSubscriberManager::GetInstance()
56 {
57     static OsAccountStaticSubscriberManager instance;
58     return instance;
59 }
60 
Init(const std::map<OsAccountState,std::set<std::string>> & staticSubscriberConfig)61 void OsAccountStaticSubscriberManager::Init(
62     const std::map<OsAccountState, std::set<std::string>> &staticSubscriberConfig)
63 {
64     std::lock_guard<std::mutex> lock(mutex_);
65     for (const auto &it : staticSubscriberConfig) {
66         std::set<std::shared_ptr<StaticSubscriber>> subscribers;
67         for (const auto &path : it.second) {
68             auto subscriber = ParseStaticSubscriber(path);
69             if (subscriber != nullptr) {
70                 subscribers.insert(subscriber);
71             }
72         }
73         if (!subscribers.empty()) {
74             state2Subscribers_[it.first] = subscribers;
75         }
76     }
77 }
78 
ParseStaticSubscriber(const std::string & path)79 std::shared_ptr<StaticSubscriber> OsAccountStaticSubscriberManager::ParseStaticSubscriber(const std::string &path)
80 {
81     auto subIt = staticSubscribers_.find(path);
82     if (subIt != staticSubscribers_.end()) {
83         ACCOUNT_LOGE("Subscriber already exists");
84         return subIt->second;
85     }
86     void* handle = dlopen(path.c_str(), RTLD_LAZY);
87     if (handle == nullptr) {
88         auto errMsg = dlerror();
89         ACCOUNT_LOGE("Failed to dlopen, path: %{public}s, error: %{public}s", path.c_str(), errMsg);
90         REPORT_OS_ACCOUNT_FAIL(0, Constants::OPERATION_EVENT_PUBLISH, ERR_ACCOUNT_COMMON_DLOPEN_ERROR,
91             "Failed to dlopen, path: " + path + ", error: " + (errMsg ? std::string(errMsg) : ""));
92         return nullptr;
93     }
94     void *func = dlsym(handle, "OnOsAccountStateChanged");
95     if (func == nullptr) {
96         auto errMsg = dlerror();
97         ACCOUNT_LOGE("Failed to dlsym, path: %{public}s, error=%{public}s", path.c_str(), errMsg);
98         REPORT_OS_ACCOUNT_FAIL(0, Constants::OPERATION_EVENT_PUBLISH, ERR_ACCOUNT_COMMON_DLSYM_ERROR,
99             "Failed to dlsym, path: " + path + ", error: " + (errMsg ? std::string(errMsg) : ""));
100         dlclose(handle);
101         handle = nullptr;
102         return nullptr;
103     }
104     auto subscriber = std::make_shared<StaticSubscriber>();
105     subscriber->path = path;
106     subscriber->handle = handle;
107     subscriber->callback = func;
108     staticSubscribers_[path] = subscriber;
109     ACCOUNT_LOGI("Parse static subscriber successfully, path: %{public}s", path.c_str());
110     return subscriber;
111 }
112 
PublishToSubscriber(const std::shared_ptr<StaticSubscriber> & subscriber,const COsAccountStateData & data)113 ErrCode OsAccountStaticSubscriberManager::PublishToSubscriber(
114     const std::shared_ptr<StaticSubscriber> &subscriber, const COsAccountStateData &data)
115 {
116     if (subscriber == nullptr || subscriber->callback == nullptr) {
117         ACCOUNT_LOGE("Invalid subscriber");
118         return ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
119     }
120     ACCOUNT_LOGI("State: %{public}d, fromId: %{public}d, toId: %{public}d, subscriberPath: %{public}s",
121         data.state, data.fromId, data.toId, subscriber->path.c_str());
122 #ifdef HICOLLIE_ENABLE
123     AccountTimer timer;
124 #endif
125     // Callback will be invalid when the singleton destroyed (i.e. the process exits), so lock protection is not added,
126     // otherwise it will increase performance overhead
127     return (*reinterpret_cast<OnOsAccountStateChangedFunc>(subscriber->callback))(&data);
128 }
129 
Publish(int32_t fromId,OsAccountState state,int32_t toId)130 ErrCode OsAccountStaticSubscriberManager::Publish(int32_t fromId, OsAccountState state, int32_t toId)
131 {
132     std::lock_guard<std::mutex> lock(mutex_);
133     auto it = state2Subscribers_.find(state);
134     if (it == state2Subscribers_.end()) {
135         ACCOUNT_LOGI("No subscriber, state: %{public}d", state);
136         return ERR_OK;
137     }
138     for (const std::shared_ptr<StaticSubscriber> &subscriber : it->second) {
139         auto task = [subscriber, state, fromId, toId] {
140             COsAccountStateData data;
141             data.fromId = fromId;
142             data.state = state;
143             data.toId = toId;
144             ErrCode errCode = PublishToSubscriber(subscriber, data);
145             if (errCode != ERR_OK) {
146                 ACCOUNT_LOGE("Failed to publish to subscriber, path=%{public}s, state=%{public}d, fromId=%{public}d, "
147                     "toId=%{public}d, errCode=%{public}d", subscriber->path.c_str(), state, fromId, toId, errCode);
148                 REPORT_OS_ACCOUNT_FAIL(data.toId, Constants::OPERATION_EVENT_PUBLISH, errCode,
149                     "Failed to publish to subscriber, path=" + subscriber->path + ", state=" + std::to_string(state) +
150                     ", fromId=" + std::to_string(fromId) + ", toId=" + std::to_string(toId));
151             }
152         };
153         std::thread publishThread(task);
154         pthread_setname_np(publishThread.native_handle(), "StaticPublish");
155         publishThread.detach();
156     }
157     return ERR_OK;
158 }
159 } // AccountSA
160 } // OHOS
161