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 &parameter)
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 &parameter, 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