Android 7.1 AppOpsManager permite permisos de ventana flotante de aplicaciones de terceros de forma predeterminada

plataforma

RK3288 + Android 7.1

demanda

En la versión alta del SDK, el permiso de la aplicación de terceros para solicitar la ventana flotante se ha restringido en un paso.
Además de la solicitud para que el permiso se declare en la aplicación:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

También debe abrir los permisos en la configuración: la
Opciones abiertas
aplicación puede verificar si los permisos se han obtenido a través del código:

            AppOpsManager opsMgr = (AppOpsManager)getSystemService(APP_OPS_SERVICE);
            int res = opsMgr.checkOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, Process.myUid(), getPackageName());
            if(res != AppOpsManager.MODE_ALLOWED){
    
    
                showToast(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW + " not allowed");
            }

Puede lanzar una excepción:

java.lang.SecurityException: com.android.myapp from uid 10066 not allowed to perform SYSTEM_ALERT_WINDOW

Si necesita abrir de forma predeterminada, debe modificar el código correspondiente

modificar

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

    private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
    
    
    	//判断是否包含在白名单中, 并将其置为edit 置为 true.
    	//否则, 默认情况下, 则返回空, 导致在应用或其它服务获取packageName时, 发现其并未获取任何操作权限
        edit |= checkIfInWhitelist(packageName);
        UidState uidState = getUidStateLocked(uid, edit);
        if (uidState == null) {
    
    
            return null;
        }
        if (uidState.pkgOps == null) {
    
    
            if (!edit) {
    
    
                return null;
            }
            uidState.pkgOps = new ArrayMap<>();
        }

        Ops ops = uidState.pkgOps.get(packageName);
        if (ops == null) {
    
    
            if (!edit) {
    
    
                return null;
            }
            boolean isPrivileged = false;
            // This is the first time we have seen this package name under this uid,
            // so let's make sure it is valid.
            if (uid != 0) {
    
    
                final long ident = Binder.clearCallingIdentity();
                try {
    
    
                    int pkgUid = -1;
                    try {
    
    
                        ApplicationInfo appInfo = ActivityThread.getPackageManager()
                                .getApplicationInfo(packageName,
                                        PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                                        UserHandle.getUserId(uid));
                        if (appInfo != null) {
    
    
                            pkgUid = appInfo.uid;
                            isPrivileged = (appInfo.privateFlags
                                    & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
                        } else {
    
    
                            if ("media".equals(packageName)) {
    
    
                                pkgUid = Process.MEDIA_UID;
                                isPrivileged = false;
                            } else if ("audioserver".equals(packageName)) {
    
    
                                pkgUid = Process.AUDIOSERVER_UID;
                                isPrivileged = false;
                            } else if ("cameraserver".equals(packageName)) {
    
    
                                pkgUid = Process.CAMERASERVER_UID;
                                isPrivileged = false;
                            }
                        }
                    } catch (RemoteException e) {
    
    
                        Slog.w(TAG, "Could not contact PackageManager", e);
                    }
                    if (pkgUid != uid) {
    
    
                        // Oops!  The package name is not valid for the uid they are calling
                        // under.  Abort.
                        RuntimeException ex = new RuntimeException("here");
                        ex.fillInStackTrace();
                        Slog.w(TAG, "Bad call: specified package " + packageName
                                + " under uid " + uid + " but it is really " + pkgUid, ex);
                        return null;
                    }
                } finally {
    
    
                    Binder.restoreCallingIdentity(ident);
                }
            }
            ops = new Ops(packageName, uidState, isPrivileged);
            if(checkIfInWhitelist(packageName)){
    
    
                //添加默认权限并设置为允许, 这里只加了SYTEM_ALERT_WINDOW
                Op op = new Op(ops.uidState.uid, ops.packageName, AppOpsManager.OP_SYSTEM_ALERT_WINDOW);
                op.mode = AppOpsManager.MODE_ALLOWED;
                ops.put(op.op, op);
            }
            uidState.pkgOps.put(packageName, ops);
        }
        return ops;
    }

    //allow special package for some permission
    //把需要添加默认权限的应用包名加入到白名单中.
    private boolean checkIfInWhitelist(String pkg){
    
    
        if("com.android.testapp".equals(pkg)){
    
    
            return true;
        }
        //....更多应用
        return false;
    }

Código relacionado

Una vez instalada la aplicación, los permisos son el valor predeterminado, es decir, sin cambios , el valor predeterminado:
frameworks / base / core / java / android / app / AppOpsManager.java

    public static final int OP_NONE = -1;
	//..........
    /** @hide */
    public static final int OP_WRITE_SETTINGS = 23;
    /** @hide */
    public static final int OP_SYSTEM_ALERT_WINDOW = 24;

    /**
     * This specifies the default mode for each operation.
     */
    private static int[] sOpDefaultMode = new int[] {
    
    
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_DEFAULT, // OP_WRITE_SETTINGS
            AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
            AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ERRORED,  // OP_MOCK_LOCATION
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,  // OP_TURN_ON_SCREEN
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,  // OP_RUN_IN_BACKGROUND
    };

AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW

  • Obtenga el permiso de la aplicación en los paquetes de configuración
    / aplicaciones / Configuración / src / com / android / settings / applications / AppStateAppOpsBridge.java
    public PermissionState getPermissionInfo(String pkg, int uid) {
    
    
        PermissionState permissionState = new PermissionState(pkg, new UserHandle(UserHandle
                .getUserId(uid)));
        try {
    
    
            permissionState.packageInfo = mIPackageManager.getPackageInfo(pkg,
                    PackageManager.GET_PERMISSIONS | PackageManager.MATCH_UNINSTALLED_PACKAGES,
                    permissionState.userHandle.getIdentifier());
            // Check static permission state (whatever that is declared in package manifest)
            String[] requestedPermissions = permissionState.packageInfo.requestedPermissions;
            int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
            if (requestedPermissions != null) {
    
    
                for (int i = 0; i < requestedPermissions.length; i++) {
    
    
                    if (doesAnyPermissionMatch(requestedPermissions[i], mPermissions)) {
    
    
                        permissionState.permissionDeclared = true;
                        if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
    
    
                            permissionState.staticPermissionGranted = true;
                            break;
                        }
                    }
                }
            }
            // Check app op state.
            List<PackageOps> ops = mAppOpsManager.getOpsForPackage(uid, pkg, mAppOpsOpCodes);
            if (ops != null && ops.size() > 0 && ops.get(0).getOps().size() > 0) {
    
    
                permissionState.appOpMode = ops.get(0).getOps().get(0).getMode();
            }
        } catch (RemoteException e) {
    
    
            Log.w(TAG, "PackageManager is dead. Can't get package info " + pkg, e);
        }
        return permissionState;
    }

Si el elemento de configuración no se ha cambiado, mAppOpsManager.getOpsForPackage volverá vacío.
Si se ha cambiado, devolverá el valor cambiado

Supongo que te gusta

Origin blog.csdn.net/ansondroider/article/details/106758688
Recomendado
Clasificación