裝置是 Xiaomi 25102PCBEG,myron_tw_global,HyperOS V816,Android 16。

問題很簡單也很煩:從左下角往上滑,會開 Google Assistant。那個 FloatyActivity 視窗每次都跳出來,玩遊戲或橫向操作的時候特別容易誤觸。

我以為關掉很簡單。

畢竟 AOSP 本來就有 assistant_touch_gesture_enabled 這個 secure setting,寫個 0 就該沒事了。

結果不是。

第一個坑:key 名字寫錯了

網路上流傳的解法大多長這樣:

settings put --user 0 secure assistant_touch_gesture_enabled 0

我寫了。

沒用。

後來把 MiuiSystemUI.apk/system_ext/priv-app/MiuiSystemUI/ 拉出來反編譯,才看到 SystemUI 真正讀的 key 是:

secure assist_touch_gesture_enabled

不是 assistant_touch_gesture_enabled。少一個 ant,整個 key 就不對。

NavBarHelper.java:402 寫得很清楚:

this.mAssistantTouchGestureEnabled =
    Settings.Secure.getIntForUser(
        this.mContentResolver,
        "assist_touch_gesture_enabled",
        this.mContext.getResources().getBoolean(
            R.bool.config_assistTouchGestureEnabledDefault) ? 1 : 0,
        ((UserTrackerImpl) this.mUserTracker).getUserId()
    ) != 0;

而且這個值有 live observer,寫進去就生效,不用重啟 SystemUI:

this.mContentResolver.registerContentObserver(
    Settings.Secure.getUriFor("assist_touch_gesture_enabled"),
    false, this.mAssistContentObserver, -1);

所以我寫了正確的 key:

settings put --user 0 secure assist_touch_gesture_enabled 0

dump 出來確認:

NavbarTaskbarFriendster
  longPressHomeEnabled=true
  mAssistantTouchGestureEnabled=false
  mAssistantAvailable=false
  mNavBarMode=2

SystemUI 這邊確實關掉了。

然後我從左下角上滑一次。

Google Assistant 還是開了。

第二個坑:SystemUI 關了也沒用

這時候我開始覺得不對勁。

SystemUI 已經回 mAssistantAvailable=false,為什麼手勢還會觸發?

dumpsys activity activities 看了一下,左下角上滑後前台是:

com.google.android.googlequicksearchbox/
com.google.android.apps.search.assistant.surfaces.voice.robin.ui.floaty.activity.FloatyActivity

launched-from 指向:

com.mi.android.globallauncher

不是 SystemUI。

是 Launcher。

HyperOS 的 Launcher 叫 MiLauncherGlobal,路徑在 /product/priv-app/MiLauncherGlobal/,版本 RELEASE-6.01.03.1943-01051706

所以這台機器上,左下角上滑這個手勢根本不是 SystemUI 在處理的,是 Launcher 自己有一套。

拆 MiLauncherGlobal

關鍵類別集中在這幾個:

com.miui.home.recents.FsGestureAssistHelper
com.miui.home.recents.FsGestureAssistEnableHelper
com.miui.home.recents.NavStubView
com.miui.home.recents.TouchInteractionService

真正呼叫 assistant 的地方在 FsGestureAssistHelper.java:96

Bundle bundle = new Bundle();
bundle.putInt("triggered_by", 83);
bundle.putInt("invocation_type", 1);
MiuiSystemUiProxyWrapper.INSTANCE.onAssistantGestureCompletion();
MiuiSystemUiProxyWrapper.INSTANCE.startAssistant(bundle);

gate 在 canTriggerAssistantAction()

public boolean canTriggerAssistantAction(float f, float f2, long j) {
    if (FsGestureAssistEnableHelper.getInstance().supportAssistantGesture()
            && !isAssistantGestureDisabled(j)) {
        int i = this.mAssistantWidth;
        if (f < i || f > f2 - i) {
            return true;
        }
    }
    return false;
}

判斷條件是 supportAssistantGesture()

這個值哪裡來?

FsGestureAssistEnableHelper.java:67

boolean zIsSupportGoogleAssist =
    AssistManager.getInstance(Application.getInstance())
        .isSupportGoogleAssist(LauncherUtils.getCurrentUserId());

this.mIsSupportGoogleAssist = zIsSupportGoogleAssist;
this.mIsAssistantAvailable = zIsSupportGoogleAssist;

if (DeviceConfigs.IS_KDDI_BUILD) {
    boolean z = false;
    if (zIsSupportGoogleAssist
            && Settings.Secure.getInt(
                Application.getInstance().getContentResolver(),
                MiuiSettingsUtils.GOOGLE_ASSIST_ENABLE,
                0
            ) != 0) {
        z = true;
    }
    this.mIsAssistantAvailable = z;
}

看到那個 IS_KDDI_BUILD 了嗎?

我這台是 ro.miui.region=TWro.product.mod_device=myron_tw_global

不是 KDDI build。

所以 google_assist_enable 這個 key 在這台根本不會被拿來 gate mIsAssistantAvailable。我還是死馬當活馬醫試了一下:

settings put --user 0 secure google_assist_enable 0

左下角上滑還是會開。

沒用。

測完還原成 null

SystemUI 傳來的 availability,Launcher 直接忽略

這段我覺得是最扯的。

MiLauncherGlobal 的 TouchInteractionService 有收到 SystemUI 的 overview proxy callback:

// TouchInteractionService.java:170
public void onAssistantAvailable(boolean z, boolean z2) {
}

空的。

另一個 overload 也只是 log:

// TouchInteractionService.java:248
public void onAssistantAvailable(boolean z) {
    Log.d("TouchInteractionService", "onAssistantAvailable :" + z);
}

SystemUI 那邊已經把 mAssistantAvailable 設成 false 了,結果 Launcher 收到之後什麼都沒做。

它照自己的 FsGestureAssistEnableHelper 判斷要不要觸發,完全不理 SystemUI 講什麼。

所以你以為你關掉了,其實只關了一半。另一半在 Launcher 手裡,而 Launcher 根本沒在聽。

最後有效的組合

試到最後,真正能擋住的是:

settings put --user 0 secure assist_touch_gesture_enabled 0
settings delete --user 0 secure assistant

把系統的 assistant component 直接刪掉。

Launcher 還是會偵測到手勢,但 startAssistant 找不到目標,所以就不會開 FloatyActivity 了。

驗證流程:

adb shell input keyevent HOME
adb logcat -c
adb shell input swipe 5 2570 180 2050 220
adb shell dumpsys activity activities | rg -i "topResumedActivity|FloatyActivity|globallauncher"

前台還是 Launcher:

topResumedActivity=... com.mi.android.globallauncher/com.miui.home.launcher.Launcher

沒有再進 Google Assistant。

但這個做法有代價。

voice_interaction_service 我沒動:

settings get --user 0 secure voice_interaction_service
# com.google.android.googlequicksearchbox/com.google.android.voiceinteraction.GsaVoiceInteractionService

理論上 OK Google 熱詞路徑還在。

secure assistant=null 可能把某些 Google App 的 UI 入口或系統 ASSIST intent 弄壞了,這個要實際喊一次才知道。Google App 內部會不會有自己的綁定邏輯,我也還沒驗證。

如果 OK Google 壞了,恢復很簡單:

settings put --user 0 secure assistant com.google.android.googlequicksearchbox/com.google.android.voiceinteraction.GsaVoiceInteractionService

但恢復 assistant 之後角落手勢會不會跟著回來?

大概會。

因為 MiLauncherGlobal 把「角落手勢能不能用」和「系統 assistant 是不是 Google」綁在一起了,沒有公開的 per-gesture key 可以單獨切。

locked bootloader、沒 root 的前提下,這台機器的乾淨切分點有限。

比較乾淨但需要更高權限的替代方案是 hook:用 LSPosed 把 FsGestureAssistHelper.canTriggerAssistantAction() 永遠回 false,或只對 corner gesture 把 FsGestureAssistEnableHelper.supportAssistantGesture()false

至於直接改 MiLauncherGlobal 或 SystemUI 的 overlay,locked bootloader 下就別想了。

被排除的路

記一下,避免下次又繞進去。

assistant_touch_gesture_enabled:key 名字錯了,SystemUI 讀的是 assist_touch_gesture_enabled,少一個 ant

google_assist_enable:這台不是 KDDI build,程式碼裡那個 gate 只在 IS_KDDI_BUILD 時生效。

entity_config_key_voice_assistant:這條是導航列長按 / 雙擊 shortcut,onLongPress() -> doAction(2)onDoubleTap() -> doAction(4),跟左下角上滑無關。

重啟 SystemUI:不用,assist_touch_gesture_enabledContentObserver,live 生效。

學到的事

這次真正的坑不是「找不到 key」。

第一個找到的 SystemUI key 其實是對的,寫進去也確實生效了。

問題是那個 key 不是最後那個 gate。

SystemUI 這邊已經照設定關掉、dump 也確認 false 了,但 MiLauncherGlobal 自己又做了一套 assistant gesture 判斷,而且擺明不甩 SystemUI 傳來的 assistantAvailable=false。callback 函式是空的,連 log 都只寫一行。

所以之後遇到 HyperOS gesture 問題,不能只拆 SystemUI。

只要觸發點跟 full-screen gesture、recents、home gesture 有關,就必須同時拆:

MiuiSystemUI.apk
MiLauncherGlobal.apk
TouchInteractionService
NavStubView
FsGesture*

這才是這台機器上真正的手勢管線。

SystemUI 只是其中一層,而且不一定是最後一層。

至於那個「刪掉 secure assistant 會不會弄壞 OK Google」的疑問,我還沒驗證。等下次有機會喊一聲再補上。