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 &param)
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