1 /*
2 * Copyright (c) 2022 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 #define LOG_TAG "RdbManagerImpl"
16 #include "rdb_manager_impl.h"
17
18 #include <thread>
19
20 #include "ipc_skeleton.h"
21 #include "irdb_service.h"
22 #include "iservice_registry.h"
23 #include "itypes_util.h"
24 #include "logger.h"
25 #include "rdb_errno.h"
26 #include "rdb_service_proxy.h"
27 #include "system_ability_definition.h"
28
29 namespace OHOS::DistributedRdb {
30 using namespace OHOS::Rdb;
31 using RdbServiceProxy = DistributedRdb::RdbServiceProxy;
32 using namespace OHOS::NativeRdb;
33 using namespace OHOS::DistributedRdb::RelationalStore;
34
35 class DeathStub : public IRemoteBroker {
36 public:
37 DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedRdb.DeathStub");
38 };
39 class DeathStubImpl : public IRemoteStub<DeathStub> {
40 };
GetDistributedDataManager(const std::string & bundleName)41 std::shared_ptr<RdbStoreDataServiceProxy> RdbManagerImpl::GetDistributedDataManager(const std::string &bundleName)
42 {
43 auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
44 if (manager == nullptr) {
45 LOG_ERROR("get system ability manager failed.");
46 return nullptr;
47 }
48 auto dataMgr = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
49 if (dataMgr == nullptr) {
50 LOG_ERROR("get distributed data manager failed.");
51 return nullptr;
52 }
53 sptr<RdbStoreDataServiceProxy> dataService = new (std::nothrow) RdbStoreDataServiceProxy(dataMgr);
54 if (dataService == nullptr) {
55 LOG_ERROR("new RdbStoreDataServiceProxy failed.");
56 return nullptr;
57 }
58
59 sptr<IRemoteObject> observer = new (std::nothrow) DeathStubImpl();
60 dataService->RegisterDeathObserver(bundleName, observer);
61 return std::shared_ptr<RdbStoreDataServiceProxy>(dataService.GetRefPtr(), [dataService, observer](const auto *) {});
62 }
63
LinkToDeath(const sptr<IRemoteObject> & remote)64 static void LinkToDeath(const sptr<IRemoteObject>& remote)
65 {
66 auto& manager = RdbManagerImpl::GetInstance();
67 sptr<RdbManagerImpl::ServiceDeathRecipient> deathRecipient =
68 new(std::nothrow) RdbManagerImpl::ServiceDeathRecipient(&manager);
69 if (deathRecipient == nullptr) {
70 LOG_ERROR("new ServiceDeathRecipient failed.");
71 return;
72 }
73 if (!remote->AddDeathRecipient(deathRecipient)) {
74 LOG_ERROR("add death recipient failed.");
75 }
76 }
77
RdbManagerImpl()78 RdbManagerImpl::RdbManagerImpl()
79 {
80 }
81
~RdbManagerImpl()82 RdbManagerImpl::~RdbManagerImpl()
83 {
84 LOG_INFO("destroy.");
85 }
86
GetInstance()87 RdbManagerImpl& RdbManagerImpl::GetInstance()
88 {
89 static RdbManagerImpl manager;
90 return manager;
91 }
92
GetRdbService(const RdbSyncerParam & param)93 std::pair<int32_t, std::shared_ptr<RdbService>> RdbManagerImpl::GetRdbService(const RdbSyncerParam ¶m)
94 {
95 if (param.bundleName_.empty()) {
96 return { E_INVALID_ARGS, nullptr };
97 }
98
99 std::lock_guard<std::mutex> lock(mutex_);
100 if (rdbService_ != nullptr) {
101 return { E_OK, rdbService_ };
102 }
103
104 if (distributedDataMgr_ == nullptr) {
105 distributedDataMgr_ = GetDistributedDataManager(param.bundleName_);
106 }
107 if (distributedDataMgr_ == nullptr) {
108 LOG_ERROR("get distributed data manager failed.");
109 return { E_SERVICE_NOT_FOUND, nullptr };
110 }
111
112 auto remote = distributedDataMgr_->GetFeatureInterface(DistributedRdb::RdbService::SERVICE_NAME);
113 if (remote == nullptr) {
114 LOG_ERROR("get rdb service failed.");
115 return { E_NOT_SUPPORT, nullptr };
116 }
117
118 if (!remote->IsProxyObject()) {
119 return { E_NOT_SUPPORT, nullptr };
120 }
121
122 sptr<RdbServiceProxy> rdbService = iface_cast<RdbServiceProxy>(remote);
123 if (rdbService == nullptr) {
124 rdbService = new (std::nothrow) RdbServiceProxy(remote);
125 }
126
127 if (rdbService == nullptr || rdbService->InitNotifier(param) != RDB_OK) {
128 LOG_ERROR("init notifier failed.");
129 return { E_ERROR, nullptr };
130 }
131
132 sptr<IRdbService> serviceBase = rdbService;
133 LinkToDeath(serviceBase->AsObject());
134 // the rdbService is not null, so rdbService.GetRefPtr() is not null;
135 rdbService_ = std::shared_ptr<RdbService>(rdbService.GetRefPtr(), [rdbService](const auto *) {});
136 param_ = param;
137 return { E_OK, rdbService_ };
138 }
139
OnRemoteDied()140 void RdbManagerImpl::OnRemoteDied()
141 {
142 LOG_INFO("rdb service has dead!");
143 if (rdbService_ == nullptr) {
144 ResetServiceHandle();
145 return;
146 }
147 auto proxy = std::static_pointer_cast<RdbServiceProxy>(rdbService_);
148 auto observers = proxy->ExportObservers();
149 ResetServiceHandle();
150
151 std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME));
152 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param_);
153 if (errCode != E_OK) {
154 return;
155 }
156 proxy = std::static_pointer_cast<RdbServiceProxy>(service);
157 if (proxy == nullptr) {
158 return;
159 }
160 proxy->ImportObservers(observers);
161 }
162
ResetServiceHandle()163 void RdbManagerImpl::ResetServiceHandle()
164 {
165 std::lock_guard<std::mutex> lock(mutex_);
166 distributedDataMgr_ = nullptr;
167 rdbService_ = nullptr;
168 }
169
RdbStoreDataServiceProxy(const sptr<IRemoteObject> & impl)170 RdbStoreDataServiceProxy::RdbStoreDataServiceProxy(const sptr<IRemoteObject> &impl)
171 : IRemoteProxy<DistributedRdb::IKvStoreDataService>(impl)
172 {
173 }
174
GetFeatureInterface(const std::string & name)175 sptr<IRemoteObject> RdbStoreDataServiceProxy::GetFeatureInterface(const std::string &name)
176 {
177 LOG_DEBUG("%{public}s", name.c_str());
178 MessageParcel data;
179 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
180 LOG_ERROR("write descriptor failed.");
181 return nullptr;
182 }
183
184 if (!ITypesUtil::Marshal(data, name)) {
185 LOG_ERROR("write descriptor failed.");
186 return nullptr;
187 }
188
189 MessageParcel reply;
190 MessageOption mo { MessageOption::TF_SYNC };
191 int32_t error = Remote()->SendRequest(
192 static_cast<uint32_t>(KvStoreInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo);
193 if (error != 0) {
194 LOG_ERROR("SendRequest returned %{public}d", error);
195 return nullptr;
196 }
197
198 sptr<IRemoteObject> remoteObject;
199 if (!ITypesUtil::Unmarshal(reply, remoteObject)) {
200 LOG_ERROR("remote object is nullptr.");
201 return nullptr;
202 }
203 return remoteObject;
204 }
205
RegisterDeathObserver(const std::string & bundleName,sptr<IRemoteObject> observer)206 int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundleName, sptr<IRemoteObject> observer)
207 {
208 MessageParcel data;
209 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
210 LOG_ERROR("write descriptor failed.");
211 return E_ERROR;
212 }
213
214 if (!ITypesUtil::Marshal(data, bundleName, observer)) {
215 LOG_ERROR("write descriptor failed.");
216 return E_ERROR;
217 }
218
219 MessageParcel reply;
220 MessageOption mo { MessageOption::TF_SYNC };
221 int32_t error = Remote()->SendRequest(
222 static_cast<uint32_t>(KvStoreInterfaceCode::REGISTER_DEATH_OBSERVER), data, reply, mo);
223 if (error != 0) {
224 LOG_ERROR("SendRequest returned %{public}d", error);
225 return E_ERROR;
226 }
227
228 int32_t status = E_ERROR;
229 ITypesUtil::Unmarshal(reply, status);
230 return status;
231 }
232 } // namespace OHOS::DistributedRdb
233