• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     } else {
189         LOG_WARN("connect timeout uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str());
190     }
191     return GetDataShareProxy();
192 }
193 
194 /**
195  * @brief disconnect remote ability of DataShareExtAbility.
196  */
DisconnectDataShareExtAbility()197 void DataShareConnection::DisconnectDataShareExtAbility()
198 {
199     std::string uri;
200     {
201         std::lock_guard<std::mutex> lock(mutex_);
202         uri = uri_.ToString();
203         uri_ = Uri("");
204         if (dataShareProxy_ == nullptr) {
205             return;
206         }
207     }
208 
209     ErrCode ret = Disconnect();
210     LOG_INFO("disconnect uri:%{public}s, ret = %{public}d", DataShareStringUtils::Change(uri).c_str(), ret);
211     if (ret == E_OK) {
212         return;
213     }
214 }
215 
~DataShareConnection()216 DataShareConnection::~DataShareConnection()
217 {
218 }
219 
GetDataShareProxy(const Uri & uri,const sptr<IRemoteObject> & token)220 std::shared_ptr<DataShareProxy> DataShareConnection::GetDataShareProxy(const Uri &uri,
221     const sptr<IRemoteObject> &token)
222 {
223     return ConnectDataShareExtAbility(uri, token);
224 }
225 
SetConnectInvalid()226 void DataShareConnection::SetConnectInvalid()
227 {
228     isInvalid_.store(true);
229 }
230 
Disconnect()231 ErrCode DataShareConnection::Disconnect()
232 {
233     AmsMgrProxy* instance = AmsMgrProxy::GetInstance();
234     if (instance == nullptr) {
235         return -1;
236     }
237     return instance->DisConnect(this);
238 }
239 
GetDataShareProxy()240 std::shared_ptr<DataShareProxy> DataShareConnection::GetDataShareProxy()
241 {
242     std::lock_guard<std::mutex> lock(mutex_);
243     return dataShareProxy_;
244 }
245 }  // namespace DataShare
246 }  // namespace OHOS