AndroidL的checkPermission方法详解

    在Android源码的很多地方都会出现权限检查的方法checkPermission,此篇文字主要介绍Android5.1.1源码中的checkPermission方法是如何实现的,在此以WallpaperManagerService.java中的checkPermission方法为例来分析。

./base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java

    ........
    final Context mContext;
    ........
    public WallpaperManagerService(Context context) {
        mContext = context;
        ........
    }
    ........
    private void checkPermission(String permission) {

        // 调用Context的checkCallingOrSelfPermission来检查权限

        if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) { 

            throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
                    + ", must have permission " + permission);
        }
    }


checkCallingOrSelfPermission中checkCallingOrSelfPermission定义

./base/core/java/android/context/Context.java 

    public abstract int checkCallingOrSelfPermission(@NonNull String permission);



ContextImpl实现了Context接口,权限检查是在ContextImpl类的checkPermission方法来完成的
./base/core/java/android/app/ContextImpl.java 
    @Override
    public int checkPermission(String permission, int pid, int uid) {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }

        try {
            return ActivityManagerNative.getDefault().checkPermission(
                    permission, pid, uid); // 调用ActivityManagerNative的getDefault()方法来获取ActivityManagerService的对象
        } catch (RemoteException e) {
            return PackageManager.PERMISSION_DENIED;
        }
    }
    ........
    @Override
    public int checkCallingOrSelfPermission(String permission) {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }

        return checkPermission(permission, Binder.getCallingPid(),
                Binder.getCallingUid()); // 调用checkPermission函数来检查权限
    }


ActivityManagerNative中getDefault方法实现过程
./base/core/java/android/app/ActivityManagerNative.java
    static public IActivityManager getDefault() {
        return gDefault.get(); // 最终返回的是个ActivityManagerService的对象
    }


ActivityManagerService中checkPermission的实现过程
./base/services/core/java/com/android/server/am/ActivityManagerService.java
    int checkComponentPermission(String permission, int pid, int uid,
            int owningUid, boolean exported) {
        // We might be performing an operation on behalf of an indirect binder
        // invocation, e.g. via {@link #openContentUri}.  Check and adjust the
        // client identity accordingly before proceeding.
        Identity tlsIdentity = sCallerIdentity.get();
        if (tlsIdentity != null) {
            Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
                    + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
            uid = tlsIdentity.uid;
            pid = tlsIdentity.pid;
        }

        if (pid == MY_PID) {
            return PackageManager.PERMISSION_GRANTED;
        }

        return ActivityManager.checkComponentPermission(permission, uid,
                owningUid, exported); // 调用ActivityManager的checkComponentPermission来检查权限
    }
    ........
    @Override
    public int checkPermission(String permission, int pid, int uid) {
        if (permission == null) {
            return PackageManager.PERMISSION_DENIED;

        }

        // 调用checkComponentPermission函数来检查权限

        return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
    }


ActivityManager中checkComponentPermission的实现过程
./base/core/java/android/app/ActivityManager.java
    public static int checkComponentPermission(String permission, int uid,
            int owningUid, boolean exported) {
        ........
        try {
            return AppGlobals.getPackageManager() // 调用AppGlobals的getPackageManager()函数返回IPackageManager对象
                    .checkUidPermission(permission, uid);
        } catch (RemoteException e) {
            // Should never happen, but if it does... deny!
            Slog.e(TAG, "PackageManager is dead?!?", e);
        }
        return PackageManager.PERMISSION_DENIED;
    }


AppGlobals的getPackageManager方法实现过程
./base/core/java/android/app/AppGlobals.java
    public static IPackageManager getPackageManager() {
        return ActivityThread.getPackageManager(); // 调用ActivityThread的getPackageManager()函数
    }


ActivityThread的getPackageManager实现过程
./base/core/java/android/app/ActivityThread.java
    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
            return sPackageManager;
        }
        IBinder b = ServiceManager.getService("package");
        //Slog.v("PackageManager", "default service binder = " + b);
        sPackageManager = IPackageManager.Stub.asInterface(b);  // 最终获取的是PackageManagerService的对象
        //Slog.v("PackageManager", "default service = " + sPackageManager);
        return sPackageManager;
    }



PackageManagerService的checkUidPermission实现过程
./base/services/core/java/com/android/server/pm/PackageManagerService.java
    @Override
    public int checkUidPermission(String permName, int uid) {
        synchronized (mPackages) {
            Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
            if (obj != null) {
                GrantedPermissions gp = (GrantedPermissions)obj;
                if (gp.grantedPermissions.contains(permName)) { // 判断应用是否已声明了此权限
                    return PackageManager.PERMISSION_GRANTED;
                }
            } else {
                HashSet<String> perms = mSystemPermissions.get(uid);
                if (perms != null && perms.contains(permName)) {
                    return PackageManager.PERMISSION_GRANTED;
                }
            }
        }
        return PackageManager.PERMISSION_DENIED;

    }


至此权限检查就已完成

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值