获取应用显存

Signed-off-by: yuhaoqiang <yuhaoqiang@huawei.com>
This commit is contained in:
yuhaoqiang 2024-08-14 17:28:16 +08:00
parent 868314ea98
commit e379f65239
13 changed files with 394 additions and 51 deletions

View File

@ -163,3 +163,20 @@ HiDebug_ErrorCode OH_HiDebug_StopAppTraceCapture()
} }
return nativeInterface->StopAppTraceCapture(); return nativeInterface->StopAppTraceCapture();
} }
HiDebug_ErrorCode OH_HiDebug_GetGraphicsMemory(uint32_t *value)
{
if (value == nullptr) {
return HIDEBUG_INVALID_ARGUMENT;
}
auto nativeInterface = OHOS::HiviewDFX::HidebugNativeInterface::CreateInstance();
if (!nativeInterface) {
return HIDEBUG_TRACE_ABNORMAL;
}
std::optional<int32_t> ret = nativeInterface->GetGraphicsMemory();
if (!ret.has_value() || ret < 0) {
return HIDEBUG_TRACE_ABNORMAL;
}
*value = static_cast<uint32_t>(ret.value());
return HIDEBUG_SUCCESS;
}

View File

@ -54,6 +54,7 @@ ohos_shared_library("hidebug_native") {
sources = [ sources = [
"src/hidebug_app_thread_cpu.cpp", "src/hidebug_app_thread_cpu.cpp",
"src/hidebug_native_interface_impl.cpp", "src/hidebug_native_interface_impl.cpp",
"src/hidebug_util.cpp",
] ]
external_deps = [ external_deps = [

View File

@ -52,6 +52,7 @@ public:
virtual std::optional<HiDebug_NativeMemInfo> GetAppNativeMemInfo() = 0; virtual std::optional<HiDebug_NativeMemInfo> GetAppNativeMemInfo() = 0;
virtual std::optional<SysMemory> GetSystemMemInfo() = 0; virtual std::optional<SysMemory> GetSystemMemInfo() = 0;
virtual bool IsDebuggerConnected() = 0; virtual bool IsDebuggerConnected() = 0;
virtual std::optional<int32_t> GetGraphicsMemory() = 0;
}; };
} }
} }

View File

@ -0,0 +1,51 @@
/*
* 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 HIDEBUG_UTIL_H_
#define HIDEBUG_UTIL_H_
#include <cstdint>
#include <functional>
#include <optional>
namespace OHOS {
namespace HiviewDFX {
int64_t GetElapsedNanoSecondsSinceBoot();
template<typename T>
class CachedValue {
public:
CachedValue() = default;
std::optional<T> GetOrUpdateCachedValue(int64_t effectiveTime, std::function<bool(T &)> getValue)
{
int64_t currentTime = GetElapsedNanoSecondsSinceBoot();
if (currentTime <= expirationTime_) {
return cachedValue_;
}
if (getValue(cachedValue_)) {
expirationTime_ = currentTime + effectiveTime;
return cachedValue_;
}
return {};
};
private:
T cachedValue_;
int64_t expirationTime_ = -1;
};
}
}
#endif // HIDEBUG_UTIL_H_

View File

@ -23,6 +23,7 @@
#include "dump_usage.h" #include "dump_usage.h"
#include "hidebug_app_thread_cpu.h" #include "hidebug_app_thread_cpu.h"
#include "hidebug_util.h"
#include "hilog/log.h" #include "hilog/log.h"
#include "client/cpu_collector.h" #include "client/cpu_collector.h"
#include "client/memory_collector.h" #include "client/memory_collector.h"
@ -52,17 +53,8 @@ public:
std::optional<HiDebug_NativeMemInfo> GetAppNativeMemInfo() override; std::optional<HiDebug_NativeMemInfo> GetAppNativeMemInfo() override;
std::optional<SysMemory> GetSystemMemInfo() override; std::optional<SysMemory> GetSystemMemInfo() override;
bool IsDebuggerConnected() override; bool IsDebuggerConnected() override;
std::optional<int32_t> GetGraphicsMemory() override;
private: private:
/**
* GetElapsedNanoSecondsSinceBoot
*
* @return NanoSecondsSinceBoot
*/
int64_t GetElapsedNanoSecondsSinceBoot();
constexpr static int SECOND_TO_NANOSECOND = 1 * 1000 * 1000 * 1000;
constexpr static int CPU_USAGE_VALIDITY = 2 * SECOND_TO_NANOSECOND; // 2s
static inline int64_t lastCpuUsageGetTime_ = 0;
static inline double lastCpuUsage_ = 0;
static inline HidebugAppThreadCpu threadCpu_; static inline HidebugAppThreadCpu threadCpu_;
}; };
@ -127,26 +119,24 @@ HiDebug_ErrorCode HidebugNativeInterfaceImpl::StopAppTraceCapture()
std::optional<double> HidebugNativeInterfaceImpl::GetSystemCpuUsage() std::optional<double> HidebugNativeInterfaceImpl::GetSystemCpuUsage()
{ {
static CachedValue<double> cachedCpuUsage;
HILOG_INFO(LOG_CORE, "GetSystemCpuUsage"); HILOG_INFO(LOG_CORE, "GetSystemCpuUsage");
int64_t now = GetElapsedNanoSecondsSinceBoot(); constexpr const int64_t effectiveTime = 2 * 1000 * 1000 * 1000; // 2s
if (lastCpuUsageGetTime_ > 0 && now <= lastCpuUsageGetTime_ + CPU_USAGE_VALIDITY) { return cachedCpuUsage.GetOrUpdateCachedValue(effectiveTime, [](double& cachedValue) {
HILOG_WARN(LOG_CORE, "GetSystemCpuUsage too frequently, return the last result");
return lastCpuUsage_;
}
std::shared_ptr<UCollectClient::CpuCollector> collector = UCollectClient::CpuCollector::Create(); std::shared_ptr<UCollectClient::CpuCollector> collector = UCollectClient::CpuCollector::Create();
if (!collector) { if (!collector) {
HILOG_ERROR(LOG_CORE, "GetSystemCpuUsage Failed, return the last result"); HILOG_ERROR(LOG_CORE, "GetSystemCpuUsage Failed");
return std::nullopt; return false;
} }
auto collectResult = collector->GetSysCpuUsage(); auto collectResult = collector->GetSysCpuUsage();
if (collectResult.retCode != UCollect::UcError::SUCCESS) { if (collectResult.retCode != UCollect::UcError::SUCCESS) {
HILOG_ERROR(LOG_CORE, "GetSystemCpuUsage Failed, retCode: %{public}d, return the last result", HILOG_ERROR(LOG_CORE, "GetSystemCpuUsage Failed, retCode: %{public}d",
static_cast<int>(collectResult.retCode)); static_cast<int>(collectResult.retCode));
return std::nullopt; return false;
} }
lastCpuUsage_ = collectResult.data; cachedValue = collectResult.data;
lastCpuUsageGetTime_ = GetElapsedNanoSecondsSinceBoot(); return true;
return lastCpuUsage_; });
} }
std::optional<MemoryLimit> HidebugNativeInterfaceImpl::GetAppMemoryLimit() std::optional<MemoryLimit> HidebugNativeInterfaceImpl::GetAppMemoryLimit()
@ -266,11 +256,25 @@ bool HidebugNativeInterfaceImpl::IsDebuggerConnected()
return false; return false;
} }
int64_t HidebugNativeInterfaceImpl::GetElapsedNanoSecondsSinceBoot() std::optional<int32_t> HidebugNativeInterfaceImpl::GetGraphicsMemory()
{ {
struct timespec times = {0, 0}; static CachedValue<int32_t> cachedGraphicUsage;
clock_gettime(CLOCK_MONOTONIC, &times); constexpr const int64_t effectiveTime = 2 * 1000 * 1000 * 1000; // 2s
return times.tv_sec * SECOND_TO_NANOSECOND + times.tv_nsec; return cachedGraphicUsage.GetOrUpdateCachedValue(effectiveTime, [](int32_t& cachedValue) {
auto collector = UCollectClient::MemoryCollector::Create();
if (!collector) {
HILOG_ERROR(LOG_CORE, "GetGraphicUsage Failed");
return false;
}
auto collectResult = collector->GetGraphicUsage();
if (collectResult.retCode != UCollect::UcError::SUCCESS) {
HILOG_ERROR(LOG_CORE, "GetGraphicUsage Failed,retCode = %{public}d",
static_cast<int>(collectResult.retCode));
return false;
}
cachedValue = collectResult.data;
return true;
});
} }
} }
} }

View File

@ -0,0 +1,31 @@
/*
* 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 "hidebug_util.h"
#include <ctime>
#include <thread>
namespace OHOS {
namespace HiviewDFX {
int64_t GetElapsedNanoSecondsSinceBoot()
{
struct timespec times = {0, 0};
clock_gettime(CLOCK_BOOTTIME, &times);
constexpr static int secondToNanosecond = 1 * 1000 * 1000 * 1000;
return times.tv_sec * secondToNanosecond + times.tv_nsec;
}
}
}

View File

@ -17,8 +17,8 @@ import("//developtools/profiler/hidebug/hidebug.gni")
ohos_shared_library("hidebug") { ohos_shared_library("hidebug") {
include_dirs = [ include_dirs = [
"util",
"$hidebug_path/frameworks/native/include", "$hidebug_path/frameworks/native/include",
".",
"$hidebug_path/interfaces/native/kits/include", "$hidebug_path/interfaces/native/kits/include",
] ]
@ -26,6 +26,7 @@ ohos_shared_library("hidebug") {
"napi_hidebug.cpp", "napi_hidebug.cpp",
"napi_hidebug_gc.cpp", "napi_hidebug_gc.cpp",
"napi_hidebug_init.cpp", "napi_hidebug_init.cpp",
"util/napi_util.cpp",
] ]
deps = [ "$hidebug_path/frameworks/native:hidebug_native" ] deps = [ "$hidebug_path/frameworks/native:hidebug_native" ]

View File

@ -45,6 +45,7 @@
#include "storage_acl.h" #include "storage_acl.h"
#include "system_ability_definition.h" #include "system_ability_definition.h"
#include "napi_hidebug_gc.h" #include "napi_hidebug_gc.h"
#include "napi_util.h"
namespace OHOS { namespace OHOS {
namespace HiviewDFX { namespace HiviewDFX {
@ -310,22 +311,6 @@ static bool GetTraceParam(napi_env env, napi_callback_info info,
return true; return true;
} }
static napi_value CreateUndefined(napi_env env)
{
napi_value res = nullptr;
napi_get_undefined(env, &res);
return res;
}
static napi_value CreateErrorMessage(napi_env env, std::string msg)
{
napi_value result = nullptr;
napi_value message = nullptr;
napi_create_string_utf8(env, (char *)msg.data(), msg.size(), &message);
napi_create_error(env, nullptr, message, &result);
return result;
}
napi_value StartProfiling(napi_env env, napi_callback_info info) napi_value StartProfiling(napi_env env, napi_callback_info info)
{ {
std::string fileName = GetFileNameParam(env, info); std::string fileName = GetFileNameParam(env, info);
@ -1027,6 +1012,52 @@ napi_value IsDebugState(napi_env env, napi_callback_info info)
return result; return result;
} }
class GraphicAsyncTask : public AsyncTask {
public:
GraphicAsyncTask() : AsyncTask("graphicAsyncTask") {}
protected:
void Work(napi_env env) override
{
result_ = HidebugNativeInterface::CreateInstance()->GetGraphicsMemory();
}
void Done(napi_env env, napi_status status) override
{
if (result_.has_value()) {
napi_value ret;
napi_create_int32(env, result_.value(), &ret);
napi_resolve_deferred(env, deferred_, ret);
} else {
constexpr const char* errMsg = "Failed to get the application memory due to a remote exception";
napi_reject_deferred(env, deferred_,
CreateErrorMessage(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL), errMsg));
}
}
private:
std::optional<int> result_{};
};
napi_value GetGraphicsMemory(napi_env env, napi_callback_info info)
{
return AsyncTask::GetPromise<GraphicAsyncTask>(env);
}
napi_value GetGraphicsMemorySync(napi_env env, napi_callback_info info)
{
std::optional<int32_t> result = HidebugNativeInterface::CreateInstance()->GetGraphicsMemory();
if (result.has_value()) {
napi_value ret;
napi_create_int32(env, result.value(), &ret);
return ret;
}
constexpr const char* errMsg = "Failed to get the application memory due to a remote exception";
napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errMsg);
return CreateUndefined(env);
}
napi_value DeclareHiDebugInterface(napi_env env, napi_value exports) napi_value DeclareHiDebugInterface(napi_env env, napi_value exports)
{ {
napi_property_descriptor desc[] = { napi_property_descriptor desc[] = {
@ -1057,7 +1088,9 @@ napi_value DeclareHiDebugInterface(napi_env env, napi_value exports)
DECLARE_NAPI_FUNCTION("getVMRuntimeStats", GetVMRuntimeStats), DECLARE_NAPI_FUNCTION("getVMRuntimeStats", GetVMRuntimeStats),
DECLARE_NAPI_FUNCTION("getVMRuntimeStat", GetVMRuntimeStat), DECLARE_NAPI_FUNCTION("getVMRuntimeStat", GetVMRuntimeStat),
DECLARE_NAPI_FUNCTION("setAppResourceLimit", SetAppResourceLimit), DECLARE_NAPI_FUNCTION("setAppResourceLimit", SetAppResourceLimit),
DECLARE_NAPI_FUNCTION("isDebugState", IsDebugState) DECLARE_NAPI_FUNCTION("isDebugState", IsDebugState),
DECLARE_NAPI_FUNCTION("getGraphicsMemory", GetGraphicsMemory),
DECLARE_NAPI_FUNCTION("getGraphicsMemorySync", GetGraphicsMemorySync),
}; };
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
InitNapiClass(env, exports); InitNapiClass(env, exports);

View File

@ -0,0 +1,77 @@
/*
* 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 "napi_util.h"
namespace OHOS {
namespace HiviewDFX {
napi_value CreateErrorMessage(napi_env env, const std::string& msg)
{
napi_value result = nullptr;
napi_value message = nullptr;
napi_create_string_utf8(env, (char *)msg.data(), msg.size(), &message);
napi_create_error(env, nullptr, message, &result);
return result;
}
napi_value CreateErrorMessage(napi_env env, const std::string& errCode, const std::string& msg)
{
napi_value result = nullptr;
napi_value message = nullptr;
napi_value code = nullptr;
napi_create_string_utf8(env, errCode.data(), errCode.size(), &code);
napi_create_string_utf8(env, msg.data(), msg.size(), &message);
napi_create_error(env, code, message, &result);
return result;
}
napi_value CreateUndefined(napi_env env)
{
napi_value res = nullptr;
napi_get_undefined(env, &res);
return res;
}
bool AsyncTask::CreatePromise(napi_env env, napi_value &promise)
{
if (napi_create_promise(env, &deferred_, &promise) != napi_ok) {
return false;
}
napi_value resourceName;
if (napi_create_string_utf8(env, resourceName_.c_str(), resourceName_.size(), &resourceName) != napi_ok) {
return false;
};
if (napi_create_async_work(env, nullptr, resourceName, ExecuteCallBack, CompletedCallBack,
static_cast<void *>(this), &worker_) != napi_ok) {
return false;
}
return napi_queue_async_work(env, worker_) == napi_ok;
}
void AsyncTask::ExecuteCallBack(napi_env env, void* data)
{
auto asyncTaskPtr = reinterpret_cast<AsyncTask *>(data);
asyncTaskPtr->Work(env);
}
void AsyncTask::CompletedCallBack(napi_env env, napi_status status, void* data)
{
auto asyncTaskPtr = reinterpret_cast<AsyncTask *>(data);
asyncTaskPtr->Done(env, status);
napi_delete_async_work(env, asyncTaskPtr->worker_);
delete asyncTaskPtr;
}
} // namespace HiviewDFX
} // namespace OHOS

View File

@ -0,0 +1,70 @@
/*
* 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 HIDEBUG_ASYNCTASK_H_
#define HIDEBUG_ASYNCTASK_H_
#include "napi/native_api.h"
#include <functional>
#include <string>
#include <type_traits>
namespace OHOS {
namespace HiviewDFX {
napi_value CreateErrorMessage(napi_env env, const std::string& msg);
napi_value CreateErrorMessage(napi_env env, const std::string& errCode, const std::string& msg);
napi_value CreateUndefined(napi_env env);
class AsyncTask {
public:
explicit AsyncTask(const std::string& resourceName): resourceName_(resourceName) {};
virtual ~AsyncTask() = default;
template<typename T, typename = typename std::enable_if<std::is_base_of<AsyncTask, T>::value>::type>
static napi_value GetPromise(napi_env env, std::function<void(T*)> setReqParam = [](T*) {})
{
napi_value promise = nullptr;
T* asyncTask = new (std::nothrow) T();
if (asyncTask == nullptr) {
return nullptr;
}
setReqParam(asyncTask);
if (!asyncTask->CreatePromise(env, promise)) {
delete asyncTask;
return nullptr;
}
return promise;
};
protected:
napi_async_work worker_ = nullptr;
napi_deferred deferred_ = nullptr;
std::string resourceName_;
virtual void Work(napi_env env) = 0;
virtual void Done(napi_env env, napi_status status) = 0;
private:
bool CreatePromise(napi_env env, napi_value& promise);
static void ExecuteCallBack(napi_env env, void* data);
static void CompletedCallBack(napi_env env, napi_status status, void* data);
};
}
}
#endif //HIDEBUG_ASYNCTASK_H_

View File

@ -138,6 +138,18 @@ HiDebug_ErrorCode OH_HiDebug_StartAppTraceCapture(HiDebug_TraceFlag flag,
*/ */
HiDebug_ErrorCode OH_HiDebug_StopAppTraceCapture(); HiDebug_ErrorCode OH_HiDebug_StopAppTraceCapture();
/**
* @brief Get the graphics memory of application.
*
* @param value Indicates value of graphics memory, in kibibytes.
* @return Result code
* {@link HIDEBUG_SUCCESS} Get graphics memory success.
* {@link HIDEBUG_INVALID_ARGUMENT} Invalid argumentvalue is null.
* {@link HIDEBUG_TRACE_ABNORMAL} Failed to get the application memory due to a remote exception.
* @since 13
*/
HiDebug_ErrorCode OH_HiDebug_GetGraphicsMemory(uint32_t *value);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif // __cplusplus #endif // __cplusplus

View File

@ -760,4 +760,38 @@ describe("HidebugJsTest", function () {
console.info(error.message); console.info(error.message);
} }
}) })
/**
* @tc.name: HidebugJsTest_034
* @tc.desc: getGraphicsMemory
* @tc.type: FUNC
*/
it('HidebugJsTest_034', 0, async function () {
console.info("---------------------------HidebugJsTest_034----------------------------------");
try {
let graphicMemory = await getGraphicsMemory();
expect(graphicMemory >= 0).assertTrue();
} catch (err) {
console.info(error.code);
console.info(error.message);
expect(false).assertTrue();
}
})
/**
* @tc.name: HidebugJsTest_035
* @tc.desc: getGraphicsMemorySync
* @tc.type: FUNC
*/
it('HidebugJsTest_035', 0, function () {
console.info("---------------------------HidebugJsTest_035----------------------------------");
try {
let graphicMemory = getGraphicsMemorySync();
expect(graphicMemory >= 0).assertTrue();
} catch (err) {
console.info(error.code);
console.info(error.message);
expect(false).assertTrue();
}
})
}) })

View File

@ -306,4 +306,15 @@ HWTEST_F(HidebugTest, OH_HiDebug_StartAppTraceCapture3, TestSize.Level1)
} }
} }
/**
* @tc.name: OH_HiDebug_GetGraphicsMemory
* @tc.desc: test OH_HiDebug_GetGraphicsMemory. get graphics memory.
* @tc.type: FUNC
*/
HWTEST_F(HidebugTest, OH_HiDebug_GetGraphicsMemory, TestSize.Level1)
{
uint32_t value = 0;
EXPECT_EQ(OH_HiDebug_GetGraphicsMemory(&value), HIDEBUG_SUCCESS);
EXPECT_GE(value, 0);
}
} // namespace } // namespace