遇到一个Android P相关的问题,和原来CTS/GTS 问题分析1的表现是一样的,但是将http://gerrit.pt.miui.com/#/c/387000/这个修复cp过来,发现不生效,仍然报错,因此记录一下
问题初探
测试命令: run gts -m GtsGmscoreHostTestCases -t com.google.android.gts.devicepolicy.managedprovisioning.DeviceOwnerProvisioningHostsideTest#testRequiredAppsInManagedDevice
报错堆栈:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
09-28 13:54:41 W/XtsHostTestBase: java.lang.AssertionError: Should have at least one packages to handle Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] }, found [] Expected: a value greater than <0> but: <0> was equal to <0> at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:18) at com.google.android.gts.managedprovisioning.AfwRequiredAppsTest.assertAndGetPackagesHandleIntent(AfwRequiredAppsTest.java:450) at com.google.android.gts.managedprovisioning.AfwRequiredAppsTest.assertRequiredAppsInDeviceOwnerOrManagedUser(AfwRequiredAppsTest.java:490) at com.google.android.gts.managedprovisioning.AfwRequiredAppsTest.assertRequiredAppsInDeviceOwner(AfwRequiredAppsTest.java:474) at com.google.android.gts.managedprovisioning.AfwRequiredAppsTest.testRequiredApps_DeviceOwner_withGms(AfwRequiredAppsTest.java:124) at java.lang.reflect.Method.invoke(Native Method) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:52) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:148) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:142) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:764) |
上面还有:
09-28 01:54:32.486 18930 18956 D ManagedProvisioning: Deleting package [com.mi.android.globallauncher] as user 0
问题分析
可见,E10这个机器自定义的桌面被删掉了,导致case fail。在OverlayPackagesProvider.java中调试一下,结果如下:
可见我们得到的是vendor/google/products/gms_overlay下面的资源,那么首先怀疑的是不是和上面链接的一样,overlay顺序问题导致资源加载不正确?
那么我们在本地加log看一下:
在build/core/package_internal.mk中添加log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
ifdef enforce_rro_enabled ifneq ($(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS),) static_only_resource_overlays := $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(package_resource_overlays)) ifneq ($(static_only_resource_overlays),) package_resource_overlays := $(filter-out $(static_only_resource_overlays),$(package_resource_overlays)) LOCAL_RESOURCE_DIR := $(static_only_resource_overlays) $(LOCAL_RESOURCE_DIR) ifeq ($(package_resource_overlays),) enforce_rro_enabled := endif endif endif else LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR) $(warning ------>a1) $(warning ------>$(LOCAL_RESOURCE_DIR)) $(warning ------>a2) endif |
注意这个log不是在lunch时出现的,而是在packages/apps/ManagedProvisioning这里编译时出现的
国内版log
1 2 3 |
build/make/core/package_internal.mk:136: warning: ------>a1 build/make/core/package_internal.mk:137: warning: ------>miui/config-overlay/v6/common/packages/apps/ManagedProvisioning/res packages/apps/ManagedProvisioning/res build/make/core/package_internal.mk:138: warning: ------>a2 |
国际版
在根目录执行deploy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Deploy menu... pick a combo: 1. cn 2. cn_chinaunicom 3. cn_chinatelecom 4. cn_chinamobile 5. cn_cta 6. cn_chinamobile-cta 7. global Which would you like? [cn] 7 global ============================================ MIUI_CURRENT_CUST_VARIANT=global ============================================ |
重新回到packages/apps/ManagedProvisioning进行mm
1 2 3 |
build/make/core/package_internal.mk:136: warning: ------>a1 build/make/core/package_internal.mk:137: warning: ------>miui/config-overlay/v6/global/packages/apps/ManagedProvisioning/res miui/config-overlay/v6/common/packages/apps/ManagedProvisioning/res packages/apps/ManagedProvisioning/res build/make/core/package_internal.mk:138: warning: ------>a2 |
看着overlay的顺序完全正确,为了再确定下,我们用Android Studio看一下ManagedProvisioning.apk的资源,发现:
果然,资源已经顺利被aapt打包到相应apk里面了,前面的怀疑是错的,和原来不是一个问题。
那么剩下的还有两个怀疑点,1. apk的逻辑有问题或改动 2.资源加载出错;我们调试的时候发现加载的资源id是
和上面的id对不上,那么肯定是资源就没加载对。然后突然想到,我调试的时候attach的是system_process进程,那么会不会加载的是framework的资源呢,查看framework-res.apk,果然:
id对上了。那么可以肯定,是逻辑更改造成的问题
逻辑更改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
99 public Set<String> getSystemAppsToRemove(int userId){ 100 if (!shouldDeleteSystemApps(userId)) { 101 return Collections.emptySet(); 102 } 103 104 // Start with all system apps 105 Set<String> newSystemApps = mUtils.getCurrentSystemApps(mIPackageManager, userId); 106 107 // Remove the ones that were already present in the last snapshot only when OTA 108 if (!mNewProfile) { 109 newSystemApps.removeAll(mSnapshot.getSnapshot(userId)); 110 } 111 ComponentName deviceAdminComponentName; 112 try { 113 deviceAdminComponentName = mParams.inferDeviceAdminComponentName( 114 mUtils, mContext, userId); 115 } catch (IllegalProvisioningArgumentException ex) { 116 // Should not happen 117 throw new RuntimeException("Failed to infer device admin component name", ex); 118 } 119 // Get the packages from the black/white lists 120 Set<String> packagesToDelete = mDevicePolicyManager.getDisallowedSystemApps( 121 deviceAdminComponentName, userId, mParams.provisioningAction); 122 123 // Retain only new system apps 124 packagesToDelete.retainAll(newSystemApps); 125 126 return packagesToDelete; 127 } 70 /** 71 * Computes non-required apps. All the system apps with a launcher that are not in 72 * the required set of packages will be considered as non-required apps. 73 * 74 * Note: If an app is mistakenly listed as both required and disallowed, it will be treated as 75 * disallowed. 76 * 77 * @param admin Which {@link DeviceAdminReceiver} this request is associated with. 78 * @param userId The userId for which the non-required apps needs to be computed. 79 * @param provisioningAction action indicating type of provisioning, should be one of 80 * {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link 81 * ACTION_PROVISION_MANAGED_PROFILE} or 82 * {@link ACTION_PROVISION_MANAGED_USER}. 83 * @return the set of non-required apps. 84 */ 85 @NonNull 86 public Set<String> getNonRequiredApps(@NonNull ComponentName admin, int userId, 87 @NonNull String provisioningAction){ 88 final Set<String> nonRequiredApps = getLaunchableApps(userId); 89 // Newly installed system apps are uninstalled when they are not required and are either 90 // disallowed or have a launcher icon. 91 nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName())); 92 // Don't delete the system input method packages in case of Device owner provisioning. 93 if (ACTION_PROVISION_MANAGED_DEVICE.equals(provisioningAction) 94 || ACTION_PROVISION_MANAGED_USER.equals(provisioningAction)) { 95 nonRequiredApps.removeAll(getSystemInputMethods()); 96 } 97 nonRequiredApps.addAll(getDisallowedApps(provisioningAction)); 98 return nonRequiredApps; 99 } 195 private Set<String> getVendorRequiredAppsSet(String provisioningAction){ 196 final int resId; 197 switch (provisioningAction) { 198 case ACTION_PROVISION_MANAGED_USER: 199 resId = R.array.vendor_required_apps_managed_user; 200 break; 201 case ACTION_PROVISION_MANAGED_PROFILE: 202 resId = R.array.vendor_required_apps_managed_profile; 203 break; 204 case ACTION_PROVISION_MANAGED_DEVICE: 205 resId = R.array.vendor_required_apps_managed_device; 206 break; 207 default: 208 throw new IllegalArgumentException("Provisioning type " 209 + provisioningAction + " not supported."); 210 } 211 return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId))); 212 } |
可见,ManagedProvisioning将这部分逻辑放到了framework中,所以取的是framework的资源;
总结
ManagedProvisioning.apk也会随着大版本升级改动,我们进行CTS测试时需要注意这一点,尤其是其越来越与framework依赖时,我们要注意观察以往的overlay逻辑是否适用