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 "ipc/daemon.h"
17
18#include <exception>
19#include <regex>
20#include <stdexcept>
21#include <string>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <unordered_set>
25
26#include "accesstoken_kit.h"
27#include "all_connect/all_connect_manager.h"
28#include "asset_callback_manager.h"
29#include "common_event_manager.h"
30#include "common_event_support.h"
31#include "connection_detector.h"
32#include "device/device_manager_agent.h"
33#include "dfs_daemon_event_dfx.h"
34#include "dfs_error.h"
35#include "dfsu_access_token_helper.h"
36#include "i_file_dfs_listener.h"
37#include "ipc_skeleton.h"
38#include "iremote_object.h"
39#include "iservice_registry.h"
40#include "mountpoint/mount_manager.h"
41#include "network/softbus/softbus_handler_asset.h"
42#include "network/softbus/softbus_handler.h"
43#include "network/softbus/softbus_session_dispatcher.h"
44#include "network/softbus/softbus_session_listener.h"
45#include "network/softbus/softbus_session_pool.h"
46#include "sandbox_helper.h"
47#include "system_ability_definition.h"
48#include "trans_mananger.h"
49#include "utils_directory.h"
50#include "utils_log.h"
51
52namespace OHOS {
53namespace Storage {
54namespace DistributedFile {
55using namespace std;
56using namespace OHOS::AppFileService;
57using namespace OHOS::FileManagement;
58using namespace OHOS::Storage::DistributedFile;
59using HapTokenInfo = OHOS::Security::AccessToken::HapTokenInfo;
60using AccessTokenKit = OHOS::Security::AccessToken::AccessTokenKit;
61
62namespace {
63const string FILE_MANAGER_AUTHORITY = "docs";
64const string MEDIA_AUTHORITY = "media";
65const int32_t E_PERMISSION_DENIED_NAPI = 201;
66const int32_t E_INVAL_ARG_NAPI = 401;
67const int32_t E_CONNECTION_FAILED = 13900045;
68const int32_t E_UNMOUNT = 13600004;
69constexpr int32_t CHECK_SESSION_DELAY_TIME_TWICE = 5000000;
70constexpr mode_t DEFAULT_UMASK = 0002;
71constexpr int32_t BLOCK_INTERVAL_SEND_FILE = 8 * 1000;
72}
73
74REGISTER_SYSTEM_ABILITY_BY_ID(Daemon, FILEMANAGEMENT_DISTRIBUTED_FILE_DAEMON_SA_ID, true);
75
76void Daemon::PublishSA()
77{
78    LOGI("Begin to init");
79    if (!registerToService_) {
80        bool ret = SystemAbility::Publish(this);
81        if (!ret) {
82            throw runtime_error("Failed to publish the daemon");
83        }
84        registerToService_ = true;
85    }
86    LOGI("Init finished successfully");
87}
88
89void Daemon::RegisterOsAccount()
90{
91    EventFwk::MatchingSkills matchingSkills;
92    matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
93    EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
94    subScriber_ = std::make_shared<OsAccountObserver>(subscribeInfo);
95    bool subRet = EventFwk::CommonEventManager::SubscribeCommonEvent(subScriber_);
96    if (!subRet) {
97        LOGE("Subscribe common event failed");
98    }
99}
100
101void Daemon::OnStart()
102{
103    LOGI("Begin to start service");
104    if (state_ == ServiceRunningState::STATE_RUNNING) {
105        LOGD("Daemon has already started");
106        return;
107    }
108
109    try {
110        PublishSA();
111        StartEventHandler();
112        AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
113        AddSystemAbilityListener(SOFTBUS_SERVER_SA_ID);
114        umask(DEFAULT_UMASK);
115        AllConnectManager::GetInstance().InitAllConnectManager();
116    } catch (const exception &e) {
117        LOGE("%{public}s", e.what());
118    }
119
120    state_ = ServiceRunningState::STATE_RUNNING;
121    LOGI("Start service successfully");
122}
123
124void Daemon::OnStop()
125{
126    LOGI("Begin to stop");
127    state_ = ServiceRunningState::STATE_NOT_START;
128    registerToService_ = false;
129    bool subRet = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subScriber_);
130    if (!subRet) {
131        LOGE("UnSubscribe common event failed");
132    }
133    subScriber_ = nullptr;
134    daemonExecute_ = nullptr;
135    eventHandler_ = nullptr;
136    SoftBusHandlerAsset::GetInstance().DeleteAssetLocalSessionServer();
137    AllConnectManager::GetInstance().UnInitAllConnectManager();
138    LOGI("Stop finished successfully");
139}
140
141void Daemon::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
142{
143    if (systemAbilityId == COMMON_EVENT_SERVICE_ID) {
144        (void)systemAbilityId;
145        (void)deviceId;
146        RegisterOsAccount();
147    } else if (systemAbilityId == SOFTBUS_SERVER_SA_ID) {
148        SoftBusHandlerAsset::GetInstance().CreateAssetLocalSessionServer();
149    }
150}
151
152void Daemon::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
153{
154    (void)deviceId;
155    if (systemAbilityId == COMMON_EVENT_SERVICE_ID) {
156        if (subScriber_ == nullptr) {
157            LOGE("Daemon::OnRemoveSystemAbility subscriberPtr is nullptr");
158            return;
159        }
160
161        bool subscribeResult = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subScriber_);
162        LOGI("Daemon::OnRemoveSystemAbility subscribeResult = %{public}d", subscribeResult);
163        subScriber_ = nullptr;
164    } else if (systemAbilityId == SOFTBUS_SERVER_SA_ID) {
165        SoftBusHandlerAsset::GetInstance().DeleteAssetLocalSessionServer();
166    }
167}
168
169int32_t Daemon::OpenP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo)
170{
171    LOGI("OpenP2PConnection networkId %{public}s", Utils::GetAnonyString(deviceInfo.networkId).c_str());
172    RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_BUILD__LINK, RadarReporter::DFX_SUCCESS,
173        RadarReporter::BIZ_STATE, RadarReporter::DFX_BEGIN);
174    auto path = ConnectionDetector::ParseHmdfsPath();
175    stringstream ss;
176    ss << ConnectionDetector::MocklispHash(path);
177    auto targetDir = ss.str();
178    auto networkId = std::string(deviceInfo.networkId);
179    int32_t ret = 0;
180    if (!ConnectionDetector::GetConnectionStatus(targetDir, networkId)) {
181        DeviceManagerAgent::GetInstance()->ClearCount(deviceInfo);
182        LOGI("Get connection status not ok, try again.");
183        ret = DeviceManagerAgent::GetInstance()->OnDeviceP2POnline(deviceInfo);
184        if (ret != NO_ERROR) {
185            LOGE("OpenP2PConnection failed, ret = %{public}d", ret);
186        } else {
187            ret = ConnectionDetector::RepeatGetConnectionStatus(targetDir, networkId);
188            LOGI("RepeatGetConnectionStatus end, ret = %{public}d", ret);
189        }
190    }
191    if (ret == FileManagement::ERR_BAD_VALUE) {
192        LOGI("OpenP2PConnection check connection status failed, start to clean up");
193        CloseP2PConnection(deviceInfo);
194    }
195    RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_BUILD__LINK, RadarReporter::DFX_SUCCESS,
196        RadarReporter::BIZ_STATE, RadarReporter::DFX_END);
197    return ret;
198}
199
200int32_t Daemon::CloseP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo)
201{
202    LOGI("Close P2P Connection networkId %{public}s", Utils::GetAnonyString(deviceInfo.networkId).c_str());
203    std::thread([=]() {
204        int32_t ret = DeviceManagerAgent::GetInstance()->OnDeviceP2POffline(deviceInfo);
205        LOGI("Close P2P Connection result %d", ret);
206        return ret;
207        }).detach();
208    return 0;
209}
210
211int32_t Daemon::ConnectionCount(const DistributedHardware::DmDeviceInfo &deviceInfo)
212{
213    auto path = ConnectionDetector::ParseHmdfsPath();
214    stringstream ss;
215    ss << ConnectionDetector::MocklispHash(path);
216    auto targetDir = ss.str();
217    auto networkId = std::string(deviceInfo.networkId);
218    int32_t ret = 0;
219    ret = DeviceManagerAgent::GetInstance()->OnDeviceP2POnline(deviceInfo);
220    if (ret != NO_ERROR) {
221        LOGE("OpenP2PConnection failed, ret = %{public}d", ret);
222    } else {
223        ret = ConnectionDetector::RepeatGetConnectionStatus(targetDir, networkId);
224        LOGI("RepeatGetConnectionStatus first time, ret = %{public}d", ret);
225    }
226    ret = ConnectionDetector::RepeatGetConnectionStatus(targetDir, networkId);
227    if (ret != NO_ERROR) {
228        LOGI("RepeatGetConnectionStatus third times, ret = %{public}d", ret);
229        usleep(CHECK_SESSION_DELAY_TIME_TWICE);
230        ret = ConnectionDetector::RepeatGetConnectionStatus(targetDir, networkId);
231    }
232    return ret;
233}
234
235int32_t Daemon::CleanUp(const DistributedHardware::DmDeviceInfo &deviceInfo,
236                        const std::string &networkId, uint32_t callingTokenId)
237{
238    LOGI("CleanUp start");
239    auto deviceManager = DeviceManagerAgent::GetInstance();
240    if (deviceManager->RemoveRemoteReverseObj(false, callingTokenId) != E_OK) {
241        LOGE("fail to RemoveRemoteReverseObj");
242    }
243    deviceManager->RemoveNetworkIdByOne(callingTokenId, networkId);
244    int32_t ret = CloseP2PConnection(deviceInfo);
245    if (ret != NO_ERROR) {
246        LOGE("Daemon::CleanUp CloseP2PConnection failed");
247        return E_CONNECTION_FAILED;
248    }
249    return 0;
250}
251
252int32_t Daemon::ConnectionAndMount(const DistributedHardware::DmDeviceInfo &deviceInfo,
253                                   const std::string &networkId, uint32_t callingTokenId)
254{
255    LOGI("ConnectionAndMount start");
256    int32_t ret = NO_ERROR;
257    ret = ConnectionCount(deviceInfo);
258    if (ret != NO_ERROR) {
259        LOGE("connection failed");
260        return ret;
261    }
262    auto deviceManager = DeviceManagerAgent::GetInstance();
263    deviceManager->AddNetworkId(callingTokenId, networkId);
264    if (!DfsuAccessTokenHelper::CheckCallerPermission(FILE_ACCESS_MANAGER_PERMISSION)) {
265        LOGW("permission denied: FILE_ACCESS_MANAGER_PERMISSION");
266        return ret;
267    }
268    std::string deviceId = deviceManager->GetDeviceIdByNetworkId(networkId);
269    ret = deviceManager->MountDfsDocs(networkId, deviceId);
270    if (ret != NO_ERROR) {
271        LOGE("[MountDfsDocs] failed");
272    }
273    return ret;
274}
275
276int32_t Daemon::OpenP2PConnectionEx(const std::string &networkId, sptr<IFileDfsListener> remoteReverseObj)
277{
278    LOGI("Daemon::OpenP2PConnectionEx start, networkId %{public}s", Utils::GetAnonyString(networkId).c_str());
279    if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
280        LOGE("[OpenP2PConnectionEx] DATASYNC permission denied");
281        return E_PERMISSION_DENIED_NAPI;
282    }
283    if (dfsListenerDeathRecipient_ == nullptr) {
284        LOGE("Daemon::OpenP2PConnectionEx, new death recipient");
285        dfsListenerDeathRecipient_ = new (std::nothrow) DfsListenerDeathRecipient();
286    }
287    if (remoteReverseObj == nullptr) {
288        LOGE("Daemon::OpenP2PConnectionEx remoteReverseObj is nullptr");
289        return E_INVAL_ARG_NAPI;
290    }
291    remoteReverseObj->AsObject()->AddDeathRecipient(dfsListenerDeathRecipient_);
292    auto deviceManager = DeviceManagerAgent::GetInstance();
293    if (networkId.empty()) {
294        LOGE("Daemon::OpenP2PConnectionEx networkId is null");
295        return E_INVAL_ARG_NAPI;
296    }
297    DistributedHardware::DmDeviceInfo deviceInfo{};
298    auto res = strcpy_s(deviceInfo.networkId, networkId.size() + 1, networkId.c_str());
299    if (res != NO_ERROR) {
300        LOGE("OpenP2PConnectionEx strcpy failed, res = %{public}d", res);
301        return E_INVAL_ARG_NAPI;
302    }
303    auto callingTokenId = IPCSkeleton::GetCallingTokenID();
304    if (deviceManager->AddRemoteReverseObj(callingTokenId, remoteReverseObj) != E_OK) {
305        LOGE("Daemon::OpenP2PConnectionEx::fail to AddRemoteReverseObj");
306    }
307    int32_t ret = ConnectionAndMount(deviceInfo, networkId, callingTokenId);
308    if (ret != NO_ERROR) {
309        CleanUp(deviceInfo, networkId, callingTokenId);
310        return E_CONNECTION_FAILED;
311    }
312    LOGI("Daemon::OpenP2PConnectionEx end");
313    return ret;
314}
315
316int32_t Daemon::CloseP2PConnectionEx(const std::string &networkId)
317{
318    LOGI("Daemon::CloseP2PConnectionEx start, networkId: %{public}s", Utils::GetAnonyString(networkId).c_str());
319    if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
320        LOGE("[CloseP2PConnectionEx] DATASYNC permission denied");
321        return E_PERMISSION_DENIED_NAPI;
322    }
323    auto deviceManager = DeviceManagerAgent::GetInstance();
324    auto callingTokenId = IPCSkeleton::GetCallingTokenID();
325    if (networkId.empty()) {
326        LOGE("[OpenP2PConnectionEx] networkId is null");
327        return E_INVAL_ARG_NAPI;
328    }
329    std::string deviceId = deviceManager->GetDeviceIdByNetworkId(networkId);
330    if (deviceId.empty()) {
331        LOGE("fail to get deviceId");
332        return E_CONNECTION_FAILED;
333    }
334    if (DfsuAccessTokenHelper::CheckCallerPermission(FILE_ACCESS_MANAGER_PERMISSION)) {
335        LOGE("[UMountDfsDocs] permission ok: FILE_ACCESS_MANAGER_PERMISSION");
336        int32_t ret_umount = deviceManager->UMountDfsDocs(networkId, deviceId, false);
337        if (ret_umount != E_OK) {
338            LOGE("[UMountDfsDocs] failed");
339            return E_UNMOUNT;
340        }
341    }
342    DistributedHardware::DmDeviceInfo deviceInfo{};
343    auto res = strcpy_s(deviceInfo.networkId, networkId.size() + 1, networkId.c_str());
344    if (res != NO_ERROR) {
345        LOGE("strcpy failed, res = %{public}d", res);
346        return E_INVAL_ARG_NAPI;
347    }
348    int32_t ret = CleanUp(deviceInfo, networkId, callingTokenId);
349    if (ret != NO_ERROR) {
350        LOGE("Daemon::CloseP2PConnectionEx disconnection failed");
351        return E_CONNECTION_FAILED;
352    }
353    LOGI("Daemon::CloseP2PConnectionEx end");
354    return 0;
355}
356
357int32_t Daemon::RequestSendFile(const std::string &srcUri,
358                                const std::string &dstPath,
359                                const std::string &dstDeviceId,
360                                const std::string &sessionName)
361{
362    LOGI("RequestSendFile begin dstDeviceId: %{public}s", Utils::GetAnonyString(dstDeviceId).c_str());
363
364    auto requestSendFileBlock = std::make_shared<BlockObject<int32_t>>(BLOCK_INTERVAL_SEND_FILE, ERR_BAD_VALUE);
365    auto requestSendFileData = std::make_shared<RequestSendFileData>(
366        srcUri, dstPath, dstDeviceId, sessionName, requestSendFileBlock);
367    auto msgEvent = AppExecFwk::InnerEvent::Get(DEAMON_EXECUTE_REQUEST_SEND_FILE, requestSendFileData, 0);
368    {
369        std::lock_guard<std::mutex> lock(eventHandlerMutex_);
370        if (eventHandler_ == nullptr) {
371            LOGE("eventHandler has not find");
372            return E_EVENT_HANDLER;
373        }
374        bool isSucc = eventHandler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
375        if (!isSucc) {
376            LOGE("Daemon event handler post push asset event fail.");
377            return E_EVENT_HANDLER;
378        }
379    }
380
381    auto ret = requestSendFileBlock->GetValue();
382    LOGI("RequestSendFile end, ret is %{public}d", ret);
383    return ret;
384}
385
386int32_t Daemon::PrepareSession(const std::string &srcUri,
387                               const std::string &dstUri,
388                               const std::string &srcDeviceId,
389                               const sptr<IRemoteObject> &listener,
390                               HmdfsInfo &info)
391{
392    LOGI("PrepareSession begin srcDeviceId: %{public}s", Utils::GetAnonyString(srcDeviceId).c_str());
393    AllConnectManager::GetInstance().PublishServiceState(srcDeviceId,
394        ServiceCollaborationManagerBussinessStatus::SCM_IDLE);
395
396    auto listenerCallback = iface_cast<IFileTransListener>(listener);
397    if (listenerCallback == nullptr) {
398        LOGE("ListenerCallback is nullptr");
399        return E_NULLPTR;
400    }
401
402    auto daemon = GetRemoteSA(srcDeviceId);
403    if (daemon == nullptr) {
404        LOGE("Daemon is nullptr");
405        return E_SA_LOAD_FAILED;
406    }
407
408    std::string physicalPath;
409    auto ret = GetRealPath(srcUri, dstUri, physicalPath, info, daemon);
410    if (ret != E_OK) {
411        LOGE("GetRealPath failed, ret = %{public}d", ret);
412        return ret;
413    }
414
415    SoftBusSessionPool::SessionInfo sessionInfo{.dstPath = physicalPath, .uid = IPCSkeleton::GetCallingUid()};
416    auto sessionName = SoftBusSessionPool::GetInstance().GenerateSessionName(sessionInfo);
417    if (sessionName.empty()) {
418        LOGE("SessionServer exceed max");
419        return E_SOFTBUS_SESSION_FAILED;
420    }
421    info.sessionName = sessionName;
422    StoreSessionAndListener(physicalPath, sessionName, listenerCallback);
423    auto socketId = SoftBusHandler::GetInstance().CreateSessionServer(IDaemon::SERVICE_NAME, sessionName,
424        DFS_CHANNLE_ROLE_SINK, physicalPath);
425    if (socketId <= 0) {
426        LOGE("CreateSessionServer failed, ret = %{public}d", ret);
427        DeleteSessionAndListener(sessionName, socketId);
428        return E_SOFTBUS_SESSION_FAILED;
429    }
430    physicalPath.clear();
431    if (info.authority == FILE_MANAGER_AUTHORITY || info.authority == MEDIA_AUTHORITY) {
432        LOGI("authority is media or docs");
433        physicalPath = "??" + info.dstPhysicalPath;
434    }
435    ret = Copy(srcUri, physicalPath, daemon, sessionName);
436    if (ret != E_OK) {
437        LOGE("Remote copy failed,ret = %{public}d", ret);
438        DeleteSessionAndListener(sessionName, socketId);
439        return ret;
440    }
441    return ret;
442}
443
444void Daemon::StoreSessionAndListener(const std::string &physicalPath,
445                                     const std::string &sessionName,
446                                     const sptr<IFileTransListener> &listener)
447{
448    TransManager::GetInstance().AddTransTask(sessionName, listener);
449}
450
451int32_t Daemon::GetRealPath(const std::string &srcUri,
452                            const std::string &dstUri,
453                            std::string &physicalPath,
454                            HmdfsInfo &info,
455                            const sptr<IDaemon> &daemon)
456{
457    auto start = std::chrono::high_resolution_clock::now();
458    bool isSrcFile = false;
459    bool isSrcDir = false;
460    if (daemon == nullptr) {
461        LOGE("Daemon::GetRealPath daemon is nullptr");
462        return E_INVAL_ARG_NAPI;
463    }
464    auto ret = daemon->GetRemoteCopyInfo(srcUri, isSrcFile, isSrcDir);
465    if (ret != E_OK) {
466        LOGE("GetRemoteCopyInfo failed, ret = %{public}d", ret);
467        RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
468            RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
469            RadarReporter::GET_REMOTE_COPY_INFO_ERROR);
470        return E_SOFTBUS_SESSION_FAILED;
471    }
472
473    HapTokenInfo hapTokenInfo;
474    int result = AccessTokenKit::GetHapTokenInfo(IPCSkeleton::GetCallingTokenID(), hapTokenInfo);
475    if (result != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
476        LOGE("GetHapTokenInfo failed, errCode = %{public}d", result);
477        RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
478            RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
479            RadarReporter::GET_HAP_TOKEN_INFO_ERROR, RadarReporter::PACKAGE_NAME,
480            RadarReporter::accessTokenKit + to_string(result));
481        return E_GET_USER_ID;
482    }
483    ret = SandboxHelper::GetPhysicalPath(dstUri, std::to_string(hapTokenInfo.userID), physicalPath);
484    if (ret != E_OK) {
485        LOGE("invalid uri, ret = %{public}d", ret);
486        return E_GET_PHYSICAL_PATH_FAILED;
487    }
488
489    LOGI("physicalPath %{public}s, userId %{public}s", GetAnonyString(physicalPath).c_str(),
490         std::to_string(hapTokenInfo.userID).c_str());
491    info.dstPhysicalPath = physicalPath;
492    ret = CheckCopyRule(physicalPath, dstUri, hapTokenInfo, isSrcFile, info);
493    if (ret != E_OK) {
494        LOGE("CheckCopyRule failed, ret = %{public}d", ret);
495        return E_GET_PHYSICAL_PATH_FAILED;
496    }
497    auto end = std::chrono::high_resolution_clock::now();
498    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
499    Utils::SysEventFileParse(duration.count());
500    return E_OK;
501}
502
503int32_t Daemon::CheckCopyRule(std::string &physicalPath,
504                              const std::string &dstUri,
505                              HapTokenInfo &hapTokenInfo,
506                              const bool &isSrcFile,
507                              HmdfsInfo &info)
508{
509    auto checkPath = physicalPath;
510    if (isSrcFile && !Utils::IsFolder(physicalPath)) {
511        auto pos = physicalPath.rfind('/');
512        if (pos == std::string::npos) {
513            LOGE("invalid file path");
514            return E_GET_PHYSICAL_PATH_FAILED;
515        }
516        physicalPath = physicalPath.substr(0, pos);
517    }
518
519    std::error_code errCode;
520    if (!std::filesystem::exists(physicalPath, errCode) && info.dirExistFlag) {
521        LOGI("Not CheckValidPath, physicalPath %{public}s", GetAnonyString(physicalPath).c_str());
522    } else {
523        auto pos = checkPath.rfind('/');
524        if (pos == std::string::npos) {
525            LOGE("invalid file path");
526            return E_GET_PHYSICAL_PATH_FAILED;
527        }
528        checkPath = checkPath.substr(0, pos);
529        if (!SandboxHelper::CheckValidPath(checkPath)) {
530            LOGE("invalid path.");
531            return E_GET_PHYSICAL_PATH_FAILED;
532        }
533    }
534
535    Uri uri(dstUri);
536    auto authority = uri.GetAuthority();
537    info.authority = authority;
538    if (authority != FILE_MANAGER_AUTHORITY && authority != MEDIA_AUTHORITY) {
539        auto bundleName = SoftBusSessionListener::GetBundleName(dstUri);
540        physicalPath = "/data/service/el2/" + to_string(hapTokenInfo.userID) + "/hmdfs/account/data/" + bundleName +
541                       "/" + info.copyPath;
542        if (!SandboxHelper::CheckValidPath(physicalPath)) {
543            LOGE("invalid path.");
544            return E_GET_PHYSICAL_PATH_FAILED;
545        }
546    } else {
547        std::regex pathRegex("^[a-zA-Z0-9_\\-/\\\\]*$");
548        if (!std::filesystem::exists(physicalPath, errCode) && std::regex_match(physicalPath.c_str(), pathRegex)) {
549            std::filesystem::create_directory(physicalPath, errCode);
550            if (errCode.value() != 0) {
551                LOGE("Create directory failed, physicalPath %{public}s", GetAnonyString(physicalPath).c_str());
552                return E_GET_PHYSICAL_PATH_FAILED;
553            }
554        }
555    }
556    return E_OK;
557}
558
559int32_t Daemon::GetRemoteCopyInfo(const std::string &srcUri, bool &isSrcFile, bool &srcIsDir)
560{
561    LOGI("GetRemoteCopyInfo begin.");
562    auto physicalPath = SoftBusSessionListener::GetRealPath(srcUri);
563    if (physicalPath.empty()) {
564        LOGE("GetRemoteCopyInfo GetRealPath failed.");
565        return E_SOFTBUS_SESSION_FAILED;
566    }
567    isSrcFile = Utils::IsFile(physicalPath);
568    srcIsDir = Utils::IsFolder(physicalPath);
569    return E_OK;
570}
571
572sptr<IDaemon> Daemon::GetRemoteSA(const std::string &remoteDeviceId)
573{
574    LOGI("GetRemoteSA begin, DeviceId: %{public}s", Utils::GetAnonyString(remoteDeviceId).c_str());
575    auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
576    if (sam == nullptr) {
577        LOGE("Sam is nullptr");
578        return nullptr;
579    }
580
581    auto object = sam->GetSystemAbility(FILEMANAGEMENT_DISTRIBUTED_FILE_DAEMON_SA_ID, remoteDeviceId);
582    if (object == nullptr) {
583        LOGE("GetSystemAbility failed");
584        RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
585            RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
586            RadarReporter::GET_SYSTEM_ABILITY_ERROR, RadarReporter::PACKAGE_NAME, RadarReporter::saMgr);
587        return nullptr;
588    }
589    auto daemon = iface_cast<IDaemon>(object);
590    if (daemon == nullptr) {
591        LOGE("Connect service nullptr");
592        return nullptr;
593    }
594    LOGI("GetRemoteSA success, DeviceId: %{public}s", Utils::GetAnonyString(remoteDeviceId).c_str());
595    return daemon;
596}
597
598int32_t Daemon::Copy(const std::string &srcUri,
599                     const std::string &dstPath,
600                     const sptr<IDaemon> &daemon,
601                     const std::string &sessionName)
602{
603    auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
604    DistributedHardware::DmDeviceInfo localDeviceInfo{};
605    int errCode = deviceManager.GetLocalDeviceInfo(IDaemon::SERVICE_NAME, localDeviceInfo);
606    if (errCode != E_OK) {
607        LOGE("GetLocalDeviceInfo failed, errCode = %{public}d", errCode);
608        return E_GET_DEVICE_ID;
609    }
610    if (daemon == nullptr) {
611        LOGE("Daemon::Copy daemon is nullptr");
612        return E_INVAL_ARG_NAPI;
613    }
614    LOGI("Copy localDeviceInfo.networkId: %{public}s", Utils::GetAnonyString(localDeviceInfo.networkId).c_str());
615    auto ret = daemon->RequestSendFile(srcUri, dstPath, localDeviceInfo.networkId, sessionName);
616    if (ret != E_OK) {
617        LOGE("RequestSendFile failed, ret = %{public}d", ret);
618        RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
619            RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
620            RadarReporter::REQUEST_SEND_FILE_ERROR, RadarReporter::PACKAGE_NAME, ret);
621        return E_SA_LOAD_FAILED;
622    }
623    return E_OK;
624}
625
626int32_t Daemon::CancelCopyTask(const std::string &sessionName)
627{
628    LOGI("Cancel copy task in. sessionName = %{public}s", sessionName.c_str());
629    SoftBusSessionPool::SessionInfo sessionInfo{};
630    bool isExist = SoftBusSessionPool::GetInstance().GetSessionInfo(sessionName, sessionInfo);
631    if (!isExist) {
632        LOGE("CancelCopyTask failed, cannot get session info for input session name=%{public}s.", sessionName.c_str());
633        return E_INVAL_ARG;
634    }
635    auto callingUid = IPCSkeleton::GetCallingUid();
636    if (callingUid != sessionInfo.uid) {
637        LOGE("CancelCopyTask failed, calling uid=%{public}d has no permission to cancel copy for uid=%{public}d.",
638             callingUid, sessionInfo.uid);
639        return E_PERMISSION_DENIED;
640    }
641    SoftBusHandler::GetInstance().CloseSessionWithSessionName(sessionName);
642    return E_OK;
643}
644
645void Daemon::DeleteSessionAndListener(const std::string &sessionName, const int32_t socketId)
646{
647    SoftBusSessionPool::GetInstance().DeleteSessionInfo(sessionName);
648    TransManager::GetInstance().DeleteTransTask(sessionName);
649    SoftBusHandler::GetInstance().CloseSession(socketId, sessionName);
650}
651
652void Daemon::DfsListenerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
653{
654    sptr<IRemoteObject> diedRemote = remote.promote();
655    if (diedRemote == nullptr) {
656        LOGE("Daemon::DfsListenerDeathRecipient OnremoteDied received died notify nullptr");
657        return;
658    }
659    auto deviceManager = DeviceManagerAgent::GetInstance();
660    uint32_t callingTokenId = 0;
661    sptr<IFileDfsListener> listener = nullptr;
662    deviceManager->FindListenerByObject(remote, callingTokenId, listener);
663    if (callingTokenId==0 || listener == nullptr) {
664        LOGE("fail to FindListenerByObject");
665        return;
666    }
667    if (deviceManager->RemoveRemoteReverseObj(false, callingTokenId) != E_OK) {
668        LOGE("fail to RemoveRemoteReverseObj");
669    }
670    auto networkIdSet = deviceManager->GetNetworkIds(callingTokenId);
671    if (networkIdSet.empty()) {
672        LOGE("fail to get networkIdSet");
673        return;
674    }
675    for (auto it = networkIdSet.begin(); it != networkIdSet.end(); ++it) {
676        if (it->empty()) {
677            LOGE("[DfsListenerDeathRecipient] networkId is null");
678            continue;
679        }
680        std::string deviceId = deviceManager->GetDeviceIdByNetworkId(*it);
681        if (deviceId.empty()) {
682            LOGE("fail to get deviceId, networkId: %{public}s", Utils::GetAnonyString(*it).c_str());
683            continue;
684        }
685        deviceManager->UMountDfsDocs(*it, deviceId, false);
686        DistributedHardware::DmDeviceInfo deviceInfo{};
687        auto res = strcpy_s(deviceInfo.networkId, it->size() + 1, it->c_str());
688        if (res != 0) {
689            LOGE("strcpy failed, res = %{public}d", res);
690            return;
691        }
692        std::thread([=]() {
693            int32_t ret = deviceManager->OnDeviceP2POffline(deviceInfo);
694            LOGI("Close P2P Connection result %d", ret);
695            }).detach();
696    }
697    deviceManager->RemoveNetworkId(callingTokenId);
698    LOGI("Daemon::DfsListenerDeathRecipient OnremoteDied end");
699    return;
700}
701
702int32_t Daemon::PushAsset(int32_t userId,
703                          const sptr<AssetObj> &assetObj,
704                          const sptr<IAssetSendCallback> &sendCallback)
705{
706    LOGI("Daemon::PushAsset begin.");
707    if (assetObj == nullptr || sendCallback == nullptr) {
708        LOGE("param is nullptr.");
709        return E_NULLPTR;
710    }
711    auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
712    if (taskId.empty()) {
713        LOGE("assetObj info is null.");
714        return E_NULLPTR;
715    }
716    AssetCallbackManager::GetInstance().AddSendCallback(taskId, sendCallback);
717    auto pushData = std::make_shared<PushAssetData>(userId, assetObj);
718    auto msgEvent = AppExecFwk::InnerEvent::Get(DEAMON_EXECUTE_PUSH_ASSET, pushData, 0);
719
720    std::lock_guard<std::mutex> lock(eventHandlerMutex_);
721    if (eventHandler_ == nullptr) {
722        LOGE("eventHandler has not find");
723        AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
724        return E_EVENT_HANDLER;
725    }
726    bool isSucc = eventHandler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
727    if (!isSucc) {
728        LOGE("Daemon event handler post push asset event fail.");
729        AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
730        return E_EVENT_HANDLER;
731    }
732    return E_OK;
733}
734
735int32_t Daemon::RegisterAssetCallback(const sptr<IAssetRecvCallback> &recvCallback)
736{
737    LOGI("Daemon::RegisterAssetCallback begin.");
738    if (recvCallback == nullptr) {
739        LOGE("recvCallback is nullptr.");
740        return E_NULLPTR;
741    }
742    AssetCallbackManager::GetInstance().AddRecvCallback(recvCallback);
743    return E_OK;
744}
745
746int32_t Daemon::UnRegisterAssetCallback(const sptr<IAssetRecvCallback> &recvCallback)
747{
748    LOGI("Daemon::UnRegisterAssetCallback begin.");
749    if (recvCallback == nullptr) {
750        LOGE("recvCallback is nullptr.");
751        return E_NULLPTR;
752    }
753    AssetCallbackManager::GetInstance().RemoveRecvCallback(recvCallback);
754    return E_OK;
755}
756
757void Daemon::StartEventHandler()
758{
759    LOGI("StartEventHandler begin");
760    if (daemonExecute_ == nullptr) {
761        daemonExecute_ = std::make_shared<DaemonExecute>();
762    }
763
764    std::lock_guard<std::mutex> lock(eventHandlerMutex_);
765    auto runer = AppExecFwk::EventRunner::Create(IDaemon::SERVICE_NAME.c_str());
766    eventHandler_ = std::make_shared<DaemonEventHandler>(runer, daemonExecute_);
767}
768} // namespace DistributedFile
769} // namespace Storage
770} // namespace OHOS