diff --git a/frameworks/native/sensor/BUILD.gn b/frameworks/native/sensor/BUILD.gn index 9f9c6c3f30563805223a86e625fbc60b0b62ed08..9fbac9260bed90ee86b09425af1e56946a7a3577 100755 --- a/frameworks/native/sensor/BUILD.gn +++ b/frameworks/native/sensor/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -25,16 +25,21 @@ ohos_shared_library("libsensor_native") { "src/sensor_file_descriptor_listener.cpp", "src/sensor_service_client.cpp", "src/sensor_service_proxy.cpp", + "src/client_info_file_descriptor_listener.cpp", ] include_dirs = [ "include", "//commonlibrary/c_utils/base/include", "//utils/system/safwk/native/include", - "$SUBSYSTEM_DIR/sensor/utils/include", + "$SUBSYSTEM_DIR/sensor/utils/common/include", + "$SUBSYSTEM_DIR/sensor/utils/ipc/include", "$SUBSYSTEM_DIR/sensor/interfaces/native/include", ] - deps = [ "$SUBSYSTEM_DIR/sensor/utils:libsensor_utils" ] + deps = [ + "$SUBSYSTEM_DIR/sensor/utils/common:libsensor_utils", + "$SUBSYSTEM_DIR/sensor/utils/ipc:libsensor_ipc", + ] external_deps = [ "c_utils:utils", diff --git a/frameworks/native/sensor/include/client_info_file_descriptor_listener.h b/frameworks/native/sensor/include/client_info_file_descriptor_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..ec107974b3b92d65a29e0bae9864665ce54c0620 --- /dev/null +++ b/frameworks/native/sensor/include/client_info_file_descriptor_listener.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 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 CLIENT_INFO_FILE_DESCRIPTOR_LISTENER_H +#define CLIENT_INFO_FILE_DESCRIPTOR_LISTENER_H + +#include "file_descriptor_listener.h" + +#include "sensor_data_channel.h" + +namespace OHOS { +namespace Sensors { +class ClientInfoFileDescriptorListener : public AppExecFwk::FileDescriptorListener { +public: + ClientInfoFileDescriptorListener() = default; + ~ClientInfoFileDescriptorListener() override = default; + void OnReadable(int32_t fd) override; + void OnShutdown(int32_t fd) override; + void OnException(int32_t fd) override; + void SetChannel(SensorDataChannel *channel); + DISALLOW_COPY_AND_MOVE(ClientInfoFileDescriptorListener); + +private: + SensorDataChannel *channel_ = nullptr; +}; +} // namespace Sensors +} // namespace OHOS +#endif // CLIENT_INFO_FILE_DESCRIPTOR_LISTENER_H diff --git a/frameworks/native/sensor/include/i_sensor_service.h b/frameworks/native/sensor/include/i_sensor_service.h index dab25cb40366ea6aa2068974715969ec12757660..d6da491ec4c3943f34e7bc5a19c93c47abe64c8a 100755 --- a/frameworks/native/sensor/include/i_sensor_service.h +++ b/frameworks/native/sensor/include/i_sensor_service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -24,6 +24,7 @@ #include "i_sensor_client.h" #include "sensor_basic_data_channel.h" #include "sensor.h" +#include "subscribe_info.h" namespace OHOS { namespace Sensors { @@ -39,6 +40,13 @@ public: virtual ErrCode TransferDataChannel(const sptr &sensorBasicDataChannel, const sptr &sensorClient) = 0; virtual ErrCode DestroySensorChannel(sptr sensorClient) = 0; + virtual ErrCode SuspendSensors(int32_t pid) = 0; + virtual ErrCode ResumeSensors(int32_t pid) = 0; + virtual ErrCode GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) = 0; + virtual ErrCode CreateSocketChannel(int32_t &clientFd, const sptr &sensorClient) = 0; + virtual ErrCode DestroySocketChannel(const sptr &sensorClient) = 0; + virtual ErrCode EnableClientInfoCallback() = 0; + virtual ErrCode DisableClientInfoCallback() = 0; enum { ENABLE_SENSOR = 0, DISABLE_SENSOR, @@ -47,6 +55,13 @@ public: GET_SENSOR_LIST, TRANSFER_DATA_CHANNEL, DESTROY_SENSOR_CHANNEL, + SUSPEND_SENSORS, + RESUME_SENSORS, + GET_SUBSCRIBE_INFO_LIST, + CREATE_SOCKET_CHANNEL, + DESTROY_SOCKET_CHANNEL, + ENABLE_CLIENT_INFO_CALLBACK, + DISABLE_CLIENT_INFO_CALLBACK, }; }; } // namespace Sensors diff --git a/frameworks/native/sensor/include/sensor_agent_proxy.h b/frameworks/native/sensor/include/sensor_agent_proxy.h index a14ea60d025a305583ed80e6abbfe291b4e07a40..ddb0684ea68700089cf1b26bf6168850ec6b4700 100644 --- a/frameworks/native/sensor/include/sensor_agent_proxy.h +++ b/frameworks/native/sensor/include/sensor_agent_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -43,6 +43,11 @@ public: int32_t SetMode(int32_t sensorId, const SensorUser *user, int32_t mode) const; int32_t SetOption(int32_t sensorId, const SensorUser *user, int32_t option) const; int32_t GetAllSensors(SensorInfo **sensorInfo, int32_t *count) const; + int32_t SuspendSensors(int32_t pid) const; + int32_t ResumeSensors(int32_t pid) const; + int32_t GetSubscribeInfos(int32_t pid, SubscribeSensorInfo **subscribeSensorInfos, int32_t *count) const; + int32_t RegisterClientInfoCallback(ClientInfoCallback callback) const; + int32_t UnregisterClientInfoCallback(ClientInfoCallback callback) const; private: int32_t CreateSensorDataChannel() const; diff --git a/frameworks/native/sensor/include/sensor_data_channel.h b/frameworks/native/sensor/include/sensor_data_channel.h index ecf87bac672e816fa1cf0d4d350a88a7f9817c2d..1b004337bf0900025c320a4e8a1661de9f1a5095 100644 --- a/frameworks/native/sensor/include/sensor_data_channel.h +++ b/frameworks/native/sensor/include/sensor_data_channel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -18,6 +18,8 @@ #include #include +#include +#include #include "sensor_agent_type.h" #include "sensor_event_handler.h" @@ -28,6 +30,9 @@ namespace Sensors { typedef void (*DataChannelCB)(SensorEvent *events, int32_t num, void *data); class SensorDataChannel : public SensorBasicDataChannel { public: + using ReceiveMessageFun = std::function; + using DisconnectFun = std::function; + SensorDataChannel() = default; ~SensorDataChannel(); static int32_t HandleEvent(int32_t fd, int32_t events, void *data); @@ -40,13 +45,19 @@ public: DataChannelCB dataCB_ = nullptr; void *privateData_ = nullptr; + int32_t AddFdListener(int32_t fd, ReceiveMessageFun receiveMessage, DisconnectFun disconnect); + int32_t DelFdListener(int32_t fd); + ReceiveMessageFun receiveMessage_; + DisconnectFun disconnect_; + private: static void ThreadProcessTask(SensorDataChannel *sensorChannel); int32_t InnerSensorDataChannel(); std::mutex eventRunnerMutex_; - static std::shared_ptr eventHandler_; + std::shared_ptr eventHandler_; static std::shared_ptr eventRunner_; static int32_t receiveFd_; + std::unordered_set listenedFdSet_; }; } // namespace Sensors } // namespace OHOS diff --git a/frameworks/native/sensor/include/sensor_service_client.h b/frameworks/native/sensor/include/sensor_service_client.h index ce45bad04dff32dcdd559d2f02cf4d3f34e490e8..21ff983750f8f668afeadc9ec130e6c64715f877 100755 --- a/frameworks/native/sensor/include/sensor_service_client.h +++ b/frameworks/native/sensor/include/sensor_service_client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -17,6 +17,7 @@ #define SENSOR_SERVICE_CLIENT_H #include +#include #include #include "iservice_registry.h" @@ -29,12 +30,14 @@ #include "sensor_data_channel.h" #include "sensor.h" #include "sensor_service_proxy.h" - +#include "stream_socket.h" +#include "subscribe_info.h" namespace OHOS { namespace Sensors { -class SensorServiceClient : public Singleton { +class SensorServiceClient : public StreamSocket, public Singleton { public: + ~SensorServiceClient(); std::vector GetSensorList(); int32_t EnableSensor(int32_t sensorId, int64_t samplingPeriod, int64_t maxReportDelay); int32_t DisableSensor(int32_t sensorId); @@ -42,6 +45,15 @@ public: int32_t DestroyDataChannel(); void ProcessDeathObserver(const wptr &object); bool IsValid(int32_t sensorId); + int32_t SuspendSensors(int32_t pid); + int32_t ResumeSensors(int32_t pid); + int32_t GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList); + + int32_t RegisterClientInfoCallback(ClientInfoCallback callback, sptr sensorDataChannel); + int32_t UnregisterClientInfoCallback(ClientInfoCallback callback); + + void ReceiveMessage(const char *buf, size_t size); + void Disconnect(); private: int32_t InitServiceClient(); @@ -55,8 +67,15 @@ private: sptr sensorClientStub_; std::mutex mapMutex_; std::map sensorInfoMap_; + + int32_t CreateSocketChannel(); + void HandleNetPacke(NetPacket &pkt); + std::atomic_bool isConnected_ = false; + CircleStreamBuffer circBuf_; + + std::mutex clientInfoCallbackMutex_; + std::set clientInfoCallbackSet_; }; } // namespace Sensors } // namespace OHOS - #endif // SENSOR_SERVICE_CLIENT_H diff --git a/frameworks/native/sensor/include/sensor_service_proxy.h b/frameworks/native/sensor/include/sensor_service_proxy.h index 01bfde3eadfbf5e818a10c2a0fcec2ebe8c2ceff..495230926dc563fa3dd9ce1f907b939f7824c416 100755 --- a/frameworks/native/sensor/include/sensor_service_proxy.h +++ b/frameworks/native/sensor/include/sensor_service_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -35,6 +35,13 @@ public: ErrCode TransferDataChannel(const sptr &sensorBasicDataChannel, const sptr &sensorClient) override; ErrCode DestroySensorChannel(sptr sensorClient) override; + ErrCode SuspendSensors(int32_t pid) override; + ErrCode ResumeSensors(int32_t pid) override; + ErrCode GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) override; + ErrCode CreateSocketChannel(int32_t &clientFd, const sptr &sensorClient) override; + ErrCode DestroySocketChannel(const sptr &sensorClient) override; + ErrCode EnableClientInfoCallback() override; + ErrCode DisableClientInfoCallback() override; private: DISALLOW_COPY_AND_MOVE(SensorServiceProxy); diff --git a/frameworks/native/sensor/src/client_info_file_descriptor_listener.cpp b/frameworks/native/sensor/src/client_info_file_descriptor_listener.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4782e63a26792fc018a82a8f318b71b28590c5c9 --- /dev/null +++ b/frameworks/native/sensor/src/client_info_file_descriptor_listener.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 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 "client_info_file_descriptor_listener.h" + +#include + +#include "sensors_errors.h" +#include "stream_socket.h" + +namespace OHOS { +namespace Sensors { +using namespace OHOS::AppExecFwk; +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "ClientInfoFileDescriptorListener" }; +} + +void ClientInfoFileDescriptorListener::SetChannel(SensorDataChannel *channel) +{ + channel_ = channel; +} + +void ClientInfoFileDescriptorListener::OnReadable(int32_t fd) +{ + if (fd < 0) { + SEN_HILOGE("Invalid fd"); + return; + } + char szBuf[PROTO_MAX_PACKET_BUF_SIZE] = {}; + for (int32_t i = 0; i < PROTO_MAX_RECV_LIMIT; i++) { + ssize_t size = recv(fd, szBuf, PROTO_MAX_PACKET_BUF_SIZE, MSG_DONTWAIT | MSG_NOSIGNAL); + if (size > 0) { + channel_->receiveMessage_(szBuf, size); + } else if (size < 0) { + if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { + SEN_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, size:%{public}zu, errno:%{public}d", + size, errno); + continue; + } + SEN_HILOGE("Recv return %{public}zu, errno:%{public}d", size, errno); + break; + } else { + SEN_HILOGD("The service side disconnect with the client. size:0, count:%{public}d, errno:%{public}d", + i, errno); + break; + } + if (size < PROTO_MAX_PACKET_BUF_SIZE) { + break; + } + } +} + +void ClientInfoFileDescriptorListener::OnShutdown(int32_t fd) +{ + if (fd < 0) { + SEN_HILOGE("Invalid fd"); + } + channel_->disconnect_(); +} + +void ClientInfoFileDescriptorListener::OnException(int32_t fd) +{ + if (fd < 0) { + SEN_HILOGE("Invalid fd"); + } + channel_->disconnect_(); +} +} // namespace Sensors +} // namespace OHOS diff --git a/frameworks/native/sensor/src/sensor_agent_proxy.cpp b/frameworks/native/sensor/src/sensor_agent_proxy.cpp index 21c4671577bdce7b748f5c046c2fa7520d1340bf..7438e442a7e1a40fe46483a7d87c60897117f00f 100644 --- a/frameworks/native/sensor/src/sensor_agent_proxy.cpp +++ b/frameworks/native/sensor/src/sensor_agent_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -18,6 +18,7 @@ #include #include "securec.h" + #include "sensor_service_client.h" #include "sensors_errors.h" @@ -38,6 +39,8 @@ std::recursive_mutex SensorAgentProxy::subscribeMutex_; std::mutex SensorAgentProxy::chanelMutex_; std::mutex sensorInfoMutex_; SensorInfo *sensorInfos_ = nullptr; +std::mutex subscribeSensorInfoMutex_; +SubscribeSensorInfo *subscribeSensorInfos_ = nullptr; int32_t sensorInfoCount_ = 0; std::map SensorAgentProxy::g_subscribeMap; std::map SensorAgentProxy::g_unsubscribeMap; @@ -266,6 +269,10 @@ int32_t SensorAgentProxy::SetMode(int32_t sensorId, const SensorUser *user, int3 void SensorAgentProxy::ClearSensorInfos() const { + if (subscribeSensorInfos_ != nullptr) { + free(subscribeSensorInfos_); + subscribeSensorInfos_ = nullptr; + } CHKPV(sensorInfos_); free(sensorInfos_); sensorInfos_ = nullptr; @@ -330,5 +337,98 @@ int32_t SensorAgentProxy::GetAllSensors(SensorInfo **sensorInfo, int32_t *count) *count = sensorInfoCount_; return SUCCESS; } + +int32_t SensorAgentProxy::SuspendSensors(int32_t pid) const +{ + CALL_LOG_ENTER; + if (pid < 0) { + SEN_HILOGE("Pid is invalid"); + return PARAMETER_ERROR; + } + int32_t ret = SenClient.SuspendSensors(pid); + if (ret != 0) { + SEN_HILOGE("Suspend pid sensors failed, ret:%{public}d", ret); + } + return ret; +} + +int32_t SensorAgentProxy::ResumeSensors(int32_t pid) const +{ + CALL_LOG_ENTER; + if (pid < 0) { + SEN_HILOGE("Pid is invalid"); + return PARAMETER_ERROR; + } + int32_t ret = SenClient.ResumeSensors(pid); + if (ret != 0) { + SEN_HILOGE("Resume pid sensors failed, ret:%{public}d", ret); + } + return ret; +} + +int32_t SensorAgentProxy::GetSubscribeInfos(int32_t pid, SubscribeSensorInfo **subscribeSensorInfos, int32_t *count) const +{ + CALL_LOG_ENTER; + if (pid < 0) { + SEN_HILOGE("Pid is invalid"); + return PARAMETER_ERROR; + } + CHKPR(subscribeSensorInfos, OHOS::Sensors::ERROR); + CHKPR(count, OHOS::Sensors::ERROR); + std::lock_guard subscribeSensorInfoLock(subscribeSensorInfoMutex_); + if (subscribeSensorInfos_ != nullptr) { + free(subscribeSensorInfos_); + subscribeSensorInfos_ = nullptr; + } + std::vector subscribeInfoList; + int32_t ret = SenClient.GetSubscribeInfoList(pid, subscribeInfoList); + if (ret != 0) { + SEN_HILOGE("Get subscribe info list failed, ret:%{public}d", ret); + return ERROR; + } + if (subscribeInfoList.empty()) { + SEN_HILOGE("Subscribe info list is empty"); + return ERROR; + } + size_t subscribeInfoCount = subscribeInfoList.size(); + if (subscribeInfoCount > MAX_SENSOR_LIST_SIZE) { + SEN_HILOGE("The number of subscribe info exceeds the maximum value, count:%{public}zu", subscribeInfoCount); + return ERROR; + } + subscribeSensorInfos_ = (SubscribeSensorInfo *)malloc(sizeof(SubscribeSensorInfo) * subscribeInfoCount); + CHKPR(subscribeSensorInfos_, ERROR); + for (size_t i = 0; i < subscribeInfoCount; ++i) { + SubscribeSensorInfo *curSubscribeInfo= subscribeSensorInfos_ + i; + curSubscribeInfo->pid = subscribeInfoList[i].GetPid(); + curSubscribeInfo->sensorId = subscribeInfoList[i].GetSensorId(); + curSubscribeInfo->isActive = subscribeInfoList[i].IsActive(); + curSubscribeInfo->samplingPeriodNs = subscribeInfoList[i].GetSamplingPeriodNs(); + curSubscribeInfo->maxReportDelayNs = subscribeInfoList[i].GetMaxReportDelayNs(); + } + *subscribeSensorInfos = subscribeSensorInfos_; + *count = static_cast(subscribeInfoCount); + return SUCCESS; +} + +int32_t SensorAgentProxy::RegisterClientInfoCallback(ClientInfoCallback callback) const +{ + CHKPR(callback, OHOS::Sensors::ERROR); + CHKPR(dataChannel_, INVALID_POINTER); + int32_t ret = SenClient.RegisterClientInfoCallback(callback, dataChannel_); + if (ret != ERR_OK) { + SEN_HILOGE("Register client info callback failed, ret:%{public}d", ret); + } + return SUCCESS; +} + +int32_t SensorAgentProxy::UnregisterClientInfoCallback(ClientInfoCallback callback) const +{ + CHKPR(callback, OHOS::Sensors::ERROR); + int32_t ret = SenClient.UnregisterClientInfoCallback(callback); + if (ret != ERR_OK) { + SEN_HILOGE("Unregister client info callback failed, ret:%{public}d, ret", ret); + } + return SUCCESS; +} } // namespace Sensors } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/sensor/src/sensor_data_channel.cpp b/frameworks/native/sensor/src/sensor_data_channel.cpp index 501a6d0e0b9fcb558548b99623f3824ff5cc23db..cc64075577d3780cd3e7e7da76dcdfd530646b77 100644 --- a/frameworks/native/sensor/src/sensor_data_channel.cpp +++ b/frameworks/native/sensor/src/sensor_data_channel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -16,14 +16,14 @@ #include "sensor_data_channel.h" #include "errors.h" + +#include "client_info_file_descriptor_listener.h" #include "sensor_file_descriptor_listener.h" #include "sensors_errors.h" - namespace OHOS { namespace Sensors { using namespace OHOS::HiviewDFX; using namespace OHOS::AppExecFwk; -std::shared_ptr SensorDataChannel::eventHandler_; namespace { constexpr HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "SensorDataChannel" }; @@ -58,9 +58,11 @@ int32_t SensorDataChannel::InnerSensorDataChannel() } auto listener = std::make_shared(); listener->SetChannel(this); - auto myRunner = AppExecFwk::EventRunner::Create(true); - CHKPR(myRunner, ERROR); - eventHandler_ = std::make_shared(myRunner); + if (eventHandler_ == nullptr) { + auto myRunner = AppExecFwk::EventRunner::Create(true); + CHKPR(myRunner, ERROR); + eventHandler_ = std::make_shared(myRunner); + } int32_t receiveFd = GetReceiveDataFd(); auto inResult = eventHandler_->AddFileDescriptorListener(receiveFd, AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, listener); @@ -68,6 +70,11 @@ int32_t SensorDataChannel::InnerSensorDataChannel() SEN_HILOGE("AddFileDescriptorListener fail"); return ERROR; } + auto pairRet = listenedFdSet_.insert(receiveFd); + if (!pairRet.second) { + SEN_HILOGE("ListenedFdSet insert fd fail"); + return ERROR; + } return ERR_OK; } @@ -75,8 +82,16 @@ int32_t SensorDataChannel::DestroySensorDataChannel() { std::lock_guard eventRunnerLock(eventRunnerMutex_); CHKPL(eventHandler_); - eventHandler_ = nullptr; - // destroy sensor basic channelx + int32_t receiveFd = GetReceiveDataFd(); + eventHandler_->RemoveFileDescriptorListener(receiveFd); + auto it = listenedFdSet_.find(receiveFd); + if (it != listenedFdSet_.end()) { + listenedFdSet_.erase(it); + } + if (listenedFdSet_.empty() && eventHandler_ != nullptr) { + eventHandler_ = nullptr; + SEN_HILOGD("Set eventHandler_ nullptr"); + } return DestroySensorBasicChannel(); } @@ -84,5 +99,48 @@ SensorDataChannel::~SensorDataChannel() { DestroySensorDataChannel(); } + +int32_t SensorDataChannel::AddFdListener(int32_t fd, ReceiveMessageFun receiveMessage, DisconnectFun disconnect) +{ + receiveMessage_ = receiveMessage; + disconnect_ = disconnect; + std::lock_guard eventRunnerLock(eventRunnerMutex_); + if (eventHandler_ == nullptr) { + auto myRunner = AppExecFwk::EventRunner::Create(true); + CHKPR(myRunner, ERROR); + eventHandler_ = std::make_shared(myRunner); + } + auto listener = std::make_shared(); + listener->SetChannel(this); + auto errCode = eventHandler_->AddFileDescriptorListener(fd, AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, listener); + if (errCode != ERR_OK) { + SEN_HILOGE("Add fd listener failed, errCode:%{public}u", errCode); + return ERROR; + } + auto pairRet = listenedFdSet_.insert(fd); + if (!pairRet.second) { + SEN_HILOGE("ListenedFdSet insert fd fail"); + return ERROR; + } + return ERR_OK; +} + +int32_t SensorDataChannel::DelFdListener(int32_t fd) +{ + std::lock_guard eventRunnerLock(eventRunnerMutex_); + CHKPL(eventHandler_); + eventHandler_->RemoveFileDescriptorListener(fd); + auto it = listenedFdSet_.find(fd); + if (it == listenedFdSet_.end()) { + SEN_HILOGE("ListenedFdSet not find fd"); + return ERROR; + } + listenedFdSet_.erase(it); + if (listenedFdSet_.empty() && eventHandler_ != nullptr) { + eventHandler_ = nullptr; + SEN_HILOGD("Set eventHandler_ nullptr"); + } + return ERR_OK; +} } // namespace Sensors } // namespace OHOS diff --git a/frameworks/native/sensor/src/sensor_service_client.cpp b/frameworks/native/sensor/src/sensor_service_client.cpp index 419f0e14def90aab8098fc6931c3420e3d2bcd50..2979dfc6d786c27fba655b905bfe68c7041ca9cf 100755 --- a/frameworks/native/sensor/src/sensor_service_client.cpp +++ b/frameworks/native/sensor/src/sensor_service_client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -38,6 +38,11 @@ constexpr int32_t GET_SERVICE_MAX_COUNT = 30; constexpr uint32_t WAIT_MS = 200; } // namespace +SensorServiceClient::~SensorServiceClient() +{ + Disconnect(); +} + int32_t SensorServiceClient::InitServiceClient() { CALL_LOG_ENTER; @@ -182,7 +187,6 @@ void SensorServiceClient::ProcessDeathObserver(const wptr &object dataChannel_->DestroySensorDataChannel(); // STEP2 : Restore data channel dataChannel_->RestoreSensorDataChannel(); - // STEP3 : Clear sensorlist and sensorServer_ sensorList_.clear(); sensorServer_ = nullptr; @@ -200,6 +204,13 @@ void SensorServiceClient::ProcessDeathObserver(const wptr &object for (const auto &it : sensorInfoMap_) { sensorServer_->EnableSensor(it.first, it.second.GetSamplingPeriodNs(), it.second.GetMaxReportDelayNs()); } + + if (!isConnected_) { + SEN_HILOGD("Previous socket channel status is false, not need retry creat socket channel"); + return; + } + Disconnect(); + CreateSocketChannel(); } void SensorServiceClient::UpdateSensorInfoMap(int32_t sensorId, int64_t samplingPeriod, int64_t maxReportDelay) @@ -224,5 +235,187 @@ void SensorServiceClient::DeleteSensorInfoItem(int32_t sensorId) } return; } + +int32_t SensorServiceClient::SuspendSensors(int32_t pid) +{ + CALL_LOG_ENTER; + int32_t ret = InitServiceClient(); + if (ret != ERR_OK) { + SEN_HILOGE("InitServiceClient failed, ret:%{public}d", ret); + return ret; + } + CHKPR(sensorServer_, ERROR); + StartTrace(HITRACE_TAG_SENSORS, "SuspendSensors"); + ret = sensorServer_->SuspendSensors(pid); + FinishTrace(HITRACE_TAG_SENSORS); + return ret; +} + +int32_t SensorServiceClient::ResumeSensors(int32_t pid) +{ + CALL_LOG_ENTER; + int32_t ret = InitServiceClient(); + if (ret != ERR_OK) { + SEN_HILOGE("InitServiceClient failed, ret:%{public}d", ret); + return ret; + } + CHKPR(sensorServer_, ERROR); + StartTrace(HITRACE_TAG_SENSORS, "ResumeSensors"); + ret = sensorServer_->ResumeSensors(pid); + FinishTrace(HITRACE_TAG_SENSORS); + return ret; +} +int32_t SensorServiceClient::GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) +{ + CALL_LOG_ENTER; + int32_t ret = InitServiceClient(); + if (ret != ERR_OK) { + SEN_HILOGE("InitServiceClient failed, ret:%{public}d", ret); + return ret; + } + CHKPR(sensorServer_, ERROR); + StartTrace(HITRACE_TAG_SENSORS, "GetSubscribeInfoList"); + ret = sensorServer_->GetSubscribeInfoList(pid, subscribeInfoList); + FinishTrace(HITRACE_TAG_SENSORS); + return ret; +} + +int32_t SensorServiceClient::RegisterClientInfoCallback(ClientInfoCallback callback, sptr sensorDataChannel) +{ + CALL_LOG_ENTER; + + if (!isConnected_) { + CHKPR(sensorDataChannel, INVALID_POINTER); + dataChannel_ = sensorDataChannel; + int32_t ret = CreateSocketChannel(); + if (ret != ERR_OK) { + SEN_HILOGE("Register client info callback failed, ret:%{public}d", ret); + return ret; + } + } + std::lock_guard clientInfoCallbackLock(clientInfoCallbackMutex_); + clientInfoCallbackSet_.insert(callback); + return ERR_OK; +} + +int32_t SensorServiceClient::UnregisterClientInfoCallback(ClientInfoCallback callback) +{ + CALL_LOG_ENTER; + std::lock_guard clientInfoCallbackLock(clientInfoCallbackMutex_); + clientInfoCallbackSet_.erase(callback); + if (!clientInfoCallbackSet_.empty()) { + return ERR_OK; + } + int32_t ret = InitServiceClient(); + if (ret != ERR_OK) { + SEN_HILOGE("InitServiceClient failed, ret:%{public}d", ret); + return ret; + } + CHKPR(sensorServer_, ERROR); + StartTrace(HITRACE_TAG_SENSORS, "DisableClientInfoCallback"); + ret = sensorServer_->DisableClientInfoCallback(); + FinishTrace(HITRACE_TAG_SENSORS); + if (ret != ERR_OK) { + SEN_HILOGE("Disable clientInfo callback failed, ret:%{public}d", ret); + return ret; + } + Disconnect(); + StartTrace(HITRACE_TAG_SENSORS, "DestroySocketChannel"); + ret = sensorServer_->DestroySocketChannel(sensorClientStub_); + FinishTrace(HITRACE_TAG_SENSORS); + if (ret != ERR_OK) { + SEN_HILOGE("Destroy socket channel failed, ret:%{public}d", ret); + return ret; + } + isConnected_ = false; + return ERR_OK; +} + +void SensorServiceClient::ReceiveMessage(const char *buf, size_t size) +{ + CHKPV(buf); + if (size == 0 || size > PROTO_MAX_PACKET_BUF_SIZE) { + SEN_HILOGE("Invalid input param size. size:%{public}zu", size); + return; + } + if (!circBuf_.Write(buf, size)) { + SEN_HILOGE("Write data failed. size:%{public}zu", size); + } + OnReadPackets(circBuf_, std::bind(&SensorServiceClient::HandleNetPacke, this, std::placeholders::_1)); +} + +void SensorServiceClient::HandleNetPacke(NetPacket &pkt) +{ + auto id = pkt.GetMsgId(); + if (id != MessageId::CLIENT_INFO) { + SEN_HILOGE("NetPacke message id is not CLIENT_INFO"); + return; + } + SubscribeSensorInfo subscribeSensorInfo; + pkt >> subscribeSensorInfo.pid >> subscribeSensorInfo.sensorId >> subscribeSensorInfo.isActive >> + subscribeSensorInfo.samplingPeriodNs >> subscribeSensorInfo.maxReportDelayNs; + if (pkt.ChkRWError()) { + SEN_HILOGE("Packet read type failed"); + return; + } + std::lock_guard clientInfoCallbackLock(clientInfoCallbackMutex_); + for (auto callback : clientInfoCallbackSet_) { + if (callback != nullptr) { + callback(subscribeSensorInfo); + } + } +} + +void SensorServiceClient::Disconnect() +{ + CALL_LOG_ENTER; + if (fd_ < 0) { + return; + } + CHKPV(dataChannel_); + int32_t ret = dataChannel_->DelFdListener(fd_); + if (ret != ERR_OK) { + SEN_HILOGE("Delete fd listener failed, ret:%{public}d", ret); + } + Close(); +} + +int32_t SensorServiceClient::CreateSocketChannel() +{ + CALL_LOG_ENTER; + int32_t ret = InitServiceClient(); + if (ret != ERR_OK) { + SEN_HILOGE("InitServiceClient failed, ret:%{public}d", ret); + return ret; + } + CHKPR(sensorServer_, ERROR); + int32_t clientFd = -1; + StartTrace(HITRACE_TAG_SENSORS, "CreateSocketChannel"); + ret = sensorServer_->CreateSocketChannel(clientFd, sensorClientStub_); + FinishTrace(HITRACE_TAG_SENSORS); + if (!(ret == ERR_OK && clientFd >= 0)) { + Close(); + SEN_HILOGE("Create socket channel failed, ret:%{public}d", ret); + return ret; + } + fd_ = clientFd; + if (dataChannel_->AddFdListener(fd_, + std::bind(&SensorServiceClient::ReceiveMessage, this, std::placeholders::_1, std::placeholders::_2), + std::bind(&SensorServiceClient::Disconnect, this)) != ERR_OK) { + Close(); + SEN_HILOGE("Add fd listener failed"); + return ERROR; + } + StartTrace(HITRACE_TAG_SENSORS, "EnableClientInfoCallback"); + ret = sensorServer_->EnableClientInfoCallback(); + FinishTrace(HITRACE_TAG_SENSORS); + if (ret != ERR_OK) { + SEN_HILOGE("Enable clientInfo callback failed, ret:%{public}d", ret); + Disconnect(); + return ret; + } + isConnected_ = true; + return ERR_OK; +} } // namespace Sensors } // namespace OHOS diff --git a/frameworks/native/sensor/src/sensor_service_proxy.cpp b/frameworks/native/sensor/src/sensor_service_proxy.cpp index 5ed9c4b2f3aeca04e6490e91f7cb97a1c91080ae..e88340550a2aa0eef47a200d436a7814b570af37 100755 --- a/frameworks/native/sensor/src/sensor_service_proxy.cpp +++ b/frameworks/native/sensor/src/sensor_service_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -46,19 +46,19 @@ ErrCode SensorServiceProxy::EnableSensor(int32_t sensorId, int64_t samplingPerio MessageOption option; if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { SEN_HILOGE("write descriptor failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } if (!data.WriteInt32(sensorId)) { SEN_HILOGE("write sensorId failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } if (!data.WriteInt64(samplingPeriodNs)) { SEN_HILOGE("write samplingPeriodNs failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } if (!data.WriteInt64(maxReportDelayNs)) { SEN_HILOGE("write maxReportDelayNs failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } sptr remote = Remote(); CHKPR(remote, ERROR); @@ -78,11 +78,11 @@ ErrCode SensorServiceProxy::DisableSensor(int32_t sensorId) MessageOption option; if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { SEN_HILOGE("write descriptor failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } if (!data.WriteInt32(sensorId)) { SEN_HILOGE("write sensorId failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } sptr remote = Remote(); CHKPR(remote, ERROR); @@ -147,12 +147,12 @@ ErrCode SensorServiceProxy::TransferDataChannel(const sptrSendToBinder(data); if (!data.WriteRemoteObject(sensorClient)) { SEN_HILOGE("sensorClient failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } sptr remote = Remote(); CHKPR(remote, ERROR); @@ -174,11 +174,11 @@ ErrCode SensorServiceProxy::DestroySensorChannel(sptr sensorClien MessageOption option; if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { SEN_HILOGE("write descriptor failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } if (!data.WriteRemoteObject(sensorClient)) { SEN_HILOGE("write sensorClient failed"); - return WRITE_MSG_ERR; + return WRITE_PARCEL_ERR; } sptr remote = Remote(); CHKPR(remote, ERROR); @@ -190,5 +190,188 @@ ErrCode SensorServiceProxy::DestroySensorChannel(sptr sensorClien } return static_cast(ret); } + +ErrCode SensorServiceProxy::SuspendSensors(int32_t pid) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("Write descriptor failed"); + return WRITE_PARCEL_ERR; + } + if (!data.WriteInt32(pid)) { + SEN_HILOGE("Write pid failed"); + return WRITE_PARCEL_ERR; + } + sptr remote = Remote(); + CHKPR(remote, ERROR); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ISensorService::SUSPEND_SENSORS, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SENSOR_SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "SuspendSensors", "ERROR_CODE", ret); + SEN_HILOGE("Failed, ret:%{public}d", ret); + } + return static_cast(ret); +} + +ErrCode SensorServiceProxy::ResumeSensors(int32_t pid) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("Write descriptor failed"); + return WRITE_PARCEL_ERR; + } + if (!data.WriteInt32(pid)) { + SEN_HILOGE("Write pid failed"); + return WRITE_PARCEL_ERR; + } + sptr remote = Remote(); + CHKPR(remote, ERROR); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ISensorService::RESUME_SENSORS, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SENSOR_SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "ResumeSensors", "ERROR_CODE", ret); + SEN_HILOGE("Failed, ret:%{public}d", ret); + } + return static_cast(ret); +} + +ErrCode SensorServiceProxy::GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("Write descriptor failed"); + return WRITE_PARCEL_ERR; + } + if (!data.WriteInt32(pid)) { + SEN_HILOGE("Write pid failed"); + return WRITE_PARCEL_ERR; + } + sptr remote = Remote(); + CHKPR(remote, ERROR); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ISensorService::GET_SUBSCRIBE_INFO_LIST, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SENSOR_SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "GetSubscribeInfoList", "ERROR_CODE", ret); + SEN_HILOGE("Failed, ret:%{public}d", ret); + return static_cast(ret); + } + int32_t subscribeInfoCount; + if (!reply.ReadInt32(subscribeInfoCount)) { + SEN_HILOGE("Parcel read subscribeInfoCount failed"); + return READ_PARCEL_ERR; + } + SubscribeInfo subscribeInfo; + for (int32_t i = 0; i < subscribeInfoCount; ++i) { + auto tmpSubscribeInfo = subscribeInfo.Unmarshalling(reply); + if (tmpSubscribeInfo == nullptr) { + SEN_HILOGE("Current subscribeInfo is nullptr, i:%{public}d", i); + continue; + } + subscribeInfoList.push_back(*tmpSubscribeInfo); + } + return static_cast(ret); +} + +ErrCode SensorServiceProxy::CreateSocketChannel(int32_t &clientFd, const sptr &sensorClient) +{ + CHKPR(sensorClient, OBJECT_NULL); + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("Write descriptor failed"); + return WRITE_PARCEL_ERR; + } + if (!data.WriteRemoteObject(sensorClient)) { + SEN_HILOGE("Write sensorClient failed"); + return WRITE_PARCEL_ERR; + } + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + CHKPR(remote, ERROR); + int32_t ret = remote->SendRequest(ISensorService::CREATE_SOCKET_CHANNEL, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "CreateSocketChannel", "ERROR_CODE", ret); + SEN_HILOGE("failed, ret:%{public}d", ret); + return ERROR; + } + clientFd = reply.ReadFileDescriptor(); + if (clientFd < 0) { + SEN_HILOGE("Read file descriptor failed"); + return ERROR; + } + return static_cast(ret); +} + +ErrCode SensorServiceProxy::DestroySocketChannel(const sptr &sensorClient) +{ + CHKPR(sensorClient, OBJECT_NULL); + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("write descriptor failed"); + return WRITE_PARCEL_ERR; + } + if (!data.WriteRemoteObject(sensorClient)) { + SEN_HILOGE("Write sensorClient failed"); + return WRITE_PARCEL_ERR; + } + sptr remote = Remote(); + CHKPR(remote, ERROR); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ISensorService::DESTROY_SOCKET_CHANNEL, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "DestroySocketChannel", "ERROR_CODE", ret); + SEN_HILOGE("failed, ret:%{public}d", ret); + } + return static_cast(ret); +} + +ErrCode SensorServiceProxy::EnableClientInfoCallback() +{ + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("write descriptor failed"); + return WRITE_PARCEL_ERR; + } + sptr remote = Remote(); + CHKPR(remote, ERROR); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ISensorService::ENABLE_CLIENT_INFO_CALLBACK, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "EnableClientInfoCallback", "ERROR_CODE", ret); + SEN_HILOGE("failed, ret:%{public}d", ret); + } + return static_cast(ret); +} + +ErrCode SensorServiceProxy::DisableClientInfoCallback() +{ + MessageParcel data; + if (!data.WriteInterfaceToken(SensorServiceProxy::GetDescriptor())) { + SEN_HILOGE("write descriptor failed"); + return WRITE_PARCEL_ERR; + } + sptr remote = Remote(); + CHKPR(remote, ERROR); + MessageParcel reply; + MessageOption option; + int32_t ret = remote->SendRequest(ISensorService::DISABLE_CLIENT_INFO_CALLBACK, data, reply, option); + if (ret != NO_ERROR) { + HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SERVICE_IPC_EXCEPTION", + HiSysEvent::EventType::FAULT, "PKG_NAME", "DISABLE_CLIENT_INFO_CALLBACK", "ERROR_CODE", ret); + SEN_HILOGE("failed, ret:%{public}d", ret); + } + return static_cast(ret); +} } // namespace Sensors } // namespace OHOS diff --git a/interfaces/native/BUILD.gn b/interfaces/native/BUILD.gn index 1050549d522b9148360c3a4b4ac6a2f606a5fb52..9e1bece6fcfc741575bed5145d525c32ad55a25b 100644 --- a/interfaces/native/BUILD.gn +++ b/interfaces/native/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -27,7 +27,7 @@ config("sensor_private_config") { "//commonlibrary/c_utils/base/include", "//utils/system/safwk/native/include", "$SUBSYSTEM_DIR/frameworks/native/sensor/include", - "$SUBSYSTEM_DIR/utils/include", + "$SUBSYSTEM_DIR/utils/common/include", "$SUBSYSTEM_DIR/interfaces/native/include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", "//base/notification/eventhandler/interfaces/inner_api", diff --git a/interfaces/native/include/sensor_agent.h b/interfaces/native/include/sensor_agent.h index ead362c940d06fbf0c0bbac8ae409765c13a1933..afc4331f3dbf455119202c4830dbb26acf227488 100755 --- a/interfaces/native/include/sensor_agent.h +++ b/interfaces/native/include/sensor_agent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -127,6 +127,53 @@ int32_t DeactivateSensor(int32_t sensorTypeId, const SensorUser *user); * @since 5 */ int32_t SetMode(int32_t sensorTypeId, const SensorUser *user, int32_t mode); +/** + * @brief 休眠一个进程订阅的所有传感器 + * + * @param pid 进程号 + * @return 返回0表示成功,否则表示失败 + * + * @since 10 + */ +int32_t SuspendSensors(int32_t pid); +/** + * @brief 唤醒一个进程订阅的所有传感器 + * + * @param pid 进程号 + * @return 返回0表示成功,否则表示失败 + * + * @since 10 + */ +int32_t ResumeSensors(int32_t pid); +/** + * @brief 查询一个进程订阅的所有传感器的信息 + * + * @param pid 进程号 + * @param subscribeSensorInfos 返回进程订阅的所有传感器信息 + * @param count 返回进程订阅的传感器数量 + * @return 返回0表示成功,否则表示失败 + * + * @since 10 + */ +int32_t GetSubscribeInfos(int32_t pid, SubscribeSensorInfo **subscribeSensorInfos, int32_t *count); +/** + * @brief 注册传感器订阅信息上报函数 + * + * @param callback 回调函数 + * @return 返回0表示成功,否则表示失败 + * + * @since 10 + */ +int32_t RegisterClientInfoCallback(ClientInfoCallback callback); +/** + * @brief 取消注册传感器订阅信息上报函数 + * + * @param callback 回调函数 + * @return 返回0表示成功,否则表示失败 + * + * @since 10 + */ +int32_t UnregisterClientInfoCallback(ClientInfoCallback callback); #ifdef __cplusplus #if __cplusplus diff --git a/interfaces/native/include/sensor_agent_type.h b/interfaces/native/include/sensor_agent_type.h index 37b0de0e57418519152160a8e4307367945e1d8f..9448f98cd631ced411218893aac35eda5445cc72 100644 --- a/interfaces/native/include/sensor_agent_type.h +++ b/interfaces/native/include/sensor_agent_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -395,6 +395,16 @@ typedef struct WearDetectionData { float value; } WearDetectionData; +typedef struct SubscribeSensorInfo { + int32_t pid = -1; /**< PID */ + int32_t sensorId = -1; /**< Sensor ID */ + bool isActive = false; /**< Whether the process enable the sensor */ + int64_t samplingPeriodNs = -1; /**< Sample period, in ns */ + int64_t maxReportDelayNs = -1; /**< Maximum Report Delay, in ns */ +} SubscribeSensorInfo; + +typedef void (*ClientInfoCallback)(SubscribeSensorInfo &subscribeSensorInfo); + #ifdef __cplusplus #if __cplusplus } diff --git a/interfaces/native/src/sensor_agent.cpp b/interfaces/native/src/sensor_agent.cpp index ccae1ff7ad4a70a9a3263e0613f6de74f845fc1e..9c400650182d208306b72326e977b497c3de7548 100755 --- a/interfaces/native/src/sensor_agent.cpp +++ b/interfaces/native/src/sensor_agent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -146,4 +146,81 @@ int32_t SetMode(int32_t sensorId, const SensorUser *user, int32_t mode) return SERVICE_EXCEPTION; } return proxy->SetMode(sensorId, user, mode); +} + +int32_t SuspendSensors(int32_t pid) +{ + const SensorAgentProxy *proxy = GetInstance(); + if (proxy == nullptr) { + SEN_HILOGE("Proxy is nullptr"); + return SERVICE_EXCEPTION; + } + int32_t ret = proxy->SuspendSensors(pid); + if (ret != OHOS::ERR_OK) { + SEN_HILOGE("Suspend pid sensors failed, ret:%{public}d", ret); + return NormalizeErrCode(ret); + } + return ret; +} + +int32_t ResumeSensors(int32_t pid) +{ + const SensorAgentProxy *proxy = GetInstance(); + if (proxy == nullptr) { + SEN_HILOGE("Proxy is nullptr"); + return SERVICE_EXCEPTION; + } + int32_t ret = proxy->ResumeSensors(pid); + if (ret != OHOS::ERR_OK) { + SEN_HILOGE("Resume pid sensors failed, ret:%{public}d", ret); + return NormalizeErrCode(ret); + } + return ret; +} + +int32_t GetSubscribeInfos(int32_t pid, SubscribeSensorInfo **subscribeSensorInfos, int32_t *count) +{ + CHKPR(subscribeSensorInfos, OHOS::Sensors::ERROR); + CHKPR(count, OHOS::Sensors::ERROR); + const SensorAgentProxy *proxy = GetInstance(); + if (proxy == nullptr) { + SEN_HILOGE("Proxy is nullptr"); + return SERVICE_EXCEPTION; + } + int32_t ret = proxy->GetSubscribeInfos(pid, subscribeSensorInfos, count); + if (ret != OHOS::ERR_OK) { + SEN_HILOGE("Get subscribe Infos failed, ret:%{public}d", ret); + return NormalizeErrCode(ret); + } + return ret; +} + +int32_t RegisterClientInfoCallback(ClientInfoCallback callback) +{ + const SensorAgentProxy *proxy = GetInstance(); + if (proxy == nullptr) { + SEN_HILOGE("proxy is nullptr"); + return SERVICE_EXCEPTION; + } + int32_t ret = proxy->RegisterClientInfoCallback(callback); + if (ret != OHOS::ERR_OK) { + SEN_HILOGE("Register client info callback failed, ret:%{public}d", ret); + return NormalizeErrCode(ret); + } + return ret; +} + +int32_t UnregisterClientInfoCallback(ClientInfoCallback callback) +{ + const SensorAgentProxy *proxy = GetInstance(); + if (proxy == nullptr) { + SEN_HILOGE("proxy is nullptr"); + return SERVICE_EXCEPTION; + } + int32_t ret = proxy->UnregisterClientInfoCallback(callback); + if (ret != OHOS::ERR_OK) { + SEN_HILOGE("Unregister client info callback failed, ret:%{public}d", ret); + return NormalizeErrCode(ret); + } + return ret; } \ No newline at end of file diff --git a/interfaces/native/test/BUILD.gn b/interfaces/native/test/BUILD.gn index 5a175be21419441dd1c75a3cef2b693b9dfae6c5..ea0d5c97838279bb5c6858f1c6396a131ef182b6 100644 --- a/interfaces/native/test/BUILD.gn +++ b/interfaces/native/test/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -27,14 +27,14 @@ ohos_unittest("SensorAgentTest") { include_dirs = [ "//commonlibrary/c_utils/base/include", - "$SUBSYSTEM_DIR/sensor/utils/include", + "$SUBSYSTEM_DIR/sensor/utils/common/include", "$SUBSYSTEM_DIR/sensor/interfaces/native/include", "$SUBSYSTEM_DIR/sensor/test/unittest/common/include", ] deps = [ "$SUBSYSTEM_DIR/sensor/interfaces/native:sensor_ndk_target", - "$SUBSYSTEM_DIR/sensor/utils:libsensor_utils", + "$SUBSYSTEM_DIR/sensor/utils/common:libsensor_utils", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", ] @@ -55,14 +55,14 @@ ohos_unittest("SensorAlgorithmTest") { include_dirs = [ "//commonlibrary/c_utils/base/include", - "$SUBSYSTEM_DIR/sensor/utils/include", + "$SUBSYSTEM_DIR/sensor/utils/common/include", "$SUBSYSTEM_DIR/sensor/interfaces/native/include", "$SUBSYSTEM_DIR/sensor/test/unittest/common/include", ] deps = [ "$SUBSYSTEM_DIR/sensor/interfaces/native:sensor_ndk_target", - "$SUBSYSTEM_DIR/sensor/utils:libsensor_utils", + "$SUBSYSTEM_DIR/sensor/utils/common:libsensor_utils", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", ] @@ -73,11 +73,43 @@ ohos_unittest("SensorAlgorithmTest") { ] } +ohos_unittest("SensorPowerTest") { + module_out_path = module_output_path + + sources = [ + "$SUBSYSTEM_DIR/sensor/test/unittest/common/src/system_info.cpp", + "unittest/sensor_power_test.cpp", + ] + + include_dirs = [ + "//commonlibrary/c_utils/base/include", + "$SUBSYSTEM_DIR/sensor/utils/common/include", + "$SUBSYSTEM_DIR/sensor/interfaces/native/include", + "$SUBSYSTEM_DIR/sensor/test/unittest/common/include", + ] + + deps = [ + "$SUBSYSTEM_DIR/sensor/interfaces/native:sensor_ndk_target", + "$SUBSYSTEM_DIR/sensor/utils/common:libsensor_utils", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + ###########################end########################### group("unittest") { testonly = true deps = [ ":SensorAgentTest", ":SensorAlgorithmTest", + ":SensorPowerTest", ] } diff --git a/interfaces/native/test/unittest/sensor_power_test.cpp b/interfaces/native/test/unittest/sensor_power_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da5a3dfb86bb3c25d8d2a95dbeb74ed39e58cf41 --- /dev/null +++ b/interfaces/native/test/unittest/sensor_power_test.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2023 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 +#include +#include + +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" + +#include "sensor_agent.h" +#include "sensors_errors.h" +#include "system_info.h" + +namespace OHOS { +namespace Sensors { +using namespace testing::ext; +using namespace OHOS::HiviewDFX; +using namespace Security::AccessToken; +using Security::AccessToken::AccessTokenID; + +namespace { +constexpr HiLogLabel LABEL = { LOG_CORE, OHOS::Sensors::SENSOR_LOG_DOMAIN, "SensorPowerTest" }; +constexpr int32_t sensorId { 1 }; +constexpr int32_t invalidValue { -1 }; +} // namespace + +class SensorPowerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +int32_t process_pid = 0; + +void SensorPowerTest::SetUpTestCase() +{ + const char **perms = new const char *[1]; + perms[0] = "ohos.permission.ACCELEROMETER"; + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 1, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "SensorPowerTest", + .aplStr = "system_core", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + ASSERT_EQ(SetSelfTokenID(tokenId), 0); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; + + SYSTEM_INFO::CpuInfo cpuInfo; + const std::string process_name = "SensorPowerTest"; + process_pid = cpuInfo.GetTaskPidFile(process_name); + SEN_HILOGI("Current process pid is %{public}d", process_pid); + ASSERT_NE(process_pid, 0); +} + +void SensorPowerTest::TearDownTestCase() {} + +void SensorPowerTest::SetUp() {} + +void SensorPowerTest::TearDown() {} + +void SensorDataCallbackImpl(SensorEvent *event) +{ + if (event == nullptr) { + SEN_HILOGE("SensorEvent is null"); + return; + } + float *sensorData = (float *)event[0].data; + SEN_HILOGI("SensorId:%{public}d, version:%{public}d,dataLen:%{public}d,data:%{public}f", + event[0].sensorTypeId, event[0].version, event[0].dataLen, *(sensorData)); +} + +void ClientInfoCallbackImpl(SubscribeSensorInfo &subscribeSensorInfo) +{ + SEN_HILOGI("pid:%{public}d, sensorId:%{public}d, isActive:%{public}d, " + "samplingPeriodNs:%{public}" PRId64 ", maxReportDelayNs:%{public}" PRId64 "", + subscribeSensorInfo.pid, subscribeSensorInfo.sensorId, subscribeSensorInfo.isActive, + subscribeSensorInfo.samplingPeriodNs, subscribeSensorInfo.maxReportDelayNs); +} + +void ClientInfoCallbackImpl2(SubscribeSensorInfo &subscribeSensorInfo) +{ + SEN_HILOGI("pid:%{public}d, sensorId:%{public}d, isActive:%{public}d, " + "samplingPeriodNs:%{public}" PRId64 ", maxReportDelayNs:%{public}" PRId64 "", + subscribeSensorInfo.pid, subscribeSensorInfo.sensorId, subscribeSensorInfo.isActive, + subscribeSensorInfo.samplingPeriodNs, subscribeSensorInfo.maxReportDelayNs); +} + +HWTEST_F(SensorPowerTest, SuspendSensorsTest_001, TestSize.Level1) +{ + // 休眠接口异常用例 + SEN_HILOGI("SuspendSensorsTest_001 in"); + int32_t ret = SuspendSensors(invalidValue); + ASSERT_NE(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, ResumeSensorsTest_001, TestSize.Level1) +{ + // 恢复接口异常用例 + SEN_HILOGI("ResumeSensorsTest_001 in"); + int32_t ret = ResumeSensors(invalidValue); + ASSERT_NE(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, GetSubscribeInfosTest_001, TestSize.Level1) +{ + // 查询接口异常用例 + SEN_HILOGI("GetSubscribeInfosTest_001 in"); + SubscribeSensorInfo *subscribeSensorInfo {nullptr}; + int32_t count { 0 }; + int32_t ret = GetSubscribeInfos(invalidValue, &subscribeSensorInfo, &count); + ASSERT_NE(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, RegisterClientInfoCallback_001, TestSize.Level1) +{ + // 注册接口异常用例 + SEN_HILOGI("RegisterClientInfoCallback_001 in"); + ClientInfoCallback callback = nullptr; + int32_t ret = RegisterClientInfoCallback(callback); + ASSERT_NE(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, UnregisterClientInfoCallback_001, TestSize.Level1) +{ + // 取消注册接口异常用例 + SEN_HILOGI("UnregisterClientInfoCallback_001 in"); + ClientInfoCallback callback = nullptr; + int32_t ret = UnregisterClientInfoCallback(callback); + ASSERT_NE(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, SensorPowerTest_001, TestSize.Level1) +{ + // 场景用例1,订阅ACC传感器》查询传感器订阅数据》休眠进程的传感器》恢复进程的传感器》取消订阅ACC传感器 + SEN_HILOGI("SensorPowerTest_001 in"); + SensorUser user; + user.callback = SensorDataCallbackImpl; + + int32_t ret = SubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = SetBatch(sensorId, &user, 100000000, 100000000); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = ActivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + SubscribeSensorInfo *subscribeSensorInfo {nullptr}; + int32_t count { 0 }; + ret = GetSubscribeInfos(process_pid, &subscribeSensorInfo, &count); + for (int32_t i = 0; i < count; ++i) { + SubscribeSensorInfo *curSubscribeSensorInfo = subscribeSensorInfo + i; + SEN_HILOGI("i:%{public}d, pid:%{public}d, sensorId:%{public}d, isActive:%{public}d, " + "samplingPeriodNs:%{public}" PRId64 ", maxReportDelayNs:%{public}" PRId64 "", + i, curSubscribeSensorInfo->pid, curSubscribeSensorInfo->sensorId, curSubscribeSensorInfo->isActive, + curSubscribeSensorInfo->samplingPeriodNs, curSubscribeSensorInfo->maxReportDelayNs); + } + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = SuspendSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + + ret = ResumeSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + ret = DeactivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = UnsubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, SensorPowerTest_002, TestSize.Level1) +{ + // 场景用例2,订阅ACC传感器》休眠进程的传感器》查询传感器订阅数据》恢复进程的传感器》取消订阅ACC传感器 + SEN_HILOGI("SensorPowerTest_002 in"); + SensorUser user; + user.callback = SensorDataCallbackImpl; + + int32_t ret = SubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = SetBatch(sensorId, &user, 100000000, 100000000); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = ActivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + ret = SuspendSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + + SubscribeSensorInfo *subscribeSensorInfo {nullptr}; + int32_t count { 0 }; + ret = GetSubscribeInfos(process_pid, &subscribeSensorInfo, &count); + for (int32_t i = 0; i < count; ++i) { + SubscribeSensorInfo *curSubscribeSensorInfo = subscribeSensorInfo + i; + SEN_HILOGI("i:%{public}d, pid:%{public}d, sensorId:%{public}d, isActive:%{public}d, " + "samplingPeriodNs:%{public}" PRId64 ", maxReportDelayNs:%{public}" PRId64 "", + i, curSubscribeSensorInfo->pid, curSubscribeSensorInfo->sensorId, curSubscribeSensorInfo->isActive, + curSubscribeSensorInfo->samplingPeriodNs, curSubscribeSensorInfo->maxReportDelayNs); + } + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = ResumeSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + ret = DeactivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = UnsubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, SensorPowerTest_003, TestSize.Level1) +{ + // 场景用例3,订阅ACC传感器》休眠进程的传感器》恢复进程的传感器》查询传感器订阅数据》取消订阅ACC传感器 + SEN_HILOGI("SensorPowerTest_003 in"); + SensorUser user; + user.callback = SensorDataCallbackImpl; + + int32_t ret = SubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = SetBatch(sensorId, &user, 100000000, 100000000); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = ActivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + ret = SuspendSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + + ret = ResumeSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + SubscribeSensorInfo *subscribeSensorInfo {nullptr}; + int32_t count { 0 }; + ret = GetSubscribeInfos(process_pid, &subscribeSensorInfo, &count); + for (int32_t i = 0; i < count; ++i) { + SubscribeSensorInfo *curSubscribeSensorInfo = subscribeSensorInfo + i; + SEN_HILOGI("i:%{public}d, pid:%{public}d, sensorId:%{public}d, isActive:%{public}d, " + "samplingPeriodNs:%{public}" PRId64 ", maxReportDelayNs:%{public}" PRId64 "", + i, curSubscribeSensorInfo->pid, curSubscribeSensorInfo->sensorId, curSubscribeSensorInfo->isActive, + curSubscribeSensorInfo->samplingPeriodNs, curSubscribeSensorInfo->maxReportDelayNs); + } + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = DeactivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = UnsubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, SensorPowerTest_004, TestSize.Level1) +{ + // 场景用例4,注册回调函数》订阅ACC传感器》休眠进程的传感器》恢复进程的传感器》取消订阅ACC传感器》取消注册回调函数 + SEN_HILOGI("SensorPowerTest_004 in"); + SensorUser user; + user.callback = SensorDataCallbackImpl; + ClientInfoCallback callback = ClientInfoCallbackImpl; + + int32_t ret = RegisterClientInfoCallback(callback); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = SubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = SetBatch(sensorId, &user, 100000000, 100000000); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = ActivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + ret = SuspendSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + + ret = ResumeSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + ret = DeactivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = UnsubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = UnregisterClientInfoCallback(callback); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, SensorPowerTest_005, TestSize.Level1) +{ + // 场景用例5,注册回调函数》订阅ACC传感器》休眠进程的传感器》恢复进程的传感器》取消注册回调函数》取消订阅ACC传感器 + SEN_HILOGI("SensorPowerTest_005 in"); + SensorUser user; + user.callback = SensorDataCallbackImpl; + ClientInfoCallback callback = ClientInfoCallbackImpl; + + int32_t ret = RegisterClientInfoCallback(callback); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = SubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = SetBatch(sensorId, &user, 100000000, 100000000); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = ActivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + ret = SuspendSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + + ret = ResumeSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + ret = DeactivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = UnregisterClientInfoCallback(callback); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = UnsubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); +} + +HWTEST_F(SensorPowerTest, SensorPowerTest_006, TestSize.Level1) +{ + // 场景用例6,注册回调函数1》注册回调函数2》订阅ACC传感器》休眠进程的传感器》恢复进程的传感器》取消订阅ACC传感器》取消注册回调函数1》取消注册回调函数2 + SEN_HILOGI("SensorPowerTest_006 in"); + SensorUser user; + user.callback = SensorDataCallbackImpl; + ClientInfoCallback callback = ClientInfoCallbackImpl; + ClientInfoCallback callback2 = ClientInfoCallbackImpl2; + + int32_t ret = RegisterClientInfoCallback(callback); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = RegisterClientInfoCallback(callback2); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = SubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = SetBatch(sensorId, &user, 100000000, 100000000); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = ActivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + ret = SuspendSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + + ret = ResumeSensors(process_pid); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + ret = DeactivateSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = UnsubscribeSensor(sensorId, &user); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + + ret = UnregisterClientInfoCallback(callback); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); + ret = UnregisterClientInfoCallback(callback2); + ASSERT_EQ(ret, OHOS::Sensors::SUCCESS); +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/plugin/BUILD.gn b/interfaces/plugin/BUILD.gn index d84452593cb927399ef09017acafd3ecc0080477..4c3db194fd74cad3b67d20f73a53347c94258705 100644 --- a/interfaces/plugin/BUILD.gn +++ b/interfaces/plugin/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -21,7 +21,7 @@ ohos_shared_library("libsensor") { "//third_party/libuv/include", "//commonlibrary/c_utils/base/include", "./include", - "//base/sensors/sensor/utils/include", + "./../../utils/common/include", "//foundation/arkui/napi/interfaces/inner_api/napi", ] defines = [ diff --git a/services/sensor/BUILD.gn b/services/sensor/BUILD.gn index de3715a3eaa3c506362f44685db6e83781cc344b..24c33870785ef7ca713234ff6757bcf3abc1baf0 100644 --- a/services/sensor/BUILD.gn +++ b/services/sensor/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -29,6 +29,8 @@ ohos_shared_library("libsensor_service") { "src/sensor_manager.cpp", "src/sensor_service.cpp", "src/sensor_service_stub.cpp", + "src/stream_server.cpp", + "src/sensor_suspend_policy.cpp", ] include_dirs = [ @@ -37,7 +39,8 @@ ohos_shared_library("libsensor_service") { "$SUBSYSTEM_DIR/sensor/interfaces/native/include", "//commonlibrary/c_utils/base/include", "//utils/system/safwk/native/include", - "$SUBSYSTEM_DIR/sensor/utils/include", + "$SUBSYSTEM_DIR/sensor/utils/common/include", + "$SUBSYSTEM_DIR/sensor/utils/ipc/include", "$SUBSYSTEM_DIR/sensor/services/sensor/include", "//drivers/peripheral/sensor/interfaces/include", "hdi_connection/interface/include", @@ -45,7 +48,10 @@ ohos_shared_library("libsensor_service") { "hdi_connection/hardware/include", ] - deps = [ "$SUBSYSTEM_DIR/sensor/utils:libsensor_utils" ] + deps = [ + "$SUBSYSTEM_DIR/sensor/utils/common:libsensor_utils", + "$SUBSYSTEM_DIR/sensor/utils/ipc:libsensor_ipc", + ] external_deps = [ "access_token:libaccesstoken_sdk", diff --git a/services/sensor/include/client_info.h b/services/sensor/include/client_info.h index 558e8c226b008d3efd69a9ea73ee7cefb2b607a5..dd4167be201e9221dd6ec3934d83df498decdd82 100644 --- a/services/sensor/include/client_info.h +++ b/services/sensor/include/client_info.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "refbase.h" @@ -75,6 +76,11 @@ public: int32_t GetUidByPid(int32_t pid); AccessTokenID GetTokenIdByPid(int32_t pid); + int32_t AddClientInfoCallbackPid(int32_t pid); + int32_t DelClientInfoCallbackPid(int32_t pid); + std::unordered_set GetClientInfoCallbackPidSet(); + bool IsUnregisterClientDeathRecipient(int32_t pid); + private: DISALLOW_COPY_AND_MOVE(ClientInfo); std::vector GetCmdList(int32_t sensorId, int32_t uid); @@ -92,6 +98,9 @@ private: std::map, int32_t> clientPidMap_; std::unordered_map>> cmdMap_; std::unordered_map> dumpQueue_; + + std::mutex clientInfoCallbackMutex_; + std::unordered_set clientInfoCallbackPidSet_; }; } // namespace Sensors } // namespace OHOS diff --git a/services/sensor/include/sensor_service.h b/services/sensor/include/sensor_service.h index e77d05ed44b557bd1c9f24b2578120cdbcec7020..ccd7a65b71a883da1b91d0ed9bf57e1f1a55ba63 100644 --- a/services/sensor/include/sensor_service.h +++ b/services/sensor/include/sensor_service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -29,6 +29,8 @@ #include "sensor_hdi_connection.h" #include "sensor_manager.h" #include "sensor_service_stub.h" +#include "sensor_suspend_policy.h" +#include "stream_server.h" namespace OHOS { namespace Sensors { @@ -37,7 +39,7 @@ enum class SensorServiceState { STATE_RUNNING, }; -class SensorService : public SystemAbility, public SensorServiceStub { +class SensorService : public SystemAbility, public StreamServer, public SensorServiceStub { DECLARE_SYSTEM_ABILITY(SensorService) public: @@ -54,6 +56,13 @@ public: const sptr &sensorClient) override; ErrCode DestroySensorChannel(sptr sensorClient) override; void ProcessDeathObserver(const wptr &object); + ErrCode SuspendSensors(int32_t pid) override; + ErrCode ResumeSensors(int32_t pid) override; + ErrCode GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) override; + ErrCode CreateSocketChannel(int32_t &clientFd, const sptr &sensorClient) override; + ErrCode DestroySocketChannel(const sptr &sensorClient) override; + ErrCode EnableClientInfoCallback() override; + ErrCode DisableClientInfoCallback() override; private: DISALLOW_COPY_AND_MOVE(SensorService); @@ -76,12 +85,16 @@ private: ClientInfo &clientInfo_ = ClientInfo::GetInstance(); SensorManager &sensorManager_ = SensorManager::GetInstance(); FlushInfoRecord &flushInfo_ = FlushInfoRecord::GetInstance(); + SensorSuspendPolicy &suspendPolicy_ = SensorSuspendPolicy::GetInstance(); sptr sensorDataProcesser_ = nullptr; sptr reportDataCallback_ = nullptr; std::mutex uidLock_; // death recipient of sensor client sptr clientDeathObserver_ = nullptr; ErrCode SaveSubscriber(int32_t sensorId, int64_t samplingPeriodNs, int64_t maxReportDelayNs); + + std::atomic_bool isReportClientInfo_ = false; + void ReportClientInfo(int32_t sensorId, bool isActive, int32_t pid); }; } // namespace Sensors } // namespace OHOS diff --git a/services/sensor/include/sensor_service_stub.h b/services/sensor/include/sensor_service_stub.h index 9259e793f11101593e9d19465052a4a08266169e..6e79f402554b3bb75f7a8a6053e557b0ceec5ac4 100644 --- a/services/sensor/include/sensor_service_stub.h +++ b/services/sensor/include/sensor_service_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -39,6 +39,13 @@ private: ErrCode GetAllSensorsInner(MessageParcel &data, MessageParcel &reply); ErrCode CreateDataChannelInner(MessageParcel &data, MessageParcel &reply); ErrCode DestroyDataChannelInner(MessageParcel &data, MessageParcel &reply); + ErrCode SuspendSensorsInner(MessageParcel &data, MessageParcel &reply); + ErrCode ResumeSensorsInner(MessageParcel &data, MessageParcel &reply); + ErrCode GetSubscribeInfoListInner(MessageParcel &data, MessageParcel &reply); + ErrCode CreateSocketChannelInner(MessageParcel &data, MessageParcel &reply); + ErrCode DestroySocketChannelInner(MessageParcel &data, MessageParcel &reply); + ErrCode EnableClientInfoCallbackInner(MessageParcel &data, MessageParcel &reply); + ErrCode DisableClientInfoCallbackInner(MessageParcel &data, MessageParcel &reply); std::unordered_map baseFuncs_; }; } // namespace Sensors diff --git a/services/sensor/include/sensor_suspend_policy.h b/services/sensor/include/sensor_suspend_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..35769bc809901a46e66f27d18935468f921567a7 --- /dev/null +++ b/services/sensor/include/sensor_suspend_policy.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 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 SENSOR_SUSPEND_POLICY_H +#define SENSOR_SUSPEND_POLICY_H + +#include +#include +#include + +#include "nocopyable.h" + +#include "client_info.h" +#include "sensor_agent_type.h" +#include "sensor_hdi_connection.h" +#include "sensor_manager.h" +#include "sensors_errors.h" +#include "stream_session.h" +#include "subscribe_info.h" + +namespace OHOS { +namespace Sensors { +class SensorSuspendPolicy : public Singleton{ +public: + ErrCode DoSuspend(int32_t pid); + ErrCode DoResume(int32_t pid); + ErrCode GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList); + void ReportClientInfo(SubscribeSensorInfo subscribeSensorInfo, const std::vector &sessionList); + +private: + bool CheckFreezingSensor(int32_t sensorId); + bool DisableSensorList(std::unordered_map &SensorInfoMap, + std::vector &sensorIdList, int32_t pid); + ErrCode DisableSensor(std::unordered_map &SensorInfoMap, + int32_t sensorId, int32_t pid); + ErrCode EnableSensor(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, int64_t maxReportDelayNs); + ErrCode RestoreSensorInfo(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, int64_t maxReportDelayNs); + SensorHdiConnection &sensorHdiConnection_ = SensorHdiConnection::GetInstance(); + ClientInfo &clientInfo_ = ClientInfo::GetInstance(); + SensorManager &sensorManager_ = SensorManager::GetInstance(); + std::mutex pidSensorInfoMutex_; + std::unordered_map> pidSensorInfoMap_; +}; +} // namespace Sensors +} // namespace OHOS +#endif // SENSOR_SUSPEND_POLICY_H \ No newline at end of file diff --git a/services/sensor/include/stream_server.h b/services/sensor/include/stream_server.h new file mode 100644 index 0000000000000000000000000000000000000000..32d3c590cf8fe438778dbe5f2fe8d0bb1034e6af --- /dev/null +++ b/services/sensor/include/stream_server.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 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 STREAM_SERVER_H +#define STREAM_SERVER_H + +#include +#include + +#include "nocopyable.h" +#include "refbase.h" + +#include "stream_session.h" +#include "stream_socket.h" + +namespace OHOS { +namespace Sensors { +class StreamServer : public RefBase, public StreamSocket { +public: + StreamServer() = default; + virtual ~StreamServer(); + bool SendMsg(int32_t fd, NetPacket& pkt); + void Multicast(const std::vector& fdList, NetPacket& pkt); + int32_t GetClientFd(int32_t pid); + int32_t GetClientPid(int32_t fd); + SessionPtr GetSession(int32_t fd); + SessionPtr GetSessionByPid(int32_t pid); + int32_t AddSocketPairInfo(int32_t uid, int32_t pid, int32_t tokenType, int32_t &serverFd, int32_t &clientFd); + DISALLOW_COPY_AND_MOVE(StreamServer); + +protected: + bool AddSession(SessionPtr ses); + void DelSession(int32_t pid); + std::mutex idxPidMutex_; + std::map idxPidMap_; + std::mutex sessionMutex_; + std::map sessionsMap_; +}; +} // namespace Sensors +} // namespace OHOS +#endif // STREAM_SERVER_H diff --git a/services/sensor/src/client_info.cpp b/services/sensor/src/client_info.cpp index 8396fd43c682e2a2a0a2349c7658d5e57be2cd5a..18037d309f3c769859c829741247b8702d472810 100644 --- a/services/sensor/src/client_info.cpp +++ b/services/sensor/src/client_info.cpp @@ -684,5 +684,50 @@ void ClientInfo::ClearDataQueue(int32_t sensorId) dumpQueue_.erase(it); } } + +int32_t ClientInfo::AddClientInfoCallbackPid(int32_t pid) +{ + std::lock_guard clientInfoCallbackLock(clientInfoCallbackMutex_); + auto pairRet = clientInfoCallbackPidSet_.insert(pid); + if (!pairRet.second) { + SEN_HILOGE("ClientInfoCallbackPidSet_ insert pid fail"); + return ERROR; + } + return ERR_OK; +} + +int32_t ClientInfo::DelClientInfoCallbackPid(int32_t pid) +{ + std::lock_guard clientInfoCallbackLock(clientInfoCallbackMutex_); + auto it = clientInfoCallbackPidSet_.find(pid); + if (it == clientInfoCallbackPidSet_.end()) { + SEN_HILOGE("ClientInfoCallbackPidSet_ not find pid"); + return ERROR; + } + clientInfoCallbackPidSet_.erase(it); + return ERR_OK; +} + +std::unordered_set ClientInfo::GetClientInfoCallbackPidSet() +{ + return clientInfoCallbackPidSet_; +} + +bool ClientInfo::IsUnregisterClientDeathRecipient(int32_t pid) +{ + std::lock_guard channelLock(channelMutex_); + auto channelIt = channelMap_.find(pid); + if (channelIt != channelMap_.end()) { + SEN_HILOGD("pid exist in channelMap"); + return false; + } + std::lock_guard clientInfoCallbackLock(clientInfoCallbackMutex_); + auto pidIt = clientInfoCallbackPidSet_.find(pid); + if (pidIt != clientInfoCallbackPidSet_.end()) { + SEN_HILOGD("pid exist in clientInfoCallbackPidSet"); + return false; + } + return true; +} } // namespace Sensors } // namespace OHOS diff --git a/services/sensor/src/sensor_service.cpp b/services/sensor/src/sensor_service.cpp index 2c7563b78a2aa52bbef294032e093f361af6762d..e98885d14aa79f39f60ff10dfbb91bcacbd19f2e 100644 --- a/services/sensor/src/sensor_service.cpp +++ b/services/sensor/src/sensor_service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -20,11 +20,13 @@ #include #include +#include "accesstoken_kit.h" #include "hisysevent.h" #include "iservice_registry.h" #include "permission_util.h" #include "securec.h" #include "sensor.h" +#include "sensor_agent_type.h" #include "sensor_dump.h" #include "sensors_errors.h" #include "system_ability_definition.h" @@ -32,7 +34,7 @@ namespace OHOS { namespace Sensors { using namespace OHOS::HiviewDFX; - +using namespace Security::AccessToken; namespace { constexpr HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "SensorService" }; constexpr int32_t INVALID_SENSOR_ID = -1; @@ -233,6 +235,9 @@ ErrCode SensorService::EnableSensor(int32_t sensorId, int64_t samplingPeriodNs, SEN_HILOGE("ret : %{public}d", ret); } ReportOnChangeData(sensorId); + if (isReportClientInfo_) { + ReportClientInfo(sensorId, true, pid); + } return ERR_OK; } auto ret = SaveSubscriber(sensorId, samplingPeriodNs, maxReportDelayNs); @@ -248,6 +253,9 @@ ErrCode SensorService::EnableSensor(int32_t sensorId, int64_t samplingPeriodNs, return ENABLE_SENSOR_ERR; } ReportSensorSysEvent(sensorId, true, pid); + if (isReportClientInfo_) { + ReportClientInfo(sensorId, true, pid); + } return ret; } @@ -266,6 +274,9 @@ ErrCode SensorService::DisableSensor(int32_t sensorId, int32_t pid) std::lock_guard serviceLock(serviceLock_); if (sensorManager_.IsOtherClientUsingSensor(sensorId, pid)) { SEN_HILOGW("other client is using this sensor now, cannot disable"); + if (isReportClientInfo_) { + ReportClientInfo(sensorId, false, pid); + } return ERR_OK; } if (sensorHdiConnection_.DisableSensor(sensorId) != ERR_OK) { @@ -275,6 +286,9 @@ ErrCode SensorService::DisableSensor(int32_t sensorId, int32_t pid) int32_t uid = clientInfo_.GetUidByPid(pid); clientInfo_.DestroyCmd(uid); clientInfo_.ClearDataQueue(sensorId); + if (isReportClientInfo_) { + ReportClientInfo(sensorId, false, pid); + } return sensorManager_.AfterDisableSensor(sensorId); } @@ -357,6 +371,8 @@ void SensorService::ProcessDeathObserver(const wptr &object) SEN_HILOGE("disablesensor failed, ret:%{public}d", ret); } } + DelSession(pid); + clientInfo_.DelClientInfoCallbackPid(pid); clientInfo_.DestroySensorChannel(pid); clientInfo_.DestroyClientPid(client); clientInfo_.DestroyCmd(clientInfo_.GetUidByPid(pid)); @@ -375,6 +391,15 @@ void SensorService::RegisterClientDeathRecipient(sptr sensorClien void SensorService::UnregisterClientDeathRecipient(sptr sensorClient) { CALL_LOG_ENTER; + int32_t pid = clientInfo_.FindClientPid(sensorClient); + if (pid == INVALID_PID) { + SEN_HILOGE("Pid is invalid"); + return; + } + if (!clientInfo_.IsUnregisterClientDeathRecipient(pid)) { + SEN_HILOGD("Client call other service, not need unregister client death recipient"); + return; + } sptr client = iface_cast(sensorClient); clientDeathObserver_ = new (std::nothrow) DeathRecipientTemplate(*const_cast(this)); CHKPV(clientDeathObserver_); @@ -404,5 +429,113 @@ int32_t SensorService::Dump(int32_t fd, const std::vector &args) sensorDump.ParseCommand(fd, argList, sensors_, clientInfo_); return ERR_OK; } + +ErrCode SensorService::SuspendSensors(int32_t pid) +{ + CALL_LOG_ENTER; + if (pid < 0) { + SEN_HILOGE("Pid is invalid"); + return CLIENT_PID_INVALID_ERR; + } + int32_t ret = suspendPolicy_.DoSuspend(pid); + if (ret != ERR_OK) { + SEN_HILOGE("Suspend pid sensors failed, ret:%{public}d", ret); + return ERROR; + } + return ERR_OK; +} + +ErrCode SensorService::ResumeSensors(int32_t pid) +{ + CALL_LOG_ENTER; + if (pid < 0) { + SEN_HILOGE("Pid is invalid"); + return CLIENT_PID_INVALID_ERR; + } + int32_t ret = suspendPolicy_.DoResume(pid); + if (ret != ERR_OK) { + SEN_HILOGE("Resume pid sensors failed, ret:%{public}d", ret); + return ERROR; + } + return ERR_OK; +} + +ErrCode SensorService::GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) +{ + CALL_LOG_ENTER; + if (pid < 0) { + SEN_HILOGE("Pid is invalid"); + return CLIENT_PID_INVALID_ERR; + } + int32_t ret = suspendPolicy_.GetSubscribeInfoList(pid, subscribeInfoList); + if (ret != ERR_OK) { + SEN_HILOGE("Get subscribe info list failed, ret:%{public}d", ret); + return ERROR; + } + return ERR_OK; +} + +ErrCode SensorService::CreateSocketChannel(int32_t &clientFd, const sptr &sensorClient) +{ + CALL_LOG_ENTER; + int32_t uid = GetCallingUid(); + int32_t pid = GetCallingPid(); + int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(GetCallingTokenID()); + int32_t serverFd = -1; + clientFd = -1; + int32_t ret = AddSocketPairInfo(uid, pid, tokenType, serverFd, std::ref(clientFd)); + if (ret != ERR_OK) { + SEN_HILOGE("Add socket pair info failed, ret:%{public}d", ret); + return ERROR; + } + RegisterClientDeathRecipient(sensorClient, pid); + return ERR_OK; +} + +ErrCode SensorService::DestroySocketChannel(const sptr &sensorClient) +{ + CALL_LOG_ENTER; + int32_t pid = GetCallingPid(); + DelSession(pid); + UnregisterClientDeathRecipient(sensorClient); + return ERR_OK; +} + +ErrCode SensorService::EnableClientInfoCallback() +{ + CALL_LOG_ENTER; + isReportClientInfo_ = true; + int32_t pid = GetCallingPid(); + return clientInfo_.AddClientInfoCallbackPid(pid); +} + +ErrCode SensorService::DisableClientInfoCallback() +{ + CALL_LOG_ENTER; + isReportClientInfo_ = false; + int32_t pid = GetCallingPid(); + return clientInfo_.DelClientInfoCallbackPid(pid); +} + +void SensorService::ReportClientInfo(int32_t sensorId, bool isActive, int32_t pid) +{ + CALL_LOG_ENTER; + std::vector sessionList; + auto pidSet = clientInfo_.GetClientInfoCallbackPidSet(); + for (auto pid : pidSet) { + auto sess = GetSessionByPid(pid); + if (sess != nullptr) { + sessionList.push_back(sess); + } + } + SensorBasicInfo sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, pid); + SubscribeSensorInfo subscribeSensorInfo; + subscribeSensorInfo.pid = pid; + subscribeSensorInfo.sensorId = sensorId; + subscribeSensorInfo.isActive = isActive; + subscribeSensorInfo.samplingPeriodNs = sensorInfo.GetSamplingPeriodNs(); + subscribeSensorInfo.maxReportDelayNs = sensorInfo.GetMaxReportDelayNs(); + suspendPolicy_.ReportClientInfo(subscribeSensorInfo, sessionList); +} } // namespace Sensors } // namespace OHOS diff --git a/services/sensor/src/sensor_service_stub.cpp b/services/sensor/src/sensor_service_stub.cpp index 94c2a8af6f5a92ba5b2c7021b74a0be2ce2f8b7d..744ed910b047051fa7ddd19db1e5f6ca1c8ef780 100755 --- a/services/sensor/src/sensor_service_stub.cpp +++ b/services/sensor/src/sensor_service_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -30,7 +30,6 @@ namespace OHOS { namespace Sensors { using namespace OHOS::HiviewDFX; - namespace { constexpr HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "SensorServiceStub" }; } // namespace @@ -43,6 +42,13 @@ SensorServiceStub::SensorServiceStub() baseFuncs_[GET_SENSOR_LIST] = &SensorServiceStub::GetAllSensorsInner; baseFuncs_[TRANSFER_DATA_CHANNEL] = &SensorServiceStub::CreateDataChannelInner; baseFuncs_[DESTROY_SENSOR_CHANNEL] = &SensorServiceStub::DestroyDataChannelInner; + baseFuncs_[SUSPEND_SENSORS] = &SensorServiceStub::SuspendSensorsInner; + baseFuncs_[RESUME_SENSORS] = &SensorServiceStub::ResumeSensorsInner; + baseFuncs_[GET_SUBSCRIBE_INFO_LIST] = &SensorServiceStub::GetSubscribeInfoListInner; + baseFuncs_[CREATE_SOCKET_CHANNEL] = &SensorServiceStub::CreateSocketChannelInner; + baseFuncs_[DESTROY_SOCKET_CHANNEL] = &SensorServiceStub::DestroySocketChannelInner; + baseFuncs_[ENABLE_CLIENT_INFO_CALLBACK] = &SensorServiceStub::EnableClientInfoCallbackInner; + baseFuncs_[DISABLE_CLIENT_INFO_CALLBACK] = &SensorServiceStub::DisableClientInfoCallbackInner; } SensorServiceStub::~SensorServiceStub() @@ -153,5 +159,116 @@ ErrCode SensorServiceStub::DestroyDataChannelInner(MessageParcel &data, MessageP CHKPR(sensorClient, OBJECT_NULL); return DestroySensorChannel(sensorClient); } + +ErrCode SensorServiceStub::SuspendSensorsInner(MessageParcel &data, MessageParcel &reply) +{ + PermissionUtil &permissionUtil = PermissionUtil::GetInstance(); + if(!permissionUtil.IsNativeToken(GetCallingTokenID())) { + SEN_HILOGE("TokenType is not TOKEN_NATIVE"); + return PERMISSION_DENIED; + } + (void)reply; + int32_t pid; + if (!data.ReadInt32(pid)) { + SEN_HILOGE("Parcel read failed"); + return ERROR; + } + return SuspendSensors(pid); +} + +ErrCode SensorServiceStub::ResumeSensorsInner(MessageParcel &data, MessageParcel &reply) +{ + PermissionUtil &permissionUtil = PermissionUtil::GetInstance(); + if(!permissionUtil.IsNativeToken(GetCallingTokenID())) { + SEN_HILOGE("TokenType is not TOKEN_NATIVE"); + return PERMISSION_DENIED; + } + (void)reply; + int32_t pid; + if (!data.ReadInt32(pid)) { + SEN_HILOGE("Parcel read failed"); + return ERROR; + } + return ResumeSensors(pid); +} + +ErrCode SensorServiceStub::GetSubscribeInfoListInner(MessageParcel &data, MessageParcel &reply) +{ + PermissionUtil &permissionUtil = PermissionUtil::GetInstance(); + if(!permissionUtil.IsNativeToken(GetCallingTokenID())) { + SEN_HILOGE("TokenType is not TOKEN_NATIVE"); + return PERMISSION_DENIED; + } + int32_t pid; + if (!data.ReadInt32(pid)) { + SEN_HILOGE("Parcel read failed"); + return ERROR; + } + std::vector subscribeInfoList; + GetSubscribeInfoList(pid, subscribeInfoList); + int32_t subscribeInfoCount = int32_t { subscribeInfoList.size() }; + reply.WriteInt32(subscribeInfoCount); + for (int32_t i = 0; i < subscribeInfoCount; i++) { + if (!subscribeInfoList[i].Marshalling(reply)) { + SEN_HILOGE("SubscribeInfo %{public}d failed", i); + return ERROR; + } + } + return NO_ERROR; +} + +ErrCode SensorServiceStub::CreateSocketChannelInner(MessageParcel &data, MessageParcel &reply) +{ + sptr sensorClient = data.ReadRemoteObject(); + CHKPR(sensorClient, OBJECT_NULL); + int32_t clientFd = -1; + int32_t ret = CreateSocketChannel(clientFd, sensorClient); + if (ret != ERR_OK) { + SEN_HILOGE("Create socket channel failed"); + if (clientFd >= 0) { + close(clientFd); + } + return ret; + } + if (!reply.WriteFileDescriptor(clientFd)) { + SEN_HILOGE("Write file descriptor failed"); + close(clientFd); + return ERROR; + } + close(clientFd); + return ERR_OK; +} + +ErrCode SensorServiceStub::DestroySocketChannelInner(MessageParcel &data, MessageParcel &reply) +{ + sptr sensorClient = data.ReadRemoteObject(); + CHKPR(sensorClient, OBJECT_NULL); + int32_t ret = DestroySocketChannel(sensorClient); + if (ret != ERR_OK) { + SEN_HILOGE("DestroySocketChannel failed"); + return ret; + } + return ERR_OK; +} + +ErrCode SensorServiceStub::EnableClientInfoCallbackInner(MessageParcel &data, MessageParcel &reply) +{ + PermissionUtil &permissionUtil = PermissionUtil::GetInstance(); + if(!permissionUtil.IsNativeToken(GetCallingTokenID())) { + SEN_HILOGE("TokenType is not TOKEN_NATIVE"); + return PERMISSION_DENIED; + } + return EnableClientInfoCallback(); +} + +ErrCode SensorServiceStub::DisableClientInfoCallbackInner(MessageParcel &data, MessageParcel &reply) +{ + PermissionUtil &permissionUtil = PermissionUtil::GetInstance(); + if(!permissionUtil.IsNativeToken(GetCallingTokenID())) { + SEN_HILOGE("TokenType is not TOKEN_NATIVE"); + return PERMISSION_DENIED; + } + return DisableClientInfoCallback(); +} } // namespace Sensors } // namespace OHOS diff --git a/services/sensor/src/sensor_suspend_policy.cpp b/services/sensor/src/sensor_suspend_policy.cpp index 82ac98324343a998174c455212e19b7ea2382bbf..a86c25ade80c0ac7eeb5ad6be6f1659df2a18699 100644 --- a/services/sensor/src/sensor_suspend_policy.cpp +++ b/services/sensor/src/sensor_suspend_policy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -17,8 +17,6 @@ #include "sensor.h" #include "sensor_agent_type.h" -#include "sensor_service.h" -#include "system_ability_definition.h" namespace OHOS { namespace Sensors { @@ -28,73 +26,117 @@ namespace { constexpr HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "SensorSuspendPolicy" }; constexpr int32_t INVALID_SENSOR_ID = -1; constexpr int64_t MAX_EVENT_COUNT = 1000; -constexpr int64_t DEFAULT_SAMPLING_RATE = 200000000; -constexpr int64_t DEFAULT_REPORT_DELAY = 0; } // namespace -SensorSuspendPolicy::~SensorSuspendPolicy() -{} - bool SensorSuspendPolicy::CheckFreezingSensor(int32_t sensorId) { return ((sensorId == SENSOR_TYPE_ID_PEDOMETER_DETECTION) || (sensorId == SENSOR_TYPE_ID_PEDOMETER)); } -ErrCode SensorSuspendPolicy::DisableSensor(int32_t sensorId, int32_t pid) +ErrCode SensorSuspendPolicy::DoSuspend(int32_t pid) { CALL_LOG_ENTER; - if (sensorId == INVALID_SENSOR_ID) { - SEN_HILOGE("sensorId is invalid"); - return ERR_NO_INIT; + std::vector sensorIdList = clientInfo_.GetSensorIdByPid(pid); + std::lock_guard pidSensorInfoLock(pidSensorInfoMutex_); + auto pidSensorInfoIt = pidSensorInfoMap_.find(pid); + if (pidSensorInfoIt != pidSensorInfoMap_.end()) { + if (sensorIdList.empty()) { + SEN_HILOGD("Pid already suspend, all sensors suspend success, not need suspend again"); + return ERR_OK; + } else { + SEN_HILOGD("Pid already suspend, some sensors suspend failed, suspend these sensors again"); + std::unordered_map SensorInfoMap = pidSensorInfoIt->second; + if (!DisableSensorList(SensorInfoMap, sensorIdList, pid)) { + SEN_HILOGE("Some sensor disable failed"); + return DISABLE_SENSOR_ERR; + } + return ERR_OK; + } } - if (sensorManager_.IsOtherClientUsingSensor(sensorId, pid)) { - SEN_HILOGW("other client is using this sensor now, cannot disable"); - return ERR_OK; + if (sensorIdList.empty()) { + SEN_HILOGE("Pid sensorId list is empty"); + return ERROR; } - if (interface_.DisableSensor(sensorId) != ERR_OK) { - SEN_HILOGE("DisableSensor is failed"); + std::unordered_map SensorInfoMap; + bool suspendAllSensors = DisableSensorList(SensorInfoMap, sensorIdList, pid); + pidSensorInfoMap_.insert(std::make_pair(pid, SensorInfoMap)); + if (!suspendAllSensors) { + SEN_HILOGE("Some sensor disable failed"); return DISABLE_SENSOR_ERR; } - return sensorManager_.AfterDisableSensor(sensorId); + return ERR_OK; } -void SensorSuspendPolicy::DoSuspend(const std::shared_ptr &info) +bool SensorSuspendPolicy::DisableSensorList(std::unordered_map &SensorInfoMap, + std::vector &sensorIdList, int32_t pid) { CALL_LOG_ENTER; - std::lock_guard suspendLock(suspendMutex_); - auto &list = info->GetAppIPCInfoList(); - for (const auto &appInfo : list) { - std::vector sensorIdList = clientInfo_.GetSensorIdByPid(appInfo.pid); - if (sensorIdList.empty()) { + bool suspendAllSensors = true; + for (auto &sensorId : sensorIdList) { + if (CheckFreezingSensor(sensorId)) { continue; } - pidSensorIdMap_.emplace(std::make_pair(appInfo.pid, sensorIdList)); - for (auto &sensorId : sensorIdList) { - if (CheckFreezingSensor(sensorId)) { - continue; - } - auto sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, appInfo.pid); - sensorIdInfoMap_.emplace(std::make_pair(sensorId, sensorInfo)); - DisableSensor(sensorId, appInfo.pid); + auto ret = DisableSensor(SensorInfoMap, sensorId, pid); + if (ret != ERR_OK) { + SEN_HILOGE("Disable Sensor is failed. sensorId:%{public}d, ret:%{public}d", sensorId, ret); + suspendAllSensors = false; } } + return suspendAllSensors; } -ErrCode SensorSuspendPolicy::SaveSubscriber(int32_t sensorId, int64_t samplingPeriodNs, - int64_t maxReportDelayNs, int32_t pid) +ErrCode SensorSuspendPolicy::DisableSensor(std::unordered_map &SensorInfoMap, + int32_t sensorId, int32_t pid) { - auto ret = sensorManager_.SaveSubscriber(sensorId, pid, samplingPeriodNs, maxReportDelayNs); - if (ret != ERR_OK) { - SEN_HILOGE("SaveSubscriber is failed"); - return ret; + CALL_LOG_ENTER; + if (sensorId == INVALID_SENSOR_ID) { + SEN_HILOGE("SensorId is invalid"); + return ERR_NO_INIT; } - sensorManager_.StartDataReportThread(); - if (!sensorManager_.SetBestSensorParams(sensorId, samplingPeriodNs, maxReportDelayNs)) { - SEN_HILOGE("SetBestSensorParams is failed"); - clientInfo_.RemoveSubscriber(sensorId, pid); + auto sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, pid); + if (sensorManager_.IsOtherClientUsingSensor(sensorId, pid)) { + SEN_HILOGW("Other client is using this sensor now, cannot disable"); + SensorInfoMap.insert(std::make_pair(sensorId, sensorInfo)); + return ERR_OK; + } + if (sensorHdiConnection_.DisableSensor(sensorId) != ERR_OK) { + SEN_HILOGE("DisableSensor is failed"); + return DISABLE_SENSOR_ERR; + } + SensorInfoMap.insert(std::make_pair(sensorId, sensorInfo)); + return sensorManager_.AfterDisableSensor(sensorId); +} + +ErrCode SensorSuspendPolicy::DoResume(int32_t pid) +{ + CALL_LOG_ENTER; + std::lock_guard pidSensorInfoLock(pidSensorInfoMutex_); + auto pidSensorInfoIt = pidSensorInfoMap_.find(pid); + if (pidSensorInfoIt == pidSensorInfoMap_.end()) { + SEN_HILOGE("Pid not have suspend sensors"); + return ERROR; + } + bool resumeAllSensors = true; + std::unordered_map SensorInfoMap = pidSensorInfoIt->second; + for (auto sensorIt = SensorInfoMap.begin(); sensorIt != SensorInfoMap.end();) { + int32_t sensorId = sensorIt->first; + int64_t samplingPeriodNs = sensorIt->second.GetSamplingPeriodNs(); + int64_t maxReportDelayNs = sensorIt->second.GetMaxReportDelayNs(); + auto ret = EnableSensor(sensorId, pid, samplingPeriodNs, maxReportDelayNs); + if (ret != ERR_OK) { + SEN_HILOGE("Enable Sensor is failed. sensorId:%{public}d, ret:%{public}d", sensorId, ret); + resumeAllSensors = false; + ++sensorIt; + } else { + sensorIt = SensorInfoMap.erase(sensorIt); + } + } + if (!resumeAllSensors) { + SEN_HILOGE("Some sensor enable failed"); return ENABLE_SENSOR_ERR; } - return ret; + pidSensorInfoMap_.erase(pidSensorInfoIt); + return ERR_OK; } ErrCode SensorSuspendPolicy::EnableSensor(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, @@ -103,76 +145,99 @@ ErrCode SensorSuspendPolicy::EnableSensor(int32_t sensorId, int32_t pid, int64_t CALL_LOG_ENTER; if ((sensorId == INVALID_SENSOR_ID) || (samplingPeriodNs == 0) || ((samplingPeriodNs != 0L) && (maxReportDelayNs / samplingPeriodNs > MAX_EVENT_COUNT))) { - SEN_HILOGE("sensorId is 0 or maxReportDelayNs exceed the maximum value"); + SEN_HILOGE("SensorId is 0 or maxReportDelayNs exceed the maximum value"); return ERR_NO_INIT; } - if (clientInfo_.GetSensorState(sensorId) == SENSOR_ENABLED) { - SEN_HILOGW("sensor has been enabled already"); - auto ret = SaveSubscriber(sensorId, samplingPeriodNs, maxReportDelayNs, pid); + if (clientInfo_.GetSensorState(sensorId)) { + SEN_HILOGD("Sensor has been enabled already, sensorId: %{public}d", sensorId); + auto ret = RestoreSensorInfo(sensorId, pid, samplingPeriodNs, maxReportDelayNs); if (ret != ERR_OK) { - SEN_HILOGE("SaveSubscriber is failed"); + SEN_HILOGE("RestoreSensorInfo is failed, ret: %{public}d", ret); return ret; } - uint32_t flag = sensorManager_.GetSensorFlag(sensorId); - ret = flushInfo_.FlushProcess(sensorId, flag, pid, true); - if (ret != ERR_OK) { - SEN_HILOGW("ret:%{public}d", ret); - } return ERR_OK; } - auto ret = SaveSubscriber(sensorId, samplingPeriodNs, maxReportDelayNs, pid); + auto ret = RestoreSensorInfo(sensorId, pid, samplingPeriodNs, maxReportDelayNs); if (ret != ERR_OK) { - SEN_HILOGE("SaveSubscriber is failed"); + SEN_HILOGE("RestoreSensorInfo is failed, ret: %{public}d", ret); return ret; } - ret = interface_.EnableSensor(sensorId); + ret = sensorHdiConnection_.EnableSensor(sensorId); if (ret != ERR_OK) { - SEN_HILOGE("EnableSensor is failed"); + SEN_HILOGE("EnableSensor is failed, ret: %{public}d", ret); + clientInfo_.RemoveSubscriber(sensorId, pid); + return ENABLE_SENSOR_ERR; + } + return ERR_OK; +} + +ErrCode SensorSuspendPolicy::RestoreSensorInfo(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, + int64_t maxReportDelayNs) +{ + auto ret = sensorManager_.SaveSubscriber(sensorId, pid, samplingPeriodNs, maxReportDelayNs); + if (ret != ERR_OK) { + SEN_HILOGE("RestoreSensorInfo is failed, ret: %{public}d", ret); + return ret; + } + sensorManager_.StartDataReportThread(); + if (!sensorManager_.SetBestSensorParams(sensorId, samplingPeriodNs, maxReportDelayNs)) { + SEN_HILOGE("SetBestSensorParams is failed"); clientInfo_.RemoveSubscriber(sensorId, pid); return ENABLE_SENSOR_ERR; } return ret; } -std::vector SensorSuspendPolicy::GetSensorIdByPid(int32_t pid) +ErrCode SensorSuspendPolicy::GetSubscribeInfoList(int32_t pid, std::vector &subscribeInfoList) { - SEN_HILOGD("pid:%{public}d", pid); - auto it = pidSensorIdMap_.find(pid); - if (it != pidSensorIdMap_.end()) { - SEN_HILOGD("pid:%{public}d found", pid); - return it->second; - } - SEN_HILOGD("pid:%{public}d not found", pid); - return {}; + CALL_LOG_ENTER; + std::vector sensorIdList = clientInfo_.GetSensorIdByPid(pid); + for (auto &sensorId : sensorIdList) { + auto sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, pid); + SubscribeSensorInfo subscribeSensorInfo; + subscribeSensorInfo.pid = pid; + subscribeSensorInfo.sensorId = sensorId; + subscribeSensorInfo.isActive = true; + subscribeSensorInfo.samplingPeriodNs = sensorInfo.GetSamplingPeriodNs(); + subscribeSensorInfo.maxReportDelayNs = sensorInfo.GetMaxReportDelayNs(); + SubscribeInfo subscribeInfo(subscribeSensorInfo); + subscribeInfoList.push_back(subscribeInfo); + } + std::lock_guard pidSensorInfoLock(pidSensorInfoMutex_); + auto pidSensorInfoIt = pidSensorInfoMap_.find(pid); + if (pidSensorInfoIt != pidSensorInfoMap_.end()) { + std::unordered_map SensorInfoMap = pidSensorInfoIt->second; + for (auto &sensorInfo : SensorInfoMap) { + SubscribeSensorInfo subscribeSensorInfo; + subscribeSensorInfo.pid = pid; + subscribeSensorInfo.sensorId = sensorInfo.first; + subscribeSensorInfo.isActive = false; + subscribeSensorInfo.samplingPeriodNs = sensorInfo.second.GetSamplingPeriodNs(); + subscribeSensorInfo.maxReportDelayNs = sensorInfo.second.GetMaxReportDelayNs(); + SubscribeInfo subscribeInfo(subscribeSensorInfo); + subscribeInfoList.push_back(subscribeInfo); + } + } + return ERR_OK; } -void SensorSuspendPolicy::DoActive(const std::shared_ptr &info) +void SensorSuspendPolicy::ReportClientInfo(SubscribeSensorInfo subscribeSensorInfo, + const std::vector &sessionList) { CALL_LOG_ENTER; - int64_t samplePeriod = DEFAULT_SAMPLING_RATE; - int64_t maxReportDelay = DEFAULT_REPORT_DELAY; - std::vector sensorIdList; - std::lock_guard suspendLock(suspendMutex_); - auto &list = info->GetAppIPCInfoList(); - for (const auto &appInfo : list) { - sensorIdList = GetSensorIdByPid(appInfo.pid); - for (auto &sensorId : sensorIdList) { - if (CheckFreezingSensor(sensorId)) { - continue; - } - auto it = sensorIdInfoMap_.find(sensorId); - if (it != sensorIdInfoMap_.end()) { - samplePeriod = it->second.GetSamplingPeriodNs(); - maxReportDelay = it->second.GetMaxReportDelayNs(); - } - auto ret = EnableSensor(sensorId, appInfo.pid, samplePeriod, maxReportDelay); - if (ret != ERR_OK) { - SEN_HILOGE("sensorId:%{public}u,pid:%{public}d,ret:%{public}d", sensorId, appInfo.pid, ret); - } + NetPacket pkt(MessageId::CLIENT_INFO); + pkt << subscribeSensorInfo.pid << subscribeSensorInfo.sensorId << subscribeSensorInfo.isActive << + subscribeSensorInfo.samplingPeriodNs << subscribeSensorInfo.maxReportDelayNs; + if (pkt.ChkRWError()) { + SEN_HILOGE("Packet write data failed"); + return; + } + for (auto sess : sessionList) { + if (!sess->SendMsg(pkt)) { + SEN_HILOGE("Packet send failed"); + continue; } } - pidSensorIdMap_.clear(); - sensorIdInfoMap_.clear(); } } // namespace Sensors -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/services/sensor/src/stream_server.cpp b/services/sensor/src/stream_server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31399c256381b73070671e77ffa74df20306a7b5 --- /dev/null +++ b/services/sensor/src/stream_server.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2023 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 "stream_server.h" + +#include +#include + +#include "accesstoken_kit.h" + +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +namespace { +using namespace Security::AccessToken; +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "StreamServer" }; +constexpr int32_t INVALID_PID = -1; +constexpr int32_t INVALID_FD = -1; +} // namespace +StreamServer::~StreamServer() +{ + CALL_LOG_ENTER; + idxPidMap_.clear(); + for (const auto &item : sessionsMap_) { + item.second->Close(); + } + sessionsMap_.clear(); +} + +bool StreamServer::SendMsg(int32_t fd, NetPacket& pkt) +{ + CALL_LOG_ENTER; + if (fd < 0) { + SEN_HILOGE("Fd is invalid"); + return false; + } + auto ses = GetSession(fd); + if (ses == nullptr) { + SEN_HILOGE("Fd not found, The message was discarded. errCode:%{public}d", PROTO_SESSION_NOT_FOUND); + return false; + } + return ses->SendMsg(pkt); +} + +void StreamServer::Multicast(const std::vector& fdList, NetPacket& pkt) +{ + CALL_LOG_ENTER; + for (const auto &item : fdList) { + SendMsg(item, pkt); + } +} + +int32_t StreamServer::GetClientFd(int32_t pid) +{ + std::lock_guard idxPidLock(idxPidMutex_); + auto it = idxPidMap_.find(pid); + if (it == idxPidMap_.end()) { + return INVALID_FD; + } + return it->second; +} + +int32_t StreamServer::GetClientPid(int32_t fd) +{ + std::lock_guard sessionLock(sessionMutex_); + auto it = sessionsMap_.find(fd); + if (it == sessionsMap_.end()) { + return INVALID_PID; + } + return it->second->GetPid(); +} + +SessionPtr StreamServer::GetSession(int32_t fd) +{ + std::lock_guard sessionLock(sessionMutex_); + auto it = sessionsMap_.find(fd); + if (it == sessionsMap_.end()) { + SEN_HILOGE("Session not found"); + return nullptr; + } + CHKPP(it->second); + return it->second->GetSharedPtr(); +} + +SessionPtr StreamServer::GetSessionByPid(int32_t pid) +{ + int32_t fd = GetClientFd(pid); + if (fd <= 0) { + SEN_HILOGE("Session not found"); + return nullptr; + } + return GetSession(fd); +} + +int32_t StreamServer::AddSocketPairInfo(int32_t uid, int32_t pid, int32_t tokenType, + int32_t &serverFd, int32_t &clientFd) +{ + CALL_LOG_ENTER; + std::string programName = ""; + int32_t moduleType = 0; + int32_t sockFds[2] = { -1 }; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) != 0) { + SEN_HILOGE("Call socketpair failed, errno:%{public}d", errno); + return ERROR; + } + serverFd = sockFds[0]; + clientFd = sockFds[1]; + if (serverFd < 0 || clientFd < 0) { + SEN_HILOGE("Call fcntl failed, errno:%{public}d", errno); + return ERROR; + } + static constexpr size_t bufferSize = 32 * 1024; + static constexpr size_t nativeBufferSize = 64 * 1024; + SessionPtr sess = nullptr; + if (setsockopt(serverFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) { + SEN_HILOGE("Setsockopt serverFd failed, errno: %{public}d", errno); + goto CLOSE_SOCK; + } + if (setsockopt(serverFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) { + SEN_HILOGE("Setsockopt serverFd failed, errno: %{public}d", errno); + goto CLOSE_SOCK; + } + if (tokenType == ATokenTypeEnum::TOKEN_NATIVE) { + if (setsockopt(clientFd, SOL_SOCKET, SO_SNDBUF, &nativeBufferSize, sizeof(nativeBufferSize)) != 0) { + SEN_HILOGE("Setsockopt clientFd failed, errno: %{public}d", errno); + goto CLOSE_SOCK; + } + if (setsockopt(clientFd, SOL_SOCKET, SO_RCVBUF, &nativeBufferSize, sizeof(nativeBufferSize)) != 0) { + SEN_HILOGE("Setsockopt clientFd failed, errno: %{public}d", errno); + goto CLOSE_SOCK; + } + } else { + if (setsockopt(clientFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) { + SEN_HILOGE("Setsockopt clientFd failed, errno: %{public}d", errno); + goto CLOSE_SOCK; + } + if (setsockopt(clientFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) { + SEN_HILOGE("Setsockopt clientFd failed, errno: %{public}d", errno); + goto CLOSE_SOCK; + } + } + sess = std::make_shared(programName, moduleType, serverFd, uid, pid); + sess->SetTokenType(tokenType); + if (!AddSession(sess)) { + SEN_HILOGE("AddSession fail errCode:%{public}d", PROTO_ADD_SESSION_FAIL); + goto CLOSE_SOCK; + } + return ERR_OK; + +CLOSE_SOCK: + close(serverFd); + serverFd = -1; + close(clientFd); + clientFd = -1; + return ERROR; +} + +bool StreamServer::AddSession(SessionPtr ses) +{ + CALL_LOG_ENTER; + CHKPF(ses); + auto fd = ses->GetFd(); + if (fd < 0) { + SEN_HILOGE("Fd is Invalid"); + return false; + } + auto pid = ses->GetPid(); + if (pid <= 0) { + SEN_HILOGE("Get process failed"); + return false; + } + if (sessionsMap_.size() > PROTO_MAX_SESSON_ALARM) { + SEN_HILOGE("Too many clients. Warning Value:%{public}d, Current Value:%{public}zd", + PROTO_MAX_SESSON_ALARM, sessionsMap_.size()); + return false; + } + DelSession(pid); + std::lock_guard idxPidLock(idxPidMutex_); + idxPidMap_[pid] = fd; + std::lock_guard sessionLock(sessionMutex_); + sessionsMap_[fd] = ses; + return true; +} + +void StreamServer::DelSession(int32_t pid) +{ + CALL_LOG_ENTER; + std::lock_guard idxPidLock(idxPidMutex_); + auto pidIt = idxPidMap_.find(pid); + if (pidIt == idxPidMap_.end()) { + return; + } + int32_t fd = pidIt->second; + idxPidMap_.erase(pidIt); + std::lock_guard sessionLock(sessionMutex_); + auto fdIt = sessionsMap_.find(fd); + if (fdIt != sessionsMap_.end()) { + sessionsMap_.erase(fdIt); + } + if (fd >= 0) { + auto rf = close(fd); + if (rf > 0) { + SEN_HILOGE("Socket fd close failed, rf:%{public}d", rf); + } + } +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/common/include/system_info.h b/test/unittest/common/include/system_info.h index b48b8fdad025a93d9677b2581cd72edd083d8afe..0a59896935782f623a8e295918e64b30e17e5f09 100644 --- a/test/unittest/common/include/system_info.h +++ b/test/unittest/common/include/system_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 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 @@ -36,6 +36,8 @@ class CpuInfo : public SystemInfo { public: double GetSystemCpuUsage(); double GetProcCpuUsage(const std::string& process_name); + int32_t GetTaskPidFile(const std::string& process_name); + private: struct Total_Cpu_Occupy { char name[20] { 0 }; @@ -56,7 +58,6 @@ private: int32_t cutime { 0 }; int32_t cstime { 0 }; }; - int32_t GetTaskPidFile(const std::string& process_name); int32_t GetProcOccupy(int32_t pid); int32_t GetSystemCpuStatInfo(Total_Cpu_Occupy& info); diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 7a971bb7473fb530b345c66e18a97912ea76e55d..80796c29f2fe5b3edabbe9022504a66bab5b2728 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -11,38 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build/ohos.gni") -SUBSYSTEM_DIR = "//base/sensors" -ohos_shared_library("libsensor_utils") { - sources = [ - "src/permission_util.cpp", - "src/report_data_callback.cpp", - "src/sensor.cpp", - "src/sensor_basic_data_channel.cpp", - "src/sensor_basic_info.cpp", - "src/sensor_channel_info.cpp", - ] - - include_dirs = [ - "include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//drivers/peripheral/sensor/interfaces/include", - "$SUBSYSTEM_DIR/sensor/interfaces/native/include", - ] - - external_deps = [ - "access_token:libaccesstoken_sdk", - "access_token:libprivacy_sdk", - "c_utils:utils", - "hisysevent_native:libhisysevent", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - ] - part_name = "sensor" - subsystem_name = "sensors" -} - group("sensor_utils_target") { - deps = [ ":libsensor_utils" ] + deps = [ + "common:libsensor_utils", + "ipc:libsensor_ipc", + ] } diff --git a/utils/common/BUILD.gn b/utils/common/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..5e1ef88f1503293d8415ab9c2503bb154036b384 --- /dev/null +++ b/utils/common/BUILD.gn @@ -0,0 +1,43 @@ +# Copyright (c) 2023 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") + +ohos_shared_library("libsensor_utils") { + sources = [ + "src/permission_util.cpp", + "src/report_data_callback.cpp", + "src/sensor.cpp", + "src/sensor_basic_data_channel.cpp", + "src/sensor_basic_info.cpp", + "src/sensor_channel_info.cpp", + "src/subscribe_info.cpp", + ] + + include_dirs = [ + "include", + "./../../interfaces/native/include", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libprivacy_sdk", + "c_utils:utils", + "hisysevent_native:libhisysevent", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + part_name = "sensor" + subsystem_name = "sensors" +} diff --git a/utils/include/app_thread_info.h b/utils/common/include/app_thread_info.h similarity index 100% rename from utils/include/app_thread_info.h rename to utils/common/include/app_thread_info.h diff --git a/utils/include/death_recipient_template.h b/utils/common/include/death_recipient_template.h similarity index 100% rename from utils/include/death_recipient_template.h rename to utils/common/include/death_recipient_template.h diff --git a/utils/include/miscdevice_common.h b/utils/common/include/miscdevice_common.h similarity index 100% rename from utils/include/miscdevice_common.h rename to utils/common/include/miscdevice_common.h diff --git a/utils/include/permission_util.h b/utils/common/include/permission_util.h similarity index 96% rename from utils/include/permission_util.h rename to utils/common/include/permission_util.h index ba61b2f896dc9f6710ed433d8f406e56ed9e539a..dadbacbd87bea822a9349374eb8d4bedb306a844 100644 --- a/utils/include/permission_util.h +++ b/utils/common/include/permission_util.h @@ -30,6 +30,7 @@ public: PermissionUtil() = default; virtual ~PermissionUtil() {}; int32_t CheckSensorPermission(AccessTokenID callerToken, int32_t sensorTypeId); + bool IsNativeToken(AccessTokenID tokenID); private: void AddPermissionRecord(AccessTokenID tokenID, const std::string& permissionName, bool status); diff --git a/utils/include/report_data_callback.h b/utils/common/include/report_data_callback.h similarity index 100% rename from utils/include/report_data_callback.h rename to utils/common/include/report_data_callback.h diff --git a/utils/include/sensor.h b/utils/common/include/sensor.h similarity index 100% rename from utils/include/sensor.h rename to utils/common/include/sensor.h diff --git a/utils/include/sensor_basic_data_channel.h b/utils/common/include/sensor_basic_data_channel.h similarity index 100% rename from utils/include/sensor_basic_data_channel.h rename to utils/common/include/sensor_basic_data_channel.h diff --git a/utils/include/sensor_basic_info.h b/utils/common/include/sensor_basic_info.h similarity index 100% rename from utils/include/sensor_basic_info.h rename to utils/common/include/sensor_basic_info.h diff --git a/utils/include/sensor_channel_info.h b/utils/common/include/sensor_channel_info.h similarity index 100% rename from utils/include/sensor_channel_info.h rename to utils/common/include/sensor_channel_info.h diff --git a/utils/include/sensor_data_event.h b/utils/common/include/sensor_data_event.h similarity index 100% rename from utils/include/sensor_data_event.h rename to utils/common/include/sensor_data_event.h diff --git a/utils/include/sensor_log.h b/utils/common/include/sensor_log.h similarity index 100% rename from utils/include/sensor_log.h rename to utils/common/include/sensor_log.h diff --git a/utils/include/sensors_errors.h b/utils/common/include/sensors_errors.h similarity index 98% rename from utils/include/sensors_errors.h rename to utils/common/include/sensors_errors.h index 55e11c3c1811330cd08f4607e528d3235cfae0ee..43edceab7f28f318574e95ec0dfa9506deb4539c 100644 --- a/utils/include/sensors_errors.h +++ b/utils/common/include/sensors_errors.h @@ -87,8 +87,9 @@ enum { COPY_ERR = NO_EVENT + 1, REGIST_PERMISSION_CHANGED_ERR = COPY_ERR + 1, DUMP_PARAM_ERR = REGIST_PERMISSION_CHANGED_ERR + 1, - WRITE_MSG_ERR = DUMP_PARAM_ERR + 1, - SET_SENSOR_MODE_ERR = WRITE_MSG_ERR + 1, + WRITE_PARCEL_ERR = DUMP_PARAM_ERR + 1, + READ_PARCEL_ERR = WRITE_PARCEL_ERR + 1, + SET_SENSOR_MODE_ERR = READ_PARCEL_ERR + 1, SET_SENSOR_OPTION_ERR = SET_SENSOR_MODE_ERR + 1, REGIST_CALLBACK_ERR = SET_SENSOR_OPTION_ERR + 1, }; diff --git a/utils/common/include/subscribe_info.h b/utils/common/include/subscribe_info.h new file mode 100644 index 0000000000000000000000000000000000000000..fbcd41b154bcebdc10c861f884ff5bcc07b38683 --- /dev/null +++ b/utils/common/include/subscribe_info.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 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 SUBSCRIBE_INFO_H +#define SUBSCRIBE_INFO_H + +#include "parcel.h" + +#include "sensor_agent_type.h" + +namespace OHOS { +namespace Sensors { +class SubscribeInfo : public Parcelable { +public: + SubscribeInfo() = default; + SubscribeInfo(SubscribeSensorInfo subscribeSensorInfo); + virtual ~SubscribeInfo() = default; + int32_t GetPid() const; + void SetPid(int32_t pid); + int32_t GetSensorId() const; + void SetSensorId(int32_t sensorId); + bool IsActive() const; + void Enable(bool isActive); + int64_t GetSamplingPeriodNs() const; + void SetSamplingPeriodNs(int64_t samplingPeriodNs); + int64_t GetMaxReportDelayNs() const; + void SetMaxReportDelayNs(int64_t maxReportDelayNs); + bool Marshalling(Parcel &parcel) const; + std::unique_ptr Unmarshalling(Parcel &parcel); + +private: + int32_t pid_ { -1 }; + int32_t sensorId_ { -1 }; + bool isActive_ { -1 }; + int64_t samplingPeriodNs_ { -1 }; + int64_t maxReportDelayNs_ { -1 }; +}; +} // namespace Sensors +} // namespace OHOS +#endif // SUBSCRIBE_INFO_H \ No newline at end of file diff --git a/utils/src/permission_util.cpp b/utils/common/src/permission_util.cpp similarity index 90% rename from utils/src/permission_util.cpp rename to utils/common/src/permission_util.cpp index 4e2d91e00fa3f6c7d3029739ca6cca88e7107d0a..9e5bd3050f1ea9e1479a29fa31e7e3b6aca336ba 100644 --- a/utils/src/permission_util.cpp +++ b/utils/common/src/permission_util.cpp @@ -67,5 +67,15 @@ void PermissionUtil::AddPermissionRecord(AccessTokenID tokenID, const std::strin permissionName.c_str(), successCount, failCount); } } + +bool PermissionUtil::IsNativeToken(AccessTokenID tokenID) +{ + int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(tokenID); + if (tokenType != ATokenTypeEnum::TOKEN_NATIVE) { + SEN_HILOGE("TokenType is not TOKEN_NATIVE, tokenType:%{public}d", tokenType); + return false; + } + return true; +} } // namespace Sensors } // namespace OHOS diff --git a/utils/src/report_data_callback.cpp b/utils/common/src/report_data_callback.cpp similarity index 100% rename from utils/src/report_data_callback.cpp rename to utils/common/src/report_data_callback.cpp diff --git a/utils/src/sensor.cpp b/utils/common/src/sensor.cpp similarity index 100% rename from utils/src/sensor.cpp rename to utils/common/src/sensor.cpp diff --git a/utils/src/sensor_basic_data_channel.cpp b/utils/common/src/sensor_basic_data_channel.cpp similarity index 100% rename from utils/src/sensor_basic_data_channel.cpp rename to utils/common/src/sensor_basic_data_channel.cpp diff --git a/utils/src/sensor_basic_info.cpp b/utils/common/src/sensor_basic_info.cpp similarity index 100% rename from utils/src/sensor_basic_info.cpp rename to utils/common/src/sensor_basic_info.cpp diff --git a/utils/src/sensor_channel_info.cpp b/utils/common/src/sensor_channel_info.cpp similarity index 100% rename from utils/src/sensor_channel_info.cpp rename to utils/common/src/sensor_channel_info.cpp diff --git a/utils/common/src/subscribe_info.cpp b/utils/common/src/subscribe_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18c8605c5c276334370263e2a9d86dbfff6c6974 --- /dev/null +++ b/utils/common/src/subscribe_info.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 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 "subscribe_info.h" + +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +using namespace OHOS::HiviewDFX; +namespace { +constexpr HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "SubscribeInfo" }; +} + +SubscribeInfo::SubscribeInfo(SubscribeSensorInfo subscribeSensorInfo) +{ + pid_ = subscribeSensorInfo.pid; + sensorId_ = subscribeSensorInfo.sensorId; + isActive_ = subscribeSensorInfo.isActive; + samplingPeriodNs_ = subscribeSensorInfo.samplingPeriodNs; + maxReportDelayNs_ = subscribeSensorInfo.maxReportDelayNs; +} + +int32_t SubscribeInfo::GetPid() const +{ + return pid_; +} + +void SubscribeInfo::SetPid(int32_t pid) +{ + pid_ = pid; +} + +int32_t SubscribeInfo::GetSensorId() const +{ + return sensorId_; +} + +void SubscribeInfo::SetSensorId(int32_t sensorId) +{ + sensorId_ = sensorId; +} + +bool SubscribeInfo::IsActive() const +{ + return isActive_; +} + +void SubscribeInfo::Enable(bool isActive) +{ + isActive_ = isActive; +} + +int64_t SubscribeInfo::GetSamplingPeriodNs() const +{ + return samplingPeriodNs_; +} + +void SubscribeInfo::SetSamplingPeriodNs(int64_t samplingPeriodNs) +{ + samplingPeriodNs_ = samplingPeriodNs; +} + +int64_t SubscribeInfo::GetMaxReportDelayNs() const +{ + return maxReportDelayNs_; +} + +void SubscribeInfo::SetMaxReportDelayNs(int64_t maxReportDelayNs) +{ + maxReportDelayNs_ = maxReportDelayNs; +} + +bool SubscribeInfo::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteInt32(pid_)) { + SEN_HILOGE("Write pid failed"); + return false; + } + if (!parcel.WriteInt32(sensorId_)) { + SEN_HILOGE("Write sensorId failed"); + return false; + } + if (!parcel.WriteBool(isActive_)) { + SEN_HILOGE("Write isActive failed"); + return false; + } + if (!parcel.WriteInt64(samplingPeriodNs_)) { + SEN_HILOGE("Write samplingPeriodNs failed"); + return false; + } + if (!parcel.WriteInt64(maxReportDelayNs_)) { + SEN_HILOGE("Write maxReportDelayNs failed"); + return false; + } + return true; +} + +std::unique_ptr SubscribeInfo::Unmarshalling(Parcel &parcel) +{ + int32_t pid = -1; + int32_t sensorId = -1; + bool isActive = false; + int64_t samplingPeriodNs = -1; + int64_t maxReportDelayNs = -1; + if (!(parcel.ReadInt32(pid) && parcel.ReadInt32(sensorId) && parcel.ReadBool(isActive) && + parcel.ReadInt64(samplingPeriodNs) && parcel.ReadInt64(maxReportDelayNs))) { + SEN_HILOGE("ReadFromParcel is failed"); + return nullptr; + } + auto subscribeInfo = std::make_unique(); + subscribeInfo->SetPid(pid); + subscribeInfo->SetSensorId(sensorId); + subscribeInfo->Enable(isActive); + subscribeInfo->SetSamplingPeriodNs(samplingPeriodNs); + subscribeInfo->SetMaxReportDelayNs(maxReportDelayNs); + return subscribeInfo; +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file diff --git a/utils/ipc/BUILD.gn b/utils/ipc/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3b78d1ff9da0d0df5534e07a7932e4b7f47c49ec --- /dev/null +++ b/utils/ipc/BUILD.gn @@ -0,0 +1,39 @@ +# Copyright (c) 2023 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") + +ohos_shared_library("libsensor_ipc") { + sources = [ + "src/circle_stream_buffer.cpp", + "src/net_packet.cpp", + "src/stream_buffer.cpp", + "src/stream_client.cpp", + "src/stream_session.cpp", + "src/stream_socket.cpp", + ] + + include_dirs = [ + "include", + "./../common/include", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + ] + + part_name = "sensor" + subsystem_name = "sensors" +} diff --git a/utils/ipc/include/circle_stream_buffer.h b/utils/ipc/include/circle_stream_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..3aaea4904083164440034d1d97a6f06564ad3709 --- /dev/null +++ b/utils/ipc/include/circle_stream_buffer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 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 CIRCLE_STREAM_BUFFER_H +#define CIRCLE_STREAM_BUFFER_H + +#include "stream_buffer.h" + +namespace OHOS { +namespace Sensors { +class CircleStreamBuffer : public StreamBuffer { + static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "CircleStreamBuffer" }; +public: + CircleStreamBuffer() = default; + virtual ~CircleStreamBuffer() = default; + bool CheckWrite(size_t size); + virtual bool Write(const char *buf, size_t size) override; + DISALLOW_MOVE(CircleStreamBuffer); + +protected: + void CopyDataToBegin(); +}; +} // namespace Sensors +} // namespace OHOS +#endif // CIRCLE_STREAM_BUFFER_H \ No newline at end of file diff --git a/utils/ipc/include/net_packet.h b/utils/ipc/include/net_packet.h new file mode 100644 index 0000000000000000000000000000000000000000..33d3545eb2e648dfeb3b50a77b748f9a423eeb09 --- /dev/null +++ b/utils/ipc/include/net_packet.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 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 NET_PACKET_H +#define NET_PACKET_H + +#include "proto.h" +#include "stream_buffer.h" + +#pragma pack(1) +using PACKHEAD = struct PackHead { + OHOS::Sensors::MessageId idMsg; + int32_t size; +}; + +#pragma pack() +namespace OHOS { +namespace Sensors { +class NetPacket : public StreamBuffer { + static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "NetPacket" }; +public: + explicit NetPacket(MessageId msgId); + NetPacket(const NetPacket &pkt); + NetPacket &operator = (const NetPacket &pkt); + virtual ~NetPacket(); + virtual void MakeData(StreamBuffer &buf) const; + size_t GetSize() const; + int32_t GetPacketLength() const; + const char* GetData() const; + MessageId GetMsgId() const; + DISALLOW_MOVE(NetPacket); + +protected: + MessageId msgId_ = MessageId::INVALID; +}; +} // namespace Sensors +} // namespace OHOS +#endif // NET_PACKET_H \ No newline at end of file diff --git a/utils/ipc/include/proto.h b/utils/ipc/include/proto.h new file mode 100644 index 0000000000000000000000000000000000000000..207b86404ca3062255ac108b07d18e0a952f0606 --- /dev/null +++ b/utils/ipc/include/proto.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 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 PROTO_H +#define PROTO_H + +#include + +namespace OHOS { +namespace Sensors { +#define PROTO_SEND_RETRY_LIMIT 32 +#define PROTO_SEND_RETRY_SLEEP_TIME 10000 + +static const int32_t PROTO_STREAM_BUF_READ_FAIL = 1; +static const int32_t PROTO_STREAM_BUF_WRITE_FAIL = 2; +static const int32_t PROTO_MEM_OUT_OF_BOUNDS = 3; +static const int32_t PROTO_MEMCPY_SEC_FUN_FAIL = 4; +static const int32_t PROTO_PARAM_INPUT_INVALID = 5; +static const int32_t PROTO_SESSION_NOT_FOUND = 8; +static const int32_t PROTO_MAX_VECTOR_SIZE = 10; +static const int32_t PROTO_ADD_SESSION_FAIL = 11; +static const int32_t PROTO_MAX_SESSON_ALARM = 12; +static const int32_t PROTO_MAX_RECV_LIMIT = 13; + +static const int32_t PROTO_MAX_STREAM_BUF_SIZE = 256; +static const int32_t PROTO_MAX_PACKET_BUF_SIZE = 256; +static const int32_t PROTO_ONCE_PROCESS_NETPACKET_LIMIT = 100; + +enum class MessageId : int32_t { + INVALID, + CLIENT_INFO, +}; +} // namespace Sensors +} // namespace OHOS +#endif // PROTO_H \ No newline at end of file diff --git a/utils/ipc/include/stream_buffer.h b/utils/ipc/include/stream_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..0cea6faeafa0e30215db92bc4463fb5faa566312 --- /dev/null +++ b/utils/ipc/include/stream_buffer.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023 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 STREAM_BUFFER_H +#define STREAM_BUFFER_H + +#include +#include +#include + +#include "nocopyable.h" +#include "securec.h" + +#include "proto.h" +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +class StreamBuffer { + static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "StreamBuffer" }; +public: + StreamBuffer() = default; + explicit StreamBuffer(const StreamBuffer &buf); + virtual StreamBuffer &operator=(const StreamBuffer &other); + virtual ~StreamBuffer() = default; + void Reset(); + void Clean(); + bool SeekReadPos(int32_t n); + bool Read(std::string &buf); + bool Read(StreamBuffer &buf); + bool Read(char *buf, size_t size); + bool Write(const std::string &buf); + bool Write(const StreamBuffer &buf); + virtual bool Write(const char *buf, size_t size); + bool IsEmpty() const; + bool ChkRWError() const; + size_t Size() const; + int32_t UnreadSize() const; + int32_t GetAvailableBufSize() const; + const std::string& GetErrorStatusRemark() const; + const char* Data() const; + + template + bool Read(T &data); + template + bool Write(const T &data); + template + bool Read(std::vector &data); + template + bool Write(const std::vector &data); + const char *ReadBuf() const; + const char *WriteBuf() const; + template + StreamBuffer &operator >> (T &data); + template + StreamBuffer &operator << (const T &data); + DISALLOW_MOVE(StreamBuffer); + +protected: + bool Clone(const StreamBuffer &buf); + enum class ErrorStatus { + ERROR_STATUS_OK, + ERROR_STATUS_READ, + ERROR_STATUS_WRITE, + }; + ErrorStatus rwErrorStatus_ = ErrorStatus::ERROR_STATUS_OK; + int32_t rCount_ { 0 }; + int32_t wCount_ { 0 }; + int32_t rPos_ { 0 }; + int32_t wPos_ { 0 }; + char szBuff_[PROTO_MAX_STREAM_BUF_SIZE + 1] = {}; +}; + +template +bool StreamBuffer::Read(T &data) +{ + if (!Read(reinterpret_cast(&data), sizeof(data))) { + SEN_HILOGE("[%{public}s] size:%{public}zu count:%{public}d,errCode:%{public}d", + GetErrorStatusRemark().c_str(), sizeof(data), rCount_ + 1, PROTO_STREAM_BUF_READ_FAIL); + return false; + } + return true; +} + +template +bool StreamBuffer::Write(const T &data) +{ + if (!Write(reinterpret_cast(&data), sizeof(data))) { + SEN_HILOGE("[%{public}s] size:%{public}zu,count:%{public}d,errCode:%{public}d", + GetErrorStatusRemark().c_str(), sizeof(data), wCount_ + 1, PROTO_STREAM_BUF_WRITE_FAIL); + return false; + } + return true; +} + +template +bool StreamBuffer::Read(std::vector &data) +{ + int32_t size = 0; + if (!Read(size)) { + SEN_HILOGE("Read vector size error"); + return false; + } + if (size < 0 || size > PROTO_MAX_VECTOR_SIZE) { + SEN_HILOGE("Read vector size:%{public}d error", size); + return false; + } + for (int32_t i = 0; i < size; i++) { + T val; + if (!Read(val)) { + SEN_HILOGE("Read vector data error"); + return false; + } + data.push_back(val); + } + return true; +} + +template +bool StreamBuffer::Write(const std::vector &data) +{ + if (data.size() > INT32_MAX) { + SEN_HILOGE("Vector exceeds the max range"); + return false; + } + int32_t size = static_cast(data.size()); + if (!Write(size)) { + SEN_HILOGE("Write vector size error"); + return false; + } + for (const auto &item : data) { + if (!Write(item)) { + SEN_HILOGE("Write vector data error"); + return false; + } + } + return true; +} + +template +StreamBuffer &StreamBuffer::operator>>(T &data) +{ + if (!Read(data)) { + SEN_HILOGW("Read data failed"); + } + return *this; +} + +template +StreamBuffer &StreamBuffer::operator<<(const T &data) +{ + if (!Write(data)) { + SEN_HILOGW("Write data failed"); + } + return *this; +} +} // namespace Sensors +} // namespace OHOS +#endif // STREAM_BUFFER_H \ No newline at end of file diff --git a/utils/ipc/include/stream_client.h b/utils/ipc/include/stream_client.h new file mode 100644 index 0000000000000000000000000000000000000000..4dd9a1e995a70d841b89a6b41f79dd1cc9864326 --- /dev/null +++ b/utils/ipc/include/stream_client.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 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 STREAM_CLIENT_H +#define STREAM_CLIENT_H + +#include +#include +#include + +#include "nocopyable.h" + +#include "net_packet.h" +#include "stream_socket.h" + +namespace OHOS { +namespace Sensors { +class StreamClient; +using MsgClientFunCallback = std::function; +class StreamClient : public StreamSocket { +public: + StreamClient(); + virtual ~StreamClient(); + virtual int32_t Socket() = 0; + virtual void Stop(); + int32_t ConnectTo(); + bool SendMsg(const char *buf, size_t size) const; + bool SendMsg(const NetPacket &pkt) const; + bool GetConnectedStatus() const; + DISALLOW_COPY_AND_MOVE(StreamClient); + +protected: + virtual void OnConnected() {} + virtual void OnDisconnected() {} + bool StartClient(MsgClientFunCallback fun); + bool isExit { false }; + bool isRunning_ { false }; + bool isConnected_ { false }; + MsgClientFunCallback recvFun_; +}; +} // namespace Sensors +} // namespace OHOS +#endif // STREAM_CLIENT_H \ No newline at end of file diff --git a/utils/ipc/include/stream_session.h b/utils/ipc/include/stream_session.h new file mode 100644 index 0000000000000000000000000000000000000000..adbf4dc12dddbfb6688e80eefa15674d3e8a587f --- /dev/null +++ b/utils/ipc/include/stream_session.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 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 STREAM_SESSION_H +#define STREAM_SESSION_H + +#include +#include +#include + +#include +#include + +#include "accesstoken_kit.h" +#include "nocopyable.h" + +#include "net_packet.h" +#include "proto.h" + +namespace OHOS { +namespace Sensors { +class StreamSession; +using SessionPtr = std::shared_ptr; +using namespace Security::AccessToken; +class StreamSession : public std::enable_shared_from_this { +public: + StreamSession(const std::string &programName, const int32_t moduleType, const int32_t fd, const int32_t uid, + const int32_t pid); + virtual ~StreamSession() = default; + bool SendMsg(const char *buf, size_t size) const; + bool SendMsg(NetPacket &pkt) const; + void Close(); + int32_t GetUid() const; + int32_t GetPid() const; + int32_t GetModuleType() const; + SessionPtr GetSharedPtr(); + int32_t GetFd() const; + const std::string& GetDescript() const; + const std::string GetProgramName() const; + void SetTokenType(int32_t type); + int32_t GetTokenType() const; + void UpdateDescript(); + DISALLOW_COPY_AND_MOVE(StreamSession); + +protected: + struct EventTime { + int32_t id { 0 }; + int64_t eventTime { 0 }; + int32_t timerId { -1 }; + }; + std::map> events_; + std::string descript_; + const std::string programName_; + const int32_t moduleType_ { -1 }; + int32_t fd_ { -1 }; + const int32_t uid_ { -1 }; + const int32_t pid_ { -1 }; + int32_t tokenType_ { ATokenTypeEnum::TOKEN_INVALID }; +}; +} // namespace Sensors +} // namespace OHOS +#endif // STREAM_SESSION_H \ No newline at end of file diff --git a/utils/ipc/include/stream_socket.h b/utils/ipc/include/stream_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..acae2006c5cc9e8d693cb5f0c5ab9100e1e7e441 --- /dev/null +++ b/utils/ipc/include/stream_socket.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 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 STREAM_SOCKET_H +#define STREAM_SOCKET_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "nocopyable.h" + +#include "circle_stream_buffer.h" +#include "net_packet.h" + +namespace OHOS { +namespace Sensors { +class StreamSocket { +public: + using PacketCallBackFun = std::function; + StreamSocket(); + virtual ~StreamSocket(); + int32_t EpollCreate(int32_t size); + int32_t EpollCtl(int32_t fd, int32_t op, struct epoll_event &event, int32_t epollFd = -1); + int32_t EpollWait(struct epoll_event &events, int32_t maxevents, int32_t timeout, int32_t epollFd = -1); + void OnReadPackets(CircleStreamBuffer &buf, PacketCallBackFun callbackFun); + void EpollClose(); + void Close(); + int32_t GetFd() const; + int32_t GetEpollFd() const; + + DISALLOW_COPY_AND_MOVE(StreamSocket); + +protected: + int32_t fd_ { -1 }; + int32_t epollFd_ { -1 }; +}; +} // namespace Sensors +} // namespace OHOS +#endif // STREAM_SOCKET_H \ No newline at end of file diff --git a/utils/ipc/src/circle_stream_buffer.cpp b/utils/ipc/src/circle_stream_buffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f1845b2716e6a3ebaa9fccbbe2ac084cd0ba6bf --- /dev/null +++ b/utils/ipc/src/circle_stream_buffer.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 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 "circle_stream_buffer.h" + +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +bool CircleStreamBuffer::CheckWrite(size_t size) +{ + int32_t bufferSize = static_cast(size); + int32_t availSize = GetAvailableBufSize(); + if (bufferSize > availSize && rPos_ > 0) { + CopyDataToBegin(); + availSize = GetAvailableBufSize(); + } + return (availSize >= bufferSize); +} + +bool CircleStreamBuffer::Write(const char *buf, size_t size) +{ + if (!CheckWrite(size)) { + SEN_HILOGE("Out of buffer memory, availableSize:%{public}d, size:%{public}zu," + "unreadSize:%{public}d, rPos:%{public}d, wPos:%{public}d", + GetAvailableBufSize(), size, UnreadSize(), rPos_, wPos_); + return false; + } + return StreamBuffer::Write(buf, size); +} + +void CircleStreamBuffer::CopyDataToBegin() +{ + int32_t unreadSize = UnreadSize(); + if (unreadSize > 0 && rPos_ > 0 && sizeof(szBuff_) > wPos_) { + int32_t pos = 0; + for (int32_t i = rPos_; i <= wPos_;) { + szBuff_[pos++] = szBuff_[i++]; + } + } + SEN_HILOGD("UnreadSize:%{public}d, rPos:%{public}d, wPos:%{public}d", unreadSize, rPos_, wPos_); + rPos_ = 0; + wPos_ = unreadSize; +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file diff --git a/utils/ipc/src/net_packet.cpp b/utils/ipc/src/net_packet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00acc027d4582d1e0e72626319975375bdf2c930 --- /dev/null +++ b/utils/ipc/src/net_packet.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 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 "net_packet.h" + +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +NetPacket::NetPacket(MessageId msgId) : msgId_(msgId) {} + +NetPacket::NetPacket(const NetPacket &pkt) : NetPacket(pkt.GetMsgId()) +{ + Clone(pkt); +} + +NetPacket::~NetPacket() {} + +void NetPacket::MakeData(StreamBuffer &buf) const +{ + PACKHEAD head = {msgId_, wPos_}; + buf << head; + if (wPos_ < 0) { + return; + } + if (!buf.Write(&szBuff_[0], wPos_)) { + SEN_HILOGE("Write data to stream failed, errCode:%{public}d", PROTO_STREAM_BUF_WRITE_FAIL); + return; + } +} + +size_t NetPacket::GetSize() const +{ + return Size(); +} + +int32_t NetPacket::GetPacketLength() const +{ + return (static_cast(sizeof(PackHead)) + wPos_); +} + +const char* NetPacket::GetData() const +{ + return Data(); +} + +MessageId NetPacket::GetMsgId() const +{ + return msgId_; +} +} // namespace Sensors +} // namespace OHOS diff --git a/utils/ipc/src/stream_buffer.cpp b/utils/ipc/src/stream_buffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a586ef72165e31bc4415cd7855bb23d2ed441f01 --- /dev/null +++ b/utils/ipc/src/stream_buffer.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2023 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 "stream_buffer.h" + +#include +#include + +namespace OHOS { +namespace Sensors { +StreamBuffer::StreamBuffer(const StreamBuffer &buf) +{ + Clone(buf); +} + +StreamBuffer &StreamBuffer::operator=(const StreamBuffer &other) +{ + Clone(other); + return *this; +} + +void StreamBuffer::Reset() +{ + rPos_ = 0; + wPos_ = 0; + rCount_ = 0; + wCount_ = 0; + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_OK; +} + +void StreamBuffer::Clean() +{ + Reset(); + errno_t ret = memset_sp(&szBuff_, sizeof(szBuff_), 0, sizeof(szBuff_)); + if (ret != EOK) { + SEN_HILOGE("Call memset_s fail"); + return; + } +} + +bool StreamBuffer::SeekReadPos(int32_t n) +{ + int32_t pos = rPos_ + n; + if (pos < 0 || pos > wPos_) { + SEN_HILOGE("The position in the calculation is not as expected. pos:%{public}d [0, %{public}d]", pos, wPos_); + return false; + } + rPos_ = pos; + return true; +} + +bool StreamBuffer::Read(std::string &buf) +{ + if (rPos_ == wPos_) { + SEN_HILOGE("Not enough memory to read, errCode:%{public}d", PROTO_STREAM_BUF_READ_FAIL); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ; + return false; + } + buf = ReadBuf(); + rPos_ += static_cast(buf.length()) + 1; + return (buf.length() > 0); +} + +bool StreamBuffer::Write(const std::string &buf) +{ + return Write(buf.c_str(), buf.length()+1); +} + +bool StreamBuffer::Read(StreamBuffer &buf) +{ + return buf.Write(Data(), Size()); +} + +bool StreamBuffer::Write(const StreamBuffer &buf) +{ + return Write(buf.Data(), buf.Size()); +} + +bool StreamBuffer::Read(char *buf, size_t size) +{ + if (ChkRWError()) { + return false; + } + if (buf == nullptr) { + SEN_HILOGE("Invalid input parameter buf=nullptr errCode:%{public}d", PROTO_PARAM_INPUT_INVALID); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ; + return false; + } + if (size == 0) { + SEN_HILOGE("Invalid input parameter size=%{public}zu errCode:%{public}d", size, PROTO_PARAM_INPUT_INVALID); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ; + return false; + } + if (rPos_ + static_cast(size) > wPos_) { + SEN_HILOGE("Memory out of bounds on read... errCode:%{public}d", PROTO_MEM_OUT_OF_BOUNDS); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ; + return false; + } + errno_t ret = memcpy_sp(buf, size, ReadBuf(), size); + if (ret != EOK) { + SEN_HILOGE("Failed to call memcpy_sp. errCode:%{public}d", PROTO_MEMCPY_SEC_FUN_FAIL); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ; + return false; + } + rPos_ += static_cast(size); + rCount_ += 1; + return true; +} + +bool StreamBuffer::Write(const char *buf, size_t size) +{ + if (ChkRWError()) { + return false; + } + if (buf == nullptr) { + SEN_HILOGE("Invalid input parameter buf=nullptr errCode:%{public}d", PROTO_PARAM_INPUT_INVALID); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE; + return false; + } + if (size == 0) { + SEN_HILOGE("Invalid input parameter size=%{public}zu errCode:%{public}d", size, PROTO_PARAM_INPUT_INVALID); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE; + return false; + } + if (wPos_ + static_cast(size) > PROTO_MAX_STREAM_BUF_SIZE) { + SEN_HILOGE("The write length exceeds buffer. wIdx:%{public}d size:%{public}zu maxBufSize:%{public}d" + "errCode:%{public}d", wPos_, size, PROTO_MAX_STREAM_BUF_SIZE, PROTO_MEM_OUT_OF_BOUNDS); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE; + return false; + } + errno_t ret = memcpy_sp(&szBuff_[wPos_], GetAvailableBufSize(), buf, size); + if (ret != EOK) { + SEN_HILOGE("Failed to call memcpy_sp. errCode:%{public}d", PROTO_MEMCPY_SEC_FUN_FAIL); + rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE; + return false; + } + wPos_ += static_cast(size); + wCount_ += 1; + return true; +} + +bool StreamBuffer::IsEmpty() const +{ + return (rPos_ == wPos_); +} + +size_t StreamBuffer::Size() const +{ + return static_cast(wPos_); +} + +int32_t StreamBuffer::UnreadSize() const +{ + return ((wPos_ <= rPos_) ? 0 : (wPos_ - rPos_)); +} + +int32_t StreamBuffer::GetAvailableBufSize() const +{ + return ((wPos_ >= PROTO_MAX_STREAM_BUF_SIZE) ? 0 : (PROTO_MAX_STREAM_BUF_SIZE - wPos_)); +} + +bool StreamBuffer::ChkRWError() const +{ + return (rwErrorStatus_ != ErrorStatus::ERROR_STATUS_OK); +} + +const std::string &StreamBuffer::GetErrorStatusRemark() const +{ + static const std::vector> remark { + {ErrorStatus::ERROR_STATUS_OK, "OK"}, + {ErrorStatus::ERROR_STATUS_READ, "READ_ERROR"}, + {ErrorStatus::ERROR_STATUS_WRITE, "WRITE_ERROR"}, + }; + static const std::string invalidStatus { "UNKNOWN" }; + + auto tIter = std::find_if(remark.cbegin(), remark.cend(), + [this](const auto &item) { + return (item.first == rwErrorStatus_); + } + ); + return (tIter != remark.cend() ? tIter->second : invalidStatus); +} + +const char *StreamBuffer::Data() const +{ + return &szBuff_[0]; +} + +const char *StreamBuffer::ReadBuf() const +{ + return &szBuff_[rPos_]; +} + +const char *StreamBuffer::WriteBuf() const +{ + return &szBuff_[wPos_]; +} + +bool StreamBuffer::Clone(const StreamBuffer &buf) +{ + Clean(); + return Write(buf.Data(), buf.Size()); +} +} // namespace Sensors +} // namespace OHOS diff --git a/utils/ipc/src/stream_client.cpp b/utils/ipc/src/stream_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e1fedf9e24fb5774a5068cf5f56d50e7523aee3 --- /dev/null +++ b/utils/ipc/src/stream_client.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023 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 "stream_client.h" + +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "StreamClient" }; +} + +StreamClient::StreamClient() {} + +StreamClient::~StreamClient() {} + +int32_t StreamClient::ConnectTo() +{ + CALL_LOG_ENTER; + if (Socket() < 0) { + SEN_HILOGE("Socket failed"); + return ERROR; + } + OnConnected(); + return SUCCESS; +} + +bool StreamClient::SendMsg(const char *buf, size_t size) const +{ + CALL_LOG_ENTER; + CHKPF(buf); + if ((size == 0) || (size > PROTO_MAX_PACKET_BUF_SIZE)) { + SEN_HILOGE("Stream buffer size out of range"); + return false; + } + if (fd_ < 0) { + SEN_HILOGE("The fd_ is less than 0"); + return false; + } + int32_t idx = 0; + int32_t retryCount = 0; + const int32_t bufSize = static_cast(size); + int32_t remSize = bufSize; + while (remSize > 0 && retryCount < PROTO_SEND_RETRY_LIMIT) { + retryCount += 1; + auto count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL); + if (count < 0) { + if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { + SEN_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d", errno); + continue; + } + SEN_HILOGE("Send return failed,error:%{public}d fd:%{public}d", errno, fd_); + return false; + } + idx += count; + remSize -= count; + if (remSize > 0) { + usleep(PROTO_SEND_RETRY_SLEEP_TIME); + } + } + if (retryCount >= PROTO_SEND_RETRY_LIMIT || remSize != 0) { + SEN_HILOGE("Send too many times:%{public}d/%{public}d,size:%{public}d/%{public}d fd:%{public}d", + retryCount, PROTO_SEND_RETRY_LIMIT, idx, bufSize, fd_); + return false; + } + return true; +} + +bool StreamClient::SendMsg(const NetPacket &pkt) const +{ + CALL_LOG_ENTER; + if (pkt.ChkRWError()) { + SEN_HILOGE("Read and write status is error"); + return false; + } + StreamBuffer buf; + pkt.MakeData(buf); + return SendMsg(buf.Data(), buf.Size()); +} + +bool StreamClient::StartClient(MsgClientFunCallback fun) +{ + CALL_LOG_ENTER; + if (isRunning_ || isConnected_) { + SEN_HILOGE("Client is connected or started"); + return false; + } + isExit = false; + recvFun_ = fun; + if (ConnectTo() < 0) { + SEN_HILOGW("Client connection failed, Try again later"); + } + return true; +} + +void StreamClient::Stop() +{ + CALL_LOG_ENTER; + isExit = true; + isRunning_ = false; + Close(); +} + +bool StreamClient::GetConnectedStatus() const +{ + return isConnected_; +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file diff --git a/utils/ipc/src/stream_session.cpp b/utils/ipc/src/stream_session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd8379742dc1fd5aa6147c3bbf64c37c0ddd158a --- /dev/null +++ b/utils/ipc/src/stream_session.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2023 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 "stream_session.h" + +#include +#include + +#include +#include +#include +#include + +#include "proto.h" +#include "stream_socket.h" +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "StreamSession" }; +} + +StreamSession::StreamSession(const std::string &programName, const int32_t moduleType, const int32_t fd, + const int32_t uid, const int32_t pid) + : programName_(programName), + moduleType_(moduleType), + fd_(fd), + uid_(uid), + pid_(pid) +{ + UpdateDescript(); +} + +bool StreamSession::SendMsg(const char *buf, size_t size) const +{ + CHKPF(buf); + if ((size == 0) || (size > PROTO_MAX_PACKET_BUF_SIZE)) { + SEN_HILOGE("Buf size:%{public}zu", size); + return false; + } + if (fd_ < 0) { + SEN_HILOGE("The fd_ is less than 0"); + return false; + } + + int32_t idx = 0; + int32_t retryCount = 0; + const int32_t bufSize = static_cast(size); + int32_t remSize = bufSize; + while (remSize > 0 && retryCount < PROTO_SEND_RETRY_LIMIT) { + retryCount += 1; + auto count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL); + if (count < 0) { + if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { + usleep(PROTO_SEND_RETRY_SLEEP_TIME); + SEN_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d", errno); + continue; + } + SEN_HILOGE("Send return failed,error:%{public}d fd:%{public}d", errno, fd_); + return false; + } + idx += count; + remSize -= count; + if (remSize > 0) { + usleep(PROTO_SEND_RETRY_SLEEP_TIME); + } + } + if (retryCount >= PROTO_SEND_RETRY_LIMIT || remSize != 0) { + SEN_HILOGE("Send too many times:%{public}d/%{public}d,size:%{public}d/%{public}d fd:%{public}d", + retryCount, PROTO_SEND_RETRY_LIMIT, idx, bufSize, fd_); + return false; + } + return true; +} + +void StreamSession::Close() +{ + SEN_HILOGD("Enter fd_:%{public}d.", fd_); + if (fd_ >= 0) { + close(fd_); + fd_ = -1; + UpdateDescript(); + } +} + +void StreamSession::UpdateDescript() +{ + std::ostringstream oss; + oss << "fd = " << fd_ + << ", programName = " << programName_ + << ", moduleType = " << moduleType_ + << ((fd_ < 0) ? ", closed" : ", opened") + << ", uid = " << uid_ + << ", pid = " << pid_ + << ", tokenType = " << tokenType_ + << std::endl; + descript_ = oss.str().c_str(); +} + +bool StreamSession::SendMsg(NetPacket &pkt) const +{ + if (pkt.ChkRWError()) { + SEN_HILOGE("Read and write status is error"); + return false; + } + StreamBuffer buf; + pkt.MakeData(buf); + return SendMsg(buf.Data(), buf.Size()); +} + +int32_t StreamSession::GetUid() const +{ + return uid_; +} + +int32_t StreamSession::GetPid() const +{ + return pid_; +} + +int32_t StreamSession::GetModuleType() const +{ + return moduleType_; +} + +SessionPtr StreamSession::GetSharedPtr() +{ + return shared_from_this(); +} + +int32_t StreamSession::GetFd() const +{ + return fd_; +} + +const std::string& StreamSession::GetDescript() const +{ + return descript_; +} + +const std::string StreamSession::GetProgramName() const +{ + return programName_; +} + +void StreamSession::SetTokenType(int32_t type) +{ + tokenType_ = type; +} + +int32_t StreamSession::GetTokenType() const +{ + return tokenType_; +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file diff --git a/utils/ipc/src/stream_socket.cpp b/utils/ipc/src/stream_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a2044dffb5a4831930acfd62c5a0089f7ebf9d6 --- /dev/null +++ b/utils/ipc/src/stream_socket.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023 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 "stream_socket.h" + +#include + +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "StreamSocket" }; +} // namespace + +StreamSocket::StreamSocket() {} + +StreamSocket::~StreamSocket() +{ + Close(); + EpollClose(); +} + +int32_t StreamSocket::EpollCreate(int32_t size) +{ + epollFd_ = epoll_create(size); + if (epollFd_ < 0) { + SEN_HILOGE("Epoll_create return %{public}d", epollFd_); + } else { + SEN_HILOGI("Epoll_create, epollFd_:%{public}d", epollFd_); + } + return epollFd_; +} + +int32_t StreamSocket::EpollCtl(int32_t fd, int32_t op, struct epoll_event &event, int32_t epollFd) +{ + if (fd < 0) { + SEN_HILOGE("Invalid fd"); + return ERROR; + } + if (epollFd < 0) { + epollFd = epollFd_; + } + if (epollFd < 0) { + SEN_HILOGE("Invalid param epollFd"); + return ERROR; + } + int32_t ret; + if (op == EPOLL_CTL_DEL) { + ret = epoll_ctl(epollFd, op, fd, NULL); + } else { + ret = epoll_ctl(epollFd, op, fd, &event); + } + if (ret < 0) { + SEN_HILOGE("Epoll_ctl return %{public}d,epollFd_:%{public}d, op:%{public}d,fd:%{public}d,errno:%{public}d", + ret, epollFd, op, fd, errno); + } + return ret; +} + +int32_t StreamSocket::EpollWait(struct epoll_event &events, int32_t maxevents, int32_t timeout, int32_t epollFd) +{ + if (epollFd < 0) { + epollFd = epollFd_; + } + if (epollFd < 0) { + SEN_HILOGE("Invalid param epollFd"); + return ERROR; + } + auto ret = epoll_wait(epollFd, &events, maxevents, timeout); + if (ret < 0) { + SEN_HILOGE("Epoll_wait ret:%{public}d,errno:%{public}d", ret, errno); + } + return ret; +} + +void StreamSocket::OnReadPackets(CircleStreamBuffer &circBuf, StreamSocket::PacketCallBackFun callbackFun) +{ + constexpr int32_t headSize = static_cast(sizeof(PackHead)); + for (int32_t i = 0; i < PROTO_ONCE_PROCESS_NETPACKET_LIMIT; i++) { + const int32_t unreadSize = circBuf.UnreadSize(); + if (unreadSize < headSize) { + break; + } + int32_t dataSize = unreadSize - headSize; + char *buf = const_cast(circBuf.ReadBuf()); + CHKPB(buf); + PackHead *head = reinterpret_cast(buf); + CHKPB(head); + if (head->size < 0 || head->size > PROTO_MAX_PACKET_BUF_SIZE) { + SEN_HILOGE("Packet header parsing error, and this error cannot be recovered. The buffer will be reset." + " head->size:%{public}d, unreadSize:%{public}d", head->size, unreadSize); + circBuf.Reset(); + break; + } + if (head->size > dataSize) { + break; + } + NetPacket pkt(head->idMsg); + if ((head->size > 0) && (!pkt.Write(&buf[headSize], head->size))) { + SEN_HILOGW("Error writing data in the NetPacket. It will be retried next time. messageid:%{public}d," + "size:%{public}d", head->idMsg, head->size); + break; + } + if (!circBuf.SeekReadPos(pkt.GetPacketLength())) { + SEN_HILOGW("Set read position error, and this error cannot be recovered, and the buffer will be reset." + " packetSize:%{public}d unreadSize:%{public}d", pkt.GetPacketLength(), unreadSize); + circBuf.Reset(); + break; + } + callbackFun(pkt); + if (circBuf.IsEmpty()) { + circBuf.Reset(); + break; + } + } +} + +void StreamSocket::EpollClose() +{ + if (epollFd_ >= 0) { + close(epollFd_); + epollFd_ = -1; + } +} + +void StreamSocket::Close() +{ + if (fd_ >= 0) { + auto rf = close(fd_); + if (rf > 0) { + SEN_HILOGE("Socket close failed rf:%{public}d", rf); + } + } + fd_ = -1; +} + +int32_t StreamSocket::GetFd() const +{ + return fd_; +} +int32_t StreamSocket::GetEpollFd() const +{ + return epollFd_; +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file