• Android9.0/8.1/6.0 默认给系统 app 授予所有权限


    前言

    最近和 PackageManagerService(PMS) 杠上了,3W 多行代码,着实精妙。网上有很多分析流程的文章,这里我就不再复述了,就来看下 PMS 的衍生修改实战吧。之前写过一篇 Android8.1 默认给第三方 app 授予所有权限,其实也能给系统 app 授权,原理大概为收到开机广播后去检查指定包名权限是否已经赋予,未授权则授权。但开机广播有时效性,有些场景不能满足要求,况且总需要去修改源码,不方便。

    修改

    大致思路如下,参考 MTK 的系统 app 可卸载配置方案,在
    vendormediatekproprietaryframeworksasedataetcpms_sysapp_removable_system_list.txt
    中增加可卸载系统 app 包名,在编译时拷贝至 out system/etc/permissions 路径下, 在 PmsExtImpl.java 中读取该文件,PMS 在扫描时判断包名是否在 pms_sysapp_removable_system_list 列表中,确定是否可卸载。

    一、新建 pms_sysapp_grant_permission_list.txt

    vendormediatekproprietaryframeworksasedataetcpms_sysapp_grant_permission_list.txt

    com.android.dialer
    com.android.soundrecorder
    com.android.browser
    com.mediatek.filemanager
    com.android.calendar
    com.android.email
    

    二、拷贝 pms_sysapp_grant_permission_list.txt 至 out 目录下

    device/mediatek/common/device.mk

     ifneq ($(strip $(MTK_BASIC_PACKAGE)), yes)
    +  PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_grant_permission_list.txt:system/etc/permissions/pms_sysapp_grant_permission_list.txt)
       PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_removable_system_list.txt:system/etc/permissions/pms_sysapp_removable_system_list.txt)
       PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_removable_vendor_list.txt:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/pms_sysapp_removable_vendor_list.txt)
     endif
    
    

    三、PMS 中系统启动完成读取 pms_sysapp_grant_permission_list.txt,给 app 授权

    frameworksaseservicescorejavacomandroidserverpmPackageManagerService.java

    @Override
        public void systemReady() {//pjz
            enforceSystemOrRoot("Only the system can claim the system is ready");
    	
    		//cczheng add for system app grant permission S
            if (mFirstBoot) {
                MTKPackageManagerUtil.slientGrantRuntimePermission(mContext);
            }
    		//cczheng add for system app grant permission E
    
            mSystemReady = true;
            final ContentResolver resolver = mContext.getContentResolver();
            ContentObserver co = new ContentObserver(mHandler) {
                @Override
                public void onChange(boolean selfChange) {
                    mEphemeralAppsDisabled =
                            (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
                                    (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
                }
            };
            mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                            .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
                    false, co, UserHandle.USER_SYSTEM);
            mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                            .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
            co.onChange(true);
    
    

    新增 MTKPackageManagerUtil

    1、读取 pms_sysapp_grant_permission_list.txt 中包名

    2、遍历包名集合获取需要申请的权限集合

    3、根据权限名称判断当前包名是否已经授权,未授权则授权

    此处有几个坑说一下,

    坑一、根据包名获取到的权限集合中有很多不在BasePermission中, 系统不能正常授权,会抛异常,导致后续的权限不能正常授权,需要剔除这部分。

    2019-01-01 08:23:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.grantRuntimePermission(PackageManagerService.java:5732)
    2019-01-01 08:23:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.grantRuntimePermission(PackageManagerService.java:5703)
    2019-01-01 08:23:51.605 656-656/system_process W/System.err:     at android.app.ApplicationPackageManager.grantRuntimePermission(ApplicationPackageManager.java:627)
    2019-01-01 08:23:51.605 656-656/system_process W/System.err:     at com.android.server.pm.MTKPackageManagerUtil.slientGrantRuntimePermission(MTKPackageManagerUtil.java:90)
    2019-01-01 08:23:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.systemReady(PackageManagerService.java:22551)
    2019-01-01 08:23:51.605 656-656/system_process D/MTKPackageManagerUtil: Unknown permission: com.qualcomm.permission.USE_PHONE_SERVICE
    
    

    坑二、用户自己声明的权限和非运行时权限,需要剔除这部分。

    2019-01-01 08:43:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(PackageManagerService.java:5696)
    2019-01-01 08:43:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.grantRuntimePermission(PackageManagerService.java:5740)
    2019-01-01 08:43:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.grantRuntimePermission(PackageManagerService.java:5703)
    2019-01-01 08:43:51.605 656-656/system_process W/System.err:     at android.app.ApplicationPackageManager.grantRuntimePermission(ApplicationPackageManager.java:627)
    2019-01-01 08:43:51.605 656-656/system_process W/System.err:     at com.android.server.pm.MTKPackageManagerUtil.slientGrantRuntimePermission(MTKPackageManagerUtil.java:90)
    2019-01-01 08:43:51.605 656-656/system_process W/System.err:     at com.android.server.pm.PackageManagerService.systemReady(PackageManagerService.java:22551)
    2019-01-01 08:43:51.605 656-656/system_process D/MTKPackageManagerUtil: Permission android.permission.ACCESS_BLUETOOTH_SHARE is not a changeable permission type
    

    frameworksaseservicescorejavacomandroidserverpmMTKPackageManagerUtil.java

    /*
     * Copyright (C) 2006 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.android.server.pm;
    
    
    import android.content.Context;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.os.Environment;
    import android.os.Process;
    import android.text.TextUtils;
    import android.util.Log;
    
    import android.content.pm.IPackageManager;
    import android.app.AppGlobals;
    import android.app.AppOpsManager;
    import android.Manifest;
    import com.android.internal.util.ArrayUtils;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.HashSet;
    import java.util.Iterator;
    
    public class MTKPackageManagerUtil{
    
        private static String TAG = "KEPackageManagerUtil";
    
        //copy from vendormediatekproprietaryframeworksaseservicescorejavacommediatekserverpmPmsExtImpl.java
        private static final File GRANT_SYS_APP_LIST_SYSTEM = Environment
                .buildPath(Environment.getRootDirectory(), "etc", "permissions",
                        "pms_sysapp_grant_permission_list.txt");
    
        private static HashSet<String> sGrantSystemAppSet = new HashSet<String>();
    
        private static HashSet<String> sGrantPermissionSet = new HashSet<String>();
    
        private static  IPackageManager mIpm;
        private static  AppOpsManager mAppOpsManager;
    
        public static void slientGrantRuntimePermission(Context mContext, Settings mSettings){
            sGetGrantSystemAppFromFile(sGrantSystemAppSet, GRANT_SYS_APP_LIST_SYSTEM);
    
            PackageManager mPackageManager = mContext.getPackageManager();
    
            mIpm = AppGlobals.getPackageManager();
            mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    
            Iterator<String> it = sGrantSystemAppSet.iterator();
            Log.d(TAG, "sGrantSystemAppSet:");
            while (it.hasNext()) {
                sGrantPermissionSet.clear();
                String pkgName = it.next();
                Log.d(TAG, "pkgName="+pkgName);
                try {
                    PackageInfo mPackageInfo =   mPackageManager.getPackageInfo(pkgName, PackageManager.GET_PERMISSIONS);
                     for (String permission : mPackageInfo.requestedPermissions){
                         int status = mPackageManager.checkPermission(permission, pkgName);
                         final BasePermission bp = mSettings.mPermissions.get(permission);
                         if (status != PackageManager.PERMISSION_GRANTED && bp != null) {
                            if (!bp.isRuntime() && !bp.isDevelopment()) {
                                Log.d(TAG, "Permission " + bp.name + " is not a changeable permission type");
                                continue;
                            }
                            sGrantPermissionSet.add(permission);
                         }
                     }
                     Log.d(TAG, " need grantRuntimePermission size:"+sGrantPermissionSet.size());
                     for (String permission : sGrantPermissionSet) {
                        mPackageManager.grantRuntimePermission(pkgName,
                                permission, Process.myUserHandle());
                     }
    
                     if (checkInstallPackagesPermission(pkgName, mPackageInfo)) {
                         Log.e(TAG, pkgName + " need grant INSTALL_PACKAGES permission");
                         mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
                            mPackageInfo.applicationInfo.uid, pkgName, AppOpsManager.MODE_ALLOWED);
                         Log.e(TAG, "grant INSTALL_PACKAGES permission done");
                     }
                } catch (Exception e) {
                    //e.printStackTrace();
                    Log.d(TAG, e.getMessage());
                }
    
            }
    
        }
    
        private static boolean checkInstallPackagesPermission(String packageName, PackageInfo mPackageInfo){
            int uid = mPackageInfo.applicationInfo.uid;
            //boolean permissionGranted = hasPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES, uid);
            boolean permissionRequested = hasRequestedAppOpPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName);
            int appOpMode = getAppOpMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, uid, packageName);
    
            return appOpMode != AppOpsManager.MODE_DEFAULT || permissionRequested;
        }
    
        private static int getAppOpMode(int appOpCode, int uid, String packageName) {
            return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName);
        }
    
        private static boolean hasRequestedAppOpPermission(String permission, String packageName) {
            try {
                String[] packages = mIpm.getAppOpPermissionPackages(permission);
                return ArrayUtils.contains(packages, packageName);
            } catch (Exception exc) {
                Log.e(TAG, "PackageManager dead. Cannot get permission info");
                return false;
            }
        }
    
        private static boolean hasPermission(String permission, int uid) {
            try {
                int result = mIpm.checkUidPermission(permission, uid);
                return result == PackageManager.PERMISSION_GRANTED;
            } catch (Exception e) {
                Log.e(TAG, "PackageManager dead. Cannot get permission info");
                return false;
            }
        }
    
        /**
         * Get removable system app list from config file
         *
         * @param resultSet
         *            Returned result list
         * @param file
         *            The config file
         */
        private static void sGetGrantSystemAppFromFile(
                HashSet<String> resultSet, File file) {
            resultSet.clear();
            FileReader fr = null;
            BufferedReader br = null;
            try {
                if (file.exists()) {
                    fr = new FileReader(file);
                } else {
                    Log.d(TAG, "file in " + file + " does not exist!");
                    return;
                }
                br = new BufferedReader(fr);
                String line;
                while ((line = br.readLine()) != null) {
                    line = line.trim();
                    if (!TextUtils.isEmpty(line)) {
                        Log.d(TAG, "read line " + line);
                        resultSet.add(line);
                    }
                }
                Log.e(TAG,"GRANT_SYS_APP_LIST_SYSTEM size="+resultSet.size());
            } catch (Exception io) {
                Log.d(TAG, io.getMessage());
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
                    if (fr != null) {
                        fr.close();
                    }
                } catch (IOException io) {
                    Log.d(TAG, io.getMessage());
                }
            }
        }
    }
    
    
    
    
  • 相关阅读:
    javascript关闭弹出窗体时刷新父窗体和居中显示弹出窗
    iOS 开发人员不可缺少的75个工具
    JavaWeb学习笔记:Servlet
    Oracle SQL 查询优化.Part4
    高速集成支付宝支付步骤及注意事项(原创)
    算法题-注水问题
    《C专家编程》数组和指针并不同--多维数组
    jQuery源代码 框架分析
    Python中strip方法的妙用
    友盟社会化分享
  • 原文地址:https://www.cnblogs.com/cczheng-666/p/13964043.html
Copyright © 2020-2023  润新知