CTS/GTS问题分析1 | weiinter105

问题初探

测试命令: run gts -m GtsGmscoreHostTestCases -t com.google.android.gts.devicepolicy.managedprovisioning.DeviceOwnerProvisioningHostsideTest#testRequiredAppsInManagedDevice

报错堆栈
07-18 16:53:12 I/XtsHostTestBase: Test com.google.android.gts.playstore.ResetPreferredAppsTest#testPersistDefaultBrowser: PASSED
07-18 16:53:19 I/XtsHostTestBase: Test com.google.android.gts.managedprovisioning.AfwRequiredAppsTest#testRequiredApps_DeviceOwner_withGms: FAILURE
07-18 16:53:19 W/XtsHostTestBase: junit.framework.AssertionFailedError: com.google.android.gms is not installed

从这个堆栈很明显看出在测试device owner相关的测试时找不到了gmscore apk导致的问题,测了一下,发现测试这条确实会复现gmscore被删除的情况,进一步查看log:

07-18 16:53:15.570 14121 14139 D ManagedProvisioning: Deleting package [com.miui.securitycenter] as user 0
07-18 16:53:15.571 14121 14139 D ManagedProvisioning: Deleting package [com.miui.gallery] as user 0

07-18 16:53:15.571 14121 14139 D ManagedProvisioning: Deleting package [com.xiaomi.bttester] as user 0
07-18 16:53:15.571 14121 14139 D ManagedProvisioning: Deleting package [com.xiaomi.market] as user 0
07-18 16:53:15.572 14121 14139 D ManagedProvisioning: Deleting package [com.google.android.gms] as user 0
07-18 16:53:15.572 14121 14139 D ManagedProvisioning: Deleting package [com.android.browser] as user 0
07-18 16:53:15.572 14121 14139 D ManagedProvisioning: Deleting package [com.miui.video] as user 0
07-18 16:53:15.577 14121 14139 D ManagedProvisioning: Deleting package [com.android.mms] as user 0
07-18 16:53:15.578 14121 14139 D ManagedProvisioning: Deleting package [com.android.thememanager] as user 0
07-18 16:53:15.578 14121 14139 D ManagedProvisioning: Deleting package [com.android.camera] as user 0
07-18 16:53:15.579 14121 14139 D ManagedProvisioning: Deleting package [com.miui.bugreport] as user 0
07-18 16:53:15.579 14121 14139 D ManagedProvisioning: Deleting package [com.android.calendar] as user 0
07-18 16:53:15.581 14121 14139 D ManagedProvisioning: Deleting package [com.android.soundrecorder] as user 0

可见测试过程中的确将com.google.android.gms删除了,导致case fail;同时case中断,导致最后测完之后删除了很多pkg

这条case与device owner有关,创建device_owner的过程基本与创建managed profile一致,需要用到ManagedProvisioning.apk这个apk,流程大致如下:

  1. 启动ProvisioningActivity,调用maybeStartProvisioning

 

  1. maybeStartProvisioning中创建ProvisioningController

 

  1. 其中初始化需要的task,我们需要看的是DeleteNonRequiredAppsTask

 

  1. DeleteNonRequiredAppsTask删除不必要的apk

 

  1. 通过NonRequiredAppsLogic,获取packagesToDelete

 

6.通过OverlayPackagesProvider提供需要删除的app

 

根据以往经验,gmscore这个package name是需要保留下来的,即在RequiredApps里面

  1. Required App获取

 

可见required apps其实是根据ManagedProvisioning.apk里面相关资源
required_apps_managed_device.xml
vendor_required_apps_managed_device.xml

通过以上的逻辑我们就有了第一个怀疑,是不是因为apk里的相关资源没有配置正确导致的问题。因此下面向着这个猜想的方向进行验证

验证猜想

首先想到的是反编译查看ManagedProvisioning.apk的values下的arrays资源,然而奇怪的是反编译的res文件夹下没有values文件夹。因此我们只能刷机调试,D5X结果:

发现果然没有gms相关包名,为了验证猜想,用E7S的global版本进行验证,结果如下:

通过调试结果验证了猜想,发现是vendor_required_apps_managed_device.xml的值不正确导致的问题;同时,通过观察调试值,很容易想到是vendor_required_apps_managed_device.xml这个属性的值overlay的不正确导致的问题;

即原本应该overlay的属性是vendor/google/products/gms_overlay/packages/apps/ManagedProvisioning/res/values/,但实际上被overlay的属性是miui/config-overlay/v6/global/packages/apps/ManagedProvisioning/res/values/;

那么进一步想到两种修改方案:

1.在实际被overlay的属性中添加gms相关包名

  1. overlay正确结果

问题解决

以上两种方案,对方案1来说,虽然简单,担不是非常好,因为这是用来overlay miui的相关属性的;但是我们可以先修改这个文件进行测试,添加gms相关包名后,发现case顺利通过,且被删除的app顺利还原;那么放心了,只要overlay正确的属性值就可以顺利解决这个问题;

那么开始调研方案2:
通过在mk文件里加log发现:
首先调用到了miui/build/common_var.mk中的

 

MIUI_CONFIG_OVERLAY_ROOT的值就是miui/config-overlay/v6

然后在miui/device/common/common.mk中

 

也就是先overlay了miui/config-overlay/v6/common里面的属性

接下来还会调用miui/device/common/v6/common.mk中的

 

发现vendor/google/products下面的overlay确实也会被调用,且在miui/config-overlay/v6/common之后,那么按照正常的思路,后面overlay应该会覆盖前面overlay的属性,那么应该不会出错才对

接下来就继续猜测为什么没有overlay成功?

我们会发现,在前面overlay时用的是MIUI_PRODUCT_PACKAGE_OVERLAYS,而后面的是PRODUCT_PACKAGE_OVERLAYS,会不会是这里产生的影响?

查看代码,果然:

 

如果有MIUI_PRODUCT_PACKAGE_OVERLAYS的overlay,那么这个优先级更高
在common_cn_gms.mk中
PRODUCT_PACKAGE_OVERLAYS := vendor/google/products/gms_overlay
MIUI_PRODUCT_PACKAGE_OVERLAYS += vendor/google/google_cn/products/gms_overlay

并在vendor/google/google_cn下面增加相应需要预置的overlay属性;但是令人惊讶的是测试结果还是fail,说明overlay还是没有成功。

加log打印MIUI_PRODUCT_PACKAGE_OVERLAYS,发现两个路径都在变量 MIUI_PRODUCT_PACKAGE_OVERLAYS中,且vendor/google/google_cn在后面,因此只能怀疑一开始的默认假设: 后面overlay应该会覆盖前面overlay的

则修改miui/device/common /common.mk

 

case pass,因此对于PRODUCT_PACKAGE_OVERLAYS,写在前面的目录优先级高于写在后面目录的优先级

到这里,问题已经得到了解决,这个问题其实不难,但是因为理清了我的一个思维误区,因此觉得有必要记录下来。

问题拓展

为什么资源的overlay是从前往后的,感觉这个不符合逻辑啊,稍稍调研了下。

不管如何,最后要将资源打进apk,最终会使用aapt,那么全局搜了一下,最终发现了相关的mk,build/core/definitions.mk

 

注意这里

 

可见,在dir目录下寻找资源其实用的是aapt -S
那么后面的PRIVATE_RESOURCE_DIR是什么呢?

 

在build/core/package_internal.mk中

 

可见,overlay就是将PRODUCT_PACKAGE_OVERLAYS里面的dir取出,添加到LOCAL_RESOURCE_DIR的前面

最后在packages/apps/ManagedProvisioning目录下执行mma,打出$(LOCAL_RESOURCE_DIR)

 

果然vendor/google/google_cn/products/gms_overlay/packages/apps/ManagedProvisioning/res在miui/config-overlay/v6/common/packages/apps/ManagedProvisioning/res 的前面了

再来查看aapt -S的意思

 

aapt -S 取第一个路径进行overlay

问题总结

这个问题其实没什么难度,但是从中理清了overlay顺序的理解误区,因此记录一下;写的比较粗糙。

作者: RESSRC

个人资源站

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据