• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "ipc/daemon.h"
17 
18 #include <exception>
19 #include <stdexcept>
20 
21 #include "accesstoken_kit.h"
22 #include "common_event_manager.h"
23 #include "common_event_support.h"
24 #include "connection_detector.h"
25 #include "device/device_manager_agent.h"
26 #include "dfs_error.h"
27 #include "ipc_skeleton.h"
28 #include "iremote_object.h"
29 #include "iservice_registry.h"
30 #include "mountpoint/mount_manager.h"
31 #include "network/softbus/softbus_handler.h"
32 #include "network/softbus/softbus_session_dispatcher.h"
33 #include "network/softbus/softbus_session_pool.h"
34 #include "network/softbus/softbus_session_listener.h"
35 #include "sandbox_helper.h"
36 #include "system_ability_definition.h"
37 #include "trans_mananger.h"
38 #include "utils_log.h"
39 
40 namespace OHOS {
41 namespace Storage {
42 namespace DistributedFile {
43 using namespace std;
44 using namespace OHOS::AppFileService;
45 using namespace OHOS::FileManagement;
46 using HapTokenInfo = OHOS::Security::AccessToken::HapTokenInfo;
47 using AccessTokenKit = OHOS::Security::AccessToken::AccessTokenKit;
48 
49 constexpr int32_t LINK_TYPE_NUM = 4;
50 const string FILE_MANAGER_AUTHORITY = "docs";
51 const string MEDIA_AUTHORITY = "media";
52 REGISTER_SYSTEM_ABILITY_BY_ID(Daemon, FILEMANAGEMENT_DISTRIBUTED_FILE_DAEMON_SA_ID, true);
53 
PublishSA()54 void Daemon::PublishSA()
55 {
56     LOGI("Begin to init");
57     if (!registerToService_) {
58         bool ret = SystemAbility::Publish(this);
59         if (!ret) {
60             throw runtime_error("Failed to publish the daemon");
61         }
62         registerToService_ = true;
63     }
64     LOGI("Init finished successfully");
65 }
66 
RegisterOsAccount()67 void Daemon::RegisterOsAccount()
68 {
69     EventFwk::MatchingSkills matchingSkills;
70     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
71     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
72     subScriber_ = std::make_shared<OsAccountObserver>(subscribeInfo);
73     bool subRet = EventFwk::CommonEventManager::SubscribeCommonEvent(subScriber_);
74     if (!subRet) {
75         LOGE("Subscribe common event failed");
76     }
77 }
78 
OnStart()79 void Daemon::OnStart()
80 {
81     LOGI("Begin to start service");
82     if (state_ == ServiceRunningState::STATE_RUNNING) {
83         LOGD("Daemon has already started");
84         return;
85     }
86 
87     try {
88         PublishSA();
89         AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
90     } catch (const exception &e) {
91         LOGE("%{public}s", e.what());
92     }
93 
94     state_ = ServiceRunningState::STATE_RUNNING;
95     LOGI("Start service successfully");
96 }
97 
OnStop()98 void Daemon::OnStop()
99 {
100     LOGI("Begin to stop");
101     state_ = ServiceRunningState::STATE_NOT_START;
102     registerToService_ = false;
103     bool subRet = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subScriber_);
104     if (!subRet) {
105         LOGE("UnSubscribe common event failed");
106     }
107     subScriber_ = nullptr;
108     LOGI("Stop finished successfully");
109 }
110 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)111 void Daemon::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
112 {
113     (void)systemAbilityId;
114     (void)deviceId;
115     RegisterOsAccount();
116 }
117 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)118 void Daemon::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
119 {
120     (void)deviceId;
121     if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
122         LOGE("systemAbilityId is not COMMON_EVENT_SERVICE_ID");
123         return;
124     }
125 
126     if (subScriber_ == nullptr) {
127         LOGE("Daemon::OnRemoveSystemAbility subscriberPtr is nullptr");
128         return;
129     }
130 
131     bool subscribeResult = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subScriber_);
132     LOGI("Daemon::OnRemoveSystemAbility subscribeResult = %{public}d", subscribeResult);
133     subScriber_ = nullptr;
134 }
135 
OpenP2PConnection(const DistributedHardware::DmDeviceInfo & deviceInfo)136 int32_t Daemon::OpenP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo)
137 {
138     auto path = ConnectionDetector::ParseHmdfsPath();
139     stringstream ss;
140     ss << ConnectionDetector::MocklispHash(path);
141     auto targetDir = ss.str();
142     auto networkId = std::string(deviceInfo.networkId);
143     int32_t ret = 0;
144     if (!ConnectionDetector::GetConnectionStatus(targetDir, networkId)) {
145         LOGI("Get connection status not ok, try again.");
146         ret = DeviceManagerAgent::GetInstance()->OnDeviceP2POnline(deviceInfo);
147         if (ret != NO_ERROR) {
148             LOGE("OpenP2PConnection failed, ret = %{public}d", ret);
149         } else {
150             ret = ConnectionDetector::RepeatGetConnectionStatus(targetDir, networkId);
151             LOGI("RepeatGetConnectionStatus end, ret = %{public}d", ret);
152         }
153     }
154     return ret;
155 }
156 
CloseP2PConnection(const DistributedHardware::DmDeviceInfo & deviceInfo)157 int32_t Daemon::CloseP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo)
158 {
159     LOGI("Close P2P Connection");
160     std::thread([=]() {
161         int32_t ret = DeviceManagerAgent::GetInstance()->OnDeviceP2POffline(deviceInfo);
162         LOGI("Close P2P Connection result %d", ret);
163         return ret;
164         }).detach();
165     return 0;
166 }
167 
RequestSendFile(const std::string & srcUri,const std::string & dstPath,const std::string & dstDeviceId,const std::string & sessionName)168 int32_t Daemon::RequestSendFile(const std::string &srcUri,
169                                 const std::string &dstPath,
170                                 const std::string &dstDeviceId,
171                                 const std::string &sessionName)
172 {
173     auto ret = SoftBusHandler::GetInstance().CreateSessionServer(IDaemon::SERVICE_NAME.c_str(), sessionName.c_str());
174     if (ret != E_OK) {
175         LOGE("CreateSessionServer failed, ret = %{public}d", ret);
176         return E_SOFTBUS_SESSION_FAILED;
177     }
178 
179     ret = SoftBusHandler::GetInstance().SetFileSendListener(IDaemon::SERVICE_NAME.c_str(), sessionName.c_str());
180     if (ret != E_OK) {
181         LOGE("SetFileSendListener failed, ret = %{public}d", ret);
182         RemoveSessionServer(IDaemon::SERVICE_NAME.c_str(), sessionName.c_str());
183         return E_SOFTBUS_SESSION_FAILED;
184     }
185 
186     SessionAttribute attr{
187         .dataType = TYPE_FILE,
188         .linkTypeNum = LINK_TYPE_NUM,
189         .linkType{LINK_TYPE_WIFI_P2P, LINK_TYPE_WIFI_WLAN_5G, LINK_TYPE_WIFI_WLAN_2G, LINK_TYPE_BR},
190         .fastTransData = nullptr,
191         .fastTransDataSize = 0,
192     };
193     auto sessionId = ::OpenSession(sessionName.c_str(), sessionName.c_str(), dstDeviceId.c_str(), "groupId", &attr);
194     if (sessionId <= 0) {
195         LOGE("OpenSession failed");
196         return E_SOFTBUS_SESSION_FAILED;
197     }
198 
199     SoftBusSessionPool::SessionInfo sessionInfo{.sessionId = sessionId, .srcUri = srcUri, .dstPath = dstPath};
200     SoftBusSessionPool::GetInstance().AddSessionInfo(sessionName, sessionInfo);
201     return E_OK;
202 }
203 
PrepareSession(const std::string & srcUri,const std::string & dstUri,const std::string & srcDeviceId,const sptr<IRemoteObject> & listener)204 int32_t Daemon::PrepareSession(const std::string &srcUri,
205                                const std::string &dstUri,
206                                const std::string &srcDeviceId,
207                                const sptr<IRemoteObject> &listener)
208 {
209     auto listenerCallback = iface_cast<IFileTransListener>(listener);
210     auto sessionName = SoftBusSessionPool::GetInstance().GenerateSessionName();
211     if (sessionName.empty() || listenerCallback == nullptr) {
212         LOGI("SessionServer exceed max or ListenerCallback is nullptr");
213         return CancelWait(sessionName, listenerCallback);
214     }
215 
216     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
217     DistributedHardware::DmDeviceInfo localDeviceInfo{};
218     int errCode = deviceManager.GetLocalDeviceInfo(IDaemon::SERVICE_NAME, localDeviceInfo);
219     if (errCode != E_OK) {
220         LOGI("GetLocalDeviceInfo failed, errCode = %{public}d", errCode);
221         return CancelWait(sessionName, listenerCallback);
222     }
223 
224     HapTokenInfo hapTokenInfo;
225     int result = AccessTokenKit::GetHapTokenInfo(IPCSkeleton::GetCallingTokenID(), hapTokenInfo);
226     if (result != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
227         LOGE("GetHapTokenInfo failed, errCode = %{public}d", result);
228         return CancelWait(sessionName, listenerCallback);
229     }
230 
231     std::string physicalPath;
232     auto ret = GetRealPath(dstUri, hapTokenInfo, sessionName, physicalPath);
233     if (ret != E_OK) {
234         LOGE("GetRealPath failed, ret = %{public}d", ret);
235         return CancelWait(sessionName, listenerCallback);
236     }
237     SoftBusSessionPool::SessionInfo sessionInfo{.dstPath = physicalPath, .uid = IPCSkeleton::GetCallingUid()};
238     SoftBusSessionPool::GetInstance().AddSessionInfo(sessionName, sessionInfo);
239     ret = SoftBusHandler::GetInstance().CreateSessionServer(IDaemon::SERVICE_NAME, sessionName);
240     if (ret != E_OK) {
241         LOGE("CreateSessionServer failed, ret = %{public}d", ret);
242         RemoveSession(sessionName);
243         return CancelWait(sessionName, listenerCallback);
244     }
245 
246     ret = SoftBusHandler::GetInstance().SetFileReceiveListener(IDaemon::SERVICE_NAME, sessionName, physicalPath);
247     if (ret != E_OK) {
248         LOGE("SetFileReceiveListener failed, ret = %{public}d", ret);
249         RemoveSession(sessionName);
250         return CancelWait(sessionName, listenerCallback);
251     }
252     TransManager::GetInstance().AddTransTask(sessionName, listenerCallback);
253     return LoadRemoteSA(srcUri, physicalPath, localDeviceInfo.networkId, srcDeviceId, sessionName);
254 }
255 
LoadRemoteSA(const std::string & srcUri,const std::string & dstPath,const std::string & localDeviceId,const std::string & remoteDeviceId,const std::string & sessionName)256 int32_t Daemon::LoadRemoteSA(const std::string &srcUri,
257                              const std::string &dstPath,
258                              const std::string &localDeviceId,
259                              const std::string &remoteDeviceId,
260                              const std::string &sessionName)
261 {
262     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
263     if (sam == nullptr) {
264         LOGE("Samgr is nullptr");
265         RemoveSession(sessionName);
266         return E_SA_LOAD_FAILED;
267     }
268 
269     auto object = sam->GetSystemAbility(FILEMANAGEMENT_DISTRIBUTED_FILE_DAEMON_SA_ID, remoteDeviceId);
270     if (object == nullptr) {
271         LOGE("GetSystemAbility failed");
272         RemoveSession(sessionName);
273         return E_SA_LOAD_FAILED;
274     }
275     auto daemon = iface_cast<OHOS::Storage::DistributedFile::IDaemon>(object);
276     if (daemon == nullptr) {
277         LOGE("Connect service nullptr");
278         RemoveSession(sessionName);
279         return E_SA_LOAD_FAILED;
280     }
281 
282     auto ret = daemon->RequestSendFile(srcUri, dstPath, localDeviceId, sessionName);
283     if (ret != E_OK) {
284         LOGE("RequestSendFile failed, ret = %{public}d", ret);
285         RemoveSession(sessionName);
286         return E_SA_LOAD_FAILED;
287     }
288     return ret;
289 }
290 
RemoveSession(const std::string & sessionName)291 void Daemon::RemoveSession(const std::string &sessionName)
292 {
293     TransManager::GetInstance().DeleteTransTask(sessionName);
294     SoftBusSessionPool::GetInstance().DeleteSessionInfo(sessionName);
295     RemoveSessionServer(IDaemon::SERVICE_NAME.c_str(), sessionName.c_str());
296 }
297 
GetRealPath(const std::string & dstUri,const HapTokenInfo & hapTokenInfo,const std::string & sessionName,std::string & physicalPath)298 int32_t Daemon::GetRealPath(const std::string &dstUri,
299                             const HapTokenInfo &hapTokenInfo,
300                             const std::string &sessionName,
301                             std::string &physicalPath)
302 {
303     Uri uri(dstUri);
304     auto authority = uri.GetAuthority();
305     if (authority == FILE_MANAGER_AUTHORITY || authority == MEDIA_AUTHORITY) {
306         auto ret = SandboxHelper::GetPhysicalPath(dstUri, std::to_string(hapTokenInfo.userID), physicalPath);
307         if (ret != E_OK) {
308             LOGE("invalid uri, ret = %{public}d", ret);
309             RemoveSession(sessionName);
310             return E_GET_PHYSICAL_PATH_FAILED;
311         }
312     } else {
313         auto bundleName = SoftBusSessionListener::GetBundleName(dstUri);
314         if (bundleName.empty()) {
315             LOGE("not find bundle name");
316             RemoveSession(sessionName);
317             return E_GET_PHYSICAL_PATH_FAILED;
318         }
319         physicalPath = "/data/service/el2/" + to_string(hapTokenInfo.userID) + "/hmdfs/account/data/" + bundleName;
320     }
321     LOGI("physicalPath %{public}s", physicalPath.c_str());
322     if (!SandboxHelper::CheckValidPath(physicalPath)) {
323         LOGE("invalid path.");
324         RemoveSession(sessionName);
325         return E_GET_PHYSICAL_PATH_FAILED;
326     }
327     return E_OK;
328 }
329 
CancelWait(const std::string & sessionName,const sptr<IFileTransListener> & listenerCallback)330 int32_t Daemon::CancelWait(const std::string &sessionName, const sptr<IFileTransListener> &listenerCallback)
331 {
332     listenerCallback->OnFailed(sessionName);
333     return E_SOFTBUS_SESSION_FAILED;
334 }
335 } // namespace DistributedFile
336 } // namespace Storage
337 } // namespace OHOS