運行時資源覆蓋故障排除

使用此內容排查運行時資源覆蓋 (RRO) 可能無法在 Android Automotive 實現中按預期運行的問題。

要了解有關 Android 中 RRO 的更多信息,請參閱運行時資源覆蓋 (RRO) 。請務必對logcat輸出保持持續警惕,這可以提供有關整個過程中發生的事情的良好信息。

第 1 步:列出 RRO

要列出 RRO:

  1. 運行以下命令:

    adb shell cmd overlay list --user current
    

    出現這樣的輸出:

    com.android.systemui
    [ ] com.android.theme.icon_pack.rounded.systemui
    [ ] com.android.theme.icon_pack.filled.systemui
    [ ] com.android.theme.icon_pack.circular.systemui
    
    com.android.permissioncontroller
    --- com.android.permissioncontroller.googlecarui.rro
    
  2. 驗證您的 RRO 是否出現在列表中。以下指標表示 RRO 狀態:

    指標RRO 狀態
    [ ]已安裝並準備好激活。
    [X]安裝並激活。
    ---已安裝但包含錯誤。

    如果您的 RRO 未在您要覆蓋的目標的包名稱下列出,則您的 RRO 未安裝。

步驟 2:啟用和禁用 RRO

如果安裝了 RRO:

  1. 使用以下命令啟用(或禁用)RRO:

    adb shell cmd overlay [enable/disable] --user current [your RRO package name]
    

第 3 步:確認 RRO 已安裝

要確認 RRO 已安裝在設備上或排除 RRO 未啟用的原因:

  1. 運行以下命令:

    adb shell cmd overlay dump [your RRO package name]
    

    出現如下輸出:

    com.android.car.rotaryplayground.googlecarui.rro:0 {
      mPackageName...........: com.android.car.rotaryplayground.googlecarui.rro
      mUserId................: 0
      mTargetPackageName.....: com.android.car.rotaryplayground
      mTargetOverlayableName.: car-ui-lib
      mBaseCodePath..........: /product/overlay/googlecarui-com-android-car-rotaryplayground/googlecarui-com-android-car-rotaryplayground.apk
      mState.................: STATE_MISSING_TARGET
      mIsEnabled.............: true
      mIsMutable.............: true
      mPriority..............: 10
      mCategory..............: BypassIdMapV1
    }
    com.android.car.rotaryplayground.googlecarui.rro:10 {
      mPackageName...........: com.android.car.rotaryplayground.googlecarui.rro
      mUserId................: 10
      mTargetPackageName.....: com.android.car.rotaryplayground
      mTargetOverlayableName.: car-ui-lib
      mBaseCodePath..........: /product/overlay/googlecarui-com-android-car-rotaryplayground/googlecarui-com-android-car-rotaryplayground.apk
      mState.................: STATE_MISSING_TARGET
      mIsEnabled.............: true
      mIsMutable.............: true
      mPriority..............: 10
      mCategory..............: BypassIdMapV1
    }
    
  2. 識別已安裝 RRO 的用戶。在上面的示例中,RRO 可用於用戶0和用戶10 (請參閱頂部代碼塊中mUserId的值。

  3. 要為所需用戶啟用(或禁用)RRO,請轉到步驟 2。

  4. 要檢查mState的值:

    • STATE_ENABLEDSTATE_ENABLED_IMMUTABLE 。 RRO 已啟用並應用於您的目標。

    • STATE_MISSING_TARGET 。您的目標未安裝。

    • STATE_NO_IDMAPAndroidManifest.xmloverlays.xmloverlayable.xml文件的設置方式有問題。使用adb logcat運行日誌並蒐索關鍵字idmap以識別錯誤。見步驟 4 和 5

    • STATE_UNKNOWNOverlayManagerService問題。

第 4 步:檢查 AndroidManifest.xml

要驗證AndroidManifest.xml

  1. 檢查targetNametargetPackage

    android:targetName應該與目標應用程序中定義的可覆蓋組具有相同的值。在定位疊加層時才需要這樣做。

    android:targetPackage始終是必需的,並且應該包含目標應用程序的包名稱。

  2. 檢查您的 RRO 是否是靜態的(或不是)。默認情況下,靜態 RRO 在引導時啟用。默認情況下,動態 RRO 不會在啟動時啟用。運行時資源覆蓋 (RRO)中提供了啟用動態 RRO 的其他方法。

  3. 檢查靜態 RRO 的優先級(不能檢查動態 RRO 的優先級)。

    多個 RRO 可能適用於同一目標。最後應用優先級較高的 RRO。在 0 到 10 的範圍內,0 為最高,10 為最低。

第 5 步:檢查 overlays.xml

此檢查適用於 Android 11(及更高版本)。

  1. 檢查overlays.xml以確認您打算覆蓋的所有資源都已在此文件中定義。例如,考慮以下overlays.xml

    <overlay>
        <item target="string/app_name" value="@string/overlaid_app_name" />
    </overlay>
    
  2. 您必須確保:

    • 目標應用程序中存在名稱為app_namestring資源。
    • 您的 RRO 中存在名為overlaid_app_namestring資源。
  3. 如果您的目標有一個overlayable.xml文件,請確保app_name包含在該文件中。確保在AndroidManifest.xml文件中使用正確的targetName (第 4 步)。

    例如:

    <overlay>
    <item target="layout/car_ui_base_layout_toolbar" value="@layout/car_ui_base_layout_toolbar" />
    <item target="id/car_ui_toolbar_background" value="@id/car_ui_toolbar_background" />
    <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf" />
    </overlay>
    

第 6 步:轉儲 idmap

在這個階段,您的 RRO 的所有問題都應該得到解決。接下來,轉儲 RRO 的idmap以了解資源是如何被解析的,以及為什麼它解析為與您預期不同的值。

  1. 要在您的設備上查找idmap的路徑:

    adb shell
    su
    ls data/resource-cache
    
  2. 要轉儲該文件的內容:

    idmap2 dump --idmap-path [path to your RRO idmap file]
    

    輸出類似於以下內容。輸出顯示 RRO 中的哪個 id 映射到目標中的哪個 id 以及覆蓋資源的名稱。

    target apk path : /system/priv-app/CarMediaApp/CarMediaApp.apk
    overlay apk path : /product/overlay/googlecarui-com-android-car-media/googlecarui-com-android-car-media.apk
    0x7f040008 -> 0x7f010000 bool/car_ui_toolbar_logo_fills_nav_icon_space
    0x7f040009 -> 0x7f010001 bool/car_ui_toolbar_nav_icon_reserve_space
    0x7f04000b -> 0x7f010002 bool/car_ui_toolbar_tab_flexible_layout
    0x7f04000c -> 0x7f010003 bool/car_ui_toolbar_tabs_on_second_row
    0x7f09006c -> 0x7f020000 id/car_ui_base_layout_content_container
    0x7f090073 -> 0x7f020001 id/car_ui_recycler_view
    0x7f090074 -> 0x7f020002 id/car_ui_scroll_bar
    0x7f090075 -> 0x7f020003 id/car_ui_scrollbar_page_down
    0x7f090076 -> 0x7f020004 id/car_ui_scrollbar_page_up
    0x7f090077 -> 0x7f020005 id/car_ui_scrollbar_thumb
    0x7f090078 -> 0x7f020006 id/car_ui_scrollbar_track
    0x7f09007a -> 0x7f020007 id/car_ui_toolbar_background
    0x7f09007e -> 0x7f020008 id/car_ui_toolbar_logo
    0x7f090084 -> 0x7f020009 id/car_ui_toolbar_menu_items_container
    0x7f090085 -> 0x7f02000a id/car_ui_toolbar_nav_icon
    0x7f090086 -> 0x7f02000b id/car_ui_toolbar_nav_icon_container
    0x7f090087 -> 0x7f02000c id/car_ui_toolbar_progress_bar
    0x7f090089 -> 0x7f02000d id/car_ui_toolbar_row_separator_guideline
    0x7f09008d -> 0x7f02000e id/car_ui_toolbar_search_view_container
    0x7f09008f -> 0x7f02000f id/car_ui_toolbar_subtitle
    0x7f090092 -> 0x7f020010 id/car_ui_toolbar_tabs
    0x7f090093 -> 0x7f020011 id/car_ui_toolbar_title
    0x7f090094 -> 0x7f020012 id/car_ui_toolbar_title_container
    0x7f090095 -> 0x7f020013 id/car_ui_toolbar_title_logo
    0x7f090096 -> 0x7f020014 id/car_ui_toolbar_title_logo_container
    0x7f0c0024 -> 0x7f030000 layout/car_ui_base_layout_toolbar
    0x7f0c0035 -> 0x7f030001 layout/car_ui_recycler_view
    0x7f0c0038 -> 0x7f030002 layout/car_ui_toolbar
    0x7f0c003f -> 0x7f030003 layout/car_ui_toolbar_two_row
    

您還可以從您的 apk 中轉儲您的佈局文件,以查看已解析的 id 以匹配上述輸出:

aapt2 dump xmltree $OUT/system/priv-app/sharedlibraryclient/sharedlibraryclient.apk --file res/layout/activity_main.xml

返回如下輸出:

N: android=http://schemas.android.com/apk/res/android (line=2)
  N: app=http://schemas.android.com/apk/res-auto (line=2)
    N: lib=http://schemas.android.com/apk/com.android.car.ui.sharedlibrary.test (line=2)
      E: androidx.constraintlayout.widget.ConstraintLayout (line=2)
        A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-1
        A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-1
          E: TextView (line=19)
            A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-2
            A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-2
            A: http://schemas.android.com/apk/res/android:text(0x0101014f)=@0x020f0000
            A: http://schemas.android.com/apk/res-auto:layout_constraintBottom_toBottomOf(0x7f0200fb)=0
            A: http://schemas.android.com/apk/res-auto:layout_constraintLeft_toLeftOf(0x7f02010e)=0
            A: http://schemas.android.com/apk/res-auto:layout_constraintRight_toRightOf(0x7f020112)=0
            A: http://schemas.android.com/apk/res-auto:layout_constraintTop_toTopOf(0x7f020118)=0
          E: com.android.car.ui.sharedlibrary.test.MyRecyclerView (line=28)
            A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-2
            A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-2
            A: http://schemas.android.com/apk/com.android.car.ui.sharedlibrary.test:implClass="HelloWorld!" (Raw: "HelloWorld!")
          E: com.android.car.ui.sharedlibraryclient.CustomView (line=34)
            A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-2
            A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-2
            A: http://schemas.android.com/apk/res-auto:implClass2(0x7f0200e8)="HelloWorld!!" (Raw: "HelloWorld!!")