preface

Recently, the PackageManagerService(PMS) has been implemented with 3W lines of code, which is pretty neat. There are many articles on the web that analyze the process, so I will not repeat them here, but take a look at the PMS derivative modification in action. I wrote an article before that Android8.1 grants all permissions to third-party apps by default. In fact, it can also authorize system apps. The principle is roughly to check whether the specified package name permission has been granted after receiving the boot broadcast. But the boot broadcast has timeliness, some scenes can not meet the requirements, and always need to modify the source code, not convenient.

Modify the

The general idea is as follows: Refer to MTK’s system APP uninstallation configuration scheme. Add the uninstalled system app package name to vendor/Mediatek/Proprietary/frameworks/base/data/etc/pMS_sysapp_removable_system_list. TXT. Copy the file to out system/etc/permissions at compile time, read the file in pmsextimpl. Java, and PMS determines whether the package name is in pMS_sysAPP_removable_system_list when scanning. Determine whether uninstallation is possible.

Create pMS_sysapp_grant_permission_list.txt

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
Copy the code

Copy pMS_sysapp_grant_permission_list. TXT to out directory

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_VEND OR)/etc/permissions/pms_sysapp_removable_vendor_list.txt) endifCopy the code

Pms_sysapp_grant_permission_list. TXT is read after system startup in PMS to authorize APP

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

@Override
    public void systemReady(a) {//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);

Copy the code

New MTKPackageManagerUtil class

1. Read the package name in pMS_sysapp_grant_permission_list. TXT

2. Traverse the package name set to obtain the permission set to be applied for

3. Determine whether the current package name is authorized according to the permission name

There are a few pits here and just to give you an idea,

Pit 1. Many permissions in the set obtained according to the package name are not in BasePermission, and the system cannot properly authorize them. Exceptions will be thrown, resulting in the failure of subsequent permissions to be properly authorized.

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

Copy the code

Pit 2: Users’ own declared permissions and non-runtime permissions need to be removed.

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
Copy the code

frameworks\base\services\core\java\com\android\server\pm\MTKPackageManagerUtil.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 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, 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);

        returnappOpMode ! = 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
       
         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()); }}}}Copy the code