androidQ Permission 权限破解合集

前言

androidQ 中权限部分做了略微改动,MTK 又增加了访问数据和 WLAN 网络权限控制,app 首次请求网络时会弹出权限框询问,大致原理就是第一次启动时扫描设备上已经安装的apk包名维护一个数据库,初始化时都为 CheckedPermRecord.STATUS_FIRST_CHECK,当首次请求网络时,拦截弹框授权。后面会详细分析,这里先跳过。
系统的运行时权限弹框风格做了调整,以前源码在 PackageInstaller 中,androidQ 中改到了 PermissionController中。

文件清单

device/mediatek/system/common/device.mk                                                                            
frameworks/base/services/core/java/com/android/server/pm/MTKPackageManagerUtil.java                                  
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java                                 
frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java                  
vendor/mediatek/proprietary/frameworks/base/data/etc/pms_sysapp_grant_permission_list.txt                            
vendor/mediatek/proprietary/packages/apps/NetworkDataController/NetworkDataControllerService/src/com/mediatek/security/datamanager/DatabaseManager.java  
vendor/mediatek/proprietary/packages/apps/NetworkDataController/NetworkDataControllerService/src/com/mediatek/security/service/NetworkDataControllerService.java                       
vendor/mediatek/proprietary/packages/apps/PermissionController/AndroidManifest.xml                                  
vendor/mediatek/proprietary/packages/apps/PermissionController/src/com/android/packageinstaller/PackageChangedService.java 
vendor/mediatek/proprietary/packages/apps/PermissionController/src/com/android/packageinstaller/PermissionGrantHelper.java 
vendor/mediatek/proprietary/packages/apps/PermissionController/src/com/android/packageinstaller/TemporaryFileManager.java

J8T2jg.png JdEenP.png J8TWuQ.png

系统app权限全开

还是通过 pms_sysapp_grant_permission_list.txt 文件来控制要全开的 app 包名

copy pms_sysapp_grant_permission_list.txt 文件到 out 的位置有所变动,不在是 device/mediatek/common/device.mk 中,改到 system 路径下
device/mediatek/system/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

vendor\mediatek\proprietary\frameworks\base\data\etc\pms_sysapp_grant_permission_list.txt

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

PMS 启动完成读取 txt 给对应的 app 授权
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

     public void systemReady() {
         enforceSystemOrRoot("Only the system can claim the system is ready");
 
+        // add for system app grant permission S
+        if (mFirstBoot) {
+            MTKPackageManagerUtil.slientGrantRuntimePermission(mContext, mPermissionManager);
+        }
+        // add for system app grant permission E
+
         mSystemReady = true;
         final ContentResolver resolver = mContext.getContentResolver();

同级目录下新增 MTKPackageManagerUtil.java,相比之前 BasePermission 通过 PermissionManagerServiceInternal 来获取

final BasePermission bp = (BasePermission) mPermissionManager.getPermissionTEMP(permission);

bp 过滤只需非 RuntimePermission,bp 无需过滤 development 相关

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


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 com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
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 = "MTKPackageManagerUtil";

    //copy from vendor\mediatek\proprietary\frameworks\base\services\core\java\com\mediatek\server\pm\PmsExtImpl.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, 
        PermissionManagerServiceInternal mPermissionManager){
        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);
                     final BasePermission bp = (BasePermission) mPermissionManager.getPermissionTEMP(permission);
                     if (status != PackageManager.PERMISSION_GRANTED && bp != null) {
                        if (!bp.isRuntime() /*&& !bp.isDevelopment()*/) {
                            Log.d(TAG, "Permission " + bp.getName() + " is not a changeable permission type");
                            continue;
                        }
                        sGrantPermissionSet.add(permission);
                     }
                 }
                 Log.e(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());
            }
        }
    }
}

installded app 权限全开

运行时权限

仿照之前的方式通过监听 ACTION_PACKAGE_ADDED 广播,当新 app 安装成功,则获取app要申请的权限进行自动授权

在 PermissionController 中新增 PackageChangedService、TemporaryFileManager、PermissionGrantHelper

**vendor/mediatek/proprietary/packages/apps/PermissionController/AndroidManifest.xml **

+++ b/alps/vendor/mediatek/proprietary/packages/apps/PermissionController/AndroidManifest.xml
@@ -6,7 +6,7 @@
   coreApp="true"
   android:versionCode="290000000"
   android:versionName="29 system image"
->
+  android:sharedUserId="android.uid.system">
 
     <original-package android:name="com.android.permissioncontroller" />
 
@@ -76,6 +76,18 @@
             </intent-filter>
         </receiver>
 
+        <!-- add S -->
+         <receiver android:name="com.android.packageinstaller.TemporaryFileManager"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
+        <service android:name="com.android.packageinstaller.PackageChangedService" 
+          android:exported="false"/>
+        <!-- add E -->
+
         <service android:name="com.android.packageinstaller.permission.service.LocationAccessCheck$LocationAccessCheckJobService"
                  android:permission="android.permission.BIND_JOB_SERVICE" />
 

PackageChangedService、TemporaryFileManager 代码和之前一样,不在贴出,PermissionGrantHelper.java 和之前有不同

AppPermissions() 构造函数类型变动,AppPermissions(Context context, PackageInfo packageInfo, boolean sortGroups, boolean delayChanges, Runnable onErrorCallback)

delayChanges 传递 false 时,app 安装完成后权限都已经默认授权,但第一次进入 app 时仍然会显示 ReviewPermissionsActivity,需要再次点击授权才能进入app 主页。

delayChanges 传递 true 时, 运行时会报 SecurityException ADJUST_RUNTIME_PERMISSIONS_POLICY

3887-3887/com.android.permissioncontroller E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.android.permissioncontroller, PID: 3887
    java.lang.SecurityException: updatePermissionFlags requires android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
        at android.os.Parcel.createException(Parcel.java:2071)
        at android.os.Parcel.readException(Parcel.java:2039)
        at android.os.Parcel.readException(Parcel.java:1987)
        at android.content.pm.IPackageManager$Stub$Proxy.updatePermissionFlags(IPackageManager.java:5569)
        at android.app.ApplicationPackageManager.updatePermissionFlags(ApplicationPackageManager.java:713)
        at com.android.packageinstaller.permission.model.AppPermissionGroup.persistChanges(AppPermissionGroup.java:1280)
        at com.android.packageinstaller.permission.model.AppPermissions.persistChanges(AppPermissions.java:196)
        at com.android.packageinstaller.permission.ui.handheld.ReviewPermissionsFragment.confirmPermissionsReviewforCTA(ReviewPermissionsFragment.java:643)
        at com.android.packageinstaller.permission.ui.handheld.ReviewPermissionsFragment.onClick(ReviewPermissionsFragment.java:173)

根据堆栈信息找到 PermissionManagerService.java 中,屏蔽对应的异常
frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

@@ -2908,8 +2908,10 @@ public class PermissionManagerService {
                 "updatePermissionFlags");
 
         if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
-            throw new SecurityException("updatePermissionFlags requires "
-                    + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
+            //20200421 annnotation for PermissionController app AppPermissionGroup.java:1280
+            //mPackageManager.updatePermissionFlags don't throw exception
+            /*throw new SecurityException("updatePermissionFlags requires "
+                    + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);*/
         }
 
         // Only the system can change these flags and nothing else.

现在运行授权时不报异常了,但是发现授权为空,app 并未授权,再次检查代码,发现遗漏了关键行代码

mAppPermissions.persistChanges(true);

完整的 PermissionGrantHelper 类如下

vendor/mediatek/proprietary/packages/apps/PermissionController/src/com/android/packageinstaller/PermissionGrantHelper.java


package com.android.packageinstaller;

import android.content.Context;
import android.util.Log;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
import com.android.packageinstaller.permission.model.Permission;
import com.android.packageinstaller.permission.utils.ArrayUtils;
import com.android.packageinstaller.permission.utils.Utils;
import java.util.List;


public class PermissionGrantHelper{

    public static void slientGrantRuntimePermission(Context context, String packageName){
        PackageInfo packageInfo;

        try {
            packageInfo =  context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e("permission", "can't get PackageInfo for packageName="+ packageName);
            return;
        }
        
       AppPermissions  mAppPermissions = new AppPermissions(context, packageInfo, false, true,
                new Runnable() {
                    @Override
                    public void run() {
                        
                    }
                });

       Log.e("permission", " AppPermissionGroup size=="+mAppPermissions.getPermissionGroups().size());
       if (mAppPermissions.getPermissionGroups().isEmpty()) {
            Log.e("permission", "mAppPermissions size isEmpty");
            return;
        }
        for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) {
            String[] permissionsToGrant = null;
            final int permissionCount = group.getPermissions().size();
            for (int j = 0; j < permissionCount; j++) {
                final Permission permission = group.getPermissions().get(j);
                if (!permission.isGranted()) {
                    permissionsToGrant = ArrayUtils.appendString(
                            permissionsToGrant, permission.getName());
                     Log.e("permission", "permissionName=" + permission.getName());
                }
            }
            if (permissionsToGrant != null) {
                group.grantRuntimePermissions(false, permissionsToGrant);
                Log.i("permission", "grantRuntimePermissions permissionsToGrant");
                //group.revokeRuntimePermissions(false);
            }
            //group.resetReviewRequired();
        }

         mAppPermissions.persistChanges(true);
    }
	
}

network 权限

烧写完第一次开机时,提示 以下系统应用需要访问数据流量和WLAN网络 界面,查找到 NetworkDataController 中

当初始化时给我们需要授权的系统应用默认赋权,这里偷懒了,用 list 包含要授权的系统app 包名,当然也可以按照之前的通过读取 txt 方式来获取包名。

vendor/mediatek/proprietary/packages/apps/NetworkDataController/NetworkDataControllerService/src/com/mediatek/security/datamanager/DatabaseManager.java

@@ -107,10 +107,15 @@ public class DatabaseManager {
             Log.d(TAG, "all = " + packageList.size() + ", old = "
                     + storedPackages.size());
             Set<Integer> uids = packageList.keySet();
+            //20200421  add for system orignal app don't need check data permission
+            List<String>  pkgNames = getSystemGrantApp();
             for (Integer uid : uids) {
+                String packageName = packageList.get(uid);
+                Log.e(TAG, "packageName = "+ packageName);
                 dataBaseHelper.addNetworkDataPerm(new CheckedPermRecord(
-                        packageList.get(uid), uid,
-                        CheckedPermRecord.STATUS_FIRST_CHECK));
+                        packageName, uid, //CheckedPermRecord.STATUS_FIRST_CHECK));
+                        pkgNames.contains(packageName) 
+                        ? CheckedPermRecord.STATUS_GRANTED : CheckedPermRecord.STATUS_FIRST_CHECK));
             }
             // delete all uninstalled package in the databases.
             for (int uid : storedPackages) {
@@ -119,6 +124,15 @@ public class DatabaseManager {
         }
     }
 
+    //20200421 add skip check data permission app list
+    private List<String> getSystemGrantApp(){
+        String[] pkgs = {"com.android.nfc", "com.android.bluetooth", "com.adups.fota", 
+                    "com.android.settings;com.qti.factory;com.android.dynsystem",
+                    "com.android.phone;com.android.mms.service;com.mediatek.mms.appservice",
+                    "com.android.networkstack","com.android.browser"};
+        return java.util.Arrays.asList(pkgs);
+    }
+
     public void setDataIntoCache() {
         mPkgPermissionsCache = dataBaseHelper.initNetworkDataPermCache();
         Log.d(TAG, "setDataIntoCache" + "cachesize: "
@@ -141,7 +155,9 @@ public class DatabaseManager {
         if (premRecord == null) {
             dataBaseHelper
                     .addNetworkDataPerm(new CheckedPermRecord(packageName,
-                           uid, CheckedPermRecord.STATUS_FIRST_CHECK));
+                           uid, //CheckedPermRecord.STATUS_FIRST_CHECK));
+                           CheckedPermRecord.STATUS_GRANTED));
+                    //20200421  change STATUS_FIRST_CHECK to granted for install app data permission
             isAdded = true;
         } else if (!premRecord.mPackageName.contains(packageName)) {
             premRecord.mergePkgName(packageName);


监听到 app 安装成功后,默认授予数据访问权限

vendor/mediatek/proprietary/packages/apps/NetworkDataController/NetworkDataControllerService/src/com/mediatek/security/service/NetworkDataControllerService.java

@@ -282,7 +282,9 @@ public class NetworkDataControllerService extends AsyncService {
                 + packageName);
         if (mDatabaseManager.add(uid, packageName)) {
             PermControlUtils.setFirewallPolicy(this, uid, -1,
-                    CheckedPermRecord.STATUS_FIRST_CHECK);
+                    CheckedPermRecord.STATUS_GRANTED);
+                    //CheckedPermRecord.STATUS_FIRST_CHECK);
+            //20200421  change STATUS_FIRST_CHECK to granted for install app data permission
             PermControlUtils.updateCtaAppStatus(uid, true);
         }
         return true;


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Android Q中,要将大数据复制到SD卡中,可以按照以下步骤进行操作: 1. 首先,确保你的应用程序具有适当的权限来访问外部存储器。可以在AndroidManifest.xml文件中添加以下权限声明: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 2. 创建一个指向外部存储器的目标文件路径。这可以通过使用Environment类中的getExternalStoragePublicDirectory()方法来实现,指定目录的类型(例如,DIRECTORY_DOCUMENTS,DIRECTORY_DOWNLOADS等)和文件名。 File srcFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "data.txt"); 3. 确保目标目录存在。 如果目录不存在,可以使用mkdirs()方法创建它。 if (!srcFile.getParentFile().exists()) { srcFile.getParentFile().mkdirs(); } 4. 创建一个用于向SD卡写入数据的输出流。可以使用FileOutputStream类进行操作。 OutputStream outputStream = new FileOutputStream(srcFile); 5. 将需要复制到SD卡的数据写入输出流中。你可以使用write()或者writeBytes()方法将数据写入输出流。 outputStream.write(data); 6. 最后,关闭输出流,释放资源。 outputStream.close(); 以上是在Android Q中将大数据复制到SD卡的基本步骤,这些步骤可以帮助你成功完成这个操作。请注意,Android Q引入了一些新的限制来增强用户的数据隐私和安全性,因此在访问外部存储器时,请遵循最新的安全最佳实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cczhengv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值