Android Overlay机制

本章要介绍的运行时Overlay(RuntimeResourceOverlay)

Android Runtime Resource Overlay 简介】并不冲突,

只是在新的Android O版本,Google对于RR0机制的安全性进行了加强,后续有详细介绍。


首先系统编译过程中一般会将packages/apps目录下的源码项目通过AAPT打包成APK,存放至system/app或者system/priv-app目录下,最后连同其他资源打包得到系统镜像,当然也可以将APK直接打包到系统镜像。

静态Overlay 
静态Overlay,简称为SRO,发生在编译时,需要在Android系统源码环境中进行配置。


配置步骤:

1.修改产品(高通msm8996对于framework层字串)的mk文件,添加如下代码:

t88909aa1/ap/android/device/qcom/
	Name		Date	Size
	common/	H	24-三月-2018	4 KiB
	msm8909/	H	31-三月-2018	4 KiB
	msm8909_512go/	H	10-三月-2018	4 KiB
	msm8909go/	H	24-三月-2018	4 KiB
	msm8996/	H	24-三月-2018	4 KiB
	sepolicy/	H	06-一月-2018	4 KiB

t88909aa1/ap/android/device/qcom/msm8996/
H A D	msm8996.mk	73 $(call inherit-product, device/qcom/common/common64.mk)

t88909aa1/ap/android/device/qcom/common/
H A D	common.mk	5 # device-vendor.mk first to make sure QC specific files gets installed.
$(call inherit-product-if-exists, $(QCPATH)/common/config/device-vendor.mk)
H A D	common64.mk	5 # device-vendor.mk first to make sure QC specific files gets installed.
$(call inherit-product-if-exists, $(QCPATH)/common/config/device-vendor.mk)

t88909aa1/ap/android/vendor/qcom/proprietary/common/config/device-vendor.mk	
$(call inherit-product-if-exists, vendor/qcom/proprietary/qrdplus/Extension/products.mk)
$(call inherit-product-if-exists, vendor/qcom/proprietary/qrdplus/Extension/products.mk)

t88909aa1/ap/android/vendor/qcom/proprietary/qrdplus/Extension/ 
PRODUCT_PACKAGE_OVERLAYS += vendor/qcom/proprietary/qrdplus/Extension/apps/BatterySaver/overlay

实际修改的overlay文件:
t88909aa1/ap/android/vendor/qcom/proprietary/qrdplus/Extension/apps/BatterySaver/overlay/frameworks/base/core/res/res/values/
	strings.xml
2.在overlays目录下添加对应产品的overlay项目,overlay项目实际上就是源项目剔除代码和替换资源后的项目,注意包名路径需要与源项目保持一致。

SRO

原理 

实际上,SRO的实现很简单,只是在通过AAPT打包成APK时,通过-S命令多增加了一个资源目录(overlay目录)而已,我们平时打包APK只是通过AAPT -S指定了一个资源目录,而Overlay又额外增加了一个资源目录而已。
AAPT -S命令可以指定多个资源目录,overlay的资源将替换原res中的重名文件。可见SRO在编译成APK时已经完成。


运行时Overlay 

运行时Overlay,简称RRO,顾名思义,该机制的资源替换发生在运行时。

与SRO的区别 

RRO能直接定制替换第三方APK的资源,而不需要其源码。SRO如上节所述,则需要对应APK的源码才能完成,一般而言,第三方是不会提供项目源码的。

RRO的编译结果会得到一个xxx_overlay.apk,加上原项目的apk,总共会有2个apk,而SRO最终只会得到一个已经完成资源替换的apk。得到的overlay.apk可以视为一个正常的apk,因为它能被安装,含有自己的AndroidManifest.xml文件,当然正常下,overlay.apk是不含有执行代码的。

RRO不能替换AndroidManifest.xml文件及layout目录中的xml文件。虽然RRO具有自己的AndroidManifest.xml文件,但它却不能替换源项目中的AndroidManifest.xml文件。关于layout目录中的xml文件,SRO是可以替换的。


配置如下:

下面以创建WuiDemo的RRO为例进行说明:

创建一个新项目,包名命名为

com.overlay.wuidemo
,事实上包名可以随意命名,这样命名可读性高,一看包名就知道是哪个项目的overlay。

编辑overlay项目的AndroidManifest.xml文件,文件内容如下:



    


其中,
android:targetPackage:需要overlay的项目的包名
android:priority:设置overlay.apk的优先级,值越大,优先级越高,用于存在多个overlay.apk情况下的判断。

替换相应的res资源

编写mk文件,编译、打包、签名,并将生成的overlay.apk输出到/vendor/overlay目录下,其中签名需要与源项目签名一致,否则不会生效。

PS:没有源码环境,或者不懂mk文件,可以通过root手机,直接将我们生成的overlay.apk直接push到/vendor/overlay目录下,来测试RRO机制。
部分厂商可能更改了路径,可通过adb shell pm path xxxx.overlay 查找到路径,前提是手机中已经安装了某个overlay的apk。


至此,我们需要额外关注就是Android O在RRO变化:

1.安全性提高,需要的不仅仅时OverLay同Target 两个Apk签名一致,还需要在Target Apk声明具有android.permission.CHANGE_OVERLAY_PACKAGES。


    

分析:

frameworks/base/services/core/java/com/android/server/om/OverlayManagerService.java
private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
        }
代码中检查权限的举动

2.配置规范行

Android O上面对于RRO,Google专门为其提供一个服务【OverlayManagerService】,如下:

t88909aa1/ap/android/frameworks/base/services/java/com/android/server/
H A D	SystemServer.java	91 import com.android.server.om.OverlayManagerService;
649 mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));

t88909aa1/ap/android/frameworks/base/core/java/android/content/om/
OverlayInfo.java	33 * com.android.server.om.OverlayManagerService} should never have this

t88909aa1/ap/android/frameworks/base/services/core/java/com/android/server/om/
	IdmapManager.java	H A D	28-十二月-2017	4.4 KiB
	OverlayManagerService.java	H A D	28-十二月-2017	37.3 KiB
	OverlayManagerServiceImpl.java	H A D	28-十二月-2017	23.5 KiB
	OverlayManagerSettings.java	H A D	28-十二月-2017	19.6 KiB
	OverlayManagerShellCommand.java	H A D	28-十二月-2017	7.1 KiB
    
/t88909aa1/ap/android/frameworks/base/services/core/java/com/android/server/pm/
H A D	PackageManagerService.java	846 // OverlayManagerService will update each of them with a correct gid from its

在【frameworks/base/services/core/java/com/android/server/om/OverlayManagerService.java】306行我们可以看到

frameworks/base/services/core/java/com/android/server/om/OverlayManagerService.java
private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme";
private static Set getDefaultOverlayPackages() {
307        final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP);
308        if (TextUtils.isEmpty(str)) {
309            return Collections.emptySet();
310        }
311
312        final ArraySet defaultPackages = new ArraySet<>();
313        for (String packageName : str.split(";")) {
314            if (!TextUtils.isEmpty(packageName)) {
315                defaultPackages.add(packageName);
316            }
317        }
318        return defaultPackages;
319    }

此处还需要配置overlay包名,多个overlay应用需要以;分隔。

故我们时需要配置【ro.boot.vendor.overlay.theme】属性的。


原理 

以我们常见的图片资源访问为例,当我们在应用层调用getDrawable方法的时候,会调用系统的getResource方法,该方法会根据资源id及设备配置信息(语言、像素密度等)来查找并返回合适的图片资源。此处,我们只关注根据id来选择资源。

如果id表明是系统资源,那么就会去framework-res.apk中查找并返回资源,一般位于/vendor/framework目录下,可root手机查看;如果是应用资源则在overlay和app中查找并返回。


RRO

个overlay包 

当对应项目只有一个overlay包时,那么查找资源时,会先从overlay.apk中进行查找,查找成功直接返回,反之则从app中查找。

多个overlay包 

当对应项目具有多个overlay包时,会按照overlay包的优先级从高到底依次进行查找,如果overlay包都查找失败,才会到app中进行查找。
以访问R.drawable.ic_01为例,会先从overlay1包先查找,因为其优先级最高,查找到则直接返回。
如果访问R.drawable.ic_02,先从overlay1查找,查找失败,接着从overlay2中查找,查找到直接返回。
如果访问R.drawable.ic_03,依次从overlay1,overlay2中查找,查找失败,最后会从app中查找到,并返回。


ps:

a.OverLay同Target Apk需要签名一致

b.Target Apk需要申请允许RRO overlay权限

c.OverLay同Target Apk必须保持统一的资源ID,系统或应用或其他自定义的资源ID

【资源ID】 

我们知道资源文件在打包之后,会在R.java文件中生成一个对应的int类型资源id,这个id遵循以下的规则:
0xppttiiii
其中,
pp:01表示是系统资源,7f表示是应用资源
tt:用于表示资源类型,如string、array、图片资源等
iiii:用于表示相同类型的不同资源


总结 

SRO实际上只是利用AAPT重新打包,发生在编译时;RRO,才是overlay机制的关键,其本质是Android系统的动态资源查找机制。

实际运用当中,Overlay机制一般用于手机厂商为不同运营商做客制化定制,或者做主题换肤;一般,第三方应用是无法享受该机制的,除非与手机厂商合作,不过应用层现在也有了换肤框架Android-Skin-Loader,其本质也是利用Android的资源查找机制。


其他补充 :https://blog.csdn.net/wh_19910525/article/details/39254815#comments




https://blog.csdn.net/Dylan_Sen/article/details/78878641 Android overlay简单总结




https://blog.csdn.net/wh_19910525/article/details/39254815  Android平台Overlay机制



你可能感兴趣的:(android,系统)