1. 程式人生 > >android 許可權控制

android 許可權控制

android6 的許可權分為幾個級別,普通的第三方應用一般會用到 normal dangerous 。系統應用可能會用到 signature|system signature|privileged signature,詳細的資訊在Manifest中定義

vim frameworks/base/core/res/AndroidManifest.xml

其中,只有定義為dangerous 的才會要求”檢查許可權”,normal級別的,只要在應用的Manifest中有宣告,就會自動允許。所以一般開發者要重地關注dangerous的許可權.
“檢查許可權” 是這樣的,

1,如果裝置執行的是 Android 5.1(API 級別 22)或更低版本,並且應用的 targetSdkVersion 是 22 或更低版本,則系統會在安裝時要求使用者授予許可權
2,targetSdkVersion>=23 && 裝置系統是android6+。需要動態申請
3,動態申請 之後,使用者會允許或者拒絕,拒絕的話,就不能使用相關功能,強行呼叫的話,會丟擲SerurityException

dangerous的許可權有:

許可權組 許可權
CALENDAR READ_CALENDAR 、WRITE_CALENDAR
CAMERA CAMERA
CONTACTS READ_CONTACTS、WRITE_CONTACTS、GET_ACCOUNTS
LOCATION ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION
MICROPHONE RECORD_AUDIO
PHONE READ_PHONE_STATE、CALL_PHONE、READ_CALL_LOG、WRITE_CALL_LOG、ADD_VOICEMAIL、USE_SIP、PROCESS_OUTGOING_CALLS
SENSORS BODY_SENSORS
SMS SEND_SMS、RECEIVE_SMS、READ_SMS、RECEIVE_WAP_PUSH、RECEIVE_MMS
STORAGE READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE

好了,遊戲規則就是這樣。從應用開發者來說,github上也有不少輔助的第三方庫,直接拿來用就可以了。顆粒度的控制權限,當然對使用者來說是好事。

背景介紹完

不過每開一個app就要彈窗授權什麼的,我覺得有點麻煩,所以先看看原始碼,改一下這個部分的功能。

以靜默安裝應用為例

vim ./frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

@Override
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
        int installFlags, String installerPackageName, VerificationParams verificationParams,
        String packageAbiOverride, int userId) {
    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);

    final int callingUid = Binder.getCallingUid();
    enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
    // ...
}

enforceCrossUserPermission 裡面呼叫了

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);

繞了幾圈,最後是在ActivityManager.java 中落地

vim ./frameworks/base/core/java/android/app/ActivityManager.java

/** @hide */
public static int checkComponentPermission(String permission, int uid,
        int owningUid, boolean exported) {
    // Root, system server get to do everything.
    final int appId = UserHandle.getAppId(uid);
    if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
        return PackageManager.PERMISSION_GRANTED;
    }
    // Isolated processes don't get any permissions.
    if (UserHandle.isIsolated(uid)) {
        return PackageManager.PERMISSION_DENIED;
    }
    // If there is a uid that owns whatever is being accessed, it has
    // blanket access to it regardless of the permissions it requires.
    if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
        return PackageManager.PERMISSION_GRANTED;
    }
    // If the target is not exported, then nobody else can get to it.
    if (!exported) {
        /*
        RuntimeException here = new RuntimeException("here");
        here.fillInStackTrace();
        Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
                here);
        */
        return PackageManager.PERMISSION_DENIED;
    }
    if (permission == null) {
        return PackageManager.PERMISSION_GRANTED;
    }
    try {
        return AppGlobals.getPackageManager()
                .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;
}

vim ./frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

@Override
public int checkUidPermission(String permName, int uid) {
    final int userId = UserHandle.getUserId(uid);

    if (!sUserManager.exists(userId)) {
        return PackageManager.PERMISSION_DENIED;
    }

    synchronized (mPackages) {
        Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
        if (obj != null) {
            final SettingBase ps = (SettingBase) obj;
            final PermissionsState permissionsState = ps.getPermissionsState();
            if (permissionsState.hasPermission(permName, userId)) {
                return PackageManager.PERMISSION_GRANTED;
            }
            // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
            if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
                    .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
                return PackageManager.PERMISSION_GRANTED;
            }
        } else {
            ArraySet<String> perms = mSystemPermissions.get(uid);
            if (perms != null) {
                if (perms.contains(permName)) {
                    return PackageManager.PERMISSION_GRANTED;
                }
                if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && perms
                        .contains(Manifest.permission.ACCESS_FINE_LOCATION)) {
                    return PackageManager.PERMISSION_GRANTED;
                }
            }
        }
    }

    return PackageManager.PERMISSION_DENIED;
}

細節程式碼完

弄通了之後就動手改一下,一開始改的是frameworks/base/core/res/AndroidManifest.xml 一開始,改掉了 STORAGE ,把READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE 的級別都變成了normal,然後儲存許可權就預設賦予了(PERMISSION_GRANTED), 之後就不會彈窗了。

再改了 SMS 然後系統就起不來了

adb connect 192.168.0.67 && adb shell logcat

報這個錯誤

09-20 16:16:25.907  5653  5653 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main
09-20 16:16:25.907  5653  5653 E AndroidRuntime: java.lang.SecurityException: Permission android.permission.READ_SMS is not a changeable permission type
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.pm.PackageManagerService.enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(PackageManagerService.java:3468)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.pm.PackageManagerService.grantRuntimePermission(PackageManagerService.java:3501)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.pm.DefaultPermissionGrantPolicy.grantRuntimePermissionsLPw(DefaultPermissionGrantPolicy.java:828)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.pm.DefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultSmsAppLPr(DefaultPermissionGrantPolicy.java:616)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.grantDefaultPermissionsToDefaultSmsApp(PackageManagerService.java:17006)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.telecom.TelecomLoaderService$TelecomServiceConnection.onServiceConnected(TelecomLoaderService.java:86)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1223)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1240)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at android.os.Handler.handleCallback(Handler.java:739)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:95)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:148)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.SystemServer.run(SystemServer.java:283)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.server.SystemServer.main(SystemServer.java:168)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
09-20 16:16:25.907  5653  5653 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)

目測是 PackageManagerService.java 拋異常,SystemServer起不來,然後就不停的重啟。

待續