1 /*
2 * Copyright (c) 2021-2024 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 "continuation_connector.h"
17
18 #include "continuation_device_callback_proxy.h"
19 #include "hilog_tag_wrapper.h"
20 #include "remote_register_service_proxy.h"
21
22 namespace OHOS {
23 namespace AppExecFwk {
24 sptr<ContinuationConnector> ContinuationConnector::instance_ = nullptr;
25 std::mutex ContinuationConnector::mutex_;
26 const std::string ContinuationConnector::CONNECTOR_DEVICE_ID("");
27 const std::string ContinuationConnector::CONNECTOR_BUNDLE_NAME("com.ohos.controlcenter");
28 const std::string ContinuationConnector::CONNECTOR_ABILITY_NAME(
29 "com.ohos.controlcenter.fatransfer.service.FeatureAbilityRegisterService");
30
ContinuationConnector(const std::weak_ptr<Context> & context)31 ContinuationConnector::ContinuationConnector(const std::weak_ptr<Context> &context) : context_(context)
32 {}
33
34 /**
35 * @brief get singleton of Class ContinuationConnector
36 *
37 * @param context: the running context for appcontext
38 *
39 * @return The singleton of ContinuationConnector
40 */
GetInstance(const std::weak_ptr<Context> & context)41 sptr<ContinuationConnector> ContinuationConnector::GetInstance(const std::weak_ptr<Context> &context)
42 {
43 if (instance_ == nullptr) {
44 std::lock_guard<std::mutex> lock(mutex_);
45 if (instance_ == nullptr) {
46 instance_ = sptr<ContinuationConnector>(new (std::nothrow) ContinuationConnector(context));
47 }
48 }
49 return instance_;
50 }
51
52 /**
53 * @brief This method is called back to receive the connection result after an ability calls the
54 * Ability#connectAbility(Want, IAbilityConnection) method to connect it to a Service ability.
55 *
56 * @param element: Indicates information about the connected Service ability.
57 * @param remote: Indicates the remote proxy object of the Service ability.
58 * @param resultCode: Indicates the connection result code. The value 0 indicates a successful connection, and any other
59 * value indicates a connection failure.
60 */
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)61 void ContinuationConnector::OnAbilityConnectDone(
62 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
63 {
64 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
65 if (remoteObject == nullptr) {
66 TAG_LOGE(AAFwkTag::CONTINUATION, "remote is nullptr");
67 return;
68 }
69 remoteRegisterService_ = iface_cast<RemoteRegisterServiceProxy>(remoteObject);
70 if (remoteRegisterService_ == nullptr) {
71 TAG_LOGE(AAFwkTag::CONTINUATION,
72 "remoteRegisterService_ is nullptr");
73 return;
74 }
75 isConnected_.store(true);
76 {
77 std::lock_guard<std::mutex> lock(mutex_);
78 for (auto &iter : continuationRequestList_) {
79 iter->Execute();
80 }
81 continuationRequestList_.clear();
82 }
83 }
84
85 /**
86 * @brief This method is called back to receive the disconnection result after the connected Service ability crashes or
87 * is killed. If the Service ability exits unexpectedly, all its connections are disconnected, and each ability
88 * previously connected to it will call onAbilityDisconnectDone.
89 *
90 * @param element: Indicates information about the disconnected Service ability.
91 * @param resultCode: Indicates the disconnection result code. The value 0 indicates a successful disconnection, and any
92 * other value indicates a disconnection failure.
93 */
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)94 void ContinuationConnector::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
95 {
96 remoteRegisterService_ = nullptr;
97 isConnected_.store(false);
98 }
99
100 /**
101 * @brief bind remote ability of RemoteRegisterService.
102 *
103 * @param request: request for continuation.
104 */
BindRemoteRegisterAbility(const std::shared_ptr<AppExecFwk::ContinuationRequest> & request)105 void ContinuationConnector::BindRemoteRegisterAbility(const std::shared_ptr<AppExecFwk::ContinuationRequest> &request)
106 {
107 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
108 std::shared_ptr tmpcontext = context_.lock();
109 if (tmpcontext == nullptr) {
110 TAG_LOGE(AAFwkTag::CONTINUATION,
111 "tmpcontext is nullptr");
112 return;
113 }
114 if (request == nullptr) {
115 TAG_LOGE(AAFwkTag::CONTINUATION, "request is nullptr");
116 return;
117 }
118 if (IsAbilityConnected()) {
119 TAG_LOGE(AAFwkTag::CONTINUATION, "remote register bounded");
120 request->Execute();
121 return;
122 }
123
124 {
125 std::lock_guard<std::mutex> lock(mutex_);
126 continuationRequestList_.push_back(request);
127 }
128 BindRemoteRegisterAbility();
129 }
130
131 /**
132 * @brief unbind remote ability of RemoteRegisterService.
133 */
UnbindRemoteRegisterAbility()134 void ContinuationConnector::UnbindRemoteRegisterAbility()
135 {
136 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
137 std::shared_ptr tmpcontext = context_.lock();
138 if (tmpcontext == nullptr) {
139 TAG_LOGE(AAFwkTag::CONTINUATION, "tmpcontext is nullptr");
140 return;
141 }
142
143 tmpcontext->DisconnectAbility(this);
144 isConnected_.store(false);
145 remoteRegisterService_ = nullptr;
146 }
147
148 /**
149 * @brief check whether connected to remote register service.
150 *
151 * @return bool true if connected, otherwise false.
152 */
IsAbilityConnected()153 bool ContinuationConnector::IsAbilityConnected()
154 {
155 return isConnected_.load();
156 }
157
158 /**
159 * @brief unregister to control center continuation register service.
160 *
161 * @param token token from register return value.
162 *
163 * @return bool result of unregister.
164 */
Unregister(int token)165 bool ContinuationConnector::Unregister(int token)
166 {
167 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
168 if (remoteRegisterService_ == nullptr) {
169 TAG_LOGE(AAFwkTag::CONTINUATION, "remoteRegisterService_ is nullptr");
170 return false;
171 }
172
173 return remoteRegisterService_->Unregister(token);
174 }
175
176 /**
177 * @brief notify continuation status to control center continuation register service.
178 *
179 * @param token token from register.
180 * @param deviceId device id.
181 * @param status device status.
182 *
183 * @return bool result of updateConnectStatus.
184 */
UpdateConnectStatus(int token,const std::string & deviceId,int status)185 bool ContinuationConnector::UpdateConnectStatus(int token, const std::string &deviceId, int status)
186 {
187 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
188 if (remoteRegisterService_ == nullptr) {
189 TAG_LOGE(AAFwkTag::CONTINUATION,
190 "remoteRegisterService_ is nullptr");
191 return false;
192 }
193
194 return remoteRegisterService_->UpdateConnectStatus(token, deviceId, status);
195 }
196
197 /**
198 * @brief notify control center continuation register service to show device list.
199 *
200 * @param token token from register
201 * @param parameter filter with supported device list.
202 * @return bool result of showDeviceList.
203 */
ShowDeviceList(int token,const AppExecFwk::ExtraParams & parameter)204 bool ContinuationConnector::ShowDeviceList(int token, const AppExecFwk::ExtraParams ¶meter)
205 {
206 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
207 if (remoteRegisterService_ == nullptr) {
208 TAG_LOGE(AAFwkTag::CONTINUATION,
209 "remoteRegisterService_ is nullptr");
210 return false;
211 }
212 return remoteRegisterService_->ShowDeviceList(token, parameter);
213 }
214
215 /**
216 * @brief register to control center continuation register service.
217 *
218 * @param context ability context.
219 * @param bundleName bundle name of ability.
220 * @param parameter filter with supported device list.
221 * @param callback callback for device connect and disconnect.
222 *
223 * @return int token.
224 */
Register(std::weak_ptr<Context> & context,std::string bundleName,const AppExecFwk::ExtraParams & parameter,std::shared_ptr<IContinuationDeviceCallback> & callback)225 int ContinuationConnector::Register(std::weak_ptr<Context> &context, std::string bundleName,
226 const AppExecFwk::ExtraParams ¶meter, std::shared_ptr<IContinuationDeviceCallback> &callback)
227 {
228 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
229 std::shared_ptr pcontext = context.lock();
230 if (pcontext == nullptr) {
231 TAG_LOGE(AAFwkTag::CONTINUATION, "pcontext is nullptr");
232 return -1;
233 }
234 if (remoteRegisterService_ == nullptr) {
235 TAG_LOGE(AAFwkTag::CONTINUATION, "remoteRegisterService_ is nullptr");
236 return -1;
237 }
238 sptr<IRemoteObject> token = pcontext->GetToken();
239 if (token == nullptr) {
240 TAG_LOGE(AAFwkTag::CONTINUATION, "token is nullptr");
241 return -1;
242 }
243
244 sptr<ContinuationDeviceCallbackProxy> callBackSptr(new (std::nothrow) ContinuationDeviceCallbackProxy(callback));
245
246 return remoteRegisterService_->Register(bundleName, token, parameter, callBackSptr);
247 }
248
249 /**
250 * @brief bind remote ability of RemoteRegisterService.
251 */
BindRemoteRegisterAbility()252 void ContinuationConnector::BindRemoteRegisterAbility()
253 {
254 TAG_LOGI(AAFwkTag::CONTINUATION, "begin");
255 std::shared_ptr tmpcontext = context_.lock();
256 if (tmpcontext == nullptr) {
257 TAG_LOGE(AAFwkTag::CONTINUATION,
258 "tmpcontext is nullptr");
259 return;
260 }
261 Want want;
262 want.SetElementName(CONNECTOR_DEVICE_ID, CONNECTOR_BUNDLE_NAME, CONNECTOR_ABILITY_NAME);
263 want.AddFlags(Want::FLAG_NOT_OHOS_COMPONENT);
264 tmpcontext->ConnectAbility(want, this);
265 }
266 } // namespace AppExecFwk
267 } // namespace OHOS
268