diff --git a/bundle.json b/bundle.json index 22658b96136f3a3bd16a507e3b77c5831d9a86ab..689ab6e8c5a9c4f4ceba37d77162793fc4e1116a 100644 --- a/bundle.json +++ b/bundle.json @@ -44,7 +44,8 @@ "//foundation/resourceschedule/qos_manager/sa_profile:concurrent_task_sa_profile", "//foundation/resourceschedule/qos_manager/services:concurrentsvc", "//foundation/resourceschedule/qos_manager/frameworks/concurrent_task_client:concurrent_task_client", - "//foundation/resourceschedule/qos_manager/qos:qos" + "//foundation/resourceschedule/qos_manager/qos:qos", + "//foundation/resourceschedule/qos_manager/frameworks/native:qos_ndk" ], "inner_kits": [ { diff --git a/frameworks/native/BUILD.gn b/frameworks/native/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..77ad594dad820ed3a6bbe38d71aac57856d27dbe --- /dev/null +++ b/frameworks/native/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos/ndk/ndk.gni") + +ohos_shared_library("qos_ndk") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "../../interfaces/", + "../../interfaces/kits/c/", + ] + + sources = [ "qos_ndk.cpp" ] + + deps = [ "../../qos:qos" ] + + output_name = "qos" + output_extension = "so" + + innerapi_tags = [ "ndk" ] + subsystem_name = "resourceschedule" + part_name = "qos_manager" +} diff --git a/frameworks/native/qos_ndk.cpp b/frameworks/native/qos_ndk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46b0abc40fafee0a57c5e611e82c402744b6cd96 --- /dev/null +++ b/frameworks/native/qos_ndk.cpp @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2024 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 "qos.h" +#include "inner_api/qos.h" +#include +#include +#include + +static constexpr int ERROR_NUM = -1; + +using namespace OHOS::QOS; +using namespace std; + +const unordered_map qos_map = { + {QoS_Level::QOS_BACKGROUND, QosLevel::QOS_BACKGROUND}, + {QoS_Level::QOS_UTILITY, QosLevel::QOS_UTILITY}, + {QoS_Level::QOS_DEFAULT, QosLevel::QOS_DEFAULT}, + {QoS_Level::QOS_USER_INITIATED, QosLevel::QOS_USER_INITIATED}, + {QoS_Level::QOS_DEADLINE_REQUEST, QosLevel::QOS_DEADLINE_REQUEST}, + {QoS_Level::QOS_USER_INTERACTIVE, QosLevel::QOS_USER_INTERACTIVE} +}; + +const unordered_map qos_reverse_map = { + {QosLevel::QOS_BACKGROUND, QoS_Level::QOS_BACKGROUND}, + {QosLevel::QOS_UTILITY, QoS_Level::QOS_UTILITY}, + {QosLevel::QOS_DEFAULT, QoS_Level::QOS_DEFAULT}, + {QosLevel::QOS_USER_INITIATED, QoS_Level::QOS_USER_INITIATED}, + {QosLevel::QOS_DEADLINE_REQUEST, QoS_Level::QOS_DEADLINE_REQUEST}, + {QosLevel::QOS_USER_INTERACTIVE, QoS_Level::QOS_USER_INTERACTIVE} +}; + + +int OH_QoS_SetThreadQoS(QoS_Level level) +{ + auto iter = qos_map.find(level); + if (iter == qos_map.end()) { + return ERROR_NUM; + } + return QosController::GetInstance().SetThreadQosForOtherThread(iter->second, gettid()); +} + +int OH_QoS_ResetThreadQoS(void) +{ + return QosController::GetInstance().ResetThreadQosForOtherThread(gettid()); +} + +int OH_QoS_GetThreadQoS(QoS_Level *level) +{ + if (level == nullptr) { + return ERROR_NUM; + } + enum QosLevel qosLevel; + int ret = QosController::GetInstance().GetThreadQosForOtherThread(qosLevel, gettid()); + if (ret < 0) { + return ERROR_NUM; + } + auto iter = qos_reverse_map.find(qosLevel); + if (iter == qos_reverse_map.end()) { + return ERROR_NUM; + } + *level = iter->second; + return 0; +} \ No newline at end of file diff --git a/interfaces/inner_api/qos.h b/interfaces/inner_api/qos.h index c74ff55564ea34531892d7b53e3d4900e2ce4931..e8d3724fd116bce8918f80a0972fd49fb0b17702 100644 --- a/interfaces/inner_api/qos.h +++ b/interfaces/inner_api/qos.h @@ -35,6 +35,7 @@ public: int SetThreadQosForOtherThread(enum QosLevel level, int tid); int ResetThreadQosForOtherThread(int tid); + int GetThreadQosForOtherThread(enum QosLevel &level, int tid); private: QosController() = default; @@ -50,6 +51,7 @@ int SetThreadQos(enum QosLevel level); int SetQosForOtherThread(enum QosLevel level, int tid); int ResetThreadQos(); int ResetQosForOtherThread(int tid); +int GetThreadQos(enum QosLevel &level); } // namespace QOS } // namespace OHOS diff --git a/interfaces/kits/BUILD.gn b/interfaces/kits/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f8791c128e5ecebf0dc97fc62a6a7b578592b361 --- /dev/null +++ b/interfaces/kits/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos/ndk/ndk.gni") + +ohos_ndk_headers("qos_header") { + dest_dir = "$ndk_headers_out_dir/qos" + sources = [ "./c/qos.h" ] +} + +ohos_ndk_library("libqos_ndk") { + output_name = "qos" + output_extension = "so" + ndk_description_file = "./libqos.ndk.json" + system_capability = "SystemCapability.Resourceschedule.QoS.Core" + system_capability_headers = [ "$ndk_headers_out_dir/qos/qos.h" ] +} diff --git a/interfaces/kits/c/qos.h b/interfaces/kits/c/qos.h new file mode 100644 index 0000000000000000000000000000000000000000..c92ab5b8622578b0b086fb042b15bda961c48c97 --- /dev/null +++ b/interfaces/kits/c/qos.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 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 QOS_H +#define QOS_H +/** + * @addtogroup QoS + * @{ + * + * @brief QoS provides APIs. + * + * @since 12 + */ + +/** + * @file qos.h + * + * @brief Declares the QoS interfaces in C. + * + * Quality-of-service (QoS) refers to the priority scheduling attribute of tasks + * in OpenHarmony. Developers can use QoS to categorize tasks to be executed to + * indicate the degree of their relevance to user interactions, the system can + * schedule the time and running order of tasks according to the QoS set by the tasks. + * + * @library libqos.so + * @syscap SystemCapability.Resourceschedule.QoS.Core + * @since 12 + */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Describes the level of QoS. + * + * @since 12 + */ +typedef enum QoS_Level { + /** + * @brief Means the QoS level is background. + */ + QOS_BACKGROUND = 0, + + /** + * @brief Means the QoS level is utility. + */ + QOS_UTILITY, + + /** + * @brief Means the QoS level is default. + */ + QOS_DEFAULT, + + /** + * @brief Means the QoS level is user-initiated. + */ + QOS_USER_INITIATED, + + /** + * @brief Means the QoS level is user-request. + */ + QOS_DEADLINE_REQUEST, + + /** + * @brief Means the QoS level is user-interactive. + */ + QOS_USER_INTERACTIVE, +} QoS_Level; + +/** + * @brief Set the QoS level of the current thread. + * + * @param level Indicates the level to set. Specific level can be referenced {@link QoS_Level}. + * @return Returns int32_t, return value == 0, success, otherwise value == -1, failed. + * @see QoS_Level + * @since 12 + */ +int OH_QoS_SetThreadQoS(QoS_Level level); + +/** + * @brief Cancel the QoS level of the current thread. + * + * @return Returns int32_t, return value == 0, success, otherwise value == -1, failed. + * @see QoS_Level + * @since 12 + */ +int OH_QoS_ResetThreadQoS(); + +/** + * @brief Obtains the QoS level of the current thread. + * + * @param level This parameter is the output parameter, + * and the QoS level of the thread as a {@link QoS_Level} is written to this variable. + * @return Returns int32_t, return value == 0, success, otherwise value == -1, failed. + * @see QoS_Level + * @since 12 + */ +int OH_QoS_GetThreadQoS(QoS_Level *level); +#ifdef __cplusplus +}; +#endif +#endif //QOS_H diff --git a/interfaces/kits/libqos.ndk.json b/interfaces/kits/libqos.ndk.json new file mode 100644 index 0000000000000000000000000000000000000000..e2b9422cc199e3766411686963a217cb823b3531 --- /dev/null +++ b/interfaces/kits/libqos.ndk.json @@ -0,0 +1,14 @@ +[ + { + "first_introduced": "12", + "name": "OH_QoS_SetThreadQoS" + }, + { + "first_introduced": "12", + "name": "OH_QoS_ResetThreadQoS" + }, + { + "first_introduced": "12", + "name": "OH_QoS_GetThreadQoS" + } +] \ No newline at end of file diff --git a/qos/qos.cpp b/qos/qos.cpp index 0fd92ca014165d259fa85cef8f0590d9c6e806d0..924f686590adb96aecdf68efd893669a99096b02 100644 --- a/qos/qos.cpp +++ b/qos/qos.cpp @@ -59,6 +59,26 @@ int QosController::ResetThreadQosForOtherThread(int tid) return ret; } +int QosController::GetThreadQosForOtherThread(enum QosLevel &level, int tid) +{ + int qos; + int ret = QosGetForOther(tid, qos); + if (ret == 0) { + CONCUR_LOGD("[Qos] qoslevel get for tid %{public}d success", tid); + } else { + CONCUR_LOGE("[Qos] qoslevel get for tid %{public}d failure", tid); + } +#ifdef QOS_EXT_ENABLE + level = static_cast(qos); + if (level < QosLevel::QOS_BACKGROUND || level >= QosLevel::QOS_MAX) { + level = QosLevel::QOS_DEFAULT; + } +#else + level = QosLevel::QOS_DEFAULT; +#endif + return ret; +} + int SetThreadQos(enum QosLevel level) { int tid = gettid(); @@ -80,5 +100,10 @@ int ResetQosForOtherThread(int tid) { return QosController::GetInstance().ResetThreadQosForOtherThread(tid); } + +int GetThreadQos(enum QosLevel &level) +{ + return QosController::GetInstance().GetThreadQosForOtherThread(level, gettid()); +} } // namespace QOS } // namespace OHOS diff --git a/services/include/qos_interface.h b/services/include/qos_interface.h index f32df50bd7d9a0d46162a6d1e4674894755d9f31..cafa8ac72cb5974964b6d7984ebb8dcdb6b36abe 100644 --- a/services/include/qos_interface.h +++ b/services/include/qos_interface.h @@ -179,6 +179,8 @@ int QosApplyForOther(unsigned int level, int tid); int QosLeave(void); int QosLeaveForOther(int tid); int QosPolicySet(const struct QosPolicyDatas *policyDatas); +int QosGet(int &level); +int QosGetForOther(int tid, int &level); #ifdef __cplusplus } diff --git a/services/src/qos_interface.cpp b/services/src/qos_interface.cpp index 0e27a43b16ea59889445988813c57c49e02ccb21..103c2abdd7069fa7b9e1aae566a06f954525c919 100644 --- a/services/src/qos_interface.cpp +++ b/services/src/qos_interface.cpp @@ -332,3 +332,36 @@ int QosPolicySet(const struct QosPolicyDatas *policyDatas) close(fd); return ret; } + +int QosGet(int &level) +{ + int tid = gettid(); + return QosGetForOther(tid, level); +} + +int QosGetForOther(int tid, int &level) +{ + int fd; + int ret = 0; + + fd = TrivalOpenQosCtrlNode(); + if (fd < 0) { + return fd; + } +#ifdef QOS_EXT_ENABLE + struct QosCtrlData data; + data.type = static_cast(QosManipulateType::QOS_GET); + data.pid = tid; + data.qos = -1; + + ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data); +#ifdef QOS_DEBUG + if (ret < 0) { + printf("get qos failed for task %d\n", tid); + } +#endif + level = data.qos; +#endif + close(fd); + return ret; +} \ No newline at end of file diff --git a/test/BUILD.gn b/test/BUILD.gn index 50494997058524410a49ade3f1fac346ebd6a93e..cc3690afa244b3b8736e1e5e6e23557a8b0ceeb9 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -24,6 +24,7 @@ config("test_config") { "../include/", "../frameworks/concurrent_task_client/include", "../interfaces/inner_api/", + "../interfaces/kits/", "../services/include/", "//third_party/jsoncpp/include/", "//foundation/resourceschedule/frame_aware_sched/common/include/", @@ -143,6 +144,7 @@ ohos_unittest("qos_interface_test") { configs = [ ":test_config" ] sources = [ "unittest/phone/qos_interface_test.cpp" ] + deps = [ "../frameworks/concurrent_task_client:concurrent_task_client", "../services:concurrentsvc", @@ -218,6 +220,7 @@ ohos_unittest("qos_test") { configs = [ ":test_config" ] sources = [ "unittest/phone/qos_test.cpp" ] + deps = [ "../qos:qos" ] external_deps = [ "c_utils:utils", @@ -232,6 +235,30 @@ ohos_unittest("qos_test") { part_name = "qos_manager" } +ohos_unittest("qos_ndk_test") { + module_out_path = module_output_path + + configs = [ ":test_config" ] + + sources = [ "unittest/phone/qos_ndk_test.cpp" ] + + deps = [ + "../frameworks/native:qos_ndk", + "../qos:qos", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + + if (is_standard_system) { + public_deps = gtest_public_deps + } + + subsystem_name = "resourceschedule" + part_name = "qos_manager" +} + group("concurrent_unittest") { testonly = true deps = [] @@ -243,6 +270,7 @@ group("concurrent_unittest") { ":concurrent_task_service_ability_test", ":concurrent_task_service_test", ":qos_interface_test", + ":qos_ndk_test", ":qos_policy_test", ":qos_test", ] diff --git a/test/unittest/phone/qos_interface_test.cpp b/test/unittest/phone/qos_interface_test.cpp index e45def569e6e62f9deb668d0e1037ac313b9c8de..485c508e831cda5a0c7bb431c3967acfb0001db8 100644 --- a/test/unittest/phone/qos_interface_test.cpp +++ b/test/unittest/phone/qos_interface_test.cpp @@ -261,6 +261,44 @@ HWTEST_F(QosInterfaceTest, QosPolicyTest, TestSize.Level1) EXPECT_EQ(ret, 0); #endif } + +/** + * @tc.name: QosGetTest + * @tc.desc: Test whether the QosGet interface are normal. + * @tc.type: FUNC + */ +HWTEST_F(QosInterfaceTest, QosGetTest, TestSize.Level1) +{ + int qos; + unsigned int level = 4; + int ret = QosApply(level); + EXPECT_EQ(ret, 0); +#ifdef QOS_EXT_ENABLE + ret = QosGet(qos); + sleep(5); + EXPECT_EQ(ret, 0); + EXPECT_EQ(qos, level); +#endif +} + +/** + * @tc.name: QosGetForOtherTest + * @tc.desc: Test whether the QosGetForOther interface are normal. + * @tc.type: FUNC + */ +HWTEST_F(QosInterfaceTest, QosGetForOtherTest, TestSize.Level1) +{ + int qos; + unsigned int level = 3; + int tid = gettid(); + int ret = QosApplyForOther(level, tid); + EXPECT_EQ(ret, 0); +#ifdef QOS_EXT_ENABLE + ret = QosGetForOther(tid, qos); + EXPECT_EQ(ret, 0); + EXPECT_EQ(qos, level); +#endif +} } } } diff --git a/test/unittest/phone/qos_ndk_test.cpp b/test/unittest/phone/qos_ndk_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b0e9005a05e8c971df701b105df9d1b76f54999 --- /dev/null +++ b/test/unittest/phone/qos_ndk_test.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include "c/qos.h" + +namespace OHOS { +namespace QOS { +using namespace testing; +using namespace testing::ext; +using namespace OHOS::QOS; + +class QoSNdkTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void QoSNdkTest::SetUpTestCase() +{ +} + +void QoSNdkTest::TearDownTestCase() +{ +} + +void QoSNdkTest::SetUp() +{ +} + +void QoSNdkTest::TearDown() +{ +} + +/** + * @tc.name: QoSNdkTest + * @tc.desc: Verify the Set and Reset QoSLevel function. + * @tc.type: FUNC + */ +HWTEST_F(QoSNdkTest, SetThreadQoSNdkTest1, TestSize.Level1) +{ + int ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_BACKGROUND); + EXPECT_EQ(ret, 0); + ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_UTILITY); + EXPECT_EQ(ret, 0); + ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_DEFAULT); + EXPECT_EQ(ret, 0); + ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_USER_INITIATED); + EXPECT_EQ(ret, 0); + ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_DEADLINE_REQUEST); + EXPECT_EQ(ret, 0); + ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_USER_INTERACTIVE); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(QoSNdkTest, ResetThreadQoSNdkTest, TestSize.Level1) +{ + int ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_USER_INTERACTIVE); + EXPECT_EQ(ret, 0); + ret = OH_QoS_ResetThreadQoS(); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(QoSNdkTest, GetThreadQoSNdkTest1, TestSize.Level1) +{ + int ret = OH_QoS_GetThreadQoS(nullptr); + EXPECT_EQ(ret, -1); +#ifdef QOS_EXT_ENABLE + ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_USER_INTERACTIVE); + EXPECT_EQ(ret, 0); + enum QoS_Level level; + ret = OH_QoS_GetThreadQoS(&level); + EXPECT_EQ(ret, 0); + EXPECT_EQ(level, QoS_Level::QOS_USER_INTERACTIVE); +#endif +} + + +} // QOS +} // OHOS \ No newline at end of file diff --git a/test/unittest/phone/qos_test.cpp b/test/unittest/phone/qos_test.cpp index 9ad18425ba20092af40d88ab6629bf4b1398471d..12f07d4c57defd6b10fdc7ebad2fc5ca21c0527d 100644 --- a/test/unittest/phone/qos_test.cpp +++ b/test/unittest/phone/qos_test.cpp @@ -100,5 +100,31 @@ HWTEST_F(QosTest, ResetThreadQosTest2, TestSize.Level1) ret = ResetQosForOtherThread(gettid()); EXPECT_EQ(ret, 0); } + +HWTEST_F(QosTest, GetThreadQosTest1, TestSize.Level1) +{ + int ret = SetThreadQos(QosLevel::QOS_USER_INITIATED); + EXPECT_EQ(ret, 0); + enum QosLevel level; +#ifdef QOS_EXT_ENABLE + ret = GetThreadQos(level); + EXPECT_EQ(ret, 0); + EXPECT_EQ(static_cast(level), static_cast(QosLevel::QOS_USER_INITIATED)); + ret = SetThreadQos(QosLevel::QOS_USER_INTERACTIVE); + EXPECT_EQ(ret, 0); + ret = GetThreadQos(level); + EXPECT_EQ(ret, 0); + EXPECT_EQ(static_cast(level), static_cast(QosLevel::QOS_USER_INTERACTIVE)); +#endif +} + +HWTEST_F(QosTest, GetThreadQosTest2, TestSize.Level1) +{ + int ret = ResetThreadQos(); + EXPECT_EQ(ret, 0); + enum QosLevel level; + ret = GetThreadQos(level); + EXPECT_EQ(ret, 0); +} } // QOS } // OHOS \ No newline at end of file