diff --git a/BUILD.gn b/BUILD.gn index 180b46ec8075e1142513c4a775109aa7584b7c3a..f630eb5aa88ecbe3ebccb93dcf5071ebe6e243a3 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -28,6 +28,10 @@ group("services_target") { ] } +group("napi_target") { + deps = [ "${distributedfile_path}/frameworks/js/napi:build_kits_js" ] +} + group("dfs_test_moudule") { testonly = true deps = [ diff --git a/bundle.json b/bundle.json index fb9e31e5b8067e543f88b38f87264d5f1985739d..5b576220296ae3be45166517146e1e3938a8135e 100644 --- a/bundle.json +++ b/bundle.json @@ -36,14 +36,16 @@ }, "build": { "sub_component": [ - "//foundation/filemanagement/dfs_service:services_target" + "//foundation/filemanagement/dfs_service:services_target", + "//foundation/filemanagement/dfs_service:napi_target" ], "inner_kits": [ { "name": "//foundation/filemanagement/dfs_service:libdistributedfile_innerkits", "header": { "header_files": [ - "i_distributedfile_service.h" + "i_distributedfile_service.h", + "i_filetransfer_callback.h" ], "header_base": "//foundation/filemanagement/dfs_service/interfaces/innerkits/native" } diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a34f0a40d1f5ad1d6815db6e9966aac4d40d2651 --- /dev/null +++ b/frameworks/js/napi/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +ohos_shared_library("sendfile") { + include_dirs = [ + "//third_party/libuv/include", + "//third_party/node/src", + "//foundation/ace/napi/interfaces/kits", + "${distributedfile_path}/interfaces/innerkits/native", + "${distributedfile_path}/frameworks/native/include", + "${distributedfile_path}/frameworks/js/napi/include", + "${distributedfile_path}/utils/log/include", + "${services_path}/distributedfileservice/include/ipc", + "//foundation/communication/ipc/interfaces/innerkits/libdbinder/include", + "//foundation/distributedschedule/samgr/services/samgr/native/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedhardware/devicemanager/interfaces/inner_kits/native_cpp/include", + "//foundation/distributeddatamgr/distributedfile/utils/filemgmt_libn/include", + ] + + sources = [ + "${distributedfile_path}/frameworks/js/napi/src/event_agent.cpp", + "${distributedfile_path}/frameworks/js/napi/src/sendfile.cpp", + "${distributedfile_path}/frameworks/js/napi/src/sendfile_napi.cpp", + "${distributedfile_path}/frameworks/js/napi/src/trans_event.cpp", + "${distributedfile_path}/frameworks/native/src/dfs_filetransfer_callback.cpp", + "${distributedfile_path}/frameworks/native/src/filetransfer_callback_proxy.cpp", + "${distributedfile_path}/frameworks/native/src/filetransfer_callback_stub.cpp", + ] + + deps = [ + "${distributedfile_path}/interfaces/innerkits/native:libdistributedfile_innerkits", + "${utils_path}:libdistributedfileutils", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/ace/napi:ace_napi", + "//foundation/distributeddatamgr/distributedfile/utils/filemgmt_libn:filemgmt_libn", + "//utils/native/base:utilsecurec", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_standard:samgr_common", + "samgr_standard:samgr_proxy", + ] + + cflags_cc = [ "-Wno-unused-function" ] + + relative_install_dir = "module" + subsystem_name = "filemanagement" + part_name = "dfs_service" +} + +group("build_kits_js") { + deps = [ ":sendfile" ] +} diff --git a/frameworks/js/napi/include/event_agent.h b/frameworks/js/napi/include/event_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..5ecb636cf788299dfe280273866d8206c088aafb --- /dev/null +++ b/frameworks/js/napi/include/event_agent.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVE_MODULE_SEND_FILE_EVENT_AGENT_H +#define NATIVE_MODULE_SEND_FILE_EVENT_AGENT_H + +#include +#include + +#include "napi/native_api.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +namespace { + constexpr int32_t LISTENER_TYPTE_MAX_LENGTH = 64; +} + +struct EventListener { + char type[LISTENER_TYPTE_MAX_LENGTH] = { 0 }; + bool isOnce = false; + napi_ref handlerRef = nullptr; + EventListener* back = nullptr; + EventListener* next = nullptr; +}; + +class Event { +public: + virtual napi_value ToJsObject(napi_env env) = 0; +}; + +class EventAgent { +public: + EventAgent(napi_env env, napi_value thisVar); + virtual ~EventAgent(); + + void On(const char* type, napi_value handler); + void Off(const char* type, napi_value handler); + void Off(const char* type); + void Emit(const char* type, Event* event); + void InsertDevice(const std::string&); + void RemoveDevice(const std::string&); + bool FindDevice(const std::string&); + void ClearDevice(); + +protected: + std::mutex deviceListMut_; + std::set deviceList_; + napi_env env_; + napi_ref thisVarRef_; + EventListener* first_; + EventListener* last_; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif /* NATIVE_MODULE_SEND_FILE_EVENT_AGENT_H */ \ No newline at end of file diff --git a/frameworks/js/napi/include/sendfile.h b/frameworks/js/napi/include/sendfile.h new file mode 100644 index 0000000000000000000000000000000000000000..a222764332097ccff99257dce73fdc9a6a0198e6 --- /dev/null +++ b/frameworks/js/napi/include/sendfile.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SENDFILE_H +#define SENDFILE_H + +#include "event_agent.h" + +#include +#include + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +int32_t NapiDeviceOnline(const std::string &cid); +int32_t NapiDeviceOffline(const std::string &cid); +int32_t NapiSendFinished(const std::string &cid, const std::string &fileName); +int32_t NapiSendError(const std::string &cid); +int32_t NapiReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num); +int32_t NapiReceiveError(const std::string &cid); +int32_t NapiWriteFile(int32_t fd, const std::string &fileName); + +napi_value RegisterSendFileNotifyCallback(); + +static std::unordered_map g_mapUidToEventAgent; + +int32_t ExecSendFile(const std::string &deviceId, const std::vector& srcList, + const std::vector& dstList, uint32_t num); +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // SENDFILE_H \ No newline at end of file diff --git a/frameworks/js/napi/include/sendfile_napi.h b/frameworks/js/napi/include/sendfile_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..775ffa22d65dd395df25240d930e634a8568dbba --- /dev/null +++ b/frameworks/js/napi/include/sendfile_napi.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SENDFILE_NAPI_H +#define SENDFILE_NAPI_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { + enum DFS_ARG_CNT { + ZERO = 0, + ONE = 1, + TWO = 2, + THREE = 3, + FOUR = 4, + FIVE = 5 + }; + enum DFS_ARG_POS { + FIRST = 0, + SECOND = 1, + THIRD = 2, + FOURTH = 3, + FIFTH = 4, + SIXTH = 5 + }; + napi_value JS_Constructor(napi_env env, napi_callback_info cbinfo); + napi_value SendFile(napi_env env, napi_callback_info info); + napi_value JS_On(napi_env env, napi_callback_info cbinfo); + napi_value JS_Off(napi_env env, napi_callback_info cbinfo); +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // SENDFILE_NAPI_H \ No newline at end of file diff --git a/frameworks/js/napi/include/trans_event.h b/frameworks/js/napi/include/trans_event.h new file mode 100644 index 0000000000000000000000000000000000000000..f44c2837fd2a748535c441dbbe95ebf86b7842fb --- /dev/null +++ b/frameworks/js/napi/include/trans_event.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRANS_EVENT_H +#define TRANS_EVENT_H + +#include "event_agent.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +class TransEvent : public Event { +public: + enum { + TRANS_SUCCESS = 0, + TRANS_FAILURE = 1 + }; +public: + TransEvent(int32_t err, std::string fname, int32_t num) : errorCode_(err), fileName_(fname), fileCount_(num) {} + TransEvent(int32_t err, std::string fname) : errorCode_(err), fileName_(fname) {} + TransEvent(int32_t err) : errorCode_(err) {} + virtual ~TransEvent() {} + napi_value ToJsObject(napi_env env); + +private: + int32_t errorCode_ = TRANS_SUCCESS; + std::string fileName_ = ""; + int32_t fileCount_ = 0; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // TRANS_EVENT_H \ No newline at end of file diff --git a/frameworks/js/napi/src/event_agent.cpp b/frameworks/js/napi/src/event_agent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2aedcd151440f395048463c51ab473d3cf391d0 --- /dev/null +++ b/frameworks/js/napi/src/event_agent.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "event_agent.h" + +#include "securec.h" +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +EventAgent::EventAgent(napi_env env, napi_value thisVar) + : env_(env), thisVarRef_(nullptr), first_(nullptr), last_(nullptr) +{ + napi_create_reference(env, thisVar, 1, &thisVarRef_); +} + +EventAgent::~EventAgent() +{ + EventListener* temp = nullptr; + for (EventListener* iter = first_; iter != nullptr; iter = temp) { + temp = iter->next; + if (iter == first_) { + first_ = first_->next; + } else if (iter == last_) { + last_ = last_->back; + } else { + iter->next->back = iter->back; + iter->back->next = iter->next; + } + napi_delete_reference(env_, iter->handlerRef); + delete iter; + } + napi_delete_reference(env_, thisVarRef_); +} + +void EventAgent::On(const char* type, napi_value handler) +{ + auto tmp = new EventListener(); + + if (strncpy_s(tmp->type, LISTENER_TYPTE_MAX_LENGTH, type, strlen(type)) == -1) { + delete tmp; + tmp = nullptr; + return; + } + + if (first_ == nullptr) { + first_ = last_ = tmp; + } else { + last_->next = tmp; + last_->next->back = last_; + last_ = last_->next; + } + last_->isOnce = false; + napi_create_reference(env_, handler, 1, &last_->handlerRef); +} + +void EventAgent::Off(const char* type) +{ + EventListener* temp = nullptr; + for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = temp) { + temp = eventListener->next; + if (strcmp(eventListener->type, type) == 0) { + if (eventListener == first_) { + first_ = first_->next; + } else if (eventListener == last_) { + last_ = last_->back; + } else { + eventListener->next->back = eventListener->back; + eventListener->back->next = eventListener->next; + } + napi_delete_reference(env_, eventListener->handlerRef); + delete eventListener; + eventListener = nullptr; + } + } +} + +void EventAgent::Emit(const char* type, Event* event) +{ + napi_handle_scope scope = nullptr; + napi_open_handle_scope(env_, &scope); + + napi_value thisVar = nullptr; + napi_get_reference_value(env_, thisVarRef_, &thisVar); + for (EventListener* eventListener = first_; eventListener != nullptr; eventListener = eventListener->next) { + if (strcmp(eventListener->type, type) == 0) { + napi_value jsEvent = event ? event->ToJsObject(env_) : nullptr; + napi_value handler = nullptr; + napi_value callbackResult = nullptr; + napi_value result = nullptr; + napi_get_undefined(env_, &result); + napi_value callbackValues[2] = {0}; + callbackValues[0] = result; + callbackValues[1] = jsEvent; + napi_get_reference_value(env_, eventListener->handlerRef, &handler); + napi_call_function(env_, thisVar, handler, std::size(callbackValues), callbackValues, &callbackResult); + if (eventListener->isOnce) { + Off(type); + } + } + } + + napi_close_handle_scope(env_, scope); +} + +void EventAgent::InsertDevice(const std::string& deviceId) +{ + if (deviceList_.find(deviceId) == deviceList_.end()) { + std::unique_lock lock(deviceListMut_); + deviceList_.insert(deviceId); + } +} + +void EventAgent::RemoveDevice(const std::string& deviceId) +{ + if (deviceList_.find(deviceId) != deviceList_.end()) { + std::unique_lock lock(deviceListMut_); + deviceList_.erase(deviceId); + } +} + +bool EventAgent::FindDevice(const std::string& deviceId) +{ + return (deviceList_.find(deviceId) != deviceList_.end()); +} + +void EventAgent::ClearDevice() +{ + deviceList_.clear(); +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/src/sendfile.cpp b/frameworks/js/napi/src/sendfile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b26aad49ee4216f45be1396d203e930b36ad0e0 --- /dev/null +++ b/frameworks/js/napi/src/sendfile.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sendfile.h" + +#include +#include +#include + +#include "dfs_filetransfer_callback.h" +#include "event_agent.h" +#include "filetransfer_callback_proxy.h" +#include "i_distributedfile_service.h" +#include "iservice_registry.h" +#include "service_proxy.h" +#include "system_ability_definition.h" +#include "system_ability_manager.h" +#include "trans_event.h" +#include "utils_directory.h" +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +namespace { +const std::string DfsAppUid { "SendFileTestUid" }; +constexpr int32_t FILE_BLOCK_SIZE = 1024; +const std::string APP_PATH { "/data/accounts/account_0/appdata/com.example.filetestkits/cache/" }; +} + +napi_value RegisterSendFileNotifyCallback() +{ + sptr systemAbilityMgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + LOGE("SendFile napi Regist callback Get ISystemAbilityManager failed ... \n"); + return nullptr; + } + + sptr remote = systemAbilityMgr->GetSystemAbility(STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + if (remote == nullptr) { + LOGE("SendFile napi Regist callback Get SaId = %{public}d fail ... \n", STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + return nullptr; + } + + sptr distributedFileService = iface_cast(remote); + if (distributedFileService == nullptr) { + LOGE("SendFile napi Regist callback == nullptr\n"); + return nullptr; + } + + sptr callback = (std::make_unique()).release(); + LOGI("INotifyCallback == callback %{public}p", callback->AsObject().GetRefPtr()); + distributedFileService->RegisterNotifyCallback(callback); + return nullptr; +} + +int32_t NapiDeviceOnline(const std::string &cid) +{ + for (std::unordered_map::iterator iter = g_mapUidToEventAgent.begin(); + iter != g_mapUidToEventAgent.end(); ++iter) { + EventAgent* agent = iter->second; + if (agent != nullptr && agent->FindDevice(DfsAppUid)) { + LOGI("NapiDeviceOnline, event agent for device[%{public}s] was found.", cid.c_str()); + agent->InsertDevice(cid); + break; + } + } + return 0; +} + +int32_t NapiDeviceOffline(const std::string &cid) +{ + for (std::unordered_map::iterator iter = g_mapUidToEventAgent.begin(); + iter != g_mapUidToEventAgent.end(); ++iter) { + EventAgent* agent = iter->second; + if (agent != nullptr && agent->FindDevice(DfsAppUid)) { + LOGI("NapiDeviceOffline, event agent for device[%{public}s] was found.", cid.c_str()); + agent->RemoveDevice(cid); + break; + } + } + return 0; +} + +int32_t NapiSendFinished(const std::string &cid, const std::string &fileName) +{ + EventAgent* agent = nullptr; + std::unordered_map::iterator iter; + for (iter = g_mapUidToEventAgent.begin(); iter != g_mapUidToEventAgent.end(); ++iter) { + agent = iter->second; + if (agent->FindDevice(cid)) { + LOGI("DEBUG_SENDFILE:OnSendFinished, event agent for device[%{public}s] was found.", cid.c_str()); + break; + } else { + sptr systemAbilityMgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + return -1; + } + sptr remote = systemAbilityMgr->GetSystemAbility(STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + if (remote == nullptr) { + return -1; + } + sptr distributedFileService = iface_cast(remote); + if (distributedFileService == nullptr) { + return -1; + } + if (distributedFileService->IsDeviceOnline(cid) == 1) { + agent->InsertDevice(cid); + } + LOGI("DEBUG_SENDFILE:OnSendFinished, ------ no event agent for device[%{public}s].", cid.c_str()); + } + } + + iter = g_mapUidToEventAgent.find(DfsAppUid); + if (g_mapUidToEventAgent.end() != iter) { + TransEvent event(TransEvent::TRANS_SUCCESS, fileName); + agent->Emit("sendFinished", reinterpret_cast(&event)); + LOGI("DEBUG_SENDFILE:OnSendFinished, [%{public}s] event was done.", cid.c_str()); + return 0; + } else { + LOGI("DEBUG_SENDFILE:OnSendFinished, [%{public}s] no event processor.", cid.c_str()); + return -1; + } +} + +int32_t NapiSendError(const std::string &cid) +{ + EventAgent* agent = nullptr; + std::unordered_map::iterator iter; + for (iter = g_mapUidToEventAgent.begin(); iter != g_mapUidToEventAgent.end(); ++iter) { + agent = iter->second; + if (agent->FindDevice(cid)) { + LOGI("DEBUG_SENDFILE:OnSendError, event agent for device[%{public}s] was found.", cid.c_str()); + break; + } else { + sptr systemAbilityMgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + return -1; + } + sptr remote = systemAbilityMgr->GetSystemAbility(STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + if (remote == nullptr) { + return -1; + } + sptr distributedFileService = iface_cast(remote); + if (distributedFileService == nullptr) { + return -1; + } + if (distributedFileService->IsDeviceOnline(cid) == 1) { + agent->InsertDevice(cid); + } + LOGI("DEBUG_SENDFILE:OnSendError, no event agent for device[%{public}s].", cid.c_str()); + } + } + + iter = g_mapUidToEventAgent.find(DfsAppUid); + if (g_mapUidToEventAgent.end() != iter) { + TransEvent event(TransEvent::TRANS_FAILURE); + agent->Emit("sendFinished", reinterpret_cast(&event)); + LOGI("DEBUG_SENDFILE:OnSendError, [%{public}s] event was done.", cid.c_str()); + return 0; + } else { + LOGI("DEBUG_SENDFILE:OnSendError, [%{public}s] no event processor.", cid.c_str()); + return -1; + } +} + +int32_t NapiReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num) +{ + EventAgent* agent = nullptr; + std::unordered_map::iterator iter; + for (auto iter = g_mapUidToEventAgent.begin(); iter != g_mapUidToEventAgent.end(); ++iter) { + agent = iter->second; + if (agent->FindDevice(cid)) { + LOGI("DEBUG_SENDFILE:OnReceiveFinished, event agent for device[%{public}s] was found.", cid.c_str()); + break; + } else { + sptr systemAbilityMgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + return -1; + } + sptr remote = systemAbilityMgr->GetSystemAbility(STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + if (remote == nullptr) { + return -1; + } + sptr distributedFileService = iface_cast(remote); + if (distributedFileService == nullptr) { + return -1; + } + if (distributedFileService->IsDeviceOnline(cid) == 1) { + agent->InsertDevice(cid); + } + LOGI("DEBUG_SENDFILE:OnReceiveFinished, no event agent for device[%{public}s].", cid.c_str()); + } + } + + iter = g_mapUidToEventAgent.find(DfsAppUid); + if (g_mapUidToEventAgent.end() != iter) { + TransEvent event(TransEvent::TRANS_SUCCESS, fileName, num); + agent->Emit("receiveFinished", reinterpret_cast(&event)); + LOGI("DEBUG_SENDFILE:OnReceiveFinished, [%{public}s] event was done.", cid.c_str()); + return 0; + } else { + LOGI("DEBUG_SENDFILE:OnReceiveFinished, [%{public}s] no event processor.", cid.c_str()); + return -1; + } +} + +int32_t NapiReceiveError(const std::string &cid) +{ + EventAgent* agent = nullptr; + std::unordered_map::iterator iter; + for (auto iter = g_mapUidToEventAgent.begin(); iter != g_mapUidToEventAgent.end(); ++iter) { + agent = iter->second; + if (agent->FindDevice(cid)) { + LOGI("OnReceiveError : event agent for device[%{public}s] was found.", cid.c_str()); + break; + } else { + sptr systemAbilityMgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + return -1; + } + sptr remote = systemAbilityMgr->GetSystemAbility(STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + if (remote == nullptr) { + return -1; + } + sptr distributedFileService = iface_cast(remote); + if (distributedFileService == nullptr) { + return -1; + } + if (distributedFileService->IsDeviceOnline(cid) == 1) { + agent->InsertDevice(cid); + } + LOGI("OnReceiveError : no event agent for device[%{public}s].", cid.c_str()); + } + } + + iter = g_mapUidToEventAgent.find(DfsAppUid); + if (g_mapUidToEventAgent.end() != iter) { + TransEvent event(TransEvent::TRANS_FAILURE); + agent->Emit("receiveFinished", reinterpret_cast(&event)); + LOGI("OnReceiveError : [%{public}s] event was done.", cid.c_str()); + return 0; + } else { + LOGI("OnReceiveError : [%{public}s] no event processor.", cid.c_str()); + return -1; + } +} + +int32_t NapiWriteFile(int32_t fd, const std::string &fileName) +{ + if (fd <= 0) { + return -1; + } + std::string filePath = APP_PATH + fileName; + int32_t flags = O_WRONLY; + + if (!Utils::IsFileExist(filePath)) { + flags |= O_CREAT; + } + + int32_t writeFd = open(filePath.c_str(), flags, (S_IREAD & S_IWRITE) | S_IRGRP | S_IROTH); + if (writeFd <= 0) { + close(fd); + LOGE("NapiWriteFile open file failed %{public}d, %{public}s, %{public}d", writeFd, strerror(errno), errno); + return -1; + } + auto buffer = std::make_unique(FILE_BLOCK_SIZE); + ssize_t actLen = 0; + do { + actLen = read(fd, buffer.get(), FILE_BLOCK_SIZE); + if (actLen > 0) { + write(writeFd, buffer.get(), actLen); + } else if (actLen == 0) { + break; + } else { + if (errno == EINTR) { + actLen = FILE_BLOCK_SIZE; + } else { + close(fd); + close(writeFd); + return -1; + } + } + } while (actLen > 0); + + close(fd); + close(writeFd); + + return 0; +} + +int32_t ExecSendFile(const std::string &deviceId, const std::vector& srcList, + const std::vector& dstList, uint32_t num) +{ + if (deviceId.empty()) { + LOGE("DeviceId can't be emptey.\n"); + return -1; + } + sptr systemAbilityMgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + LOGE("BundleService Get ISystemAbilityManager failed ... \n"); + return -1; + } + sptr remote = systemAbilityMgr->CheckSystemAbility(STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + if (remote == nullptr) { + LOGE("DistributedFileService Get STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID = %{public}d fail ... \n", + STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID); + return -1; + } + + sptr distributedFileService = iface_cast(remote); + if (distributedFileService == nullptr) { + LOGE("DistributedFileService == nullptr\n"); + return -1; + } + + int32_t fd = open(srcList.at(0).c_str(), O_RDONLY); + int32_t result = distributedFileService->OpenFile(fd, srcList.at(0), (S_IREAD & S_IWRITE) | S_IRGRP | S_IROTH); + result = distributedFileService->SendFile(deviceId, srcList, dstList, num); + LOGI(" ------------ DistributedFileService SendFile result %{public}d", result); + return result; +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/src/sendfile_napi.cpp b/frameworks/js/napi/src/sendfile_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec0e9abba82b5928be79b7275b6f7f925631feaf --- /dev/null +++ b/frameworks/js/napi/src/sendfile_napi.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sendfile_napi.h" + +#include + +#include "filemgmt_libn.h" +#include "sendfile.h" +#include "trans_event.h" +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +using namespace FileManagement::LibN; +namespace { + constexpr int32_t MAX_SEND_FILE_HAP_NUMBER = 50; + constexpr int32_t SENDFILE_NAPI_BUF_LENGTH = 256; + const std::string DfsAppUid { "SendFileTestUid" }; + static std::mutex g_uidMutex; +} + +napi_value SendFile(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(DFS_ARG_CNT::FOUR, DFS_ARG_CNT::FIVE)) { + NError(EINVAL).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + bool succ = false; + auto resultCode = std::make_shared(); + + std::unique_ptr deviceId; + std::vector sourPath; + std::vector destPath; + + uint32_t fileCount = 0; + + std::tie(succ, deviceId, std::ignore) = NVal(env, funcArg[DFS_ARG_POS::FIRST]).ToUTF8String(); + napi_get_value_uint32(env, funcArg[DFS_ARG_POS::FOURTH], &fileCount); + + napi_value result; + napi_status status; + for (uint32_t i = 0; i < fileCount; ++i) { + status = napi_get_element(env, funcArg[DFS_ARG_POS::SECOND], i, &result); + if (napi_ok != status) { + return nullptr; + } + std::unique_ptr path; + std::tie(succ, path, std::ignore) = NVal(env, result).ToUTF8String(); + sourPath.push_back(path.get()); + + status = napi_get_element(env, funcArg[DFS_ARG_POS::THIRD], i, &result); + if (napi_ok != status) { + return nullptr; + } + std::tie(succ, path, std::ignore) = NVal(env, result).ToUTF8String(); + destPath.push_back(path.get()); + } + + std::string deviceIdString(deviceId.get()); + auto cbExec = [deviceIdString, sourPath, destPath, fileCount, resultCode]() -> NError { + *resultCode = ExecSendFile(deviceIdString.c_str(), sourPath, destPath, fileCount); + return NError(*resultCode); + }; + + auto cbComplete = [resultCode](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateInt64(env, *resultCode) }; + }; + + std::string procedureName = "SendFile"; + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == DFS_ARG_CNT::FOUR) { + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_; + } else if (funcArg.GetArgc() == DFS_ARG_CNT::FIVE) { + NVal cb(env, funcArg[DFS_ARG_POS::FIFTH]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_; + } + + return NVal::CreateUndefined(env).val_; +} + + +napi_value JS_On(napi_env env, napi_callback_info cbinfo) +{ + size_t requireArgc = 2; + size_t argc = 2; + napi_value argv[2] = { 0 }; + napi_value thisVar = 0; + void* data = nullptr; + napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, &data); + + EventAgent* agent = nullptr; + napi_unwrap(env, thisVar, (void**)&agent); + + NAPI_ASSERT(env, argc >= requireArgc, "requires 2 parameter"); + + napi_valuetype eventValueType = napi_undefined; + napi_typeof(env, argv[0], &eventValueType); + NAPI_ASSERT(env, eventValueType == napi_string, "type mismatch for parameter 1"); + + napi_valuetype eventHandleType = napi_undefined; + napi_typeof(env, argv[1], &eventHandleType); + NAPI_ASSERT(env, eventHandleType == napi_function, "type mismatch for parameter 2"); + + char type[64] = { 0 }; + size_t typeLen = 0; + + napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &typeLen); + + agent->On((const char*)type, argv[1]); + + napi_value result = nullptr; + napi_get_undefined(env, &result); + return result; +} + +napi_value JS_Off(napi_env env, napi_callback_info cbinfo) +{ + size_t requireArgc = 1; + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = 0; + void* data = nullptr; + napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, &data); + + EventAgent* agent = nullptr; + napi_unwrap(env, thisVar, (void**)&agent); + + NAPI_ASSERT(env, argc == requireArgc, "requires 1 parameter"); + + napi_valuetype eventValueType = napi_undefined; + napi_typeof(env, argv[0], &eventValueType); + NAPI_ASSERT(env, eventValueType == napi_string, "type mismatch for parameter 1"); + + char* type = nullptr; + size_t typeLen = 0; + napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typeLen); + + NAPI_ASSERT(env, typeLen > 0, "typeLen == 0"); + type = new char[typeLen + 1]; + + napi_get_value_string_utf8(env, argv[0], type, typeLen + 1, &typeLen); + + agent->Off(type); + + delete[] type; + napi_value result = nullptr; + napi_get_undefined(env, &result); + return result; +} + +napi_value JS_Constructor(napi_env env, napi_callback_info cbinfo) +{ + size_t argc = 2; + napi_value argv[2] = { nullptr }; + napi_value thisVar = nullptr; + napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr); + + char bundleName[SENDFILE_NAPI_BUF_LENGTH] = { 0 }; + size_t typeLen = 0; + napi_get_value_string_utf8(env, argv[0], bundleName, sizeof(bundleName), &typeLen); + LOGI("DEBUG_SENDFILE:JS_Constructor. %{public}s", bundleName); + + EventAgent* agent = new EventAgent(env, thisVar); + { + std::unique_lock lock(g_uidMutex); + if (g_mapUidToEventAgent.end() != g_mapUidToEventAgent.find(DfsAppUid)) { + delete g_mapUidToEventAgent[DfsAppUid]; + g_mapUidToEventAgent.erase(DfsAppUid); + } + if (g_mapUidToEventAgent.size() <= MAX_SEND_FILE_HAP_NUMBER) { + auto [ignored, inserted] = g_mapUidToEventAgent.insert(make_pair(DfsAppUid, agent)); + if (!inserted) { + LOGE("map env to event agent error."); + return nullptr; + } else { + LOGI("map size %{public}d", g_mapUidToEventAgent.size()); + } + } + } + + napi_wrap(env, thisVar, agent, + [](napi_env env, void* data, void* hint) { + auto iter = g_mapUidToEventAgent.find(DfsAppUid); + if (g_mapUidToEventAgent.end() != iter) { + auto agent = (EventAgent*)data; + if (agent != nullptr) { + std::unique_lock lock(g_uidMutex); + agent->ClearDevice(); + g_mapUidToEventAgent.erase(DfsAppUid); + delete agent; + } + } + }, + nullptr, nullptr); + + return thisVar; +} + +/*********************************************** + * Module export and register + ***********************************************/ +napi_value SendFileExport(napi_env env, napi_value exports) +{ + const char className[] = "SendFile"; + static napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("sendFile", SendFile), + DECLARE_NAPI_FUNCTION("on", JS_On), + DECLARE_NAPI_FUNCTION("off", JS_Off), + }; + napi_value sendFileClass = nullptr; + + napi_define_class(env, className, sizeof(className), JS_Constructor, nullptr, + sizeof(desc) / sizeof(desc[0]), desc, &sendFileClass); + + napi_set_named_property(env, exports, "SendFile", sendFileClass); + + RegisterSendFileNotifyCallback(); + return exports; +} + +NAPI_MODULE(sendfile, SendFileExport) +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/src/trans_event.cpp b/frameworks/js/napi/src/trans_event.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d452edf13db950667508f95cdd889ec4943ae5f --- /dev/null +++ b/frameworks/js/napi/src/trans_event.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trans_event.h" + +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +napi_value TransEvent::ToJsObject(napi_env env) +{ + napi_value te; + napi_status status = napi_create_object(env, &te); + if (napi_ok == status) { + napi_value err; + status = napi_create_int32(env, errorCode_, &err); + if (napi_ok == status) { + status = napi_set_named_property(env, te, "errorCode", err); + if (napi_ok != status) { + LOGE("ToJsObject: package error code failed.\n"); + return nullptr; + } + } else { + LOGE("ToJsObject: create error code failed.\n"); + return nullptr; + } + + napi_value fname; + status = napi_create_string_utf8(env, fileName_.c_str(), fileName_.size()+1, &fname); + if (napi_ok == status) { + status = napi_set_named_property(env, te, "fileName", fname); + if (napi_ok != status) { + LOGE("ToJsObject: package filename failed.\n"); + return nullptr; + } + } else { + LOGE("ToJsObject: create filename failed.\n"); + return nullptr; + } + + napi_value fcount; + status = napi_create_int32(env, fileCount_, &fcount); + if (napi_ok == status) { + status = napi_set_named_property(env, te, "fileCount", fcount); + if (napi_ok != status) { + LOGE("ToJsObject: package file counts failed.\n"); + return nullptr; + } + } else { + LOGE("ToJsObject: create file counts failed.\n"); + return nullptr; + } + } else { + LOGE("ToJsObject: create object failed.\n"); + return nullptr; + } + + return te; +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/service_proxy.cpp b/frameworks/native/include/dfs_filetransfer_callback.h similarity index 47% rename from frameworks/native/service_proxy.cpp rename to frameworks/native/include/dfs_filetransfer_callback.h index 8d9ae82395195bf436532e85d05a3cba269d5433..f2a84517b160e2bb9c6a725b9370863a5d7ce66b 100644 --- a/frameworks/native/service_proxy.cpp +++ b/frameworks/native/include/dfs_filetransfer_callback.h @@ -1,43 +1,39 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "service_proxy.h" -#include "utils_log.h" - -namespace OHOS { -namespace Storage { -namespace DistributedFile { - -int32_t ServiceProxy::SendFile(const std::string &cid, - const std::vector &sourceFileList, - const std::vector &destinationFileList, - const uint32_t fileCount) -{ - return 0; -} - -int32_t ServiceProxy::sendTest() -{ - LOGE("sendTest enter"); - MessageParcel data; - MessageParcel reply; - MessageOption option; - int ret = Remote()->SendRequest(TEST_CODE, data, reply, option); - LOGE("sendTest sendrequest done %{public}d", ret); - return ret; -} -} // namespace DistributedFile -} // namespace Storage -} // namespace OHOS \ No newline at end of file +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DFS_FILETRANSFER_CALLBACK_H +#define DFS_FILETRANSFER_CALLBACK_H + +#include "filetransfer_callback_stub.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +class DfsFileTransferCallback : public FileTransferCallbackStub { +public: + DfsFileTransferCallback(); + virtual ~DfsFileTransferCallback() override; + int32_t DeviceOnline(const std::string &cid) override; + int32_t DeviceOffline(const std::string &cid) override; + int32_t SendFinished(const std::string &cid, std::string fileName) override; + int32_t SendError(const std::string &cid) override; + int32_t ReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num) override; + int32_t ReceiveError(const std::string &cid) override; + int32_t WriteFile(int32_t fd, const std::string &fileName) override; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // DFS_FILETRANSFER_CALLBACK_H \ No newline at end of file diff --git a/frameworks/native/include/filetransfer_callback_proxy.h b/frameworks/native/include/filetransfer_callback_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..3a6eb8befcdf72bfbc4fd95dbf7c328354af5fff --- /dev/null +++ b/frameworks/native/include/filetransfer_callback_proxy.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FILETRANSFER_CALLBACK_PROXY_H +#define FILETRANSFER_CALLBACK_PROXY_H + +#include "iremote_proxy.h" +#include "i_filetransfer_callback.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +class FileTransferCallbackProxy : public IRemoteProxy { +public: + explicit FileTransferCallbackProxy(const sptr &impl) : IRemoteProxy(impl) {} + virtual ~FileTransferCallbackProxy() {} + +public: + int32_t DeviceOnline(const std::string &cid) override; + int32_t DeviceOffline(const std::string &cid) override; + int32_t SendFinished(const std::string &cid, std::string fileName) override; + int32_t SendError(const std::string &cid) override; + int32_t ReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num) override; + int32_t ReceiveError(const std::string &cid) override; + int32_t WriteFile(int32_t fd, const std::string &fileName) override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // FILETRANSFER_CALLBACK_PROXY_H \ No newline at end of file diff --git a/frameworks/native/include/filetransfer_callback_stub.h b/frameworks/native/include/filetransfer_callback_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..a5dcce43985ac3b8b2d799fb23242a9d3d948bae --- /dev/null +++ b/frameworks/native/include/filetransfer_callback_stub.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FILETRANSFER_CALLBACK_STUB_H +#define FILETRANSFER_CALLBACK_STUB_H + +#include + +#include "iremote_stub.h" +#include "i_filetransfer_callback.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +class FileTransferCallbackStub : public IRemoteStub { +public: + FileTransferCallbackStub(); + virtual ~FileTransferCallbackStub(); + + int32_t OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + using NotifyCallbackFunc = int32_t (FileTransferCallbackStub::*)(MessageParcel &, MessageParcel &); + +private: + int32_t CmdOnDeviceOnline(MessageParcel &data, MessageParcel &reply); + int32_t CmdOnDeviceOffline(MessageParcel &data, MessageParcel &reply); + int32_t CmdOnSendFinished(MessageParcel &data, MessageParcel &reply); + int32_t CmdOnSendError(MessageParcel &data, MessageParcel &reply); + int32_t CmdOnReceiveFinished(MessageParcel &data, MessageParcel &reply); + int32_t CmdOnReceiveError(MessageParcel &data, MessageParcel &reply); + int32_t CmdWriteFile(MessageParcel &data, MessageParcel &reply); +private: + std::map memberFuncMap_; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // FILETRANSFER_CALLBACK_STUB_H \ No newline at end of file diff --git a/frameworks/native/service_proxy.h b/frameworks/native/include/service_proxy.h similarity index 81% rename from frameworks/native/service_proxy.h rename to frameworks/native/include/service_proxy.h index d5a2d52c4f2121ae4305bb5f94d7603ccb85d147..ba922b5a7dc966b9d084666aaf146c4798d6105a 100644 --- a/frameworks/native/service_proxy.h +++ b/frameworks/native/include/service_proxy.h @@ -16,7 +16,7 @@ #ifndef DISTRIBUTEDFILE_SERVICE_PROXY_H #define DISTRIBUTEDFILE_SERVICE_PROXY_H -#include +#include "iremote_proxy.h" #include "i_distributedfile_service.h" #include "message_parcel.h" @@ -31,14 +31,16 @@ public: * @param impl */ explicit ServiceProxy(const sptr &impl) : IRemoteProxy(impl) {} - virtual ~ServiceProxy() = default; int32_t SendFile(const std::string &cid, const std::vector &sourceFileList, const std::vector &destinationFileList, const uint32_t fileCount) override; - int32_t sendTest() override; + int32_t OpenFile(int32_t fd, const std::string &fileName, int32_t mode) override; + int32_t RegisterNotifyCallback(sptr &callback) override; + int32_t UnRegisterNotifyCallback() override; + int32_t IsDeviceOnline(const std::string &cid) override; private: static inline BrokerDelegator delegator_; }; diff --git a/frameworks/native/src/dfs_filetransfer_callback.cpp b/frameworks/native/src/dfs_filetransfer_callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef8aa22a96a0ce3941342b4bfecb8371dc6f23af --- /dev/null +++ b/frameworks/native/src/dfs_filetransfer_callback.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dfs_filetransfer_callback.h" + +#include "sendfile.h" +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +DfsFileTransferCallback::DfsFileTransferCallback() {} + +DfsFileTransferCallback::~DfsFileTransferCallback() {} + +int32_t DfsFileTransferCallback::DeviceOnline(const std::string &cid) +{ + NapiDeviceOnline(cid); + return 0; +} + +int32_t DfsFileTransferCallback::DeviceOffline(const std::string &cid) +{ + NapiDeviceOffline(cid); + return 0; +} + +int32_t DfsFileTransferCallback::SendFinished(const std::string &cid, std::string fileName) +{ + NapiSendFinished(cid, fileName); + return 0; +} + +int32_t DfsFileTransferCallback::SendError(const std::string &cid) +{ + NapiSendError(cid); + return 0; +} + +int32_t DfsFileTransferCallback::ReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num) +{ + NapiReceiveFinished(cid, fileName, num); + return 0; +} + +int32_t DfsFileTransferCallback::ReceiveError(const std::string &cid) +{ + NapiReceiveError(cid); + return 0; +} + +int32_t DfsFileTransferCallback::WriteFile(int32_t fd, const std::string &fileName) +{ + NapiWriteFile(fd, fileName); + return 0; +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/src/filetransfer_callback_proxy.cpp b/frameworks/native/src/filetransfer_callback_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1fd15b8e260399f6a874034462568f834b56ba98 --- /dev/null +++ b/frameworks/native/src/filetransfer_callback_proxy.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "filetransfer_callback_proxy.h" +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +int32_t FileTransferCallbackProxy::DeviceOnline(const std::string &cid) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + LOGE("[---FileTransferCallbackProxy---] WriteInterfaceToken failed"); + return DFS_CALLBACK_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("[---FileTransferCallbackProxy---] Remote is null"); + return ERR_NULL_OBJECT; + } + + data.WriteString(cid); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ON_DEVICE_ONLINE, data, reply, option); + if (ret != ERR_NONE) { + LOGE("[---FileTransferCallbackProxy---] Proxy SendRequest failed, ret code:[%{public}d]", ret); + } + return ret; +} + +int32_t FileTransferCallbackProxy::DeviceOffline(const std::string &cid) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + LOGE("[---FileTransferCallbackProxy---] WriteInterfaceToken failed"); + return 0; + } + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("[---FileTransferCallbackProxy---] Remote is null"); + return ERR_NULL_OBJECT; + } + + data.WriteString(cid); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ON_DEVICE_OFFLINE, data, reply, option); + if (ret != ERR_NONE) { + LOGE("[---FileTransferCallbackProxy---] Proxy SendRequest failed, ret code:[%{public}d]", ret); + } + return ret; +} + +int32_t FileTransferCallbackProxy::SendFinished(const std::string &cid, std::string fileName) +{ + LOGI("[---FileTransferCallbackProxy---] Proxy SendFinished"); + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + LOGE("[---FileTransferCallbackProxy---] WriteInterfaceToken failed"); + return 0; + } + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("[---FileTransferCallbackProxy---] Remote is null"); + return ERR_NULL_OBJECT; + } + + data.WriteString(cid); + data.WriteString(fileName); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ON_SEND_FINISHED, data, reply, option); + if (ret != ERR_NONE) { + LOGE("[---FileTransferCallbackProxy---] Proxy SendRequest failed, ret code:[%{public}d]", ret); + } + return ret; +} + +int32_t FileTransferCallbackProxy::SendError(const std::string &cid) +{ + LOGI("[---FileTransferCallbackProxy---] Proxy SendError"); + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + LOGE("[---FileTransferCallbackProxy---] WriteInterfaceToken failed"); + return 0; + } + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("[---FileTransferCallbackProxy---] Remote is null"); + return ERR_NULL_OBJECT; + } + + data.WriteString(cid); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ON_SEND_ERROR, data, reply, option); + if (ret != ERR_NONE) { + LOGE("[---FileTransferCallbackProxy---] Proxy SendRequest failed, ret code:[%{public}d]", ret); + } + return ret; +} + +int32_t FileTransferCallbackProxy::ReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num) +{ + LOGI("[---FileTransferCallbackProxy---] Proxy ReceiveFinished, %{public}s", cid.c_str()); + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + LOGE("[---FileTransferCallbackProxy---] WriteInterfaceToken failed"); + return 0; + } + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("[---FileTransferCallbackProxy---] Remote is null"); + return ERR_NULL_OBJECT; + } + + data.WriteString(cid); + data.WriteString(fileName); + data.WriteUint32(num); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ON_RECEIVE_FINISHED, data, reply, option); + if (ret != ERR_NONE) { + LOGE("[---FileTransferCallbackProxy---] Proxy SendRequest failed, ret code:[%{public}d]", ret); + } + return ret; +} + +int32_t FileTransferCallbackProxy::ReceiveError(const std::string &cid) +{ + LOGI("[---FileTransferCallbackProxy---] Proxy ReceiveError"); + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + LOGE("WriteInterfaceToken failed"); + return 0; + } + + sptr remote = Remote(); + if (remote == nullptr) { + LOGE("[---FileTransferCallbackProxy---] Remote is null"); + return ERR_NULL_OBJECT; + } + + data.WriteString(cid); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ON_RECEIVE_ERROR, data, reply, option); + if (ret != ERR_NONE) { + LOGE("[---FileTransferCallbackProxy---] Proxy SendRequest failed, ret code:[%{public}d]", ret); + } + return ret; +} + +int32_t FileTransferCallbackProxy::WriteFile(int32_t fd, const std::string &fileName) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(FileTransferCallbackProxy::GetDescriptor())) { + return DFS_CALLBACK_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + + data.WriteFileDescriptor(fd); + data.WriteString(fileName); + + if (Remote() == nullptr) { + LOGE("WriteFile remote object address is null"); + return DFS_CALLBACK_REMOTE_ADDRESS_IS_NULL; + } + + MessageParcel reply; + MessageOption option; + Remote()->SendRequest(ON_WRITE_FILE, data, reply, option); + + return reply.ReadInt32(); +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/src/filetransfer_callback_stub.cpp b/frameworks/native/src/filetransfer_callback_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91eaef2f825d72e30db26abedd93d504d46e00d6 --- /dev/null +++ b/frameworks/native/src/filetransfer_callback_stub.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "filetransfer_callback_stub.h" + +#include +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +FileTransferCallbackStub::FileTransferCallbackStub() +{ + memberFuncMap_[ON_SEND_FINISHED] = &FileTransferCallbackStub::CmdOnSendFinished; + memberFuncMap_[ON_SEND_ERROR] = &FileTransferCallbackStub::CmdOnSendError; + memberFuncMap_[ON_RECEIVE_FINISHED] = &FileTransferCallbackStub::CmdOnReceiveFinished; + memberFuncMap_[ON_RECEIVE_ERROR] = &FileTransferCallbackStub::CmdOnReceiveError; + memberFuncMap_[ON_DEVICE_ONLINE] = &FileTransferCallbackStub::CmdOnDeviceOnline; + memberFuncMap_[ON_DEVICE_OFFLINE] = &FileTransferCallbackStub::CmdOnDeviceOffline; + memberFuncMap_[ON_WRITE_FILE] = &FileTransferCallbackStub::CmdWriteFile; +} + +FileTransferCallbackStub::~FileTransferCallbackStub() {} + +int32_t FileTransferCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string myDescripter = FileTransferCallbackStub::GetDescriptor(); + std::u16string remoteDescripter = data.ReadInterfaceToken(); + if (myDescripter != remoteDescripter) { + LOGE("Descriptor checked failed"); + return DFS_CALLBACK_DESCRIPTOR_IS_EMPTY; + } + + auto itFunc = memberFuncMap_.find(code); + if (itFunc != memberFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int32_t FileTransferCallbackStub::CmdOnDeviceOnline(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + int32_t result = DeviceOnline(cid); + if (!reply.WriteInt32(result)) { + LOGE("Write parcel failed"); + return result; + } + + return ERR_NONE; +} + +int32_t FileTransferCallbackStub::CmdOnDeviceOffline(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + int32_t result = DeviceOffline(cid); + if (!reply.WriteInt32(result)) { + LOGE("Write parcel failed"); + return result; + } + + return ERR_NONE; +} + +int32_t FileTransferCallbackStub::CmdOnSendFinished(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + std::string fileName = data.ReadString(); + int32_t result = SendFinished(cid, fileName); + if (!reply.WriteInt32(result)) { + LOGE("Write parcel failed"); + return result; + } + + return ERR_NONE; +} + +int32_t FileTransferCallbackStub::CmdOnSendError(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + int32_t result = SendError(cid); + if (!reply.WriteInt32(result)) { + LOGE("Write parcel failed"); + return result; + } + + return ERR_NONE; +} + +int32_t FileTransferCallbackStub::CmdOnReceiveFinished(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + std::string fileName = data.ReadString(); + uint32_t num = data.ReadUint32(); + int32_t result = ReceiveFinished(cid, fileName, num); + if (!reply.WriteInt32(result)) { + LOGE("Write parcel failed"); + return result; + } + + return ERR_NONE; +} + +int32_t FileTransferCallbackStub::CmdOnReceiveError(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + int32_t result = ReceiveError(cid); + if (!reply.WriteInt32(result)) { + LOGE("Write parcel failed"); + return result; + } + + return ERR_NONE; +} + +int32_t FileTransferCallbackStub::CmdWriteFile(MessageParcel &data, MessageParcel &reply) +{ + int32_t fileData = data.ReadFileDescriptor(); + int32_t fd = fcntl(fileData, F_GETFD, 0); + if (fd < 0) { + reply.WriteInt32(DFS_CALLBACK_ERR_SET_FD_FAIL); + LOGE("FileTransferCallbackStub : Failed to get app device id, error: invalid device id"); + return DFS_CALLBACK_ERR_SET_FD_FAIL; + } + + std::string fileName = data.ReadString(); + if (fileName.empty()) { + LOGE("FileTransferCallbackStub : Failed to get app device id, error: invalid device id"); + return DFS_CALLBACK_DESCRIPTOR_IS_EMPTY; + } + + int32_t result = WriteFile(fileData, fileName); + if (!reply.WriteInt32(result)) { + LOGE("fail to write parcel"); + return DFS_CALLBACK_WRITE_REPLY_FAIL; + } + + return ERR_NONE; +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/src/service_proxy.cpp b/frameworks/native/src/service_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d9918f378100d28d88bb56224af51107961609e --- /dev/null +++ b/frameworks/native/src/service_proxy.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_proxy.h" +#include "utils_log.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +int32_t ServiceProxy::SendFile(const std::string &cid, + const std::vector &sourceFileList, + const std::vector &destinationFileList, + const uint32_t fileCount) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ServiceProxy::GetDescriptor())) { + return DFS_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + data.WriteString(cid); + int32_t sourceListNumber = sourceFileList.size(); + data.WriteInt32(sourceListNumber); + for (int32_t index = 0; index < sourceListNumber; ++index) { + data.WriteString(sourceFileList.at(index)); + } + int32_t destinationListNumber = destinationFileList.size(); + data.WriteInt32(destinationListNumber); + for (int32_t index = 0; index < destinationListNumber; ++index) { + data.WriteString(destinationFileList.at(index)); + } + data.WriteUint32(fileCount); + + if (Remote() == nullptr) { + LOGE("unregister sendfile remote object address is null"); + return DFS_REMOTE_ADDRESS_IS_NULL; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest(SEND_FILE_DISTRIBUTED, data, reply, option); + if (result != DFS_SENDFILE_SUCCESS) { + LOGE("sendfile error code : %{public}d", result); + return result; + } + + return reply.ReadInt32(); +} + +int32_t ServiceProxy::OpenFile(int32_t fd, const std::string &fileName, int32_t mode) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ServiceProxy::GetDescriptor())) { + return DFS_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + + data.WriteFileDescriptor(fd); + data.WriteString(fileName); + data.WriteInt32(mode); + + if (Remote() == nullptr) { + LOGE("openfile remote object address is null"); + return DFS_REMOTE_ADDRESS_IS_NULL; + } + + MessageParcel reply; + MessageOption option; + Remote()->SendRequest(OPEN_FILE_FD, data, reply, option); + + return reply.ReadInt32(); +} + +int32_t ServiceProxy::RegisterNotifyCallback(sptr &callback) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ServiceProxy::GetDescriptor())) { + return DFS_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + + if (callback == nullptr) { + LOGE("The parameter of callback is nullptr"); + return DFS_CALLBACK_PARAM_ERROR; + } + + if (!data.WriteRemoteObject(callback->AsObject().GetRefPtr())) { + LOGE("write remote object failed"); + return DFS_WRITE_REMOTE_OBJECT_FAIL; + } + + if (Remote() == nullptr) { + LOGE("register filetransfer callback remote object address is null"); + return DFS_REMOTE_ADDRESS_IS_NULL; + } + + MessageParcel reply; + MessageOption option; + Remote()->SendRequest(REGISTER_NOTIFY_CALLBACK, data, reply, option); + + return reply.ReadInt32(); +} + +int32_t ServiceProxy::UnRegisterNotifyCallback() +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ServiceProxy::GetDescriptor())) { + return DFS_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + + if (Remote() == nullptr) { + LOGE("unregister filetransfer callback remote object address is null"); + return DFS_REMOTE_ADDRESS_IS_NULL; + } + + MessageParcel reply; + MessageOption option; + Remote()->SendRequest(UN_REGISTER_NOTIFY_CALLBACK, data, reply, option); + + return reply.ReadInt32(); +} + +int32_t ServiceProxy::IsDeviceOnline(const std::string &cid) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ServiceProxy::GetDescriptor())) { + return DFS_WRITE_DESCRIPTOR_TOKEN_FAIL; + } + data.WriteString(cid); + + if (Remote() == nullptr) { + LOGE("Remote object address is null"); + return DFS_REMOTE_ADDRESS_IS_NULL; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest(IS_DEVICE_ONLINE, data, reply, option); + if (result != DFS_NO_ERROR) { + LOGE("Function RemoveBundleDistributedDirs! errCode:%{public}d", result); + return DFS_NO_DEVICE_ONLINE; + } + + return reply.ReadInt32(); +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/kits/js/@ohos.sendfile.d.ts b/interfaces/innerkits/kits/js/@ohos.sendfile.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..ef88807e3ecc1d3ffe25c3bd6dea054edbcb93ab --- /dev/null +++ b/interfaces/innerkits/kits/js/@ohos.sendfile.d.ts @@ -0,0 +1,60 @@ +/* +* Copyright (C) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import {AsyncCallback, Callback} from "./basic"; +/** + * Provides Environment APIs. + * + * @since 8 + * @sysCap SystemCapability.FileManagement.File.DistributeFile + */ +declare namespace SendFile { + /** + * send file. + * + * @since 8 + */ + function sendFile(deviceId: string, sourPath: Array, destPath: Array, fileCount: number, callback: AsyncCallback); + function sendFile(deviceId: string, sourPath: Array, destPath: Array, fileCount: number): Promise; + + export interface TransResult { + /** + * send file error code. + */ + errCode: number; + /** + * receive file full path. + */ + fileName: Array; + /** + * receive file count. + */ + fileCount: number; + } + /** + * event listen on. + * + * @since 8 + */ + function on(type: 'sendFinished' | 'receiveFinished', callback: AsyncCallback): void; + /** + * event listen off. + * + * @since 8 + */ + function off(type: 'sendFinished' | 'receiveFinished'): void; +} + +export default SendFile; \ No newline at end of file diff --git a/interfaces/innerkits/native/BUILD.gn b/interfaces/innerkits/native/BUILD.gn index 06431810e9e2307a97774ee766c4fbec51afd618..42a2f13efad13aaea039b331e18598f3dc6b95dd 100644 --- a/interfaces/innerkits/native/BUILD.gn +++ b/interfaces/innerkits/native/BUILD.gn @@ -14,7 +14,7 @@ import("//build/ohos.gni") import("//foundation/filemanagement/dfs_service/distributedfile.gni") config("private_config") { - include_dirs = [ "../../../frameworks/native" ] + include_dirs = [ "../../../frameworks/native/include" ] configs = [ "//build/config/compiler:exceptions" ] } @@ -24,7 +24,10 @@ config("public_config") { } ohos_shared_library("libdistributedfile_innerkits") { - sources = [ "../../../frameworks/native/service_proxy.cpp" ] + sources = [ + "${distributedfile_path}/frameworks/native/src/filetransfer_callback_proxy.cpp", + "${distributedfile_path}/frameworks/native/src/service_proxy.cpp", + ] configs = [ ":private_config" ] diff --git a/interfaces/innerkits/native/i_distributedfile_service.h b/interfaces/innerkits/native/i_distributedfile_service.h index 725725020e874e1af4c243c9890f85af0609aef8..c77f0667aae8d89a4e0b95272375027cda42bd69 100644 --- a/interfaces/innerkits/native/i_distributedfile_service.h +++ b/interfaces/innerkits/native/i_distributedfile_service.h @@ -17,6 +17,7 @@ #define I_DISTRIBUTEDFILE_SERVICE_H #include "iremote_broker.h" +#include "i_filetransfer_callback.h" namespace OHOS { namespace Storage { @@ -25,33 +26,40 @@ class IDistributedFileService : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedFile.IDistributedFileService"); // define the message code - enum DistributedFileSurfaceCode { INTERFACE1 = 0, SEND_FILE_DISTRIBUTED, TEST_CODE }; + enum DistributedFileSurfaceCode { + INTERFACE1 = 0, + SEND_FILE_DISTRIBUTED, + OPEN_FILE_FD, + REGISTER_NOTIFY_CALLBACK, + UN_REGISTER_NOTIFY_CALLBACK, + IS_DEVICE_ONLINE + }; // define the error code enum { DISTRIBUTEDFILE_SUCCESS = 0, + DFS_SUCCESS = 0, + DFS_NO_ERROR = 0, + DFS_SENDFILE_SUCCESS = 0, GET_DISTRIBUTEDFILE_DISTRIBUTED_DIR_FAIL = 1, - DISTRIBUTEDFILE_WRITE_DESCRIPTOR_TOKEN_FAIL, - ERR_FLATTEN_OBJECT, - DISTRIBUTEDFILE_NO_ERROR, - DISTRIBUTEDFILE_CONNECT_SYSTEM_ABILITY_STUB_FAIL, - REMOVE_DISTRIBUTEDFILE_DISTRIBUTEDDIRS_FAIL, - DISTRIBUTEDFILE_BAD_TYPE, - DISTRIBUTEDFILE_FAIL, - DISTRIBUTEDFILE_REMOTE_ADDRESS_IS_NULL, - DISTRIBUTEDFILE_WRITE_REPLY_FAIL, - DISTRIBUTEDFILE_DIR_NAME_IS_EMPTY, - DISTRIBUTEDFILE_NAME_NOT_FOUND, - DISTRIBUTEDFILE_PERMISSION_DENIED, - ROOT_UID, - SYSTEM_SERVICE_UID, - SEND_FILE_FAIL, - SEND_FILE_DISTRIBUTED_DESCRIPTION_FAIL + DFS_REMOTE_ADDRESS_IS_NULL, + DFS_DESCRIPTOR_IS_EMPTY, + DFS_SESSION_ID_IS_EMPTY, + DFS_WRITE_REPLY_FAIL, + DFS_WRITE_REMOTE_OBJECT_FAIL, + DFS_WRITE_DESCRIPTOR_TOKEN_FAIL, + DFS_CALLBACK_PARAM_ERROR, + DFS_NO_SUCH_FILE, + DFS_NO_DEVICE_ONLINE, + DFS_SET_FD_FAIL }; virtual int32_t SendFile(const std::string &cid, const std::vector &sourceFileList, const std::vector &destinationFileList, const uint32_t fileCount) = 0; - virtual int32_t sendTest() = 0; + virtual int32_t OpenFile(int32_t fd, const std::string &fileName, int32_t mode) = 0; + virtual int32_t RegisterNotifyCallback(sptr &callback) = 0; + virtual int32_t UnRegisterNotifyCallback() = 0; + virtual int32_t IsDeviceOnline(const std::string &cid) = 0; }; } // namespace DistributedFile } // namespace Storage diff --git a/interfaces/innerkits/native/i_filetransfer_callback.h b/interfaces/innerkits/native/i_filetransfer_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..4f71696adddf3524053c597e847261647a06691c --- /dev/null +++ b/interfaces/innerkits/native/i_filetransfer_callback.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_FILETRANSFER_CALLBACK_H +#define I_FILETRANSFER_CALLBACK_H + +#include + +#include "iremote_broker.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +class IFileTransferCallback : public IRemoteBroker { +public: + virtual ~IFileTransferCallback() = default; +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Storage.DistributedFile.IFileTransferCallback"); + enum { + ON_SEND_FINISHED = 0, + ON_SEND_ERROR, + ON_RECEIVE_FINISHED, + ON_RECEIVE_ERROR, + ON_DEVICE_ONLINE, + ON_DEVICE_OFFLINE, + ON_WRITE_FILE + }; + // define the error code + enum { + DFS_CALLBACK_SUCCESS = 0, + DFS_CALLBACK_REMOTE_ADDRESS_IS_NULL, + DFS_CALLBACK_DESCRIPTOR_IS_EMPTY, + DFS_CALLBACK_WRITE_REPLY_FAIL, + DFS_CALLBACK_WRITE_REMOTE_OBJECT_FAIL, + DFS_CALLBACK_WRITE_DESCRIPTOR_TOKEN_FAIL, + DFS_CALLBACK_ERR_SET_FD_FAIL + }; +public: + virtual int32_t SendFinished(const std::string &cid, std::string fileName) = 0; + virtual int32_t SendError(const std::string &cid) = 0; + virtual int32_t ReceiveFinished(const std::string &cid, const std::string &fileName, uint32_t num) = 0; + virtual int32_t ReceiveError(const std::string &cid) = 0; + virtual int32_t DeviceOnline(const std::string &cid) = 0; + virtual int32_t DeviceOffline(const std::string &cid) = 0; + virtual int32_t WriteFile(int32_t fd, const std::string &fileName) = 0; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS +#endif // I_FILETRANSFER_CALLBACK_H \ No newline at end of file diff --git a/services/distributedfileservice/BUILD.gn b/services/distributedfileservice/BUILD.gn index a98b9383f68f25307f5098477fea936003f28d57..3eb54f40d9ce05a765b57b7b53aa96112df96526 100644 --- a/services/distributedfileservice/BUILD.gn +++ b/services/distributedfileservice/BUILD.gn @@ -15,9 +15,11 @@ import("//foundation/filemanagement/dfs_service/distributedfile.gni") ohos_shared_library("libdistributedfileservice") { include_dirs = [ - "include/ipc", "include/device", + "include/ipc", "include/network", + "${distributedfile_path}/frameworks/native", + "${distributedfile_path}/frameworks/native/include", "//foundation/distributedhardware/devicemanager/interfaces/inner_kits/native_cpp/include", ] @@ -32,6 +34,9 @@ ohos_shared_library("libdistributedfileservice") { configs = [ "${utils_path}:compiler_configs" ] external_deps = [ + "ability_base:want", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "dsoftbus_standard:softbus_client", "ipc:ipc_core", "safwk:system_ability_fwk", diff --git a/services/distributedfileservice/include/ipc/distributedfile_service.h b/services/distributedfileservice/include/ipc/distributedfile_service.h index 8bca0a9200c4c23219b548164302e6336418b47f..6e5d68f6dedffeb83da3444c7e565176d367f152 100644 --- a/services/distributedfileservice/include/ipc/distributedfile_service.h +++ b/services/distributedfileservice/include/ipc/distributedfile_service.h @@ -20,6 +20,8 @@ #include "iremote_stub.h" #include "system_ability.h" +#include + namespace OHOS { namespace Storage { namespace DistributedFile { @@ -28,9 +30,8 @@ class DistributedFileService : public SystemAbility, public std::enable_shared_from_this { DECLARE_SYSTEM_ABILITY(DistributedFileService) public: - DistributedFileService(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) {}; - ~DistributedFileService() {}; - + explicit DistributedFileService(int32_t saId, bool runOnCreate = true) : SystemAbility(saId, runOnCreate) {} + ~DistributedFileService() {} void OnDump() override; void OnStart() override; void OnStop() override; @@ -39,7 +40,10 @@ public: const std::vector &sourceFileList, const std::vector &destinationFileList, const uint32_t fileCount) override; - int32_t sendTest() override; + int32_t OpenFile(int32_t fd, const std::string &fileName, int32_t mode) override; + int32_t RegisterNotifyCallback(sptr &callback) override; + int32_t UnRegisterNotifyCallback() override; + int32_t IsDeviceOnline(const std::string &cid) override; static inline const std::string pkgName_ { "ohos.storage.distributedfile.service" }; private: @@ -49,5 +53,4 @@ private: } // namespace DistributedFile } // namespace Storage } // namespace OHOS - #endif // DISTRIBUTEDFILE_SERVICE_H diff --git a/services/distributedfileservice/include/ipc/distributedfile_service_stub.h b/services/distributedfileservice/include/ipc/distributedfile_service_stub.h index a4c18bb514b93da1cc069c7b7c1fcb68d535b537..136ba3235996eb5e7c09e01b29b0c8e031107731 100644 --- a/services/distributedfileservice/include/ipc/distributedfile_service_stub.h +++ b/services/distributedfileservice/include/ipc/distributedfile_service_stub.h @@ -37,7 +37,9 @@ private: MessageParcel &reply); std::map memberFuncMap_; int32_t SendFileStub(MessageParcel &data, MessageParcel &reply); - int test(MessageParcel &data, MessageParcel &reply); + int32_t OpenFileStub(MessageParcel &data, MessageParcel &reply); + int32_t CmdRegisterNotifyCallback(MessageParcel &data, MessageParcel &reply); + int32_t CmdIsDeviceOnline(MessageParcel &data, MessageParcel &reply); }; } // namespace DistributedFile } // namespace Storage diff --git a/services/distributedfileservice/include/network/softbus_agent.h b/services/distributedfileservice/include/network/softbus_agent.h index ec93ec9661844ae731d6e777df7b998d15d44554..13a722371d02b13e440c4023a7abd27b14314fba 100644 --- a/services/distributedfileservice/include/network/softbus_agent.h +++ b/services/distributedfileservice/include/network/softbus_agent.h @@ -19,6 +19,8 @@ #include #include #include + +#include "i_filetransfer_callback.h" #include "utils_singleton.h" namespace OHOS { @@ -40,6 +42,8 @@ public: int OnSendFileFinished(const int sessionId, const std::string firstFile); int OnFileTransError(const int sessionId); void OnReceiveFileFinished(const int sessionId, const std::string files, int fileCnt); + void SetTransCallback(sptr &callback); + void RemoveTransCallbak(); protected: void StartInstance() override; @@ -55,6 +59,7 @@ private: std::mutex getSessionCVMut_; std::condition_variable getSessionCV_; + sptr notifyCallback_ = nullptr; }; } // namespace DistributedFile } // namespace Storage diff --git a/services/distributedfileservice/src/ipc/distributedfile_service.cpp b/services/distributedfileservice/src/ipc/distributedfile_service.cpp index 8bb1fb7d486268f6ae06085030165514dbf761cb..bdba8d1a1af38329a9df11ecfa29616c8b9f54a2 100644 --- a/services/distributedfileservice/src/ipc/distributedfile_service.cpp +++ b/services/distributedfileservice/src/ipc/distributedfile_service.cpp @@ -14,16 +14,29 @@ */ #include "distributedfile_service.h" -#include +#include +#include +#include + +#include "bundle_mgr_interface.h" +#include "bundle_mgr_proxy.h" #include "device_manager_agent.h" -#include "utils_exception.h" -#include "utils_log.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "message_parcel.h" +#include "parcel.h" #include "softbus_agent.h" +#include "system_ability_definition.h" +#include "utils_directory.h" +#include "utils_log.h" namespace OHOS { namespace Storage { namespace DistributedFile { -using namespace std; +namespace { + constexpr int32_t FILE_BLOCK_SIZE = 1024; + constexpr char TEMP_FILE_NAME[] = "/data/system_ce/tmp"; +} REGISTER_SYSTEM_ABILITY_BY_ID(DistributedFileService, STORAGE_DISTRIBUTED_FILE_SERVICE_SA_ID, false); @@ -32,14 +45,24 @@ void DistributedFileService::OnDump() LOGI("OnDump"); } +void DistributedFileService::OnStart() +{ + PublishSA(); + StartManagers(); +} + +void DistributedFileService::OnStop() +{ + LOGI("OnStop"); +} + void DistributedFileService::PublishSA() { - LOGI("Begin to init, pull the service SA"); bool ret = SystemAbility::Publish(this); if (!ret) { - throw runtime_error("publishing DistributedFileService failed"); + LOGE("Leave, publishing DistributedFileService failed!"); + return; } - LOGI("Init finished successfully"); } void DistributedFileService::StartManagers() @@ -47,33 +70,130 @@ void DistributedFileService::StartManagers() DeviceManagerAgent::GetInstance(); } -void DistributedFileService::OnStart() +int32_t DistributedFileService::SendFile(const std::string &cid, + const std::vector &sourceFileList, + const std::vector &destinationFileList, + const uint32_t fileCount) { - LOGI("DistributedFileService::OnStart"); - try { - PublishSA(); - StartManagers(); - } catch (const Exception &e) { - LOGE("%{public}s", e.what()); + if (fileCount < 0) { + return -1; + } + char **sFileList = new char* [fileCount]; + for (int index = 0; index < sourceFileList.size(); ++index) { + LOGI("DistributedFileService::SendFile Source File List %{public}d, %{public}s, %{public}d", + index, sourceFileList.at(index).c_str(), sourceFileList.at(index).length()); + if (index == 0) { + std::string tmpString("/data/system_ce/tmp"); + int32_t length = tmpString.length(); + sFileList[index] = new char[length + 1]; + if (memset_s(sFileList[index], length + 1, '\0', length + 1) != EOK) { + return -1; + } + if (memcpy_s(sFileList[index], length + 1, tmpString.c_str(), length) != EOK) { + return -1; + } + sFileList[index][length] = '\0'; + } else { + int32_t length = sourceFileList.at(index).length(); + sFileList[index] = new char[length + 1]; + if (memset_s(sFileList[index], length + 1, '\0', length + 1) != EOK) { + return -1; + } + if (memcpy_s(sFileList[index], length + 1, sourceFileList.at(index).c_str(), length) != EOK) { + return -1; + } + sFileList[index][length] = '\0'; + } + } + + char **dFileList = new char* [fileCount]; + for (int index = 0; index < destinationFileList.size(); ++index) { + LOGI("DistributedFileService::SendFile Destination File List %{public}d, %{public}s", + index, destinationFileList.at(index).c_str()); + int32_t length = destinationFileList.at(index).length(); + dFileList[index] = new char[length + 1]; + if (memset_s(dFileList[index], length + 1, '\0', length + 1) != EOK) { + return -1; + } + if (memcpy_s(dFileList[index], length + 1, destinationFileList.at(index).c_str(), length) != EOK) { + LOGE("memory copy failed"); + return -1; + } + dFileList[index][length] = '\0'; } + + auto softBusAgent = SoftbusAgent::GetInstance(); + int32_t result = softBusAgent->SendFile(cid, (const char **)sFileList, (const char **)dFileList, fileCount); + return result; } -void DistributedFileService::OnStop() +int32_t DistributedFileService::OpenFile(int32_t fd, const std::string &fileName, int32_t mode) { - LOGI("DistributedFileService::OnStop"); + if (fd <= 0) { + return -1; + } + + const char *tmpFile = TEMP_FILE_NAME; + struct stat fileStat; + bool fileExist = (stat(tmpFile, &fileStat) == 0); + if (fileExist) { + int32_t result = remove(tmpFile); + if (result != 0) { + close(fd); + LOGE("DFS SA remove temp file result %{public}d, %{public}s, %{public}d", result, strerror(errno), errno); + return -1; + } + } + + int32_t writeFd = open(tmpFile, O_WRONLY | O_CREAT, (S_IREAD & S_IWRITE) | S_IRGRP | S_IROTH); + if (writeFd <= 0) { + close(fd); + LOGE("DFS SA open temp file failed %{public}d, %{public}s, %{public}d", writeFd, strerror(errno), errno); + return -1; + } + auto buffer = std::make_unique(FILE_BLOCK_SIZE); + ssize_t actLen = 0; + do { + actLen = read(fd, buffer.get(), FILE_BLOCK_SIZE); + if (actLen > 0) { + write(writeFd, buffer.get(), actLen); + } else if (actLen == 0) { + break; + } else { + if (errno == EINTR) { + actLen = FILE_BLOCK_SIZE; + } else { + close(fd); + close(writeFd); + return -1; + } + } + } while (actLen > 0); + + close(fd); + close(writeFd); + + return 0; } -int32_t DistributedFileService::sendTest() +int32_t DistributedFileService::RegisterNotifyCallback(sptr &callback) { - LOGI("DistributedFileService::sendTest"); + SoftbusAgent::GetInstance()->SetTransCallback(callback); return 0; } -int32_t DistributedFileService::SendFile(const std::string &cid, - const std::vector &sourceFileList, - const std::vector &destinationFileList, - const uint32_t fileCount) +int32_t DistributedFileService::UnRegisterNotifyCallback() { + SoftbusAgent::GetInstance()->RemoveTransCallbak(); + return 0; +} + +int32_t DistributedFileService::IsDeviceOnline(const std::string &cid) +{ + std::set onlineDevice = DeviceManagerAgent::GetInstance()->getOnlineDevs(); + if (onlineDevice.find(cid) != onlineDevice.end()) { + return 1; + } return 0; } } // namespace DistributedFile diff --git a/services/distributedfileservice/src/ipc/distributedfile_service_stub.cpp b/services/distributedfileservice/src/ipc/distributedfile_service_stub.cpp index 79391881666a9c2e5754955a30a38755467220db..8f0195bd76d72bdb4595dc279cac0d6188d75e47 100644 --- a/services/distributedfileservice/src/ipc/distributedfile_service_stub.cpp +++ b/services/distributedfileservice/src/ipc/distributedfile_service_stub.cpp @@ -15,9 +15,11 @@ #include "distributedfile_service_stub.h" -#include +#include +#include #include +#include "ipc_skeleton.h" #include "utils_log.h" namespace OHOS { @@ -26,7 +28,9 @@ namespace DistributedFile { DistributedFileServiceStub::DistributedFileServiceStub() { memberFuncMap_[SEND_FILE_DISTRIBUTED] = &DistributedFileServiceStub::SendFileStub; - memberFuncMap_[TEST_CODE] = &DistributedFileServiceStub::test; + memberFuncMap_[OPEN_FILE_FD] = &DistributedFileServiceStub::OpenFileStub; + memberFuncMap_[REGISTER_NOTIFY_CALLBACK] = &DistributedFileServiceStub::CmdRegisterNotifyCallback; + memberFuncMap_[IS_DEVICE_ONLINE] = &DistributedFileServiceStub::CmdIsDeviceOnline; } DistributedFileServiceStub::~DistributedFileServiceStub() @@ -39,7 +43,13 @@ int DistributedFileServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &reply, MessageOption &option) { - LOGD("DistributedFileServiceStub : OnRemoteRequest enter, code %{public}d ", code); + std::u16string myDescriptor = DistributedFileServiceStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (myDescriptor != remoteDescriptor) { + LOGE("DistributedFileServiceStub descriptor information"); + return DFS_DESCRIPTOR_IS_EMPTY; + } + auto itFunc = memberFuncMap_.find(code); if (itFunc != memberFuncMap_.end()) { auto memberFunc = itFunc->second; @@ -47,20 +57,93 @@ int DistributedFileServiceStub::OnRemoteRequest(uint32_t code, return (this->*memberFunc)(data, reply); } } - return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } -int DistributedFileServiceStub::test(MessageParcel &data, MessageParcel &reply) +int32_t DistributedFileServiceStub::SendFileStub(MessageParcel &data, MessageParcel &reply) { - LOGD(" DistributedFileServiceStub : sendTest enter"); - sendTest(); - return 0; + std::string cid = data.ReadString(); + if (cid.empty()) { + LOGE("SendFileStub : Failed to get app device id, error: invalid device id"); + return DFS_SESSION_ID_IS_EMPTY; + } + + int32_t sourceListNumber = data.ReadInt32(); + std::vector srcList; + for (int32_t index = 0; index < sourceListNumber; ++index) { + srcList.push_back(data.ReadString()); + } + std::vector dstList; + int32_t destinationListNumber = data.ReadInt32(); + for (int32_t index = 0; index < destinationListNumber; ++index) { + dstList.push_back(data.ReadString()); + } + uint32_t fileCount = data.ReadUint32(); + + int32_t result = SendFile(cid, srcList, dstList, fileCount); + if (!reply.WriteInt32(result)) { + LOGE("sendfilestub fail to write parcel"); + return DFS_WRITE_REPLY_FAIL; + } + + return result; } -int32_t DistributedFileServiceStub::SendFileStub(MessageParcel &data, MessageParcel &reply) +int32_t DistributedFileServiceStub::OpenFileStub(MessageParcel &data, MessageParcel &reply) +{ + int32_t fileData = data.ReadFileDescriptor(); + int32_t fd = fcntl(fileData, F_GETFD, 0); + if (fd < 0) { + reply.WriteInt32(DFS_SET_FD_FAIL); + LOGE("DistributedFileServiceStub : Failed to get app device id, error: invalid device id"); + return DFS_SET_FD_FAIL; + } + + std::string fileName = data.ReadString(); + if (fileName.empty()) { + LOGE("DistributedFileServiceStub : Failed to get app device id, error: invalid device id"); + return DFS_NO_SUCH_FILE; + } + + int32_t modeData = data.ReadInt32(); + int32_t result = OpenFile(fileData, fileName, modeData); + if (!reply.WriteInt32(result)) { + LOGE("fail to write parcel"); + return DFS_WRITE_REPLY_FAIL; + } + + return result; +} + +int32_t DistributedFileServiceStub::CmdRegisterNotifyCallback(MessageParcel &data, MessageParcel &reply) { - return 0; + OHOS::sptr remote = data.ReadRemoteObject(); + if (remote == nullptr) { + LOGE("Callback ptr is nullptr."); + return 0; + } + + OHOS::sptr callback = iface_cast(remote); + int32_t result = RegisterNotifyCallback(callback); + reply.WriteInt32(result); + return result; +} + +int32_t DistributedFileServiceStub::CmdIsDeviceOnline(MessageParcel &data, MessageParcel &reply) +{ + std::string cid = data.ReadString(); + if (cid.empty()) { + LOGE("DistributedFileServiceStub : Failed to get app device id, error: invalid device id"); + return DFS_SESSION_ID_IS_EMPTY; + } + + int32_t result = IsDeviceOnline(cid); + if (!reply.WriteInt32(result)) { + LOGE("fail to write parcel"); + return DFS_WRITE_REPLY_FAIL; + } + + return result; } } // namespace DistributedFile } // namespace Storage diff --git a/services/distributedfileservice/src/network/softbus_agent.cpp b/services/distributedfileservice/src/network/softbus_agent.cpp index da2acb13dda5521fc4529be9c60752e19451d70c..af0734b2a8cfe3d14e3e4576afa4033ec6c59887 100644 --- a/services/distributedfileservice/src/network/softbus_agent.cpp +++ b/services/distributedfileservice/src/network/softbus_agent.cpp @@ -18,21 +18,27 @@ #include #include #include + #include "device_manager_agent.h" #include "distributedfile_service.h" +#include "i_distributedfile_service.h" +#include "iservice_registry.h" #include "session.h" #include "softbus_dispatcher.h" +#include "system_ability_definition.h" #include "utils_exception.h" +#include "utils_directory.h" #include "utils_log.h" namespace OHOS { namespace Storage { namespace DistributedFile { -using namespace std; -constexpr int32_t SOFTBUS_OK = 0; -constexpr int32_t DEVICE_ID_SIZE_MAX = 65; -constexpr int32_t IS_CLIENT = 0; -const std::string DEFAULT_ROOT_PATH = "/data/service/el2/100/hmdfs/non_account/data/"; +namespace { + constexpr int32_t SOFTBUS_OK = 0; + constexpr int32_t DEVICE_ID_SIZE_MAX = 65; + constexpr int32_t IS_CLIENT = 0; + const std::string DEFAULT_ROOT_PATH = "/data/service/el2/100/hmdfs/non_account/data/"; +} SoftbusAgent::SoftbusAgent() {} @@ -40,6 +46,7 @@ SoftbusAgent::~SoftbusAgent() { StopInstance(); } + void SoftbusAgent::StartInstance() { RegisterSessionListener(); @@ -48,9 +55,12 @@ void SoftbusAgent::StartInstance() void SoftbusAgent::StopInstance() { - for (auto iter = cidToSessionID_.begin(); iter != cidToSessionID_.end();) { - CloseSession(iter->first); - iter = cidToSessionID_.erase(iter); + { + std::unique_lock lock(sessionMapMux_); + for (auto iter = cidToSessionID_.begin(); iter != cidToSessionID_.end();) { + CloseSession(iter->first); + iter = cidToSessionID_.erase(iter); + } } getSessionCV_.notify_all(); UnRegisterSessionListener(); @@ -58,16 +68,12 @@ void SoftbusAgent::StopInstance() void SoftbusAgent::OnDeviceOnline(const std::string &cid) { - // todo:测试接口SendFile - const char *sFileList[1] = {"/data/user/0/xhl_sendfile_test/1.txt"}; - - static int sendfile_cnt = 0; - int ret = SendFile(cid, sFileList, nullptr, 1); - if (ret != 0) { - LOGE("sendfile failed, ret %{public}d", ret); + if (notifyCallback_ == nullptr) { + LOGE("OnDeviceOnline Nofify pointer is empty"); return; } - LOGE("sendfile... ret %{public}d, sendfile_cnt %{public}d", ret, sendfile_cnt); + + notifyCallback_->DeviceOnline(cid); } int SoftbusAgent::SendFile(const std::string &cid, const char *sFileList[], const char *dFileList[], uint32_t fileCnt) @@ -102,7 +108,7 @@ int SoftbusAgent::SendFile(const std::string &cid, const char *sFileList[], cons } int ret = ::SendFile(sessionId, sFileList, dFileList, fileCnt); - LOGE("sendfile is processing, sessionId:%{publid}d, ret %{public}d", sessionId, ret); + LOGD("sendfile is processing, sessionId:%{public}d, ret %{public}d", sessionId, ret); return ret; } @@ -122,7 +128,6 @@ void SoftbusAgent::OpenSession(const std::string &cid) void SoftbusAgent::OnSessionOpened(const int sessionId, const int result) { - LOGD("get session res:%{public}d, sessionId:%{public}d", result, sessionId); if (result != 0) { LOGE("open failed, result:%{public}d, sessionId:%{public}d", result, sessionId); return; @@ -135,7 +140,7 @@ void SoftbusAgent::OnSessionOpened(const int sessionId, const int result) // client session priority use, so insert list head { - std::unique_lock lock(sessionMapMux_); + std::unique_lock lock(sessionMapMux_); if (::GetSessionSide(sessionId) == IS_CLIENT) { cidToSessionID_[cid].push_front(sessionId); } else { @@ -143,26 +148,60 @@ void SoftbusAgent::OnSessionOpened(const int sessionId, const int result) } } - // cv 唤醒等待的sendfile流程 getSessionCV_.notify_one(); LOGD("get session SUCCESS, sessionId:%{public}d", sessionId); } int SoftbusAgent::OnSendFileFinished(const int sessionId, const std::string firstFile) { - LOGD("send file finish, sessionId:%{public}d, firstFile %{public}s", sessionId, firstFile.c_str()); + if (notifyCallback_ == nullptr) { + LOGE("OnSendFileFinished Nofify pointer is empty"); + return -1; + } + std::string cid = GetPeerDevId(sessionId); + notifyCallback_->SendFinished(cid, firstFile); return 0; } int SoftbusAgent::OnFileTransError(const int sessionId) { - LOGD("file trans error, sessionId:%{public}d", sessionId); + if (notifyCallback_ == nullptr) { + LOGE("OnFileTransError Nofify pointer is empty"); + return -1; + } + std::string cid = GetPeerDevId(sessionId); + if (::GetSessionSide(sessionId) == IS_CLIENT) { + notifyCallback_->SendError(cid); + } else { + notifyCallback_->ReceiveError(cid); + } return 0; } void SoftbusAgent::OnReceiveFileFinished(const int sessionId, const std::string files, int fileCnt) { - LOGD("recv file finish, sessionId:%{public}d, files %{public}s, cnt %{public}d", sessionId, files.c_str(), fileCnt); + if (notifyCallback_ == nullptr) { + LOGE("OnReceiveFileFinished Nofify pointer is empty"); + return; + } + std::string cid = GetPeerDevId(sessionId); + if (cid.empty()) { + auto alreadyOnliceDev = DeviceManagerAgent::GetInstance()->getOnlineDevs(); + LOGI("IsDeviceOnline size, %{public}d", alreadyOnliceDev.size()); + for (std::string item : alreadyOnliceDev) { + LOGI("IsDeviceOnline item, %{public}s", item.c_str()); + cid = item; + } + } + + std::string desFileName = std::string("/data/system_ce/") + files; + int32_t fd = open(desFileName.c_str(), O_RDONLY); + if (fd <= 0) { + LOGE("NapiWriteFile open recive distributedfile %{public}d, %{public}s, %{public}d", + fd, strerror(errno), errno); + } + notifyCallback_->WriteFile(fd, files); + notifyCallback_->ReceiveFinished(cid, files, fileCnt); } void SoftbusAgent::OnSessionClosed(int sessionId) @@ -172,24 +211,26 @@ void SoftbusAgent::OnSessionClosed(int sessionId) LOGE("get peer device id failed"); return; } - std::unique_lock lock(sessionMapMux_); - if (cidToSessionID_.find(cid) != cidToSessionID_.end()) { - cidToSessionID_[cid].remove(sessionId); + { + std::unique_lock lock(sessionMapMux_); + if (cidToSessionID_.find(cid) != cidToSessionID_.end()) { + cidToSessionID_[cid].remove(sessionId); + } } - return; } std::string SoftbusAgent::GetPeerDevId(const int sessionId) { std::string cid; - char peerDevId[DEVICE_ID_SIZE_MAX] = ""; + char peerDevId[DEVICE_ID_SIZE_MAX] = { '\0' }; int ret = ::GetPeerDeviceId(sessionId, peerDevId, sizeof(peerDevId)); if (ret != SOFTBUS_OK) { LOGE("get my peer device id failed, errno:%{public}d, sessionId:%{public}d", ret, sessionId); cid = ""; } else { - cid = string(peerDevId); + cid = std::string(peerDevId); } + return cid; } @@ -211,8 +252,18 @@ void SoftbusAgent::OnDeviceOffline(const std::string &cid) if (CloseSession(cid) == -1) { return; } - std::unique_lock lock(sessionMapMux_); - cidToSessionID_.erase(cid); + + { + std::unique_lock lock(sessionMapMux_); + cidToSessionID_.erase(cid); + } + + if (notifyCallback_ == nullptr) { + LOGE("OnDeviceOffline Nofify pointer is empty"); + return; + } + + notifyCallback_->DeviceOffline(cid); } void SoftbusAgent::RegisterSessionListener() @@ -223,10 +274,10 @@ void SoftbusAgent::RegisterSessionListener() }; int ret = ::CreateSessionServer(DistributedFileService::pkgName_.c_str(), sessionName_.c_str(), &sessionListener); if (ret != 0) { - stringstream ss; + std::stringstream ss; ss << "Failed to CreateSessionServer, errno:" << ret; LOGE("%{public}s, sessionName:%{public}s", ss.str().c_str(), sessionName_.c_str()); - return throw runtime_error(ss.str()); + return throw std::runtime_error(ss.str()); } LOGD("Succeed to CreateSessionServer, pkgName %{public}s, sbusName:%{public}s", DistributedFileService::pkgName_.c_str(), sessionName_.c_str()); @@ -241,10 +292,10 @@ void SoftbusAgent::RegisterFileListener() std::string pkgName = DistributedFileService::pkgName_; int ret = ::SetFileSendListener(pkgName.c_str(), sessionName_.c_str(), &fileSendListener); if (ret != 0) { - stringstream ss; + std::stringstream ss; ss << "Failed to SetFileSendListener, errno:" << ret; LOGE("%{public}s, sessionName:%{public}s", ss.str().c_str(), sessionName_.c_str()); - throw runtime_error(ss.str()); + throw std::runtime_error(ss.str()); } LOGD("Succeed to SetFileSendListener, pkgName %{public}s, sbusName:%{public}s", pkgName.c_str(), sessionName_.c_str()); @@ -256,10 +307,10 @@ void SoftbusAgent::RegisterFileListener() ret = ::SetFileReceiveListener(pkgName.c_str(), sessionName_.c_str(), &fileRecvListener, DEFAULT_ROOT_PATH.c_str()); if (ret != 0) { - stringstream ss; + std::stringstream ss; ss << "Failed to SetFileReceiveListener, errno:" << ret; LOGE("%{public}s, sessionName:%{public}s", ss.str().c_str(), sessionName_.c_str()); - throw runtime_error(ss.str()); + throw std::runtime_error(ss.str()); } LOGD("Succeed to SetFileReceiveListener, pkgName %{public}s, sbusName:%{public}s", pkgName.c_str(), sessionName_.c_str()); @@ -268,13 +319,22 @@ void SoftbusAgent::UnRegisterSessionListener() { int ret = ::RemoveSessionServer(DistributedFileService::pkgName_.c_str(), sessionName_.c_str()); if (ret != 0) { - stringstream ss; + std::stringstream ss; ss << "Failed to RemoveSessionServer, errno:" << ret; LOGE("%{public}s", ss.str().c_str()); - throw runtime_error(ss.str()); + throw std::runtime_error(ss.str()); } LOGD("RemoveSessionServer success!"); } +void SoftbusAgent::SetTransCallback(sptr &callback) +{ + notifyCallback_ = callback; +} + +void SoftbusAgent::RemoveTransCallbak() +{ + notifyCallback_ = nullptr; +} } // namespace DistributedFile } // namespace Storage } // namespace OHOS \ No newline at end of file diff --git a/services/distributedfileservice/src/network/softbus_dispatcher.cpp b/services/distributedfileservice/src/network/softbus_dispatcher.cpp index 542f089c0577b63f8bac3e7920caa54da28b77fc..e69e31aca1c768bc13915f9816be34e0a772bb38 100644 --- a/services/distributedfileservice/src/network/softbus_dispatcher.cpp +++ b/services/distributedfileservice/src/network/softbus_dispatcher.cpp @@ -20,7 +20,6 @@ namespace OHOS { namespace Storage { namespace DistributedFile { - int SoftbusDispatcher::OnSessionOpened(int sessionId, int result) { LOGD("get session res:%{public}d, sessionId:%{public}d", result, sessionId); diff --git a/utils/system/include/utils_directory.h b/utils/system/include/utils_directory.h index 48d89abcf0771a5197331b3e00d4c7a24ab05bad..8d8a57563a1e624a5eb1ae31f82e80e182619cdb 100644 --- a/utils/system/include/utils_directory.h +++ b/utils/system/include/utils_directory.h @@ -38,6 +38,9 @@ void ForceCreateDirectory(const std::string &path, mode_t mode); void ForceCreateDirectory(const std::string &path, mode_t mode, uid_t uid, gid_t gid); void ForceRemoveDirectory(const std::string &path); + +bool IsFileExist(const std::string &fileName); +int32_t RemoveFile(const std::string &fileName); } // namespace Utils } // namespace DistributedFile } // namespace Storage diff --git a/utils/system/src/utils_directory.cpp b/utils/system/src/utils_directory.cpp index 7c62a2a40001d0fe930f594e2fd3dcb11cdbe49a..deee461d01acf24c14f84f5feaded1ff3acd8ca3 100644 --- a/utils/system/src/utils_directory.cpp +++ b/utils/system/src/utils_directory.cpp @@ -78,6 +78,17 @@ void ForceRemoveDirectory(const string &path) throw system_error(errno, system_category()); } } + +bool IsFileExist(const std::string &fileName) +{ + struct stat fileStat; + return (stat(fileName.c_str(), &fileStat) == 0); +} + +int32_t RemoveFile(const std::string &fileName) +{ + return remove(fileName.c_str()); +} } // namespace Utils } // namespace DistributedFile } // namespace Storage