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
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 LOG_INFO("construct");
81 }
82
~RdbManagerImpl()83 RdbManagerImpl::~RdbManagerImpl()
84 {
85 LOG_INFO("destroy");
86 }
87
GetInstance()88 RdbManagerImpl& RdbManagerImpl::GetInstance()
89 {
90 static RdbManagerImpl manager;
91 return manager;
92 }
93
GetRdbService(const RdbSyncerParam & param)94 std::pair<int32_t, std::shared_ptr<RdbService>> RdbManagerImpl::GetRdbService(const RdbSyncerParam ¶m)
95 {
96 if (param.bundleName_.empty()) {
97 return { E_INVALID_ARGS, nullptr };
98 }
99
100 std::lock_guard<std::mutex> lock(mutex_);
101 if (rdbService_ != nullptr) {
102 return { E_OK, rdbService_ };
103 }
104
105 if (distributedDataMgr_ == nullptr) {
106 distributedDataMgr_ = GetDistributedDataManager(param.bundleName_);
107 }
108 if (distributedDataMgr_ == nullptr) {
109 LOG_ERROR("get distributed data manager failed");
110 return { E_ERROR, nullptr };
111 }
112
113 auto remote = distributedDataMgr_->GetFeatureInterface(DistributedRdb::RdbService::SERVICE_NAME);
114 if (remote == nullptr) {
115 LOG_ERROR("get rdb service failed");
116 return { E_NOT_SUPPORTED, nullptr };
117 }
118 sptr<RdbServiceProxy> rdbService = nullptr;
119 if (remote->IsProxyObject()) {
120 rdbService = iface_cast<RdbServiceProxy>(remote);
121 }
122
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 LOG_INFO("init data service proxy.");
174 }
175
GetFeatureInterface(const std::string & name)176 sptr<IRemoteObject> RdbStoreDataServiceProxy::GetFeatureInterface(const std::string &name)
177 {
178 LOG_INFO("%s", name.c_str());
179 MessageParcel data;
180 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
181 LOG_ERROR("write descriptor failed");
182 return nullptr;
183 }
184
185 if (!ITypesUtil::Marshal(data, name)) {
186 LOG_ERROR("write descriptor failed");
187 return nullptr;
188 }
189
190 MessageParcel reply;
191 MessageOption mo { MessageOption::TF_SYNC };
192 int32_t error = Remote()->SendRequest(
193 static_cast<uint32_t>(KvStoreInterfaceCode::GET_FEATURE_INTERFACE), data, reply, mo);
194 if (error != 0) {
195 LOG_ERROR("SendRequest returned %{public}d", error);
196 return nullptr;
197 }
198
199 sptr<IRemoteObject> remoteObject;
200 if (!ITypesUtil::Unmarshal(reply, remoteObject)) {
201 LOG_ERROR("remote object is nullptr");
202 return nullptr;
203 }
204 return remoteObject;
205 }
206
RegisterDeathObserver(const std::string & bundleName,sptr<IRemoteObject> observer)207 int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundleName, sptr<IRemoteObject> observer)
208 {
209 MessageParcel data;
210 if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) {
211 LOG_ERROR("write descriptor failed");
212 return E_ERROR;
213 }
214
215 if (!ITypesUtil::Marshal(data, bundleName, observer)) {
216 LOG_ERROR("write descriptor failed");
217 return E_ERROR;
218 }
219
220 MessageParcel reply;
221 MessageOption mo { MessageOption::TF_SYNC };
222 int32_t error = Remote()->SendRequest(
223 static_cast<uint32_t>(KvStoreInterfaceCode::REGISTER_DEATH_OBSERVER), data, reply, mo);
224 if (error != 0) {
225 LOG_ERROR("SendRequest returned %{public}d", error);
226 return E_ERROR;
227 }
228
229 int32_t status = E_ERROR;
230 ITypesUtil::Unmarshal(reply, status);
231 return status;
232 }
233 } // namespace OHOS::DistributedRdb
234