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

Commit 26f37d35 authored by Hai Zhang's avatar Hai Zhang
Browse files

Use RoleControllerService for role related APIs.

Move isApplicationQualifiedForRole() and isRoleVisible() from
PermissionControllerService to RoleControllerService.

Bug: 127691087
Test: manual
Change-Id: Ic9277f9e737e59dceafffabbf1e19526db609e78
parent a4959e56
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1122,6 +1122,8 @@ package android.app.role {
    method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
    method public abstract void onClearRoleHolders(@NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method public abstract void onGrantDefaultRoles(@NonNull android.app.role.RoleManagerCallback);
    method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String);
    method public abstract boolean onIsRoleVisible(@NonNull String);
    method public abstract void onRemoveRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method public abstract void onSmsKillSwitchToggled(boolean);
    field public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
@@ -5688,8 +5690,6 @@ package android.permission {
    method @NonNull public abstract java.util.List<android.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(@NonNull String);
    method @NonNull public abstract java.util.List<android.permission.RuntimePermissionUsageInfo> onGetPermissionUsages(boolean, long);
    method public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream);
    method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String);
    method public abstract boolean onIsRoleVisible(@NonNull String);
    method @BinderThread public abstract boolean onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle);
    method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream);
    method public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String);
+7 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app.role;

import android.app.role.IRoleManagerCallback;
import android.os.RemoteCallback;

/**
 * @hide
@@ -34,4 +35,9 @@ oneway interface IRoleController {
    void onClearRoleHolders(in String roleName, int flags, in IRoleManagerCallback callback);

    void onSmsKillSwitchToggled(boolean enabled);

    void isApplicationQualifiedForRole(in String roleName, in String packageName,
                                       in RemoteCallback callback);

    void isRoleVisible(in String roleName, in RemoteCallback callback);
}
+139 −0
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package android.app.role;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.UserIdInt;
import android.content.ComponentName;
@@ -27,6 +30,7 @@ import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
@@ -35,6 +39,9 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
import com.android.internal.infra.AbstractRemoteService;

import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * Interface for communicating with the role controller.
 *
@@ -45,6 +52,11 @@ public class RoleControllerManager {

    private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();

    /**
     * The key for retrieving the result from a bundle.
     */
    public static final String KEY_RESULT = "android.app.role.RoleControllerManager.key.RESULT";

    private static final Object sRemoteServicesLock = new Object();
    /**
     * Global remote services (per user) used by all {@link RoleControllerManager managers}.
@@ -118,6 +130,26 @@ public class RoleControllerManager {
        mRemoteService.scheduleAsyncRequest(new OnSmsKillSwitchToggledRequest(enabled));
    }

    /**
     * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String)
     */
    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
    public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
        mRemoteService.scheduleRequest(new IsApplicationQualifiedForRoleRequest(mRemoteService,
                roleName, packageName, executor, callback));
    }

    /**
     * @see RoleControllerService#onIsRoleVisible(String)
     */
    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
    public void isRoleVisible(@NonNull String roleName,
            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
        mRemoteService.scheduleRequest(new IsRoleVisibleRequest(mRemoteService, roleName, executor,
                callback));
    }

    /**
     * Connection to the remote service.
     */
@@ -471,4 +503,111 @@ public class RoleControllerManager {
            }
        }
    }

    /**
     * Request for {@link #isApplicationQualifiedForRole(String, String, Executor, Consumer)}
     */
    private static final class IsApplicationQualifiedForRoleRequest extends
            AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {

        @NonNull
        private final String mRoleName;
        @NonNull
        private final String mPackageName;
        @NonNull
        private final Executor mExecutor;
        @NonNull
        private final Consumer<Boolean> mCallback;

        @NonNull
        private final RemoteCallback mRemoteCallback;

        private IsApplicationQualifiedForRoleRequest(@NonNull RemoteService service,
                @NonNull String roleName, @NonNull String packageName,
                @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
            super(service);

            mRoleName = roleName;
            mPackageName = packageName;
            mExecutor = executor;
            mCallback = callback;

            mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
                long token = Binder.clearCallingIdentity();
                try {
                    boolean qualified = result != null && result.getBoolean(KEY_RESULT);
                    mCallback.accept(qualified);
                } finally {
                    Binder.restoreCallingIdentity(token);
                    finish();
                }
            }));
        }

        @Override
        protected void onTimeout(RemoteService remoteService) {
            mExecutor.execute(() -> mCallback.accept(false));
        }

        @Override
        public void run() {
            try {
                getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName,
                        mPackageName, mRemoteCallback);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling isApplicationQualifiedForRole()", e);
            }
        }
    }

    /**
     * Request for {@link #isRoleVisible(String, Executor, Consumer)}
     */
    private static final class IsRoleVisibleRequest
            extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {

        @NonNull
        private final String mRoleName;
        @NonNull
        private final Executor mExecutor;
        @NonNull
        private final Consumer<Boolean> mCallback;

        @NonNull
        private final RemoteCallback mRemoteCallback;

        private IsRoleVisibleRequest(@NonNull RemoteService service, @NonNull String roleName,
                @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
            super(service);

            mRoleName = roleName;
            mExecutor = executor;
            mCallback = callback;

            mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
                long token = Binder.clearCallingIdentity();
                try {
                    boolean visible = result != null && result.getBoolean(KEY_RESULT);
                    mCallback.accept(visible);
                } finally {
                    Binder.restoreCallingIdentity(token);
                    finish();
                }
            }));
        }

        @Override
        protected void onTimeout(RemoteService remoteService) {
            mExecutor.execute(() -> mCallback.accept(false));
        }

        @Override
        public void run() {
            try {
                getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling isRoleVisible()", e);
            }
        }
    }
}
+52 −0
Original line number Diff line number Diff line
@@ -16,12 +16,15 @@

package android.app.role;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
@@ -96,6 +99,35 @@ public abstract class RoleControllerService extends Service {
            public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) {
                RoleControllerService.this.onSmsKillSwitchToggled(smsRestrictionEnabled);
            }

            @Override
            public void isApplicationQualifiedForRole(String roleName, String packageName,
                    RemoteCallback callback) {
                enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);

                Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
                Preconditions.checkStringNotEmpty(packageName,
                        "packageName cannot be null or empty");
                Preconditions.checkNotNull(callback, "callback cannot be null");

                boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName);
                Bundle result = new Bundle();
                result.putBoolean(RoleControllerManager.KEY_RESULT, qualified);
                callback.sendResult(result);
            }

            @Override
            public void isRoleVisible(String roleName, RemoteCallback callback) {
                enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);

                Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
                Preconditions.checkNotNull(callback, "callback cannot be null");

                boolean visible = onIsRoleVisible(roleName);
                Bundle result = new Bundle();
                result.putBoolean(RoleControllerManager.KEY_RESULT, visible);
                callback.sendResult(result);
            }
        };
    }

@@ -162,6 +194,26 @@ public abstract class RoleControllerService extends Service {
    //STOPSHIP: remove this api before shipping a final version
    public abstract void onSmsKillSwitchToggled(boolean enabled);

    /**
     * Check whether an application is qualified for a role.
     *
     * @param roleName name of the role to check for
     * @param packageName package name of the application to check for
     *
     * @return whether the application is qualified for the role
     */
    public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
            @NonNull String packageName);

    /**
     * Check whether a role should be visible to user.
     *
     * @param roleName name of the role to check for
     *
     * @return whether the role should be visible to user
     */
    public abstract boolean onIsRoleVisible(@NonNull String roleName);

    private static class RoleManagerCallbackDelegate implements RoleManagerCallback {

        private IRoleManagerCallback mCallback;
+0 −3
Original line number Diff line number Diff line
@@ -38,9 +38,6 @@ oneway interface IPermissionController {
    void countPermissionApps(in List<String> permissionNames, int flags,
            in RemoteCallback callback);
    void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
    void isApplicationQualifiedForRole(String roleName, String packageName,
            in RemoteCallback callback);
    void isRoleVisible(String roleName, in RemoteCallback callback);
    void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
            String permission, int grantState, in RemoteCallback callback);
}
Loading