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 "datashare_connection.h"
17
18 #include "ams_mgr_proxy.h"
19 #include "datashare_errno.h"
20 #include "datashare_log.h"
21 #include "datashare_proxy.h"
22 #include "datashare_radar_reporter.h"
23 #include "datashare_string_utils.h"
24
25 namespace OHOS {
26 namespace DataShare {
27 using namespace AppExecFwk;
28 /**
29 * @brief This method is called back to receive the connection result after an ability calls the
30 * ConnectAbility method to connect it to an extension ability.
31 *
32 * @param element: Indicates information about the connected extension ability.
33 * @param remote: Indicates the remote proxy object of the extension ability.
34 * @param resultCode: Indicates the connection result code. The value 0 indicates a successful connection, and any
35 * other value indicates a connection failure.
36 */
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)37 void DataShareConnection::OnAbilityConnectDone(
38 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
39 {
40 LOG_INFO("on connect done, req uri:%{public}s, rev uri:%{public}s, ret=%{public}d",
41 DataShareStringUtils::Change(uri_.ToString()).c_str(),
42 DataShareStringUtils::Change(element.GetURI()).c_str(), resultCode);
43 if (remoteObject == nullptr) {
44 LOG_ERROR("remote is nullptr");
45 condition_.condition.notify_all();
46 return;
47 }
48 {
49 std::lock_guard<std::mutex> lock(mutex_);
50 sptr<DataShareProxy> proxy = new (std::nothrow) DataShareProxy(remoteObject);
51 dataShareProxy_ = std::shared_ptr<DataShareProxy>(proxy.GetRefPtr(), [holder = proxy](const auto *) {});
52 condition_.condition.notify_all();
53 }
54 if (isInvalid_.load()) {
55 LOG_ERROR("connect is invalid, req uri:%{public}s, rev uri:%{public}s, ret=%{public}d",
56 DataShareStringUtils::Change(uri_.ToString()).c_str(),
57 DataShareStringUtils::Change(element.GetURI()).c_str(), resultCode);
58 Disconnect();
59 }
60 }
61
62 /**
63 * @brief This method is called back to receive the disconnection result after the connected extension ability crashes
64 * or is killed. If the extension ability exits unexpectedly, all its connections are disconnected, and each ability
65 * previously connected to it will call onAbilityDisconnectDone.
66 *
67 * @param element: Indicates information about the disconnected extension ability.
68 * @param resultCode: Indicates the disconnection result code. The value 0 indicates a successful disconnection, and
69 * any other value indicates a disconnection failure.
70 */
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)71 void DataShareConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
72 {
73 LOG_INFO("on disconnect done, req uri:%{public}s, rev uri:%{public}s, ret=%{public}d",
74 DataShareStringUtils::Change(uri_.ToString()).c_str(),
75 DataShareStringUtils::Change(element.GetURI()).c_str(), resultCode);
76 std::string uri;
77 {
78 std::lock_guard<std::mutex> lock(mutex_);
79 dataShareProxy_ = nullptr;
80 uri = uri_.ToString();
81 }
82 if (uri.empty()) {
83 return;
84 }
85 if (pool_ == nullptr) {
86 std::lock_guard<std::mutex> lock(mutex_);
87 if (pool_ == nullptr) {
88 pool_ = std::make_shared<ExecutorPool>(MAX_THREADS, MIN_THREADS);
89 }
90 }
91 ReconnectExtAbility(uri);
92 }
93
ReconnectExtAbility(const std::string & uri)94 void DataShareConnection::ReconnectExtAbility(const std::string &uri)
95 {
96 if (reConnects_.count == 0) {
97 AmsMgrProxy* instance = AmsMgrProxy::GetInstance();
98 if (instance == nullptr) {
99 LOG_ERROR("get proxy failed uri:%{public}s", DataShareStringUtils::Change(uri_.ToString()).c_str());
100 return;
101 }
102 ErrCode ret = instance->Connect(uri, this, token_);
103 LOG_INFO("reconnect ability, uri:%{public}s, ret = %{public}d",
104 DataShareStringUtils::Change(uri).c_str(), ret);
105 if (ret == E_OK) {
106 auto curr = std::chrono::system_clock::now().time_since_epoch();
107 reConnects_.count = 1;
108 reConnects_.firstTime = std::chrono::duration_cast<std::chrono::milliseconds>(curr).count();
109 reConnects_.prevTime = std::chrono::duration_cast<std::chrono::milliseconds>(curr).count();
110 }
111 return;
112 }
113 return DelayConnectExtAbility(uri);
114 }
115
DelayConnectExtAbility(const std::string & uri)116 void DataShareConnection::DelayConnectExtAbility(const std::string &uri)
117 {
118 int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
119 std::chrono::system_clock::now().time_since_epoch()).count();
120 if (now - reConnects_.prevTime >= MAX_RECONNECT_TIME_INTERVAL.count()) {
121 reConnects_.count = 0;
122 reConnects_.firstTime = now;
123 reConnects_.prevTime = now;
124 }
125 if (reConnects_.count >= MAX_RECONNECT) {
126 return;
127 }
128 auto delay = RECONNECT_TIME_INTERVAL;
129 if (now - reConnects_.prevTime >= RECONNECT_TIME_INTERVAL.count()) {
130 delay = std::chrono::seconds(0);
131 }
132 std::weak_ptr<DataShareConnection> self = weak_from_this();
133 auto taskid = pool_->Schedule(delay, [uri, self]() {
134 auto selfSharedPtr = self.lock();
135 if (selfSharedPtr) {
136 AmsMgrProxy* instance = AmsMgrProxy::GetInstance();
137 if (instance == nullptr) {
138 LOG_ERROR("get proxy failed uri:%{public}s", DataShareStringUtils::Change(uri).c_str());
139 return;
140 }
141 ErrCode ret = instance->Connect(uri, selfSharedPtr.get(), selfSharedPtr->token_);
142 LOG_INFO("reconnect ability, uri:%{public}s, ret = %{public}d",
143 DataShareStringUtils::Change(uri).c_str(), ret);
144 if (ret == E_OK) {
145 selfSharedPtr->reConnects_.count++;
146 selfSharedPtr->reConnects_.prevTime = std::chrono::duration_cast<std::chrono::milliseconds>(
147 std::chrono::system_clock::now().time_since_epoch()).count();
148 }
149 }
150 });
151 if (taskid == ExecutorPool::INVALID_TASK_ID) {
152 LOG_ERROR("create scheduler failed, over the max capacity");
153 return;
154 }
155 LOG_DEBUG("create scheduler success");
156 return;
157 }
158
159 /**
160 * @brief connect remote ability of DataShareExtAbility.
161 */
ConnectDataShareExtAbility(const Uri & uri,const sptr<IRemoteObject> & token)162 std::shared_ptr<DataShareProxy> DataShareConnection::ConnectDataShareExtAbility(const Uri &uri,
163 const sptr<IRemoteObject> &token)
164 {
165 std::string reqUri;
166 {
167 std::lock_guard<std::mutex> lock(mutex_);
168 if (dataShareProxy_ != nullptr) {
169 return dataShareProxy_;
170 }
171 reqUri = uri_.ToString().empty() ? uri.ToString() : uri_.ToString();
172 }
173
174 AmsMgrProxy* instance = AmsMgrProxy::GetInstance();
175 if (instance == nullptr) {
176 LOG_ERROR("get proxy failed uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str());
177 return nullptr;
178 }
179 ErrCode ret = instance->Connect(reqUri, this, token);
180 LOG_INFO("connect ability, uri = %{public}s. ret = %{public}d", DataShareStringUtils::Change(reqUri).c_str(), ret);
181 if (ret != ERR_OK) {
182 return nullptr;
183 }
184 std::unique_lock<std::mutex> condLock(condition_.mutex);
185 if (condition_.condition.wait_for(condLock, std::chrono::seconds(waitTime_),
186 [this] { return dataShareProxy_ != nullptr; })) {
187 LOG_DEBUG("connect ability ended successfully uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str());
188 RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER,
189 RadarReporter::CONNECT_EXT, RadarReporter::SUCCESS,
190 RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token->GetObjectDescriptor()),
191 RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(reqUri));
192 } else {
193 LOG_WARN("connect timeout uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str());
194 RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER,
195 RadarReporter::CONNECT_EXT, RadarReporter::FAILED,
196 RadarReporter::ERROR_CODE, RadarReporter::EXT_CONNECT_TIMEOUT_ERROR,
197 RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token->GetObjectDescriptor()),
198 RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(reqUri));
199 }
200 return GetDataShareProxy();
201 }
202
203 /**
204 * @brief disconnect remote ability of DataShareExtAbility.
205 */
DisconnectDataShareExtAbility()206 void DataShareConnection::DisconnectDataShareExtAbility()
207 {
208 std::string uri;
209 {
210 std::lock_guard<std::mutex> lock(mutex_);
211 uri = uri_.ToString();
212 uri_ = Uri("");
213 if (dataShareProxy_ == nullptr) {
214 return;
215 }
216 }
217
218 ErrCode ret = Disconnect();
219 LOG_INFO("disconnect uri:%{public}s, ret = %{public}d", DataShareStringUtils::Change(uri).c_str(), ret);
220 if (ret == E_OK) {
221 RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER,
222 RadarReporter::DIS_CONNECT_EXT, RadarReporter::SUCCESS,
223 RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token_->GetObjectDescriptor()),
224 RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(uri));
225 return;
226 }
227 RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER,
228 RadarReporter::DIS_CONNECT_EXT, RadarReporter::FAILED,
229 RadarReporter::ERROR_CODE, RadarReporter::EXT_DIS_CONNECT_ERROR,
230 RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token_->GetObjectDescriptor()),
231 RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(uri));
232 }
233
~DataShareConnection()234 DataShareConnection::~DataShareConnection()
235 {
236 }
237
GetDataShareProxy(const Uri & uri,const sptr<IRemoteObject> & token)238 std::shared_ptr<DataShareProxy> DataShareConnection::GetDataShareProxy(const Uri &uri,
239 const sptr<IRemoteObject> &token)
240 {
241 return ConnectDataShareExtAbility(uri, token);
242 }
243
SetConnectInvalid()244 void DataShareConnection::SetConnectInvalid()
245 {
246 isInvalid_.store(true);
247 }
248
Disconnect()249 ErrCode DataShareConnection::Disconnect()
250 {
251 AmsMgrProxy* instance = AmsMgrProxy::GetInstance();
252 if (instance == nullptr) {
253 return -1;
254 }
255 return instance->DisConnect(this);
256 }
257
GetDataShareProxy()258 std::shared_ptr<DataShareProxy> DataShareConnection::GetDataShareProxy()
259 {
260 std::lock_guard<std::mutex> lock(mutex_);
261 return dataShareProxy_;
262 }
263 } // namespace DataShare
264 } // namespace OHOS