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