Android 11 关于app的权限重置

Android 11 Google针对权限系统又加了更多的限制,比如1.权限的单次授权;2.某个app长时间不使用,权限会被自动更新/重置!

关于app的权限重置
Android Framework权限篇四之AppOps机制

Settings里面关于app权限重置的switch 流程

./packages/apps/Settings/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java
...
Intent.ACTION_AUTO_REVOKE_PERMISSIONS, INVALID_SESSION_ID
...

./packages/apps/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
private void addAutoRevokePreferences(PreferenceScreen screen) {
        Context context = screen.getPreferenceManager().getContext();

        PreferenceCategory autoRevokeCategory = new PreferenceCategory(context);
        autoRevokeCategory.setKey(AUTO_REVOKE_CATEGORY_KEY);
        screen.addPreference(autoRevokeCategory);

        SwitchPreference autoRevokeSwitch = new SwitchPreference(context);
        autoRevokeSwitch.setOnPreferenceClickListener((preference) -> {
            mViewModel.setAutoRevoke(autoRevokeSwitch.isChecked());
            return true;
        });
    ...
./packages/apps/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt

    fun setAutoRevoke(enabled: Boolean) {
        GlobalScope.launch(IPC) {
            val aom = app.getSystemService(AppOpsManager::class.java)!!
            val uid = LightPackageInfoLiveData[packageName, user].getInitializedValue()?.uid

            if (uid != null) {
                Log.i(LOG_TAG, "sessionId $sessionId setting auto revoke enabled to $enabled for" +
                    "$packageName $user")
                val tag = if (enabled) {
                    APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__SWITCH_ENABLED
                } else {
                    APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__SWITCH_DISABLED
                }
                PermissionControllerStatsLog.write(
                    APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION, sessionId, uid, packageName,
                    tag)

                val mode = if (enabled) {
                    MODE_ALLOWED
                } else {
                    MODE_IGNORED
                }
                aom.setUidMode(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid, mode)
            }
        }
    }
    
./frameworks/base/core/java/android/app/AppOpsManager.java
    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
    public void setUidMode(int code, int uid, @Mode int mode) {
        try {
            mService.setUidMode(code, uid, mode);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    
    //或者
     /** @hide */
    @UnsupportedAppUsage
    @TestApi
    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
    public void setMode(int code, int uid, String packageName, @Mode int mode) {
        try {
            mService.setMode(code, uid, packageName, mode);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    
//关于 op code 都是大写OP为首
    /** @hide Auto-revoke app permissions if app is unused for an extended period */
    public static final int OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED =
            AppProtoEnums.APP_OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED;    
//adb 语法
AppOps service (appops) commands:
  help
    Print this help text.
  start [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> <OP> 
    Starts a given operation for a particular application.
  stop [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> <OP> 
    Stops a given operation for a particular application.
  set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>
    Set the mode for a particular application and operation.
  get [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> [<OP>]
    Return the mode for a particular application and optional operation.
  query-op [--user <USER_ID>] <OP> [<MODE>]
    Print all packages that currently have the given op in the given mode.
  reset [--user <USER_ID>] [<PACKAGE>]
    Reset the given application or all applications to default modes.
  write-settings
    Immediately write pending changes to storage.
  read-settings
    Read the last written settings, replacing current state in RAM.
  options:
    <PACKAGE> an Android package name or its UID if prefixed by --uid
    <OP>      an AppOps operation.
    <MODE>    one of allow, ignore, deny, or default
    <USER_ID> the user id under which the package is installed. If --user is
              not specified, the current user is assumed.

//给予安装位置来源apk权限
adb shell appops set com.android.settings REQUEST_INSTALL_PACKAGES allow

不过只能给Manifest关联的权限, AppOpsManager的sOpPerms[]数组
./frameworks/base/core/java/android/app/AppOpsManager.java

关于权限的几种修改方案,都是套路:
最先是要找到你需要操作的权限是啥,可以在AppOpsManager的数组里面查询!

方案一:源头操作

./frameworks/base/core/java/android/app/AppOpsManager.java
    /**
     * This specifies the default mode for each operation.
     */
    private static int[] sOpDefaultMode = new int[] {
            AppOpsManager.MODE_ALLOWED, // COARSE_LOCATION
            AppOpsManager.MODE_ALLOWED, // FINE_LOCATION
            AppOpsManager.MODE_ALLOWED, // GPS
            ...
        -   AppOpsManager.MODE_DEFAULT, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
        +   AppOpsManager.MODE_IGNORED, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
            AppOpsManager.MODE_ALLOWED, // OP_AUTO_REVOKE_MANAGED_BY_INSTALLER
            AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE
            ...

方案二:系统服务拦截

./frameworks/base/services/core/java/com/android/server/appop/AppOpsService.java

    private Op getOpLocked(Ops ops, int code, int uid, boolean edit) {
        Op op = ops.get(code);
        if (op == null) {
            if (!edit) {
                return null;
            }
            op = new Op(ops.uidState, ops.packageName, code, uid);
            ops.put(code, op);
        }
        //add text
        if(ops.packageName.equals("com.xxx")){
            Op op1 = new Op(ops.uidState, ops.packageName, AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,uid);
            op1.mode = AppOpsManager.MODE_IGNORED;//MODE_ALLOWED
            ops.put(op1.op, op1);
        }
        //add text
        if (edit) {
            scheduleWriteLocked();
        }
        return op;
    }

默认给予指定APP的AppOpsManager权限

方案三:参考

private void setSomeAppPermission(){
        int uid = 0;
        //大部分系统app才能读到
        /*PackageManager packageManager = mContext.getPackageManager();
        try {
            ApplicationInfo applicationInfo = packageManager.getApplicationInfo("com.xxx",0);
            uid = applicationInfo.uid;
        }catch (Exception e){
        }*/
        
        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
        appOpsManager.setUidMode(AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, 10136, AppOpsManager.MODE_IGNORED);
        
        /*appOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
                10136, "com.xxx", AppOpsManager.MODE_IGNORED);*/
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值