pm disable 执行过程

简单对pm disable 执行过程进行分析,未整理,顶贴到100楼会进行整理   深入工作室
如果你手机安装了360手机卫士,并root
进入adb shell执行
shell>su
shell>pm disable com.qihoo360.mobilesafe
360手机卫士就被禁用了,其中360安全卫士有禁止开机启动功能!他是怎样实现的呢?下面就行简单分析

PackageManager.setComponentEnabledSetting()实现
类关系图
Context
        ContextWrapper.java        对Context包装类
        ContextImpl.java         对Context实现类
        Activity.java
ActivitThread

IPackageManager
        PackageManagerService extends IPackageManager.Stub           对PackageManager实现
        PackageManager
                ApplicationPackageManager                         包装PackageManagerService
GrantedPermissions                权限mode
        PackageSettingBase        包含应用程序信息安装时间,更新时间等
                PackageSetting
PackageSignatures                应用签名,保存key
BasePermission
Settings
        官方解释:Holds information about dynamic settings.
        翻译为:对动态设置的信息



Activity调用getPackagemanager()
  @Override
    public PackageManager getPackageManager() {
        IPackageManager pm = ActivityThread.getPackageManager();
        // Doesn't matter if we make more than one instance.
        return new ApplicationPackageManager(this, pm);
    }
ActivityThread 获取PackageManager
public static IPackageManager getPackageManager() {
        IBinder b = ServiceManager.getService("package");
               return IPackageManager.Stub.asInterface(b);
    }

IPackageManager.aidl 实现类为 PackageManagerService下面是声明
public class PackageManagerService extends IPackageManager.Stub 

核心实现代码
Parameters
componentName         The component to enable
newState         The new enabled state for the component. The legal values for this state are: COMPONENT_ENABLED_STATE_ENABLED, COMPONENT_ENABLED_STATE_DISABLED and COMPONENT_ENABLED_STATE_DEFAULT The last one removes the setting, thereby restoring the component's state to whatever was set in it's manifest (or enabled, by default).
flags                 Optional behavior flags: DONT_KILL_APP or 0. 
public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
        setEnabledSetting(componentName.getPackageName(), componentName.getClassName(), newState, flags);
    }

        //packageName         应用包名
        //className        应用类名
        //newState        COMPONENT_ENABLED_STATE_ENABLED                启用组件
                        COMPONENT_ENABLED_STATE_DISABLED        禁用组件
                        COMPONENT_ENABLED_STATE_DEFAULT                //TODO ?
                        COMPONENT_ENABLED_STATE_DISABLED_USER   注在官方文档没有给这个参数,现在这个参数没有用处
        //flags                DONT_KILL_APP  or  0
    private void setEnabledSetting( final String packageName, String className, int newState, final int flags) {
        //支持状态检测
        if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
              || newState == COMPONENT_ENABLED_STATE_ENABLED
              || newState == COMPONENT_ENABLED_STATE_DISABLED
              || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
            throw new IllegalArgumentException("Invalid new component state: "
                    + newState);
        }
        
        PackageSetting pkgSetting;
        //用户uid检测,不是root用户你是不能禁用与启用其他应用组件的,但可以修改自己应用组件
        final int uid = Binder.getCallingUid();
        final int permission = mContext.checkCallingPermission(
                android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
        boolean sendNow = false;
        boolean isApp = (className == null);
        String componentName = isApp ? packageName : className;
        int packageUid = -1;
        ArrayList<String> components;

        // writer
        synchronized (mPackages) {
            //根据包名获取应用配置
            pkgSetting = mSettings.mPackages.get(packageName);
            if (pkgSetting == null) {
                if (className == null) {
                    throw new IllegalArgumentException(
                            "Unknown package: " + packageName);
                }
                throw new IllegalArgumentException(
                        "Unknown component: " + packageName
                        + "/" + className);
            }
            if (!allowedByPermission && (uid != pkgSetting.userId)) {
                throw new SecurityException(
                        "Permission Denial: attempt to change component state from pid="
                        + Binder.getCallingPid()
                        + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
            }
            if (className == null) {
                // We're dealing with an application/package level state change
                if (pkgSetting.enabled == newState) {
                    // Nothing to do
                    return;
                }
                pkgSetting.enabled = newState;
                pkgSetting.pkg.mSetEnabled = newState;
            } else {
                // We're dealing with a component level state change
                //这里得到配置后进行开启与禁用
                switch (newState) {
                case COMPONENT_ENABLED_STATE_ENABLED:
                    if (!pkgSetting.enableComponentLPw(className)) {
                        return;
                    }
                    break;
                case COMPONENT_ENABLED_STATE_DISABLED:
                    if (!pkgSetting.disableComponentLPw(className)) {
                        return;
                    }
                    break;
                case COMPONENT_ENABLED_STATE_DEFAULT:
                    if (!pkgSetting.restoreComponentLPw(className)) {
                        return;
                    }
                    break;
                default:
                    Slog.e(TAG, "Invalid new component state: " + newState);
                    return;
                }
            }
            //保存
            mSettings.writeLPr();
            packageUid = pkgSetting.userId;
            components = mPendingBroadcasts.get(packageName);
            final boolean newPackage = components == null;
            if (newPackage) {
                components = new ArrayList<String>();
            }
            if (!components.contains(componentName)) {
                components.add(componentName);
            }
            //设置flag,这里影响广播
            if ((flags&PackageManager.DONT_KILL_APP) == 0) {
                sendNow = true;
                // Purge entry from pending broadcast list if another one exists already
                // since we are sending one right away.
                mPendingBroadcasts.remove(packageName);
            } else {
                if (newPackage) {
                    mPendingBroadcasts.put(packageName, components);
                }
                if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
                    // Schedule a message
                    mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
                }
            }
        }

        long callingId = Binder.clearCallingIdentity();
        try {
            if (sendNow) {
                sendPackageChangedBroadcast(packageName,
                        (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
            }
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    }


Settings mSettings = new Settings();
public class Settings{
         HashMap<String, PackageSetting> mPackages =  new HashMap<String, PackageSetting>();
}
//根据应用获取设置信息
PackageSetting pkgSetting = mSettings.mPackages.get(packageName);


//Settings类
1:初始化缓存集合加载/data/system下的配置文件
        packages.xml
        packages-backup.xml
        packages.list
        packages-stopped.xml
        packages-stopped-backup.xml
2: 解析内容
3:最配置进行操作然后保存

packages.xml app列表
包名                        uid                isDebug ? " 1 " : " 0 "                app位置
....                
com.tencent.mm                 10089                 0                                 /data/data/com.tencent.mm
....
判断是否为debug 
ApplicationInfo ai = pkg.pkg.applicationInfo;
boolean isDebug  = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;



<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<packages>
        <!-- sdk 版本 -->
        <last-platform-version internal="15" external="0">
        <!-- VerifierDeviceIdentity类 -->
        <verifier device="LMJC-3UZX-YWX6-s"/>
        <!--XXX知识点:API Guides中介绍了 persimission-trees persimission persimission-group  user-persimission -->
        <persmission-trees>
                <item name="com.google.android.googleapps.permission.GOOGLE_AUTH" package="com.google.android.gsf" >
        </permission-trees>
        <!--解析所有apk中的AndroidManifest文件获取所有的权限-->
        <permissions>
                ...
                <!--
                        name 权限的名称
                        package 所在的包
                        protection 在PermissionInfo中定义取值范围0-3
                        PermissionInfo.PROTECTION_NORMAL
                        PermissionInfo.PROTECTION_DANGEROUS
                        PermissionInfo.PROTECTION_SIGNATURE
                        PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM
                        在360xml, android:protectionLevel="signature"可能会影响protection
                           <permission android:label="access permission" android:name="com.qihoo360.mobilesafe.permission.broadcast"                 
                            android:protectionLevel="signature" android:description="@string/app_name" />
                
                -->
                <item name="com.google.android.gtalkservice.permission.GTALK_SERVICE" package="com.google.android.gsf" protection="2" />    
                <item name="android.permission.ACCESS_NETWORK_STATE" package="android" /> 
                <item name="tencent.pengyou.permission.DATA" package="com.tencent.pengyou" protection="2" />    
                <item name="android.permission.CHANGE_WIFI_MULTICAST_STATE" package="android" protection="1" /> 
                <item name="android.permission.CALL_PRIVILEGED" package="android" protection="3" />  
                <item name="com.qihoo360.mobilesafe.permission.broadcast" package="com.qihoo360.mobilesafe" protection="2" /> 
                ...
        </permissions>
        <!--
                name:                        包名
                realName:                真实包名
                codePath:                安装包路径
                resourcePath:                
                nativeLibraryPath:        lib包路径
                flags:                        pkg.pkgFlags
                ft:                        pkg.timeStamp
                it:                        pkg.firstInstallTime   安装时间
                ut:                        pkg.lastUpdateTime        更新时间
                version:
                userId:
                sharedUserId:
                uidError:
                enabled:                应用被禁用 pm disable com.zhima 启用 pm enable com.zhima
                installStatus:
                installer:
                sigs:
                perms:
                disabled-components:  禁用的组件
                enable-components:        
                
        -->
        <package name="com.example.demo5" codePath="/data/app/com.example.demo5-1.apk" nativeLibraryPath="/data/data/com.example.demo5/lib" flags="0" ft="13efa2c4770" it="13eede89d9a" ut="13efa2c484a" version="1" userId="10100">
        <sigs count="1">                                                                                                                         
        <cert index="1" key="...08201e53082014ea003020102020451208ba5300d06092a864886f70d01010505003037310b30090603550406130255533110300e060355040a1307416e64726f6."/        >                                                                                                                                                            
<perms>                                                                                                                                                 
<item name="android.permission.SEND_SMS"/>                                                                                                             
<item name="android.permission.WRITE_EXTERNAL_STORAGE"/>                                                                                               
<item name="android.permission.ACCESS_WIFI_STATE"/>                                                                                                    
<item name="android.permission.ACCESS_COARSE_LOCATION"/>                                                                                               
<item name="android.permission.CALL_PHONE"/>                                                                                                           
<item name="android.permission.WRITE_CONTACTS"/>                                                                                                       
<item name="android.permission.READ_PHONE_STATE"/>                                                                                                     
<item name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>                                                                                            
<item name="android.permission.SYSTEM_ALERT_WINDOW"/>                                                                                                  
<item name="android.permission.CAMERA"/>                                                                                                               
<item name="android.permission.INTERNET"/>                                                                                                             
<item name="android.permission.CHANGE_WIFI_STATE"/>                                                                                                    
<item name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>                                                                                       
<item name="android.permission.ACCESS_FINE_LOCATION"/>                                                                                                 
<item name="android.permission.VIBRATE"/>                                                                                                              
<item name="android.permission.BROADCAST_STICKY"/>                                                                                                     
<item name="android.permission.ACCESS_NETWORK_STATE"/>                                                                                                 
<item name="android.permission.RECORD_AUDIO"/>                                                                                                         
<item name="android.permission.WAKE_LOCK"/>                                                                                                            
<item name="android.permission.ACCESS_MOCK_LOCATION"/>                                                                                                 
<perms>                                                                                                                                                
        </package>  
</packages>


理解:pm disable com.zhima 执行过程
获取PackageManage调用setComponentEnabledSetting方法,操作Settings对配置文件进行修改

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值