Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 53f4df30 authored by Eugene Susla's avatar Eugene Susla
Browse files

[fixed] Replace RemoteCallback with AndroidFuture in PermControler

This is ag/7529281 + fix ag/7572218

Test: atest AddConfigWidgetTest#testConfigCancelled
atest android.permission.cts.PermissionControllerTest
Change-Id: I9d8f28c0665a7ae4040ea471ed6a0187628a0306
parent a826bae9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -421,6 +421,7 @@ java_defaults {
        "core/java/com/android/internal/appwidget/IAppWidgetHost.aidl",
        "core/java/com/android/internal/backup/IBackupTransport.aidl",
        "core/java/com/android/internal/backup/IObbBackupService.aidl",
        "core/java/com/android/internal/infra/IAndroidFuture.aidl",
        "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
        "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
        "core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl",
+8 −7
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.os.RemoteCallback;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import com.android.internal.infra.AndroidFuture;

/**
 * Interface for system apps to communication with the permission controller.
@@ -28,17 +29,17 @@ import android.os.UserHandle;
 */
oneway interface IPermissionController {
    void revokeRuntimePermissions(in Bundle request, boolean doDryRun, int reason,
            String callerPackageName, in RemoteCallback callback);
            String callerPackageName, in AndroidFuture callback);
    void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
    void restoreRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
    void restoreDelayedRuntimePermissionBackup(String packageName, in UserHandle user,
            in RemoteCallback callback);
    void getAppPermissions(String packageName, in RemoteCallback callback);
            in AndroidFuture callback);
    void getAppPermissions(String packageName, in AndroidFuture callback);
    void revokeRuntimePermission(String packageName, String permissionName);
    void countPermissionApps(in List<String> permissionNames, int flags,
            in RemoteCallback callback);
    void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
            in AndroidFuture callback);
    void getPermissionUsages(boolean countSystem, long numMillis, in AndroidFuture callback);
    void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
            String permission, int grantState, in RemoteCallback callback);
    void grantOrUpgradeDefaultRuntimePermissions(in RemoteCallback callback);
                String permission, int grantState, in AndroidFuture callback);
    void grantOrUpgradeDefaultRuntimePermissions(in AndroidFuture callback);
}
+27 −63
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteCallback;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
@@ -57,7 +56,6 @@ import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.RemoteStream;
import com.android.internal.infra.ServiceConnector;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.Preconditions;

import libcore.util.EmptyArray;

@@ -67,7 +65,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

@@ -94,14 +91,6 @@ public final class PermissionControllerManager {
    private static ArrayMap<Pair<Integer, Thread>, ServiceConnector<IPermissionController>>
            sRemoteServices = new ArrayMap<>(1);

    /**
     * The key for retrieving the result from the returned bundle.
     *
     * @hide
     */
    public static final String KEY_RESULT =
            "android.permission.PermissionControllerManager.key.result";

    /** @hide */
    @IntDef(prefix = { "REASON_" }, value = {
            REASON_MALWARE,
@@ -291,31 +280,17 @@ public final class PermissionControllerManager {
                        new ArrayList<>(appRequest.getValue()));
            }

            AndroidFuture<Bundle> revokeRuntimePermissionsResult = new AndroidFuture<>();
            AndroidFuture<Map<String, List<String>>> revokeRuntimePermissionsResult =
                    new AndroidFuture<>();
            service.revokeRuntimePermissions(bundledizedRequest, doDryRun, reason,
                    mContext.getPackageName(),
                    new RemoteCallback(revokeRuntimePermissionsResult::complete));
                    revokeRuntimePermissionsResult);
            return revokeRuntimePermissionsResult;
        }).thenApply(revokeRuntimePermissionsResult -> {
            Map<String, List<String>> revoked = new ArrayMap<>();
            Bundle bundleizedRevoked = revokeRuntimePermissionsResult.getBundle(KEY_RESULT);

            for (String packageName : bundleizedRevoked.keySet()) {
                Preconditions.checkNotNull(packageName);

                ArrayList<String> permissions =
                        bundleizedRevoked.getStringArrayList(packageName);
                Preconditions.checkCollectionElementsNotNull(permissions,
                        "permissions");

                revoked.put(packageName, permissions);
            }
            return revoked;
        }).whenCompleteAsync((revoked, err) -> {
            long token = Binder.clearCallingIdentity();
            try {
                if (err != null) {
                    Log.e(TAG, "Failure when revoking runtime permissions", err);
                    Log.e(TAG, "Failure when revoking runtime permissions " + revoked, err);
                    callback.onRevokeRuntimePermissions(Collections.emptyMap());
                } else {
                    callback.onRevokeRuntimePermissions(revoked);
@@ -356,11 +331,10 @@ public final class PermissionControllerManager {
        checkNotNull(callback);

        mRemoteService.postAsync(service -> {
            CompletableFuture<Bundle> setRuntimePermissionGrantStateResult =
                    new CompletableFuture<>();
            AndroidFuture<Boolean> setRuntimePermissionGrantStateResult = new AndroidFuture<>();
            service.setRuntimePermissionGrantStateByDeviceAdmin(
                    callerPackageName, packageName, permission, grantState,
                    new RemoteCallback(setRuntimePermissionGrantStateResult::complete));
                    setRuntimePermissionGrantStateResult);
            return setRuntimePermissionGrantStateResult;
        }).whenCompleteAsync((setRuntimePermissionGrantStateResult, err) -> {
            long token = Binder.clearCallingIdentity();
@@ -370,8 +344,7 @@ public final class PermissionControllerManager {
                            err);
                    callback.accept(false);
                } else {
                    callback.accept(
                            setRuntimePermissionGrantStateResult.getBoolean(KEY_RESULT, false));
                    callback.accept(Boolean.TRUE.equals(setRuntimePermissionGrantStateResult));
                }
            } finally {
                Binder.restoreCallingIdentity(token);
@@ -453,10 +426,10 @@ public final class PermissionControllerManager {
        checkNotNull(callback);

        mRemoteService.postAsync(service -> {
            CompletableFuture<Bundle> restoreDelayedRuntimePermissionBackupResult =
                    new CompletableFuture<>();
            AndroidFuture<Boolean> restoreDelayedRuntimePermissionBackupResult =
                    new AndroidFuture<>();
            service.restoreDelayedRuntimePermissionBackup(packageName, user,
                    new RemoteCallback(restoreDelayedRuntimePermissionBackupResult::complete));
                    restoreDelayedRuntimePermissionBackupResult);
            return restoreDelayedRuntimePermissionBackupResult;
        }).whenCompleteAsync((restoreDelayedRuntimePermissionBackupResult, err) -> {
            long token = Binder.clearCallingIdentity();
@@ -466,8 +439,7 @@ public final class PermissionControllerManager {
                    callback.accept(true);
                } else {
                    callback.accept(
                            restoreDelayedRuntimePermissionBackupResult
                                    .getBoolean(KEY_RESULT, false));
                            Boolean.TRUE.equals(restoreDelayedRuntimePermissionBackupResult));
                }
            } finally {
                Binder.restoreCallingIdentity(token);
@@ -492,20 +464,16 @@ public final class PermissionControllerManager {
        Handler finalHandler = handler != null ? handler : mHandler;

        mRemoteService.postAsync(service -> {
            CompletableFuture<Bundle> getAppPermissionsResult = new CompletableFuture<>();
            service.getAppPermissions(packageName,
                    new RemoteCallback(getAppPermissionsResult::complete));
            AndroidFuture<List<RuntimePermissionPresentationInfo>> getAppPermissionsResult =
                    new AndroidFuture<>();
            service.getAppPermissions(packageName, getAppPermissionsResult);
            return getAppPermissionsResult;
        }).whenComplete((getAppPermissionsResult, err) -> finalHandler.post(() -> {
            if (err != null) {
                Log.e(TAG, "Error getting app permission", err);
                callback.onGetAppPermissions(Collections.emptyList());
            } else {
                List<RuntimePermissionPresentationInfo> permissions = null;
                if (getAppPermissionsResult != null) {
                    permissions = getAppPermissionsResult.getParcelableArrayList(KEY_RESULT);
                }
                callback.onGetAppPermissions(CollectionUtils.emptyIfNull(permissions));
                callback.onGetAppPermissions(CollectionUtils.emptyIfNull(getAppPermissionsResult));
            }
        }));
    }
@@ -548,18 +516,15 @@ public final class PermissionControllerManager {
        Handler finalHandler = handler != null ? handler : mHandler;

        mRemoteService.postAsync(service -> {
            CompletableFuture<Bundle> countPermissionAppsResult = new CompletableFuture<>();
            service.countPermissionApps(permissionNames, flags,
                    new RemoteCallback(countPermissionAppsResult::complete));
            AndroidFuture<Integer> countPermissionAppsResult = new AndroidFuture<>();
            service.countPermissionApps(permissionNames, flags, countPermissionAppsResult);
            return countPermissionAppsResult;
        }).whenComplete((countPermissionAppsResult, err) -> finalHandler.post(() -> {
            if (err != null) {
                Log.e(TAG, "Error counting permission apps", err);
                callback.onCountPermissionApps(0);
            } else {
                callback.onCountPermissionApps(countPermissionAppsResult != null
                        ? countPermissionAppsResult.getInt(KEY_RESULT)
                        : 0);
                callback.onCountPermissionApps(countPermissionAppsResult);
            }
        }));
    }
@@ -584,9 +549,9 @@ public final class PermissionControllerManager {


        mRemoteService.postAsync(service -> {
            CompletableFuture<Bundle> getPermissionUsagesResult = new CompletableFuture<>();
            service.getPermissionUsages(countSystem, numMillis,
                    new RemoteCallback(getPermissionUsagesResult::complete));
            AndroidFuture<List<RuntimePermissionUsageInfo>> getPermissionUsagesResult =
                    new AndroidFuture<>();
            service.getPermissionUsages(countSystem, numMillis, getPermissionUsagesResult);
            return getPermissionUsagesResult;
        }).whenCompleteAsync((getPermissionUsagesResult, err) -> {
            if (err != null) {
@@ -595,9 +560,8 @@ public final class PermissionControllerManager {
            } else {
                long token = Binder.clearCallingIdentity();
                try {
                    callback.onPermissionUsageResult(getPermissionUsagesResult != null
                            ? getPermissionUsagesResult.getParcelableArrayList(KEY_RESULT)
                            : Collections.emptyList());
                    callback.onPermissionUsageResult(
                            CollectionUtils.emptyIfNull(getPermissionUsagesResult));
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
@@ -619,17 +583,17 @@ public final class PermissionControllerManager {
    public void grantOrUpgradeDefaultRuntimePermissions(
            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
        mRemoteService.postAsync(service -> {
            CompletableFuture<Bundle> grantOrUpgradeDefaultRuntimePermissionsResult =
                    new CompletableFuture<>();
            AndroidFuture<Boolean> grantOrUpgradeDefaultRuntimePermissionsResult =
                    new AndroidFuture<>();
            service.grantOrUpgradeDefaultRuntimePermissions(
                    new RemoteCallback(grantOrUpgradeDefaultRuntimePermissionsResult::complete));
                    grantOrUpgradeDefaultRuntimePermissionsResult);
            return grantOrUpgradeDefaultRuntimePermissionsResult;
        }).whenCompleteAsync((grantOrUpgradeDefaultRuntimePermissionsResult, err) -> {
            if (err != null) {
                Log.e(TAG, "Error granting or upgrading runtime permissions", err);
                callback.accept(false);
            } else {
                callback.accept(grantOrUpgradeDefaultRuntimePermissionsResult != null);
                callback.accept(Boolean.TRUE.equals(grantOrUpgradeDefaultRuntimePermissionsResult));
            }
        }, executor);
    }
+20 −62
Original line number Diff line number Diff line
@@ -41,12 +41,13 @@ import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallback;
import android.os.UserHandle;
import android.permission.PermissionControllerManager.CountPermissionAppsFlag;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.Preconditions;

import java.io.IOException;
@@ -209,7 +210,7 @@ public abstract class PermissionControllerService extends Service {
            @Override
            public void revokeRuntimePermissions(
                    Bundle bundleizedRequest, boolean doDryRun, int reason,
                    String callerPackageName, RemoteCallback callback) {
                    String callerPackageName, AndroidFuture callback) {
                checkNotNull(bundleizedRequest, "bundleizedRequest");
                checkNotNull(callerPackageName);
                checkNotNull(callback);
@@ -237,22 +238,11 @@ public abstract class PermissionControllerService extends Service {

                onRevokeRuntimePermissions(request,
                        doDryRun, reason, callerPackageName, revoked -> {
                            checkNotNull(revoked);
                            Bundle bundledizedRevoked = new Bundle();
                            for (Map.Entry<String, List<String>> appRevocation :
                                    revoked.entrySet()) {
                                checkNotNull(appRevocation.getKey());
                                checkCollectionElementsNotNull(appRevocation.getValue(),
                                        "permissions");

                                bundledizedRevoked.putStringArrayList(appRevocation.getKey(),
                                        new ArrayList<>(appRevocation.getValue()));
                            }

                            Bundle result = new Bundle();
                            result.putBundle(PermissionControllerManager.KEY_RESULT,
                                    bundledizedRevoked);
                            callback.sendResult(result);
                            CollectionUtils.forEach(revoked, (pkg, perms) -> {
                                Preconditions.checkNotNull(pkg);
                                Preconditions.checkCollectionElementsNotNull(perms, "permissions");
                            });
                            callback.complete(revoked);
                        });
            }

@@ -294,40 +284,24 @@ public abstract class PermissionControllerService extends Service {

            @Override
            public void restoreDelayedRuntimePermissionBackup(String packageName, UserHandle user,
                    RemoteCallback callback) {
                    AndroidFuture callback) {
                checkNotNull(packageName);
                checkNotNull(user);
                checkNotNull(callback);

                enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);

                onRestoreDelayedRuntimePermissionsBackup(packageName, user,
                        hasMoreBackup -> {
                            Bundle result = new Bundle();
                            result.putBoolean(PermissionControllerManager.KEY_RESULT,
                                    hasMoreBackup);
                            callback.sendResult(result);
                        });
                onRestoreDelayedRuntimePermissionsBackup(packageName, user, callback::complete);
            }

            @Override
            public void getAppPermissions(String packageName, RemoteCallback callback) {
            public void getAppPermissions(String packageName, AndroidFuture callback) {
                checkNotNull(packageName, "packageName");
                checkNotNull(callback, "callback");

                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);

                onGetAppPermissions(packageName,
                        permissions -> {
                            if (permissions != null && !permissions.isEmpty()) {
                                Bundle result = new Bundle();
                                result.putParcelableList(PermissionControllerManager.KEY_RESULT,
                                        permissions);
                                callback.sendResult(result);
                            } else {
                                callback.sendResult(null);
                            }
                        });
                onGetAppPermissions(packageName, callback::complete);
            }

            @Override
@@ -349,43 +323,31 @@ public abstract class PermissionControllerService extends Service {

            @Override
            public void countPermissionApps(List<String> permissionNames, int flags,
                    RemoteCallback callback) {
                    AndroidFuture callback) {
                checkCollectionElementsNotNull(permissionNames, "permissionNames");
                checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
                checkNotNull(callback, "callback");

                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);

                onCountPermissionApps(permissionNames, flags, numApps -> {
                    Bundle result = new Bundle();
                    result.putInt(PermissionControllerManager.KEY_RESULT, numApps);
                    callback.sendResult(result);
                });
                onCountPermissionApps(permissionNames, flags, callback::complete);
            }

            @Override
            public void getPermissionUsages(boolean countSystem, long numMillis,
                    RemoteCallback callback) {
                    AndroidFuture callback) {
                checkArgumentNonnegative(numMillis);
                checkNotNull(callback, "callback");

                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);

                onGetPermissionUsages(countSystem, numMillis, users -> {
                    if (users != null && !users.isEmpty()) {
                        Bundle result = new Bundle();
                        result.putParcelableList(PermissionControllerManager.KEY_RESULT, users);
                        callback.sendResult(result);
                    } else {
                        callback.sendResult(null);
                    }
                });
                onGetPermissionUsages(countSystem, numMillis, callback::complete);
            }

            @Override
            public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
                    String packageName, String permission, int grantState,
                    RemoteCallback callback) {
                    AndroidFuture callback) {
                checkStringNotEmpty(callerPackageName);
                checkStringNotEmpty(packageName);
                checkStringNotEmpty(permission);
@@ -406,21 +368,17 @@ public abstract class PermissionControllerService extends Service {
                        null);

                onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName,
                        packageName, permission, grantState, wasSet -> {
                            Bundle result = new Bundle();
                            result.putBoolean(PermissionControllerManager.KEY_RESULT, wasSet);
                            callback.sendResult(result);
                        });
                        packageName, permission, grantState, callback::complete);
            }

            @Override
            public void grantOrUpgradeDefaultRuntimePermissions(@NonNull RemoteCallback callback) {
            public void grantOrUpgradeDefaultRuntimePermissions(@NonNull AndroidFuture callback) {
                checkNotNull(callback, "callback");

                enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
                        null);

                onGrantOrUpgradeDefaultRuntimePermissions(() -> callback.sendResult(Bundle.EMPTY));
                onGrantOrUpgradeDefaultRuntimePermissions(() -> callback.complete(true));
            }
        };
    }
+20 −0
Original line number Diff line number Diff line
/*
** Copyright 2019, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

package com.android.internal.infra;

/** @hide */
parcelable AndroidFuture;
Loading