1 /*
2 * Copyright (C) 2023 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 "file_access_service_proxy.h"
17
18 #include "bundle_constants.h"
19 #include "user_access_tracer.h"
20 #include "file_access_framework_errno.h"
21 #include "file_access_service_ipc_interface_code.h"
22 #include "hilog_wrapper.h"
23 #include "hitrace_meter.h"
24 #include "ipc_skeleton.h"
25 #include "iservice_registry.h"
26 #include "system_ability_definition.h"
27
28 namespace OHOS {
29 namespace FileAccessFwk {
30 constexpr int LOAD_SA_TIMEOUT_MS = 5000;
31 const std::string UID_TAG = "uid:";
GetInstance()32 sptr<FileAccessServiceProxy> FileAccessServiceProxy::GetInstance()
33 {
34 HILOG_INFO("Getinstance");
35 std::unique_lock<std::mutex> lock(proxyMutex_);
36 if (serviceProxy_ != nullptr) {
37 return serviceProxy_;
38 }
39
40 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
41 if (samgr == nullptr) {
42 HILOG_ERROR("Samgr is nullptr");
43 return nullptr;
44 }
45 sptr<ServiceProxyLoadCallback> loadCallback(new ServiceProxyLoadCallback());
46 if (loadCallback == nullptr) {
47 HILOG_ERROR("loadCallback is nullptr");
48 return nullptr;
49 }
50 int32_t ret = samgr->LoadSystemAbility(FILE_ACCESS_SERVICE_ID, loadCallback);
51 if (ret != ERR_OK) {
52 HILOG_ERROR("Failed to Load systemAbility, systemAbilityId:%{public}d, ret code:%{public}d",
53 FILE_ACCESS_SERVICE_ID, ret);
54 return nullptr;
55 }
56
57 auto waitStatus = loadCallback->proxyConVar_.wait_for(
58 lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS),
59 [loadCallback]() { return loadCallback->isLoadSuccess_.load(); });
60 if (!waitStatus) {
61 HILOG_ERROR("Load FileAccessService SA timeout");
62 return nullptr;
63 }
64 return serviceProxy_;
65 }
66
OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const sptr<IRemoteObject> & remoteObject)67 void FileAccessServiceProxy::ServiceProxyLoadCallback::OnLoadSystemAbilitySuccess(
68 int32_t systemAbilityId,
69 const sptr<IRemoteObject> &remoteObject)
70 {
71 HILOG_INFO("Load FileAccessService SA success,systemAbilityId:%{public}d, remoteObj result:%{private}s",
72 systemAbilityId, (remoteObject == nullptr ? "false" : "true"));
73 if (systemAbilityId != FILE_ACCESS_SERVICE_ID || remoteObject == nullptr) {
74 isLoadSuccess_.store(false);
75 proxyConVar_.notify_one();
76 return;
77 }
78 std::unique_lock<std::mutex> lock(proxyMutex_);
79 serviceProxy_ = iface_cast<FileAccessServiceProxy>(remoteObject);
80 if (!serviceProxy_) {
81 HILOG_ERROR("Failed to get remote object");
82 isLoadSuccess_.store(false);
83 proxyConVar_.notify_one();
84 return;
85 }
86 auto remoteObj = serviceProxy_->AsObject();
87 if (!remoteObj) {
88 HILOG_ERROR("Failed to get remote object");
89 serviceProxy_ = nullptr;
90 isLoadSuccess_.store(false);
91 proxyConVar_.notify_one();
92 return;
93 }
94
95 auto callback = [](const wptr<IRemoteObject> &obj) {
96 FileAccessServiceProxy::InvaildInstance();
97 HILOG_ERROR("service died");
98 };
99 sptr<ProxyDeathRecipient> deathRecipient = sptr(new ProxyDeathRecipient(callback));
100 remoteObj->AddDeathRecipient(deathRecipient);
101 isLoadSuccess_.store(true);
102 proxyConVar_.notify_one();
103 }
104
OnLoadSystemAbilityFail(int32_t systemAbilityId)105 void FileAccessServiceProxy::ServiceProxyLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
106 {
107 HILOG_INFO("Load FileAccessService SA failed,systemAbilityId:%{public}d", systemAbilityId);
108 std::unique_lock<std::mutex> lock(proxyMutex_);
109 serviceProxy_ = nullptr;
110 isLoadSuccess_.store(false);
111 proxyConVar_.notify_one();
112 }
113
InvaildInstance()114 void FileAccessServiceProxy::InvaildInstance()
115 {
116 HILOG_INFO("invalid instance");
117 std::unique_lock<std::mutex> lock(proxyMutex_);
118 serviceProxy_ = nullptr;
119 }
120
OnChange(Uri uri,NotifyType notifyType)121 int32_t FileAccessServiceProxy::OnChange(Uri uri, NotifyType notifyType)
122 {
123 UserAccessTracer trace;
124 trace.Start("OnChange");
125 MessageParcel data;
126 if (!data.WriteInterfaceToken(FileAccessServiceProxy::GetDescriptor())) {
127 HILOG_ERROR("WriteInterfaceToken failed");
128 return E_IPCS;
129 }
130
131 if (!data.WriteParcelable(&uri)) {
132 HILOG_ERROR("fail to WriteParcelable uri");
133 return E_IPCS;
134 }
135
136 if (!data.WriteInt32(static_cast<int32_t>(notifyType))) {
137 HILOG_ERROR("fail to WriteParcelable notifyType");
138 return E_IPCS;
139 }
140
141 MessageParcel reply;
142 MessageOption option;
143 auto remote = Remote();
144 if (!remote) {
145 HILOG_ERROR("failed to get remote");
146 return E_IPCS;
147 }
148 int err = remote->SendRequest(static_cast<uint32_t>(FileAccessServiceInterfaceCode::CMD_ONCHANGE), data, reply,
149 option);
150 if (err != ERR_OK) {
151 HILOG_ERROR("fail to SendRequest. err: %{public}d", err);
152 return err;
153 }
154
155 int ret = E_IPCS;
156 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
157 HILOG_ERROR("OnChange operation failed ret : %{public}d", ret);
158 return ret;
159 }
160
161 return ERR_OK;
162 }
163
RegisterNotify(Uri uri,bool notifyForDescendants,const sptr<IFileAccessObserver> & observer,const std::shared_ptr<ConnectExtensionInfo> & info)164 int32_t FileAccessServiceProxy::RegisterNotify(Uri uri, bool notifyForDescendants,
165 const sptr<IFileAccessObserver> &observer, const std::shared_ptr<ConnectExtensionInfo> &info)
166 {
167 UserAccessTracer trace;
168 trace.Start("RegisterNotify");
169 MessageParcel data;
170 if (!data.WriteInterfaceToken(FileAccessServiceProxy::GetDescriptor())) {
171 HILOG_ERROR("WriteInterfaceToken failed");
172 return E_IPCS;
173 }
174
175 if (!data.WriteParcelable(&uri)) {
176 HILOG_ERROR("fail to WriteParcelable uri");
177 return E_IPCS;
178 }
179
180 if (!(observer && data.WriteRemoteObject(observer->AsObject()))) {
181 HILOG_ERROR("fail to WriteRemoteObject observer");
182 return E_IPCS;
183 }
184
185 if (!data.WriteBool(notifyForDescendants)) {
186 HILOG_ERROR("fail to WriteBool notifyForDescendants");
187 return E_IPCS;
188 }
189
190 if (info == nullptr) {
191 HILOG_ERROR("ExtensionInfo is nullptr");
192 return E_GETINFO;
193 }
194
195 if (!info->WriteToParcel(data)) {
196 HILOG_ERROR("fail to WriteParcelable Info");
197 return E_IPCS;
198 }
199
200 MessageParcel reply;
201 MessageOption option;
202 auto remote = Remote();
203 if (!remote) {
204 HILOG_ERROR("failed to get remote");
205 return E_IPCS;
206 }
207 int err = remote->SendRequest(static_cast<uint32_t>(FileAccessServiceInterfaceCode::CMD_REGISTER_NOTIFY), data,
208 reply, option);
209 if (err != ERR_OK) {
210 HILOG_ERROR("fail to SendRequest. err: %{public}d", err);
211 return err;
212 }
213
214 int ret = E_IPCS;
215 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
216 HILOG_ERROR("RegisterNotify operation failed ret : %{public}d", ret);
217 return ret;
218 }
219
220 return ERR_OK;
221 }
222
UnregisterNotifyInternal(MessageParcel & data)223 int32_t FileAccessServiceProxy::UnregisterNotifyInternal(MessageParcel &data)
224 {
225 MessageParcel reply;
226 MessageOption option;
227 auto remote = Remote();
228 if (!remote) {
229 HILOG_ERROR("failed to get remote");
230 return E_IPCS;
231 }
232
233 int err = remote->SendRequest(static_cast<uint32_t>(FileAccessServiceInterfaceCode::CMD_UNREGISTER_NOTIFY), data,
234 reply, option);
235 if (err != ERR_OK) {
236 HILOG_ERROR("fail to SendRequest. err: %{public}d", err);
237 return err;
238 }
239
240 int ret = E_IPCS;
241 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
242 HILOG_ERROR("UnregisterNotify operation failed ret : %{public}d", ret);
243 return ret;
244 }
245
246 return ERR_OK;
247 }
248
UnregisterNotify(Uri uri,const sptr<IFileAccessObserver> & observer,const std::shared_ptr<ConnectExtensionInfo> & info)249 int32_t FileAccessServiceProxy::UnregisterNotify(Uri uri, const sptr<IFileAccessObserver> &observer,
250 const std::shared_ptr<ConnectExtensionInfo> &info)
251 {
252 UserAccessTracer trace;
253 trace.Start("UnregisterNotify");
254 MessageParcel data;
255 if (!data.WriteInterfaceToken(FileAccessServiceProxy::GetDescriptor())) {
256 HILOG_ERROR("WriteInterfaceToken failed");
257 return E_IPCS;
258 }
259
260 if (!data.WriteParcelable(&uri)) {
261 HILOG_ERROR("fail to WriteParcelable uri");
262 return E_IPCS;
263 }
264 bool observerNotNull = true;
265 if (observer != nullptr) {
266 if (!data.WriteBool(observerNotNull)) {
267 HILOG_ERROR("fail to WriteBool observerNotNull");
268 return E_IPCS;
269 }
270 if (!data.WriteRemoteObject(observer->AsObject())) {
271 HILOG_ERROR("fail to WriteRemoteObject observer");
272 return E_IPCS;
273 }
274 } else {
275 observerNotNull = false;
276 if (!data.WriteBool(observerNotNull)) {
277 HILOG_ERROR("fail to WriteBool observerNotNull");
278 return E_IPCS;
279 }
280 }
281
282 if (info == nullptr) {
283 HILOG_ERROR("ExtensionInfo is nullptr");
284 return E_GETINFO;
285 }
286
287 if (!info->WriteToParcel(data)) {
288 HILOG_ERROR("fail to WriteParcelable Info");
289 return E_IPCS;
290 }
291
292 // Split the code into two functions for better readability
293 int32_t result = UnregisterNotifyInternal(data);
294
295 return result;
296 }
297
ConnectFileExtAbility(const AAFwk::Want & want,const sptr<AAFwk::IAbilityConnection> & connection)298 int32_t FileAccessServiceProxy::ConnectFileExtAbility(const AAFwk::Want &want,
299 const sptr<AAFwk::IAbilityConnection>& connection)
300 {
301 UserAccessTracer trace;
302 trace.Start("ConnectFileExtAbility");
303 MessageParcel data;
304 if (!data.WriteInterfaceToken(FileAccessServiceProxy::GetDescriptor())) {
305 HILOG_ERROR("WriteInterfaceToken failed");
306 return E_IPCS;
307 }
308
309 if (!data.WriteParcelable(&want)) {
310 HILOG_ERROR("fail to WriteParcelable want");
311 return E_IPCS;
312 }
313
314 if (connection == nullptr || connection->AsObject() == nullptr) {
315 HILOG_ERROR("connection is nullptr");
316 return E_GETINFO;
317 }
318
319 if (!data.WriteRemoteObject(connection->AsObject())) {
320 HILOG_ERROR("fail to WriteParcelable connection");
321 return E_IPCS;
322 }
323
324 MessageParcel reply;
325 MessageOption option;
326 auto remote = Remote();
327 if (!remote) {
328 HILOG_ERROR("failed to get remote");
329 return E_IPCS;
330 }
331 int err = remote->SendRequest(static_cast<uint32_t>(
332 FileAccessServiceInterfaceCode::CMD_CONNECT_FILE_EXT_ABILITY), data, reply, option);
333 if (err != ERR_OK) {
334 HILOG_ERROR("fail to SendRequest. err: %{public}d", err);
335 return err;
336 }
337
338 int ret = E_IPCS;
339 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
340 HILOG_ERROR("ConnectFileExtAbility operation failed ret : %{public}d", ret);
341 return ret;
342 }
343
344 return ERR_OK;
345 }
346
DisConnectFileExtAbility(const sptr<AAFwk::IAbilityConnection> & connection)347 int32_t FileAccessServiceProxy::DisConnectFileExtAbility(const sptr<AAFwk::IAbilityConnection>& connection)
348 {
349 UserAccessTracer trace;
350 trace.Start("DisConnectFileExtAbility");
351 MessageParcel data;
352 if (!data.WriteInterfaceToken(FileAccessServiceProxy::GetDescriptor())) {
353 HILOG_ERROR("WriteInterfaceToken failed");
354 return E_IPCS;
355 }
356
357 if (connection == nullptr || connection->AsObject() == nullptr) {
358 HILOG_ERROR("connection is nullptr");
359 return E_GETINFO;
360 }
361
362 if (!data.WriteRemoteObject(connection->AsObject())) {
363 HILOG_ERROR("fail to WriteParcelable connection");
364 return E_IPCS;
365 }
366
367 MessageParcel reply;
368 MessageOption option;
369 auto remote = Remote();
370 if (!remote) {
371 HILOG_ERROR("failed to get remote");
372 return E_IPCS;
373 }
374 int err = remote->SendRequest(static_cast<uint32_t>(
375 FileAccessServiceInterfaceCode::CMD_DISCONNECT_FILE_EXT_ABILITY), data, reply, option);
376 if (err != ERR_OK) {
377 HILOG_ERROR("fail to SendRequest. err: %{public}d", err);
378 return err;
379 }
380
381 int ret = E_IPCS;
382 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
383 HILOG_ERROR("DisConnectFileExtAbility operation failed ret : %{public}d", ret);
384 return ret;
385 }
386
387 return ERR_OK;
388 }
389
GetExtensionProxy(const std::shared_ptr<ConnectExtensionInfo> & info,sptr<IFileAccessExtBase> & extensionProxy)390 int32_t FileAccessServiceProxy::GetExtensionProxy(const std::shared_ptr<ConnectExtensionInfo> &info,
391 sptr<IFileAccessExtBase> &extensionProxy)
392 {
393 UserAccessTracer trace;
394 trace.Start("GetExtensionProxy");
395 MessageParcel data;
396 if (!data.WriteInterfaceToken(FileAccessServiceProxy::GetDescriptor())) {
397 HILOG_ERROR("WriteInterfaceToken failed");
398 return E_IPCS;
399 }
400
401 if (info == nullptr) {
402 HILOG_ERROR("ExtensionInfo is nullptr");
403 return E_GETINFO;
404 }
405
406 if (!info->WriteToParcel(data)) {
407 HILOG_ERROR("fail to WriteParcelable Info");
408 return E_IPCS;
409 }
410
411 MessageParcel reply;
412 MessageOption option;
413 auto remote = Remote();
414 if (!remote) {
415 HILOG_ERROR("failed to get remote");
416 return E_IPCS;
417 }
418 int err = remote->SendRequest(static_cast<uint32_t>(FileAccessServiceInterfaceCode::CMD_GET_EXTENSION_PROXY),
419 data, reply, option);
420 if (err != ERR_OK) {
421 HILOG_ERROR("fail to SendRequest. err: %{public}d", err);
422 return err;
423 }
424
425 int ret = E_IPCS;
426 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
427 HILOG_ERROR("GetExtensionProxy operation failed ret : %{public}d", ret);
428 return ret;
429 }
430
431 sptr<IRemoteObject> obj = reply.ReadRemoteObject();
432 if (obj == nullptr) {
433 HILOG_INFO("get remote obj fail.");
434 return E_IPCS;
435 }
436
437 extensionProxy = iface_cast<IFileAccessExtBase>(obj);
438 if (extensionProxy == nullptr) {
439 HILOG_INFO("get observer fail");
440 return E_IPCS;
441 }
442
443 return ERR_OK;
444 }
445 } // namespace FileAccessFwk
446 } // namespace OHOS
447