AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

你的debug包在Android 14變卡了嗎

來源: 責(zé)編: 時(shí)間:2024-04-16 08:33:16 208觀看
導(dǎo)讀一、背景我的App怎么這么卡,誰在代碼里下毒了!有一天突然發(fā)現(xiàn)debug包運(yùn)行變的特別卡頓,經(jīng)過下面的簡單測(cè)試發(fā)現(xiàn)debug包在Android 14上出了問題。 圖片二、問題排查紀(jì)錄常規(guī)手段排查使用了systrace以及內(nèi)部的debug包 trac

一、背景

我的App怎么這么卡,誰在代碼里下毒了!DPn28資訊網(wǎng)——每日最新資訊28at.com

有一天突然發(fā)現(xiàn)debug包運(yùn)行變的特別卡頓,經(jīng)過下面的簡單測(cè)試發(fā)現(xiàn)debug包在Android 14上出了問題。 DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

二、問題排查紀(jì)錄

DPn28資訊網(wǎng)——每日最新資訊28at.com

常規(guī)手段排查

DPn28資訊網(wǎng)——每日最新資訊28at.com

使用了systrace以及內(nèi)部的debug包 trace工具dutrace進(jìn)行排查。DPn28資訊網(wǎng)——每日最新資訊28at.com

結(jié)論:CPU空閑,主線程無明顯阻塞,看上去就是純方法執(zhí)行耗時(shí)。DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

發(fā)現(xiàn)懷疑點(diǎn)

DPn28資訊網(wǎng)——每日最新資訊28at.com

第一步排查過程中沒有特別大的收獲,但是我用dutrace工具排查時(shí)發(fā)現(xiàn)了一個(gè)異常現(xiàn)象。這里簡單介紹一下dutrace的實(shí)現(xiàn)原理:DPn28資訊網(wǎng)——每日最新資訊28at.com

dutrace是利用inline hook在artmethod的執(zhí)行前后加上atrace的點(diǎn)再通過perfetto ui工具展示。有以下優(yōu)點(diǎn):DPn28資訊網(wǎng)——每日最新資訊28at.com

    1. 支持線下分析函數(shù)執(zhí)行流程,函數(shù)耗時(shí)。DPn28資訊網(wǎng)——每日最新資訊28at.com

    2. 在分析函數(shù)調(diào)用流程下:DPn28資訊網(wǎng)——每日最新資訊28at.com

        a. 可以查看整個(gè)過程的函數(shù)調(diào)用(包括framework函數(shù));DPn28資訊網(wǎng)——每日最新資訊28at.com

        b. 能夠指定監(jiān)控的函數(shù)和線程有效過濾無用trace;DPn28資訊網(wǎng)——每日最新資訊28at.com

        c. 動(dòng)態(tài)配置不需要重新打包。DPn28資訊網(wǎng)——每日最新資訊28at.com

    3. 可使用現(xiàn)成的UI分析工具,有系統(tǒng)關(guān)鍵線程的函數(shù)調(diào)用,例如渲染耗時(shí)、線程鎖,GC 耗時(shí)等,還有 I/O 操作、CPU 負(fù)載等事件。DPn28資訊網(wǎng)——每日最新資訊28at.com

流程圖流程圖DPn28資訊網(wǎng)——每日最新資訊28at.com

在對(duì)artmethod執(zhí)行前后進(jìn)行hook時(shí) 這里涉及到處理art方法解釋執(zhí)行的三種情況。DPn28資訊網(wǎng)——每日最新資訊28at.com

ART Runtime 解釋器

  1. The C++ interpreter,也就是傳統(tǒng)的基于switch結(jié)構(gòu)的解釋器,一般僅在調(diào)試環(huán)境、方法跟蹤、指令不支持或者在字節(jié)碼發(fā)生異常情況下(例如failed structured-locking verification)才走該分支。
  2. The mterp fast interpreter,核心是引入了handler table做指令映射,并通過手寫匯編以實(shí)現(xiàn)指令間的快速切換,提高了解釋器性能。
  3. Nterp是Mterp的再次優(yōu)化。Nterp省去了managed code stacks的維護(hù),采用了和Native方法一樣的棧幀結(jié)構(gòu),并且譯碼和翻譯執(zhí)行全程都由匯編代碼實(shí)現(xiàn),進(jìn)一步拉進(jìn)解釋器和compiled code的性能差距。

在這邊我發(fā)現(xiàn)了一個(gè)異常現(xiàn)象,就是Android 14的解釋執(zhí)行居然都用的switch解釋執(zhí)行方式。我又重新去測(cè)試了幾個(gè)Android 版本的解釋執(zhí)行方式。Android 12走的mterp,Android 13走的是nterp,當(dāng)進(jìn)行調(diào)試的時(shí)候才會(huì)走到switch, 理論上Android 14應(yīng)該也走nterp才對(duì),怎么會(huì)走了最慢的switch呢。以下按順序是12、13、14版本的方法執(zhí)行backtrace。DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

排查懷疑點(diǎn)

DPn28資訊網(wǎng)——每日最新資訊28at.com

開始懷疑是解釋執(zhí)行導(dǎo)致的卡頓了,翻了下源碼 art/runtime/interpreter/mterp/nterp.cc 中確實(shí)有變動(dòng) 如果是javaDebuggable 就不走nterp了。接下來嘗試去證明是是這個(gè)問題導(dǎo)致的。DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

isJavaDebuggable 是runtime.cc中的 RuntimeDebugState runtime_debug_state_ 中控制的。我們可以找到runtime的實(shí)例然后通過偏移量修改過runtime_debug_state_屬性,看了下源碼還可以通過_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE 進(jìn)行設(shè)置。 DPn28資訊網(wǎng)——每日最新資訊28at.com

void Runtime::SetRuntimeDebugState(RuntimeDebugState state) {  if (state != RuntimeDebugState::kJavaDebuggableAtInit) {    // We never change the state if we started as a debuggable runtime.    DCHECK(runtime_debug_state_ != RuntimeDebugState::kJavaDebuggableAtInit);  }  runtime_debug_state_ = state;}

我通過上述方式去進(jìn)行嘗試驗(yàn)證 把測(cè)試包的 isJavaDebuggable 設(shè)置為false 依然卡頓,把生產(chǎn)包的isJavaDebuggable設(shè)置為true,變得稍微卡了點(diǎn)。于是我推翻了自己解釋執(zhí)行方式導(dǎo)致卡頓的猜想。 DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

排查native耗時(shí)

DPn28資訊網(wǎng)——每日最新資訊28at.com

懷疑nativie方法執(zhí)行耗時(shí), 再次嘗試用simpleperf定位問題。DPn28資訊網(wǎng)——每日最新資訊28at.com

結(jié)論:基本都是解釋執(zhí)行代碼中的堆棧耗時(shí),沒有其他特殊堆棧。DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

定位到DEBUG_JAVA_DEBUGGABLE

DPn28資訊網(wǎng)——每日最新資訊28at.com

那就想著從debuggable的源頭入手,逐步縮小范圍定位影響變量。DPn28資訊網(wǎng)——每日最新資訊28at.com

AndroidManifest中的debuggable影響系統(tǒng)system進(jìn)程啟動(dòng)我們進(jìn)程中的一個(gè)runtimeFlags。DPn28資訊網(wǎng)——每日最新資訊28at.com

frameworks/base/core/java/android/os/Process.java 中的start方法 其中第6個(gè)參數(shù)就是runtimeFlags而如果是debuggableFlag runtimeFlags會(huì)被添加以下一些flag 那就先縮小標(biāo)簽范圍。DPn28資訊網(wǎng)——每日最新資訊28at.com

if (debuggableFlag) {                runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;                runtimeFlags |= Zygote.DEBUG_ENABLE_PTRACE;                runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;                // Also turn on CheckJNI for debuggable apps. It's quite                // awkward to turn on otherwise.                runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;                // Check if the developer does not want ART verification                if (android.provider.Settings.Global.getInt(mService.mContext.getContentResolver(),                        android.provider.Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE, 1) == 0) {                    runtimeFlags |= Zygote.DISABLE_VERIFIER;                    Slog.w(TAG_PROCESSES, app + ": ART verification disabled");                }            }

需要修改我們進(jìn)程的啟動(dòng)參數(shù)。那就需要去hook system進(jìn)程了。這邊涉及到手機(jī)root,安裝hook框架的一些操作,然后通過hook Process的start去做一些參數(shù)修改。DPn28資訊網(wǎng)——每日最新資訊28at.com

hookAllMethods(        Process.class,        "start",        new XC_MethodHook() {            @Override            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {                final String niceName = (String) param.args[1];                final int uid = (int) param.args[2];                final int runtimeFlags = (int) param.args[5];                XposedBridge.log("process_xx " + runtimeFlags);                if (isDebuggable(niceName, user)) {                    param.args[5] = runtimeFlags&~DEBUG_JAVA_DEBUGGABLE;                    XposedBridge.log("process_xx " + param.args[5]);                }            }        });

這次還是有一些明顯的結(jié)果的。測(cè)試包 runtimeflags 移除DEBUG_JAVA_DEBUGGABLE后不卡了。而生產(chǎn)包包括應(yīng)用市場上的應(yīng)用加上DEBUG_JAVA_DEBUGGABLE標(biāo)記后全部都變卡了。那就可以證明是DEBUG_JAVA_DEBUGGABLE這個(gè)變量引起的。DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

定位到DeoptimizeBootImage

DPn28資訊網(wǎng)——每日最新資訊28at.com

繼續(xù)源碼觀察DEBUG_JAVA_DEBUGGABLE帶來的影響。DPn28資訊網(wǎng)——每日最新資訊28at.com

if ((runtime_flags & DEBUG_JAVA_DEBUGGABLE) != 0) {    runtime->AddCompilerOption("--debuggable");    runtime_flags |= DEBUG_GENERATE_MINI_DEBUG_INFO;    runtime->SetRuntimeDebugState(Runtime::RuntimeDebugState::kJavaDebuggableAtInit);    {      // Deoptimize the boot image as it may be non-debuggable.      ScopedSuspendAll ssa(__FUNCTION__);      runtime->DeoptimizeBootImage();    }    runtime_flags &= ~DEBUG_JAVA_DEBUGGABLE;    needs_non_debuggable_classes = true;  }

這里有邏輯是DEBUG_JAVA_DEBUGGABLE帶來的影響點(diǎn),SetRuntimeDebugState之前已經(jīng)測(cè)試過了。也不是DEBUG_GENERATE_MINI_DEBUG_INFO帶來的影響,那是runtime->DeoptimizeBootImage()?于是我用debugable為false的包通過_ZN3art7Runtime19DeoptimizeBootImageEv主動(dòng)去調(diào)用了DeoptimizeBootImage方法,然后復(fù)現(xiàn)了!DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

原因分析

DPn28資訊網(wǎng)——每日最新資訊28at.com

DeoptimizeBootImage 將bootImage中AOT代碼方法轉(zhuǎn)換為java可調(diào)試。重新初始化方法入口點(diǎn),走到解釋執(zhí)行,而不使用AOT代碼。追溯到Instrumentation::InitializeMethodsCode方法,還是到了CanUseNterp(method) CanRuntimeUseNterp這個(gè)點(diǎn)。也是Android 13可以用nterp,android 14只能走switch了。DPn28資訊網(wǎng)——每日最新資訊28at.com

我再次hook代碼,讓CanRuntimeUseNterp 直接return true, 但是還是卡。我發(fā)現(xiàn)即使我hook了。下面的這些方法還是走到了switch解釋執(zhí)行。反過來想一想是因?yàn)槲襤ook已經(jīng)滯后了DeoptimizeBootImage已經(jīng)執(zhí)行了,當(dāng)調(diào)用到基礎(chǔ)方法的時(shí)候都是switch執(zhí)行了。DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

我用Android 13 debugable true的包進(jìn)行測(cè)試先hook CanRuntimeUseNterp return false,然后再執(zhí)行DeoptimizeBootImage,復(fù)現(xiàn)卡頓 。DPn28資訊網(wǎng)——每日最新資訊28at.com

初步定位:bootimage中的方法 Android 13走的nterp而Android 14走的switch  bootimage里面的方法特別基礎(chǔ)和零碎所以導(dǎo)致方法switch執(zhí)行耗時(shí)嚴(yán)重。DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

驗(yàn)證是系統(tǒng)問題

DPn28資訊網(wǎng)——每日最新資訊28at.com

如果是系統(tǒng)問題,那大家都應(yīng)該遇到的,不只我們App有這個(gè)問題, 于是我找到了幾個(gè)小伙伴幫忙驗(yàn)證debug包這個(gè)問題。果然都有這個(gè)問題,同一個(gè)包安裝在Android 14 和 Android 13上體驗(yàn)完全不一致。DPn28資訊網(wǎng)——每日最新資訊28at.com

1反饋問題

DPn28資訊網(wǎng)——每日最新資訊28at.com

在issuetracker上已經(jīng)有人反饋android 14 debug包慢了 https://issuetracker.google.com/issues/311251587。但是還沒有結(jié)果,于是我補(bǔ)上了我定位到的問題。DPn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DPn28資訊網(wǎng)——每日最新資訊28at.com

順便也提了個(gè)issue https://issuetracker.google.com/issues/328477628DPn28資訊網(wǎng)——每日最新資訊28at.com

三、臨時(shí)解決

在等Google回復(fù)的同時(shí),也同時(shí)在思考App層可以有什么辦法去規(guī)避這個(gè)問題,讓debug包的體驗(yàn)也回歸絲滑,比如如何去重新optimize bootimage中的方法。抱著這個(gè)想法又去學(xué)習(xí)了一下art的代碼,發(fā)現(xiàn)Android 14新增了一個(gè)UpdateEntrypointsForDebuggable方法,這個(gè)方法會(huì)去按照規(guī)則重新設(shè)置方法的執(zhí)行方式比如aot和nterp,那我在這之前把CanRuntimeUseNterp hook了返回true 再去調(diào)用UpdateEntrypointsForDebuggable不就會(huì)重新走到nterp了嗎。  DPn28資訊網(wǎng)——每日最新資訊28at.com

void Instrumentation::UpdateEntrypointsForDebuggable() {  Runtime* runtime = Runtime::Current();  // If we are transitioning from non-debuggable to debuggable, we patch  // entry points of methods to remove any aot / JITed entry points.  InstallStubsClassVisitor visitor(this);  runtime->GetClassLinker()->VisitClasses(&visitor);}

按照上面的思路嘗試了一波,果然變得流暢很多!!!DPn28資訊網(wǎng)——每日最新資訊28at.com

其實(shí)上面的解決方案還有遺留問題。對(duì)比debugable為false的包還是有些卡頓。我也發(fā)現(xiàn)了bootImage中的方法已經(jīng)走到nterp上了,但是apk中的大部分代碼還是走到了switch解釋執(zhí)行上,于是我改變思路。我在調(diào)用UpdateEntrypointsForDebuggable前先把RuntimeDebugState設(shè)置成非debugable,調(diào)用之后再把RuntimeDebugState設(shè)置會(huì)debugable不就行了嗎。最后的代碼如下,hook框架使用了https://github.com/bytedance/android-inline-hook。DPn28資訊網(wǎng)——每日最新資訊28at.com

Java_test_ArtMethodTrace_bootImageNterp(JNIEnv *env,                                                      jclass clazz) {    void *handler = shadowhook_dlopen("libart.so");    instance_ = static_cast<void **>(shadowhook_dlsym(handler, "_ZN3art7Runtime9instance_E"));    jobject    (*getSystemThreadGroup)(void *runtime) =(jobject (*)(void *runtime)) shadowhook_dlsym(handler,                                                                                          "_ZNK3art7Runtime20GetSystemThreadGroupEv");    void    (*UpdateEntrypointsForDebuggable)(void *instrumentation) = (void (*)(void *i)) shadowhook_dlsym(            handler,            "_ZN3art15instrumentation15Instrumentation30UpdateEntrypointsForDebuggableEv");    if (getSystemThreadGroup == nullptr || UpdateEntrypointsForDebuggable == nullptr) {        LOGE("getSystemThreadGroup  failed ");        shadowhook_dlclose(handler);        return;    }    jobject thread_group = getSystemThreadGroup(*instance_);    int vm_offset = findOffset(*instance_, 0, 4000, thread_group);    if (vm_offset < 0) {        LOGE("vm_offset not found ");        shadowhook_dlclose(handler);        return;    }    void (*setRuntimeDebugState)(void *instance_, int r) =(void (*)(void *runtime,                                                                    int r)) shadowhook_dlsym(            handler, "_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE");    if (setRuntimeDebugState != nullptr) {        setRuntimeDebugState(*instance_, 0);    }    void *instrumentation = reinterpret_cast<void *>(reinterpret_cast<char *>(*instance_) +                                                     vm_offset - 368 );    UpdateEntrypointsForDebuggable(instrumentation);    setRuntimeDebugState(*instance_, 2);    shadowhook_dlclose(handler);    LOGE("bootImageNterp success");}

DPn28資訊網(wǎng)——每日最新資訊28at.com

四、最后

最近在社區(qū)上也看到了高通工程師的一篇文章,他在我定位到的問題的基礎(chǔ)上做了更詳細(xì)的分析,確認(rèn)了Google會(huì)在Android 15上修復(fù)這個(gè)問題,如果是海外版本的Android 14設(shè)備,Google計(jì)劃通過com.android.artapex模塊的更新來修復(fù)這個(gè)問題。但是國內(nèi)由于網(wǎng)絡(luò)的問題,Google的推送無法工作,因此需要各個(gè)手機(jī)廠家來主動(dòng)合入這兩筆改動(dòng)。[1]DPn28資訊網(wǎng)——每日最新資訊28at.com

如果大家需要臨時(shí)解決debugable包的卡頓的問題也可以通過上述方式解決。 DPn28資訊網(wǎng)——每日最新資訊28at.com

DPn28資訊網(wǎng)——每日最新資訊28at.com

參考文章:DPn28資訊網(wǎng)——每日最新資訊28at.com

[1] https://juejin.cn/post/7353106089296789556DPn28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-83784-0.html你的debug包在Android 14變卡了嗎

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 詳解@Stomp/Stompjs在Vue3中的應(yīng)用與實(shí)踐

下一篇: 通過JS獲取你當(dāng)前的網(wǎng)絡(luò)狀況?建議大家學(xué)一學(xué)~

標(biāo)簽:
  • 熱門焦點(diǎn)
  • K60 Pro官方停產(chǎn) 第三方瞬間漲價(jià)

    雖然沒有官方宣布,但Redmi的一些高管也已經(jīng)透露了,Redmi K60 Pro已經(jīng)停產(chǎn)且不會(huì)補(bǔ)貨,這一切都是為了即將到來的K60 Ultra鋪路,屬于廠家的正常操作。但有意思的是該機(jī)在停產(chǎn)之后
  • 5月iOS設(shè)備好評(píng)榜:iPhone 14僅排第43?

    來到新的一月,安兔兔的各個(gè)榜單又重新匯總了數(shù)據(jù),像安卓陣營的榜單都有著比較大的變動(dòng),不過iOS由于設(shè)備的更新?lián)Q代并沒有那么快,所以相對(duì)來說變化并不大,特別是iOS好評(píng)榜,老款設(shè)
  • K6:面向開發(fā)人員的現(xiàn)代負(fù)載測(cè)試工具

    K6 是一個(gè)開源負(fù)載測(cè)試工具,可以輕松編寫、運(yùn)行和分析性能測(cè)試。它建立在 Go 和 JavaScript 之上,它被設(shè)計(jì)為功能強(qiáng)大、可擴(kuò)展且易于使用。k6 可用于測(cè)試各種應(yīng)用程序,包括 Web
  • 2023 年的 Node.js 生態(tài)系統(tǒng)

    隨著技術(shù)的不斷演進(jìn)和創(chuàng)新,Node.js 在 2023 年達(dá)到了一個(gè)新的高度。Node.js 擁有一個(gè)龐大的生態(tài)系統(tǒng),可以幫助開發(fā)人員更快地實(shí)現(xiàn)復(fù)雜的應(yīng)用。本文就來看看 Node.js 最新的生
  • 這款新興工具平臺(tái),讓你的電腦效率翻倍

    隨著信息技術(shù)的發(fā)展,我們獲取信息的渠道越來越多,但是處理信息的效率卻成為一個(gè)瓶頸。于是各種工具應(yīng)運(yùn)而生,都在爭相解決我們的工作效率問題。今天我要給大家介紹一款效率
  • 從零到英雄:高并發(fā)與性能優(yōu)化的神奇之旅

    作者 | 波哥審校 | 重樓作為公司的架構(gòu)師或者程序員,你是否曾經(jīng)為公司的系統(tǒng)在面對(duì)高并發(fā)和性能瓶頸時(shí)感到手足無措或者焦頭爛額呢?筆者在出道那會(huì)為此是吃盡了苦頭的,不過也得
  • Temu起訴SHEIN,跨境電商戰(zhàn)事升級(jí)

    來源 | 伯虎財(cái)經(jīng)(bohuFN)作者 | 陳平安日前據(jù)外媒報(bào)道,拼多多旗下跨境電商平臺(tái)Temu正對(duì)競爭對(duì)手SHEIN提起新訴訟,訴狀稱Shein&ldquo;利用市場支配力量強(qiáng)迫服裝廠商與之簽訂獨(dú)家
  • AMD的AI芯片轉(zhuǎn)單給三星可能性不大 與臺(tái)積電已合作至2nm制程

    據(jù) DIGITIMES 消息,英偉達(dá) AI GPU 出貨逐季飆升,接下來 AMD MI 300 系列將在第 4 季底量產(chǎn)。而半導(dǎo)體業(yè)內(nèi)人士表示,近日傳出 AMD 的 AI 芯片將轉(zhuǎn)單給
  • iQOO 11S新品發(fā)布會(huì)

    iQOO將在7月4日19:00舉行新品發(fā)布會(huì),推出杭州亞運(yùn)會(huì)電競賽事官方用機(jī)iQOO 11S。
Top