您的当前位置:首页正文

Android-Overlay机制

2024-11-13 来源:个人技术集锦

作用:

Overlay有两种方案,静态Overlay和动态Overlay。

静态Overlay:

静态Overlay在编译整个Android源码时就进行了替换动作。

场景:修改frameworks/base/core/res/res/values/config.xml中的属性。

device/brcm/rpi4/car/overlay/frameworks/base/core/res/res/values/config.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2015, The Android Open Source Project
**
** 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.
*/
-->

<!-- These resources are around just to allow their values to be customized
     for different hardware and product builds.  Do not translate. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <!-- Enables the GnssTimeUpdate service. This is a switch for enabling Gnss time based
         suggestions to TimeDetector service. -->
    <bool name="config_enableGnssTimeUpdateService">false</bool>
</resources>

这里表示config_enableGnssTimeUpdateService将会替换framework中声明的值,以当前声明的为准。

2.在aosp_rpi4_car.mk中添加overlay路径

PRODUCT_PACKAGE_OVERLAYS += device/brcm/rpi4/car/overlay

$(call inherit-product, packages/services/Car/car_product/build/car.mk)

这里需要注意的是因为car.mk中也会去overlay这个属性值,因此我将自己的overlay路径添加在前面,前面的优先级会更高。overlay在编译时会在build/soong/java/android_resources.go中进行处理,具体优先级可查看代码实现。

  • PRODUCT_PACKAGE_OVERLAYS  > DEVICE_PACKAGE_OVERLAYS 
  • 相同类型情况下,先添加的 > 后添加的

动态Overlay:

不同于静态Overlay,动态Overlay在编译时同时会编译原本的值和修改的值,在运行时动态读取。

场景:修改frameworks/base/packages/SettingsProvider/res/values/defaults.xml

overlay/
├── SettingsProviderRpiOverlay
│   ├── Android.bp
│   ├── AndroidManifest.xml
│   └── res
│       └── values
│           └── default.xml

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright (C) 2021-2022 KonstaKANG
**
** SPDX-License-Identifier: Apache-2.0
*/
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.providers.settings.rpi"
    android:versionCode="1"
    android:versionName="1.0" >
    <application android:hasCode="false" />
    <overlay
        android:targetPackage="com.android.providers.settings"
        android:isStatic="true"
        android:priority="0" />
</manifest>

package名字可以根据原始包名随便取一个。

targetPackage代表要替换的包名。如果是修改frameworks/res中的配置,那targetPackage设为"android"。

priority为优先级,数字越大,优先级越高,如果另外一个地方也对相同属性进行了overlay,就会比较优先级。

Android.bp

runtime_resource_overlay {
    name: "SettingsProviderRpiOverlay",
    resource_dirs: ["res"],
    sdk_version: "current",
    proprietary: true
}

default.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2009 The Android Open Source Project
     Copyright (C) 2021-2022 KonstaKANG

     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.
-->

<resources>

    <!-- Default screen brightness -->
    <integer name="def_screen_brightness">128</integer>

    <!-- Disable bluetooth by default -->
    <bool name="def_bluetooth_on">false</bool>

    <!-- Disable location by default -->
    <integer name="def_location_mode">0</integer>

    <!-- Disable the lockscreen -->
    <bool name="def_lockscreen_disabled">true</bool>

    <!-- Keep screen on at all times by default -->
    <bool name="def_stay_on_while_plugged_in">true</bool>

    <!-- No setup wizard -->
    <bool name="def_device_provisioned">true</bool>
    <bool name="def_user_setup_complete">true</bool>

</resources>

这部分最终会编译成为一个apk,放置到系统下:/vendor/overlay/SystemUIRpiOverlay.apk,运行时再动态读取里面的配置。

2. 在aosp_rpi4_car.mk中添加overlay模块

# Overlays
PRODUCT_PACKAGES += \
    SettingsProviderRpiOverlay \

3. 运行时查看动态overlay

查看overlay帮助

cmd overlay

dump android下的overlay

cmd overlay dump [package]

255|console:/ # cmd overlay dump com.android.providers.settings.rpi
com.android.providers.settings.rpi:0 {
  mPackageName...........: com.android.providers.settings.rpi
  mOverlayName...........: null
  mUserId................: 0
  mTargetPackageName.....: com.android.providers.settings
  mTargetOverlayableName.: null
  mBaseCodePath..........: /vendor/overlay/SettingsProviderRpiOverlay.apk
  mState.................: STATE_ENABLED
  mIsEnabled.............: true
  mIsMutable.............: false
  mPriority..............: 2
  mCategory..............: null
  mIsFabricated..........: false
}
com.android.providers.settings.rpi:10 {
  mPackageName...........: com.android.providers.settings.rpi
  mOverlayName...........: null
  mUserId................: 10
  mTargetPackageName.....: com.android.providers.settings
  mTargetOverlayableName.: null
  mBaseCodePath..........: /vendor/overlay/SettingsProviderRpiOverlay.apk
  mState.................: STATE_ENABLED
  mIsEnabled.............: true
  mIsMutable.............: false
  mPriority..............: 2
  mCategory..............: null
  mIsFabricated..........: false
}
IDMAP OF com.android.providers.settings.rpi
Paths:
    target path  : /system/priv-app/SettingsProvider/SettingsProvider.apk
    overlay path : /vendor/overlay/SettingsProviderRpiOverlay.apk
Mapping:
    0x7f02000d -> 0x7f010000 (bool/def_bluetooth_on -> bool/def_bluetooth_on)
    0x7f020010 -> 0x7f010001 (bool/def_device_provisioned -> bool/def_device_provisioned)
    0x7f020019 -> 0x7f010002 (bool/def_lockscreen_disabled -> bool/def_lockscreen_disabled)
    0x7f02002c -> 0x7f010003 (bool/def_stay_on_while_plugged_in -> bool/def_stay_on_while_plugged_in)
    0x7f020032 -> 0x7f010004 (bool/def_user_setup_complete -> bool/def_user_setup_complete)
    0x7f050009 -> 0x7f020000 (integer/def_location_mode -> integer/def_location_mode)
    0x7f050013 -> 0x7f020001 (integer/def_screen_brightness -> integer/def_screen_brightness)

console:/ #

查看android包下的overlay

cmd overlay list [package]

console:/ # cmd overlay list com.android.providers.settings
com.android.providers.settings
[x] com.android.providers.settings.rpi
[ ] com.android.shell:com.android.providers.settings.rpi
[ ] com.android.shell:def_dock_audio_media_enabled
console:/ #

x表示此overlay处于生效中。

enable/disable overlay (配置了isStatic=true的是无法disable的)

cmd overlay disable com.android.providers.settings

cmd overlay enable com.android.providers.settings

Exception occurred while executing 'enable':
java.lang.SecurityException: commit failed

我执行这个命令会抛异常,不知道为什么,有知道的可以告知一下。

disable除指定overlay之外其他的所有overlay

cmd overlay enable-exclusive 

查看overlay的值

cmd overlay lookup

console:/ # cmd overlay lookup com.android.providers.settings com.android.providers.settings:integer/def_screen_brightness
128

可以看到def_screen_brightness已经被改写为128。

即使没有overlay也可以用这个方法查看原生配置的值,调试时很有用。

添加一个overlay

cmd overlay fabricate --target android --name com.android.internal.systemui.navbar.twobutton android:integer/config_navBarInteractionMode 0x010 0x1

Top