0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

鴻蒙開發(fā)實(shí)戰(zhàn):【性能調(diào)優(yōu)組件】

jf_46214456 ? 來(lái)源:jf_46214456 ? 作者:jf_46214456 ? 2024-03-13 15:12 ? 次閱讀

簡(jiǎn)介

性能調(diào)優(yōu)組件包含系統(tǒng)和應(yīng)用調(diào)優(yōu)框架,旨在為開發(fā)者提供一套性能調(diào)優(yōu)平臺(tái),可以用來(lái)分析內(nèi)存、性能等問題。

該組件整體分為PC端和設(shè)備端兩部分,PC端最終作為deveco studio的插件進(jìn)行發(fā)布,內(nèi)部主要包括分為UI繪制、設(shè)備管理、進(jìn)程管理、插件管理、數(shù)據(jù)導(dǎo)入、數(shù)據(jù)存儲(chǔ)、 數(shù)據(jù)分析、Session管理、配置管理等模塊;設(shè)備端主要包括命令行工具、服務(wù)進(jìn)程、插件集合、應(yīng)用程序組件等模塊。設(shè)備端提供了插件擴(kuò)展能力,對(duì)外提供了插件接口,基于該擴(kuò)展能力可以按需定義自己的能力,并集成到框架中來(lái),目前基于插件能力已經(jīng)完成了實(shí)時(shí)內(nèi)存插件,trace插件。下文會(huì)重點(diǎn)對(duì)設(shè)備端提供的插件能力進(jìn)行介紹。

架構(gòu)圖

說明

下面針對(duì)設(shè)備端對(duì)外提供的插件擴(kuò)展能力進(jìn)行接口和使用說明。

接口說明

下面是設(shè)備端插件模塊對(duì)外提供的接口:

  • PluginModuleCallbacks為插件模塊對(duì)外提供的回調(diào)接口,插件管理模塊通過該回調(diào)接口列表與每一個(gè)插件模塊進(jìn)行交互,每一個(gè)新增插件都需要實(shí)現(xiàn)該接口列表中的函數(shù)。

表 1 PluginModuleCallbacks接口列表

[]()

[]()[]()接口名[]()[]()類型[]()[]()描述
[]()[]()PluginModuleCallbacks::onPluginSessionStart[]()[]()int (PluginSessionStartCallback)(const uint8_tconfigData, uint32_t configSize);[]()[]()- 功能:
[]()[]()插件會(huì)話開始接口,開始插件會(huì)話時(shí)會(huì)被調(diào)用,用來(lái)下發(fā)插件配置
  • 輸入參數(shù)
    []()[]()configData:配置信息內(nèi)存塊起始地址
    []()[]()configSize:配置信息內(nèi)存塊字節(jié)數(shù)
  • 返回值:
    []()[]()0:成功
    []()[]()-1:失敗 |
    | []()[]()PluginModuleCallbacks::onPluginReportResult | []()[]()int (PluginReportResultCallback)(uint8_t bufferData, uint32_t bufferSize); | []()[]()- 功能:
    []()[]()插件結(jié)果上報(bào)接口類型,當(dāng)任務(wù)下發(fā)后,框架采集任務(wù)會(huì)周期性調(diào)用此接口請(qǐng)求回填數(shù)據(jù)
  • 輸入?yún)?shù):
    []()[]()bufferData: 存放結(jié)果的內(nèi)存緩沖區(qū)起始地址
    []()[]()bufferSize: 存放結(jié)果的內(nèi)存緩沖區(qū)的字節(jié)數(shù)
  • 返回值:
    []()[]()大于0:已經(jīng)填充的內(nèi)存字節(jié)數(shù)
    []()[]()等于0:沒有填充任何內(nèi)容
    []()[]()小于0:失敗 |
    | []()[]()PluginModuleCallbacks::onPluginSessionStop | []()[]()int (*PluginSessionStopCallback)(); | []()[]()- 功能:
    []()[]()采集會(huì)話結(jié)束接口
  • 返回值:
    []()[]()0:成功
    []()[]()-1:失敗 |
    | []()[]()PluginModuleCallbacks::onRegisterWriterStruct | []()[]()int (RegisterWriterStructCallback)(WriterStruct writer); | []()[]()- 功能:
    []()[]()采集框架注冊(cè)寫數(shù)據(jù)接口,當(dāng)插件管理模塊向插件注冊(cè)此接口,插件可以主動(dòng)調(diào)用write句柄,進(jìn)行寫入數(shù)據(jù)
  • 輸入?yún)?shù):
    []()[]()writer 寫者指針
  • 返回值:
    []()[]()0:成功
    []()[]()-1:失敗 |
  • WriterStruct是上面onRegisterWriterStruct接口中的參數(shù),主要實(shí)現(xiàn)寫數(shù)據(jù)接口,將插件中采集的數(shù)據(jù)通過該接口進(jìn)行寫入。

表 2 WriterStruct接口列表

[]()

[]()[]()接口名[]()[]()類型[]()[]()描述
[]()[]()WriterStruct::write[]()[]()long (WriteFuncPtr)(WriterStructwriter, const void* data, size_t size);[]()[]()- 功能:
[]()[]()寫接口,將插件中采集的數(shù)據(jù)通過writer進(jìn)行寫入
  • 輸入?yún)?shù):
    []()[]()writer:寫者指針
    []()[]()data:數(shù)據(jù)緩沖區(qū)首字節(jié)指針
    []()[]()size: 數(shù)據(jù)緩沖區(qū)的字節(jié)數(shù)
  • 返回值:
    []()[]()0:成功
    []()[]()-1:失敗 |
    | []()[]()WriterStruct::flush | []()[]()bool (FlushFuncPtr)(WriterStruct writer); | []()[]()- 功能:
    []()[]()觸發(fā)數(shù)據(jù)上傳接口
  • 輸入?yún)?shù):
    []()[]()writer:寫者指針
  • 返回值:
    []()[]()true:成功
    []()[]()false:失敗 |
  • 下面是插件模塊對(duì)外提供的總?cè)肟?,主要包括?中的插件模塊回調(diào)函數(shù)以及插件名稱、插件模塊需要申請(qǐng)的內(nèi)存大小。

表 3 PluginModuleStruct接口列表

[]()

[]()[]()接口名[]()[]()類型[]()[]()描述
[]()[]()PluginModuleStruct::callbacks[]()[]()PluginModuleCallbacks*[]()[]()功能:定義插件回調(diào)函數(shù)列表
[]()[]()PluginModuleStruct::name[]()[]()C style string[]()[]()功能:定義插件名稱
[]()[]()PluginModuleStruct::resultBufferSizeHint[]()[]()uint32_t[]()[]()功能:用于提示插件管理模塊調(diào)用數(shù)據(jù)上報(bào)接口時(shí)使用的內(nèi)存緩沖區(qū)字節(jié)數(shù)

使用說明

下面介紹在設(shè)備端基于性能調(diào)優(yōu)框架提供的插件能力,新增一個(gè)插件涉及到的關(guān)鍵開發(fā)步驟:

  1. 編寫proto數(shù)據(jù)定義文件_plugin_data.proto_,定義數(shù)據(jù)源格式,數(shù)據(jù)源格式?jīng)Q定了插件上報(bào)哪些數(shù)據(jù):
    message PluginData {
        int32 pid = 1;
        string name = 2;
        uint64 count1 = 3;
        uint64 count2 = 4;
        uint64 count3 = 5;
        ......
    }
    
  2. 編寫數(shù)據(jù)源配置文件_plugin_config.proto_,采集的行為可以根據(jù)配置進(jìn)行變化,可以設(shè)置數(shù)據(jù)源上報(bào)間隔等信息:
    message PluginConfig {
        int32 pid = 1;
        bool report_interval = 2;
        int report_counter_id_1 = 3;
        int report_counter_id_2 = 4;
        ......
    }
    
  3. 定義PluginModuleCallbacks實(shí)現(xiàn)插件回調(diào)接口;定義PluginModuleStruct類型的g_pluginModule全局變量,注冊(cè)插件信息。
    static PluginModuleCallbacks callbacks = {
        PluginSessionStart,
        PluginReportResult,
        PluginSessionStop,
    };
    PluginModuleStruct g_pluginModule = {&callbacks, "test-plugin", MAX_BUFFER_SIZE};
    
  4. 通過PluginSessionStart(名字可以自己定義)實(shí)現(xiàn)插件回調(diào)接口列表的onPluginSessionStart接口,主要處理插件的開始流程。
    int PluginSessionStart(const uint8_t* configData, uint32_t configSize)
    {
        ......
        return 0;
    }
    
  5. 通過PluginReportResult(名字可以自己定義)實(shí)現(xiàn)插件回調(diào)接口列表的onPluginReportResult接口,將插件內(nèi)部采集的信息通過該接口進(jìn)行上報(bào):
    int PluginReportResult(uint8_t* bufferData, uint32_t bufferSize)
    {
        ......
        return 0;
    }
    
  6. 通過PluginSessionStop(名字可以自己定義)實(shí)現(xiàn)插件回調(diào)接口列表的onPluginSessionStop接口,主要進(jìn)行插件停止后的操作流程。
    int PluginSessionStop()
    {
        ......
        return 0;
    }
    
  7. 編寫proto gn構(gòu)建腳本, 生成protobuf源文件,protobuf源文件編譯生成目標(biāo)文件:
    action("plugin_cpp_gen") {
      script = "${OHOS_PROFILER_DIR}/build/protoc.sh"  //依賴的編譯工具鏈
      sources = [   //定義的插件相關(guān)的proto文件,比如插件配置文件、插件數(shù)據(jù)對(duì)應(yīng)的proto文件
        "plugin_data.proto",
        "plugin_config.proto",
      ]
      outputs = [    //通過protoc編譯生成的結(jié)果文件
        "plugin_data.pb.h",
        "plugin_data.pb.cc",
        "plugin_config.pb.h",
        "plugin_config.pb.cc",
      ]
      args = [
        "--cpp_out",
        "$proto_rel_out_dir",
        "--proto_path",
        rebase_path(".", root_build_dir),
      ]
      deps = [
        "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})",
      ]
    }
    ohos_source_set("plug_cpp") {   //將定義的proto文件生成cpp文件
      deps = [
        ":plugin_cpp_gen",
      ]
      public_deps = [
        "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf",
        "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
      ]
      include_dirs = [ "$proto_out_dir" ]
      sources = [   //目標(biāo)plug_cpp中包括的源文件
        "plugin_data.pb.h",
        "plugin_data.pb.cc",
        "plugin_config.pb.h",
        "plugin_config.pb.cc",
      ]
    }
    
  8. 編寫插件GN構(gòu)建腳本:
    ohos_shared_library("***plugin") {
      output_name = "***plugin"
      sources = [
        "src/***plugin.cpp",  //插件中的源文件
      ]
      include_dirs = [
        "../api/include",
        "${OHOS_PROFILER_DIR}/device/base/include",
      ]
      deps = [
        "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
        "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
        "${OHOS_PROFILER_DIR}/protos/types/plugins/**:plug_cpp",  //上面ohos_source_set中生成的plug_cpp
      ]
      install_enable = true
      subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
    }
    

調(diào)測(cè)驗(yàn)證:

插件動(dòng)態(tài)庫(kù)生成后,可以自己編寫測(cè)試代碼,通過dlopen加載動(dòng)態(tài)庫(kù),并調(diào)用上面代碼中實(shí)現(xiàn)的插件模塊回調(diào)函數(shù)進(jìn)行驗(yàn)證。

int main(int argc, char** argv)
{
    void* handle;
    PluginModuleStruct* memplugin;
    handle = dlopen("./libplugin.z.so", RTLD_LAZY);   //動(dòng)態(tài)打開上面生成的插件動(dòng)態(tài)庫(kù)
    if (handle == nullptr) {
        HILOGD("dlopen err:%s.", dlerror());
        return 0;
    }
     memplugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");  //獲取開發(fā)步驟3中定義的g_pluginModule全局變量
     //check memplugin- >callbacks   // 通過該指針調(diào)用上面開發(fā)步驟3中定義的回調(diào)函數(shù)
     return 0;

hiprofiler_cmd 使用說明

參數(shù)說明

執(zhí)行hiprofiler_cmd 為調(diào)優(yōu)業(yè)務(wù)的離線命令行抓取工具,具體使用方法及命令行參數(shù)介紹如下。

可以使用-h或者--help參數(shù)查看命令的使用描述信息:

hiprofiler_cmd -h
help :
  --getport        -q     : get grpc address
  --time           -t     : trace time
  --out            -o     : output file name
  --help           -h     : make some help
  --list           -l     : plugin list
  --start          -s     : start dependent process
  --kill           -k     : kill dependent process
  --config         -c     : start trace by config file

其余參數(shù)使用說明如下:

  • -q或者--getport選項(xiàng),用于查詢服務(wù)的端口信息;
  • -t或者--time選項(xiàng),用于指定抓取時(shí)間,單位是秒;
  • -o或者--out選項(xiàng),用于指定輸出的離線數(shù)據(jù)文件名;
  • -h或者--help選項(xiàng),用于輸出幫助信息;
  • -l或者--list選項(xiàng),用于查詢插件列表;
  • -s或者--start選項(xiàng),用于啟動(dòng)依賴的進(jìn)程;
  • -k或者--kill選項(xiàng),用于關(guān)閉依賴的進(jìn)程;
  • -c或者--config選項(xiàng),用于指定配置文件;

命令展示

基礎(chǔ)配置參數(shù)

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

命令參數(shù)說明:

  • request_id:本次請(qǐng)求的id
  • pages:存儲(chǔ)trace數(shù)據(jù)的buffer大?。? * pages kb)
  • result_file:結(jié)果輸出的文件路徑,與-o參數(shù)對(duì)應(yīng)
  • sample_duration:抓取時(shí)長(zhǎng)(ms),與-t參數(shù)對(duì)應(yīng)

ftrace抓取場(chǎng)景示例

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

命令參數(shù)說明:

  • sample_interval:輪循模式下,插件上報(bào)數(shù)據(jù)的間隔時(shí)間(ms)
  • trace_period_ms:ftrace插件讀取內(nèi)核緩沖區(qū)數(shù)據(jù)的間隔時(shí)間(ms)
  • hitrace_time:hitrace命令行抓取時(shí)間,與hiprofiler_cmd下發(fā)的-t配置聯(lián)動(dòng)

內(nèi)存信息抓取場(chǎng)景示例

內(nèi)核內(nèi)存信息

使用如下命令:

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<
虛擬內(nèi)存統(tǒng)計(jì)

使用如下命令:

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<
進(jìn)程內(nèi)存使用跟蹤

如配置抓取的進(jìn)程名是com.ohos.mms

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

配置參數(shù)說明:

  • pid/process_name:設(shè)置抓取的進(jìn)程ID或者進(jìn)程名
  • max_stack_depth:抓取的棧的深度
  • smb_pages:native_daemon和native_hook進(jìn)程之間存儲(chǔ)數(shù)據(jù)的共享內(nèi)存大小(4KB的倍數(shù))
  • filter_size:只抓取大于該size的malloc數(shù)據(jù)(free不受影響)

bytrace/hitrace場(chǎng)景示例

運(yùn)行如下命令:

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 30 
  -s 
<

hiperf場(chǎng)景示例

運(yùn)行如下命令:

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 存儲(chǔ)
    +關(guān)注

    關(guān)注

    13

    文章

    4314

    瀏覽量

    85851
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3025

    瀏覽量

    74054
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2352

    瀏覽量

    42859
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    鴻蒙Flutter實(shí)戰(zhàn):14-現(xiàn)有Flutter 項(xiàng)目支持鴻蒙 II

    分別安裝官方的3.22版本,以及鴻蒙社區(qū)的 3.22.0 版本 3.搭建 Flutter鴻蒙開發(fā)環(huán)境 參考文章《鴻蒙Flutter實(shí)戰(zhàn):0
    發(fā)表于 12-26 14:59

    鴻蒙Flutter實(shí)戰(zhàn):07混合開發(fā)

    # 鴻蒙Flutter實(shí)戰(zhàn):混合開發(fā) 鴻蒙Flutter混合開發(fā)主要有兩種形式。 ## 1.基于har 將flutter module
    發(fā)表于 10-23 16:00

    MMC DLL調(diào)優(yōu)

    電子發(fā)燒友網(wǎng)站提供《MMC DLL調(diào)優(yōu).pdf》資料免費(fèi)下載
    發(fā)表于 10-11 11:48 ?0次下載
    MMC DLL<b class='flag-5'>調(diào)</b><b class='flag-5'>優(yōu)</b>

    MMC SW調(diào)優(yōu)算法

    電子發(fā)燒友網(wǎng)站提供《MMC SW調(diào)優(yōu)算法.pdf》資料免費(fèi)下載
    發(fā)表于 09-20 11:14 ?0次下載
    MMC SW<b class='flag-5'>調(diào)</b><b class='flag-5'>優(yōu)</b>算法

    HarmonyOS實(shí)戰(zhàn)開發(fā)-Flex布局性能提升使用指導(dǎo)

    長(zhǎng)度分配設(shè)置為最常用場(chǎng)景的布局結(jié)果,使子組件主軸長(zhǎng)度總和等于Flex容器主軸長(zhǎng)度。 最后 如果大家覺得這篇內(nèi)容對(duì)學(xué)習(xí)鴻蒙開發(fā)有幫助,我想邀請(qǐng)大家?guī)臀胰齻€(gè)小忙: 點(diǎn)贊,轉(zhuǎn)發(fā),有你們的 『點(diǎn)贊和評(píng)論
    發(fā)表于 05-10 14:26

    HarmonyOS實(shí)戰(zhàn)開發(fā)-深度探索與打造個(gè)性化自定義組件

    今天分享一下 什么是自定義組件?及其自定義組件實(shí)戰(zhàn)。 做過前端或者android開發(fā)的都知道自定義組件,
    發(fā)表于 05-08 16:30

    HarmonyOS實(shí)戰(zhàn)開發(fā)-如何使用全局狀態(tài)保留能力彈窗來(lái)實(shí)現(xiàn)評(píng)論組件。

    開發(fā)有幫助,我想邀請(qǐng)大家?guī)臀胰齻€(gè)小忙: 點(diǎn)贊,轉(zhuǎn)發(fā),有你們的 『點(diǎn)贊和評(píng)論』,才是我創(chuàng)造的動(dòng)力。 關(guān)注小編,同時(shí)可以期待后續(xù)文章ing?,不定期分享原創(chuàng)知識(shí)。 更多鴻蒙最新技術(shù)知識(shí)點(diǎn),請(qǐng)關(guān)注作者博客:鴻蒙
    發(fā)表于 05-07 15:06

    深度解析JVM調(diào)優(yōu)實(shí)踐應(yīng)用

    Tomcat自身的調(diào)優(yōu)是針對(duì)conf/server.xml中的幾個(gè)參數(shù)的調(diào)優(yōu)設(shè)置。首先是對(duì)這幾個(gè)參數(shù)的含義要有深刻而清楚的理解。
    的頭像 發(fā)表于 04-01 10:24 ?472次閱讀
    深度解析JVM<b class='flag-5'>調(diào)</b><b class='flag-5'>優(yōu)</b>實(shí)踐應(yīng)用

    鴻蒙開發(fā)實(shí)戰(zhàn):【藍(lán)牙組件

    藍(lán)牙服務(wù)組件為設(shè)備提供接入與使用Bluetooth的相關(guān)接口,包括BLE設(shè)備gatt相關(guān)的操作,以及BLE廣播、掃描等功能。
    的頭像 發(fā)表于 03-13 17:27 ?760次閱讀

    鴻蒙實(shí)戰(zhàn)開發(fā)Camera組件:【相機(jī)】

    相機(jī)組件支持相機(jī)業(yè)務(wù)的開發(fā),開發(fā)者可以通過已開放的接口實(shí)現(xiàn)相機(jī)硬件的訪問、操作和新功能開發(fā),最常見的操作如:預(yù)覽、拍照和錄像等。
    的頭像 發(fā)表于 03-08 16:20 ?624次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>開發(fā)</b>Camera<b class='flag-5'>組件</b>:【相機(jī)】

    鴻蒙實(shí)戰(zhàn)項(xiàng)目開發(fā):【短信服務(wù)】

    、OpenHarmony 多媒體技術(shù)、Napi組件、OpenHarmony內(nèi)核、Harmony南向開發(fā)、鴻蒙項(xiàng)目實(shí)戰(zhàn)等等)鴻蒙(Harmon
    發(fā)表于 03-03 21:29

    鴻蒙ArkUI開發(fā)-Tabs組件的使用

    鴻蒙ArkUI開發(fā)-Tabs組件的使用
    的頭像 發(fā)表于 01-19 16:01 ?1910次閱讀
    <b class='flag-5'>鴻蒙</b>ArkUI<b class='flag-5'>開發(fā)</b>-Tabs<b class='flag-5'>組件</b>的使用

    鴻蒙開發(fā)OpenHarmony組件復(fù)用案例

    \\\\common.d.ts的自定義組件的生命周期里定義了aboutToReuse方法,如下: 自定義組件的生命周期回調(diào)函數(shù)用于通知用戶該自定義組件的生命周期,這些回
    發(fā)表于 01-15 17:37

    鴻蒙開發(fā)基礎(chǔ)-Web組件之cookie操作

    }) ... } ... 本文章主要是對(duì)鴻蒙開發(fā)當(dāng)中ArkTS語(yǔ)言的基礎(chǔ)應(yīng)用實(shí)戰(zhàn),Web組件里的cookie操作。更多的鴻蒙應(yīng)用
    發(fā)表于 01-14 21:31

    鴻蒙基礎(chǔ)開發(fā)實(shí)戰(zhàn)-(ArkTS)像素轉(zhuǎn)換

    的使用。通過像素轉(zhuǎn)換案例,向開發(fā)者講解了如何使用像素單位設(shè)置組件的尺寸、字體的大小以及不同像素單位之間的轉(zhuǎn)換方法。更多鴻蒙4.0的學(xué)習(xí),可以前往主頁(yè)學(xué)習(xí)或前往《鴻蒙4.0
    發(fā)表于 01-11 16:53