GTS 中testDefaultGrantsWithRemoteExceptions fail 详解

前言:

最近在做GMS 的验证,其中测试case  rmeabi-v7a GtsPermissionTestCases 的时候出现了异常,有些注意点这里总结一下。

问题1:

出现的log 如下:

Permission:android.permission.WRITE_EXTERNAL_STORAGE cannot be granted by default to package:com.android.chrome
Permission:android.permission.WRITE_EXTERNAL_STORAGE cannot be granted by default to package:com.android.exchange
Permission:android.permission.READ_PHONE_STATE cannot be granted by default to package:com.android.exchange
Permission:android.permission.READ_EXTERNAL_STORAGE cannot be granted by default to package:com.android.exchange

从log 中分析是这两个app grant 了runtime 的default permission,对于runtime permission 详细分析的可以看另一篇博文 Android Runtime Permission 详解,对于runtime permission 的默认配置,可以看下source code:

frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java

对于这个fail 的问题,下面在问题2 中一并分析。

问题2:

log 如下:(log 太多了,截取部分)

07-22 04:22:02.819  2255  2273 I TestRunner: java.lang.AssertionError: Permission:android.permission.GET_ACCOUNTS cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_PHONE_STATE cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CALL_LOG cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_CALL_LOG cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.CALL_PHONE cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:com.android.voicemail.permission.ADD_VOICEMAIL cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.PROCESS_OUTGOING_CALLS cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.RECEIVE_WAP_PUSH cannot be granted by default to package:com.android.mms
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.GET_ACCOUNTS cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CONTACTS cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_CONTACTS cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_PHONE_STATE cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CALL_LOG cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_CALL_LOG cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.CALL_PHONE cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:com.android.voicemail.permission.ADD_VOICEMAIL cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.PROCESS_OUTGOING_CALLS cannot be granted by default to package:com.qiku.android.contacts
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.GET_ACCOUNTS cannot be granted by default to package:com.google.android.gm
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CONTACTS cannot be granted by default to package:com.google.android.gm
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_CONTACTS cannot be granted by default to package:com.google.android.gm
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CALENDAR cannot be granted by default to package:com.google.android.gm
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_CALENDAR cannot be granted by default to package:com.google.android.gm
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CONTACTS cannot be granted by default to package:com.qiku.android.calendar
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_CALENDAR cannot be granted by default to package:com.qiku.android.calendar
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_CALENDAR cannot be granted by default to package:com.qiku.android.calendar
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.ACCESS_COARSE_LOCATION cannot be granted by default to package:com.google.android.apps.maps
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.ACCESS_FINE_LOCATION cannot be granted by default to package:com.google.android.apps.maps
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.CAMERA cannot be granted by default to package:com.android.camera
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.RECORD_AUDIO cannot be granted by default to package:com.android.camera
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_EXTERNAL_STORAGE cannot be granted by default to package:com.android.camera
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_EXTERNAL_STORAGE cannot be granted by default to package:com.android.camera

基本上看应该是同问题 1,当然分开分析肯定是有不同的原因的。

来看下GTS 的Test code:

    public void testDefaultGrantsWithRemoteExceptions() throws Exception {
        List<PackageInfo> allPackages = getAllPackages();
        Set<String> runtimePermNames = getRuntimePermissionNames(allPackages);
        ArrayMap<String, PackageInfo> packagesToVerify = getMsdkTargetingPackagesUsingRuntimePerms(allPackages, runtimePermNames);
        SparseArray<UidState> pregrantUidStates = new SparseArray();
        addSysComponentsAndPrivAppsDefaultPermissions(packagesToVerify, pregrantUidStates);

        ...
        ...

        addCameraDefaultPermissions(packagesToVerify, pregrantUidStates);

        ...

        addDefaultSmsDefaultPermissions(packagesToVerify, pregrantUidStates);

        ...

        addCalendarDefaultPermissions(packagesToVerify, pregrantUidStates);

        ...

        addContactsDefaultPermissions(packagesToVerify, pregrantUidStates);

        ...
        ...

        StringBuilder violations = new StringBuilder();
        PackageManager packageManager = BusinessLogicTestCase.getInstrumentation().getContext().getPackageManager();
        for (PackageInfo packageInfo : packagesToVerify.values()) {
            UidState uidState = (UidState) pregrantUidStates.get(packageInfo.applicationInfo.uid);
            if (uidState != null) {
                int grantCount = uidState.grantedPermissions.size();
                for (int i = 0; i < grantCount; i++) {
                    String permission = (String) uidState.grantedPermissions.keyAt(i);
                    if (ArrayUtils.contains(packageInfo.requestedPermissions, permission) && packageManager.checkPermission(permission, packageInfo.packageName) == 0) {
                        boolean grantBackFineLocation = false;
                        if (permission.equals("android.permission.ACCESS_COARSE_LOCATION")) {
                            if (packageManager.checkPermission("android.permission.ACCESS_FINE_LOCATION", packageInfo.packageName) == 0) {
                                setPermissionGrantState(packageInfo.packageName, "android.permission.ACCESS_FINE_LOCATION", false);
                                grantBackFineLocation = true;
                            }
                        }
                        setPermissionGrantState(packageInfo.packageName, permission, false);
                        if (!((Boolean) uidState.grantedPermissions.valueAt(i)).booleanValue() && packageManager.checkPermission(permission, packageInfo.packageName) == 0) {
                            violations.append("Permission:").append(permission).append(" grated by default to package:").append(packageInfo.packageName).append(" should be revocable").append('\n');
                        }
                        setPermissionGrantState(packageInfo.packageName, permission, true);
                        if (grantBackFineLocation) {
                            setPermissionGrantState(packageInfo.packageName, "android.permission.ACCESS_FINE_LOCATION", true);
                        }
                        packageInfo.requestedPermissions = ArrayUtils.removeString(packageInfo.requestedPermissions, permission);
                    }
                }
            }
        }
        for (PackageInfo packageInfo2 : packagesToVerify.values()) {
            int uid = packageInfo2.applicationInfo.uid;
            for (String requestedPermission : packageInfo2.requestedPermissions) {
                uidState = (UidState) pregrantUidStates.get(uid);
                if ((uidState == null || uidState.grantedPermissions.indexOfKey(requestedPermission) < 0) && runtimePermNames.contains(requestedPermission) && packageManager.checkPermission(requestedPermission, packageInfo2.packageName) == 0) {
                    violations.append("Permission:").append(requestedPermission).append(" cannot be granted by default to package:").append(packageInfo2.packageName).append('\n');
                }
            }
        }
        if (violations.length() > 0) {
            Assert.fail(violations.toString());
        }
    }

从code 上看没有多大的问题,主要是轮询系统中installed 的所有apps,然后进行遍历找到要求的app 进行verify。注意code 最后的一部分,发现打印的log 是在最后:

        for (PackageInfo packageInfo2 : packagesToVerify.values()) {
            int uid = packageInfo2.applicationInfo.uid;
            for (String requestedPermission : packageInfo2.requestedPermissions) {
                uidState = (UidState) pregrantUidStates.get(uid);
                if ((uidState == null || uidState.grantedPermissions.indexOfKey(requestedPermission) < 0) && runtimePermNames.contains(requestedPermission) && packageManager.checkPermission(requestedPermission, packageInfo2.packageName) == 0) {
                    violations.append("Permission:").append(requestedPermission).append(" cannot be granted by default to package:").append(packageInfo2.packageName).append('\n');
                }
            }
        }

这段code 是说如果没有轮询到的系统中的app 对应的UidState 对象为null 或者是UidState 对象中的grantedPermissions 为空的时候会打印 log (后面的条件就忽略就是,要求是granted 的permission),那么如果不想打印这段log,这里必须是UidState 对象不为null 而且对应的成员变量grantedPermissions 不为空。

其实,理论上,这里的Test code 中要求的permission 应该是跟framework 中对应的,要求某些特殊的app 的runtime permission默认是granted,那么之所以出现了问题,肯定就是在UidState 的对象上。

下面举其中的camera 为例,log 中出现:

07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.CAMERA cannot be granted by default to package:com.android.camera
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.RECORD_AUDIO cannot be granted by default to package:com.android.camera
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.WRITE_EXTERNAL_STORAGE cannot be granted by default to package:com.android.camera
07-22 04:22:02.819  2255  2273 I TestRunner: Permission:android.permission.READ_EXTERNAL_STORAGE cannot be granted by default to package:com.android.camera

出现这个问题,比较奇怪了,因为从包名来看应该是属于google 源生的app,那肯定google 自己GTS 是pass的,为什么这里又出问题了呢?

注意上面的Test code 中:

addCameraDefaultPermissions(packagesToVerify, pregrantUidStates);

---->

    private void addCameraDefaultPermissions(Map<String, PackageInfo> packageInfos, SparseArray<UidState> outUidStates) throws Exception {
        String packageName = getDefaultSystemHandlerActivityPackageName(new Intent("android.media.action.IMAGE_CAPTURE"));
        if (packageName != null) {
            PackageInfo packageInfo = (PackageInfo) packageInfos.get(packageName);
            if (packageInfo != null && doesPackageSupportingRuntimePermissions(packageInfo)) {
                appendPackagePregrantedPerms(packageInfo, false, CAMERA_PERMISSIONS, outUidStates);
                appendPackagePregrantedPerms(packageInfo, false, MICROPHONE_PERMISSIONS, outUidStates);
                appendPackagePregrantedPerms(packageInfo, false, STORAGE_PERMISSIONS, outUidStates);
            }
        }
    }

code 大概意思是找到对应action 的packageName,然后进行appendPackagePregrantedPerms 操作,详细的code 这里暂时不贴了,这个appendPackagePregrantedPerms 其实就是创建UidState 对象,结合之前的分析,如果UidState 为null,那么只有可能这里的append 操作失败,也就是说getDefaultSystemHandlerActivityPackageName() 函数的返回值为null。下面来看下这个函数:

    private String getDefaultSystemHandlerActivityPackageName(Intent intent) {
        return getDefaultSystemHandlerActivityPackageName(intent, 0);
    }

    private String getDefaultSystemHandlerActivityPackageName(Intent intent, int flags) {
        ResolveInfo handler = BusinessLogicTestCase.getInstrumentation().getContext().getPackageManager().resolveActivity(intent, flags);
        if (handler == null || (handler.activityInfo.applicationInfo.flags & 1) == 0) {
            return null;
        }
        return handler.activityInfo.packageName;
    }

并没有什么问题啊?怎么回事呢?看下framework 对应的source code:

    private PackageParser.Package getDefaultSystemHandlerActivityPackageLPr(
            Intent intent, int userId) {
        ResolveInfo handler = mService.resolveIntent(intent,
                intent.resolveType(mService.mContext.getContentResolver()), DEFAULT_FLAGS, userId);
        if (handler == null || handler.activityInfo == null) {
            return null;
        }
        ActivityInfo activityInfo = handler.activityInfo;
        if (activityInfo.packageName.equals(mService.mResolveActivity.packageName)
                && activityInfo.name.equals(mService.mResolveActivity.name)) {
            return null;
        }
        return getSystemPackageLPr(handler.activityInfo.packageName);
    }

这下应该知道原因了,去问问google 为什么吧!

整个流程分析完了,回到上面的问题1,结合framework 的code 和Test code,其实我们知道GTS 如果想要这一项通过,必须满足条件:

  • framework 中轮询到的app,test 中也要能轮询到,这要求轮询的条件要一样。这个就是问题2 的原因
  • framework 中grant 的app 默认runtime permission 在test 中也必须是一样的。这个就是问题1 的原因

猜你喜欢

转载自blog.csdn.net/jingerppp/article/details/81173056