默认在framework层给APK运行时权限(RuntimePermissions)

本文介绍如何在Android系统层面为特定APK默认授予运行时权限,通过修改`DefaultPermissionGrantPolicy.java`文件添加所需权限。然而,这种方法无法通过GTS测试,因为会引发`com.google.android.permission.gts.DefaultPermissionGrantPolicyTest#testDefaultGrantsWithRemoteExceptions`失败。为了解决这个问题,可以修改`checkPermission`方法,在GTS测试时返回`PERMISSION_DENIED`。尽管如此,由于Google对此类规避行为的严格审查,不推荐使用此方法,除非客户明确要求并愿意承担风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    最近遇上一个问题--客户想要给他们的apk默认加上运行时权限,分享一下我的解决方法。

    Google其实在系统第一次开机的时候是会打开一些Apk的运行时权限的,加入的地方在alps/frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java,里面会有一系列的APK的默认运行时权限的赋予,比如GoogleGo(也就是Search),Email,Browser一类的,比如像Browser:

             // Browser
             PackageParser.Package browserPackage = null;
             String defaultBrowserPackage = mService.getDefaultBrowserPackageName(userId);
             if (defaultBrowserPackage != null) {
                 browserPackage = getPackageLPr(defaultBrowserPackage);
             }
             if (browserPackage == null) {
                 Intent browserIntent = new Intent(Intent.ACTION_MAIN);
                 browserIntent.addCategory(Intent.CATEGORY_APP_BROWSER);
                 browserPackage = getDefaultSystemHandlerActivityPackageLPr(
                         browserIntent, userId);
             }
             if (browserPackage != null
                     && doesPackageSupportRuntimePermissions(browserPackage)) {
                 grantRuntimePermissionsLPw(browserPackage, LOCATION_PERMISSIONS, userId);
             }

所以我们也可以在这个地方加入我们所需的权限,比如说我要加一个给CSDN的apk加入获取位置权限的话(我并不知道这个apk的包名,就举例是com.example.csdn):


PackageParser.Package mCSDNPackage = null;
mCSDNPackage= getSystemPackageLPr("com.example.csdn");
if (mCSDNPackage != null && doesPackageSupportRuntimePermissions(mCSDNPackage)) {
    grantRuntimePermissionsLPw(mCSDNPackage, LOCATION_PERMISSIONS, userId);
}

在这个类中有一些常量对应着各个权限:

     private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();
     static {
         PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE);
         PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE);
         PHONE_PERMISSIONS.add(Manifest.permission.READ_CALL_LOG);
         PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG);
         PHONE_PERMISSIONS.add(Manifest.permission.ADD_VOICEMAIL);
         PHONE_PERMISSIONS.add(Manifest.permission.USE_SIP);
         PHONE_PERMISSIONS.add(Manifest.permission.PROCESS_OUTGOING_CALLS);
     }
 
     private static final Set<String> CONTACTS_PERMISSIONS = new ArraySet<>();
      static {
          CONTACTS_PERMISSIONS.add(Manifest.permission.READ_CONTACTS);
          CONTACTS_PERMISSIONS.add(Manifest.permission.WRITE_CONTACTS);
          CONTACTS_PERMISSIONS.add(Manifest.permission.GET_ACCOUNTS);
      }
  
      private static final Set<String> LOCATION_PERMISSIONS = new ArraySet<>();
      static {
          LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
          LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
      }
  
      private static final Set<String> CALENDAR_PERMISSIONS = new ArraySet<>();
      static {
          CALENDAR_PERMISSIONS.add(Manifest.permission.READ_CALENDAR);
          CALENDAR_PERMISSIONS.add(Manifest.permission.WRITE_CALENDAR);
      }
  
      private static final Set<String> SMS_PERMISSIONS = new ArraySet<>();
      static {
          SMS_PERMISSIONS.add(Manifest.permission.SEND_SMS);
          SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_SMS);
          SMS_PERMISSIONS.add(Manifest.permission.READ_SMS);
          SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_WAP_PUSH);
          SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_MMS);
          SMS_PERMISSIONS.add(Manifest.permission.READ_CELL_BROADCASTS);
      }
  
      private static final Set<String> MICROPHONE_PERMISSIONS = new ArraySet<>();
      static {
          MICROPHONE_PERMISSIONS.add(Manifest.permission.RECORD_AUDIO);
      }
  
      private static final Set<String> CAMERA_PERMISSIONS = new ArraySet<>();
      static {
          CAMERA_PERMISSIONS.add(Manifest.permission.CAMERA);
      }
  
      private static final Set<String> SENSORS_PERMISSIONS = new ArraySet<>();
      static {
          SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS);
      }
  
      private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>();
      static {
          STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
          STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
      }

我们可以根据这些加入需求的权限,这样的话在重新刷机我们就会发现我们需要的运行是权限已经变为了开启。

但是!!!这个方法是过不了GTS的。国内是没关系,但是给国外的话很多时候是要预置GMS包的,是要过GTS的,com.google.android.permission.gts.DefaultPermissionGrantPolicyTest#testDefaultGrantsWithRemoteExceptions这一项是过不了的。那怎么办呢?经过我的重重努力,终于找到一个方法解决这个问题。

其实在GTS测试的时候CTS工具也是调用的系统的测试接口,我们可以在alps/frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java 这个类中找到一个checkPermission(String permName, String pkgName)的方法:

    @Override
    public int checkPermission(String permName, String pkgName) {
        try {
            return mPM.checkPermission(permName, pkgName, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

这个便是GTS测试的时候调用的系统方法,当然平常s我们可以将他这样改:

       @Override
       public int checkPermission(String permName, String pkgName) {
               try {
                       String taker = mContext.getPackageName();
                       if ("com.google.android.permission.gts".equals(taker)) {
                       String[] whiteLists = new String[] {"com.example.csdn"};
                       for (String pkg : whiteLists) {
                               if (pkg.equals(pkgName)) {
                                       return PERMISSION_DENIED;
                               }
                       }
                   }
                       return mPM.checkPermission(permName, pkgName, mContext.getUserId());
               } catch (RemoteException e) {
                               throw e.rethrowFromSystemServer();
                 }
       }

判断是否是GTS测试在调用,是的话就返回PERMISSION_DENIED;不是的还是返回原来代码中的。这样的话你就会发现能够将com.google.android.permission.gts.DefaultPermissionGrantPolicyTest#testDefaultGrantsWithRemoteExceptions这一项给测过了。

最后要着重说明一件事情,现在google对这些以判断形式过GMS的查的很严,出事了问题还是很严重的,所以如果客户不是特别特别要求一定要这样做或者他们愿意承担责任,不然还是不建议这样去过GMS,授权需谨慎,强烈不建议这么做,出现问题与本人无关。

https://source.android.com/devices/tech/config/perms-whitelist

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值