Use a boolean Consumer instead of RoleManagerCallback.

And use RemoteCallback for it under the hood. This removes one AIDL
interface and allows using lambda, while aligning with what
PermissionControllerService does.

Bug: 127691087
Test: manual
Change-Id: Ia94e5bac59773380b2a4764d766bf6ff1dd5b7ff
This commit is contained in:
Hai Zhang
2019-03-06 20:12:24 -08:00
parent 908309feb5
commit f5e8ccd88f
15 changed files with 337 additions and 453 deletions

View File

@@ -110,7 +110,6 @@ java_defaults {
"core/java/android/app/role/IOnRoleHoldersChangedListener.aidl",
"core/java/android/app/role/IRoleController.aidl",
"core/java/android/app/role/IRoleManager.aidl",
"core/java/android/app/role/IRoleManagerCallback.aidl",
"core/java/android/app/slice/ISliceManager.aidl",
"core/java/android/app/slice/ISliceListener.aidl",
"core/java/android/app/timedetector/ITimeDetectorService.aidl",

View File

@@ -1118,37 +1118,32 @@ package android.app.role {
public abstract class RoleControllerService extends android.app.Service {
ctor public RoleControllerService();
method public abstract void onAddRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
method @WorkerThread public abstract boolean onAddRoleHolder(@NonNull String, @NonNull String, int);
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 @WorkerThread public abstract boolean onClearRoleHolders(@NonNull String, int);
method @WorkerThread public abstract boolean onGrantDefaultRoles();
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);
method @WorkerThread public abstract boolean onRemoveRoleHolder(@NonNull String, @NonNull String, int);
method @WorkerThread public abstract void onSmsKillSwitchToggled(boolean);
field public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
}
public final class RoleManager {
method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
}
public interface RoleManagerCallback {
method public void onFailure();
method public void onSuccess();
}
}
package android.app.usage {

View File

@@ -512,24 +512,19 @@ package android.app.role {
public final class RoleManager {
method @RequiresPermission("android.permission.OBSERVE_ROLE_HOLDERS") public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.OBSERVE_ROLE_HOLDERS") public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
}
public interface RoleManagerCallback {
method public void onFailure();
method public void onSuccess();
}
}
package android.app.usage {

View File

@@ -16,7 +16,6 @@
package android.app.role;
import android.app.role.IRoleManagerCallback;
import android.os.RemoteCallback;
/**
@@ -24,20 +23,20 @@ import android.os.RemoteCallback;
*/
oneway interface IRoleController {
void onGrantDefaultRoles(in IRoleManagerCallback callback);
void grantDefaultRoles(in RemoteCallback callback);
void onAddRoleHolder(in String roleName, in String packageName, int flags,
in IRoleManagerCallback callback);
in RemoteCallback callback);
void onRemoveRoleHolder(in String roleName, in String packageName, int flags,
in IRoleManagerCallback callback);
in RemoteCallback callback);
void onClearRoleHolders(in String roleName, int flags, in IRoleManagerCallback callback);
void onClearRoleHolders(in String roleName, int flags, in RemoteCallback callback);
void onSmsKillSwitchToggled(boolean enabled);
void isApplicationQualifiedForRole(in String roleName, in String packageName,
in RemoteCallback callback);
in RemoteCallback callback);
void isRoleVisible(in String roleName, in RemoteCallback callback);
}

View File

@@ -17,8 +17,8 @@
package android.app.role;
import android.app.role.IOnRoleHoldersChangedListener;
import android.app.role.IRoleManagerCallback;
import android.os.Bundle;
import android.os.RemoteCallback;
import android.telephony.IFinancialSmsCallback;
/**
@@ -33,13 +33,13 @@ interface IRoleManager {
List<String> getRoleHoldersAsUser(in String roleName, int userId);
void addRoleHolderAsUser(in String roleName, in String packageName, int flags, int userId,
in IRoleManagerCallback callback);
in RemoteCallback callback);
void removeRoleHolderAsUser(in String roleName, in String packageName, int flags, int userId,
in IRoleManagerCallback callback);
in RemoteCallback callback);
void clearRoleHoldersAsUser(in String roleName, int flags, int userId,
in IRoleManagerCallback callback);
in RemoteCallback callback);
void addOnRoleHoldersChangedListenerAsUser(IOnRoleHoldersChangedListener listener, int userId);
@@ -55,6 +55,7 @@ interface IRoleManager {
List<String> getHeldRolesFromController(in String packageName);
String getDefaultSmsPackage(int userId);
/**
* Get filtered SMS messages for financial app.
*/

View File

@@ -1,27 +0,0 @@
/*
* Copyright (C) 2018 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 android.app.role;
/**
* @hide
*/
oneway interface IRoleManagerCallback {
void onSuccess();
void onFailure();
}

View File

@@ -52,11 +52,6 @@ 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}.
@@ -90,35 +85,37 @@ public class RoleControllerManager {
}
/**
* @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
* @see RoleControllerService#onGrantDefaultRoles()
*/
public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
mRemoteService.scheduleRequest(new OnGrantDefaultRolesRequest(mRemoteService, callback));
public void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<Boolean> callback) {
mRemoteService.scheduleRequest(new GrantDefaultRolesRequest(mRemoteService, executor,
callback));
}
/**
* @see RoleControllerService#onAddRoleHolder(String, String, int, RoleManagerCallback)
* @see RoleControllerService#onAddRoleHolder(String, String, int)
*/
public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName,
packageName, flags, callback));
}
/**
* @see RoleControllerService#onRemoveRoleHolder(String, String, int, RoleManagerCallback)
* @see RoleControllerService#onRemoveRoleHolder(String, String, int)
*/
public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName,
packageName, flags, callback));
}
/**
* @see RoleControllerService#onClearRoleHolders(String, int, RoleManagerCallback)
* @see RoleControllerService#onClearRoleHolders(String, int)
*/
public void onClearRoleHolders(@NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName,
flags, callback));
}
@@ -210,68 +207,55 @@ public class RoleControllerManager {
}
/**
* Request for {@link #onGrantDefaultRoles(IRoleManagerCallback)}.
* Request for {@link #grantDefaultRoles(Executor, Consumer)}.
*/
private static final class OnGrantDefaultRolesRequest
private static final class GrantDefaultRolesRequest
extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
@NonNull
private final IRoleManagerCallback mCallback;
private final Executor mExecutor;
@NonNull
private final Consumer<Boolean> mCallback;
@NonNull
private final IRoleManagerCallback mRemoteCallback;
private final RemoteCallback mRemoteCallback;
private OnGrantDefaultRolesRequest(@NonNull RemoteService service,
@NonNull IRoleManagerCallback callback) {
private GrantDefaultRolesRequest(@NonNull RemoteService service,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
super(service);
mExecutor = executor;
mCallback = callback;
mRemoteCallback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
long token = Binder.clearCallingIdentity();
try {
boolean successful = result != null;
mCallback.accept(successful);
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
@Override
public void onFailure() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
}
};
}));
}
@Override
protected void onTimeout(@NonNull RemoteService remoteService) {
try {
mCallback.onFailure();
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
}
mExecutor.execute(() -> mCallback.accept(false));
}
@Override
public void run() {
try {
getService().getServiceInterface().onGrantDefaultRoles(mRemoteCallback);
getService().getServiceInterface().grantDefaultRoles(mRemoteCallback);
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onGrantDefaultRoles()", e);
Log.e(LOG_TAG, "Error calling grantDefaultRoles()", e);
}
}
}
/**
* Request for {@link #onAddRoleHolder(String, String, int, IRoleManagerCallback)}.
* Request for {@link #onAddRoleHolder(String, String, int, RemoteCallback)}.
*/
private static final class OnAddRoleHolderRequest
extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
@@ -283,14 +267,14 @@ public class RoleControllerManager {
@RoleManager.ManageHoldersFlags
private final int mFlags;
@NonNull
private final IRoleManagerCallback mCallback;
private final RemoteCallback mCallback;
@NonNull
private final IRoleManagerCallback mRemoteCallback;
private final RemoteCallback mRemoteCallback;
private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
@NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
@NonNull IRoleManagerCallback callback) {
@NonNull RemoteCallback callback) {
super(service);
mRoleName = roleName;
@@ -298,37 +282,20 @@ public class RoleControllerManager {
mFlags = flags;
mCallback = callback;
mRemoteCallback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
mRemoteCallback = new RemoteCallback(result -> {
long token = Binder.clearCallingIdentity();
try {
mCallback.sendResult(result);
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
@Override
public void onFailure() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
}
};
});
}
@Override
protected void onTimeout(@NonNull RemoteService remoteService) {
try {
mCallback.onFailure();
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
}
mCallback.sendResult(null);
}
@Override
@@ -343,7 +310,7 @@ public class RoleControllerManager {
}
/**
* Request for {@link #onRemoveRoleHolder(String, String, int, IRoleManagerCallback)}.
* Request for {@link #onRemoveRoleHolder(String, String, int, RemoteCallback)}.
*/
private static final class OnRemoveRoleHolderRequest
extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
@@ -355,14 +322,14 @@ public class RoleControllerManager {
@RoleManager.ManageHoldersFlags
private final int mFlags;
@NonNull
private final IRoleManagerCallback mCallback;
private final RemoteCallback mCallback;
@NonNull
private final IRoleManagerCallback mRemoteCallback;
private final RemoteCallback mRemoteCallback;
private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
@NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
@NonNull IRoleManagerCallback callback) {
@NonNull RemoteCallback callback) {
super(service);
mRoleName = roleName;
@@ -370,37 +337,20 @@ public class RoleControllerManager {
mFlags = flags;
mCallback = callback;
mRemoteCallback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
mRemoteCallback = new RemoteCallback(result -> {
long token = Binder.clearCallingIdentity();
try {
mCallback.sendResult(result);
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
@Override
public void onFailure() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
}
};
});
}
@Override
protected void onTimeout(@NonNull RemoteService remoteService) {
try {
mCallback.onFailure();
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
}
mCallback.sendResult(null);
}
@Override
@@ -415,7 +365,7 @@ public class RoleControllerManager {
}
/**
* Request for {@link #onClearRoleHolders(String, int, IRoleManagerCallback)}.
* Request for {@link #onClearRoleHolders(String, int, RemoteCallback)}.
*/
private static final class OnClearRoleHoldersRequest
extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
@@ -425,50 +375,33 @@ public class RoleControllerManager {
@RoleManager.ManageHoldersFlags
private final int mFlags;
@NonNull
private final IRoleManagerCallback mCallback;
private final RemoteCallback mCallback;
@NonNull
private final IRoleManagerCallback mRemoteCallback;
private final RemoteCallback mRemoteCallback;
private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
super(service);
mRoleName = roleName;
mFlags = flags;
mCallback = callback;
mRemoteCallback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
mRemoteCallback = new RemoteCallback(result -> {
long token = Binder.clearCallingIdentity();
try {
mCallback.sendResult(result);
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
@Override
public void onFailure() throws RemoteException {
long token = Binder.clearCallingIdentity();
try {
mCallback.onSuccess();
} finally {
Binder.restoreCallingIdentity(token);
finish();
}
}
};
});
}
@Override
protected void onTimeout(@NonNull RemoteService remoteService) {
try {
mCallback.onFailure();
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
}
mCallback.sendResult(null);
}
@Override
@@ -535,7 +468,7 @@ public class RoleControllerManager {
mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
long token = Binder.clearCallingIdentity();
try {
boolean qualified = result != null && result.getBoolean(KEY_RESULT);
boolean qualified = result != null;
mCallback.accept(qualified);
} finally {
Binder.restoreCallingIdentity(token);
@@ -587,7 +520,7 @@ public class RoleControllerManager {
mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
long token = Binder.clearCallingIdentity();
try {
boolean visible = result != null && result.getBoolean(KEY_RESULT);
boolean visible = result != null;
mCallback.accept(visible);
} finally {
Binder.restoreCallingIdentity(token);

View File

@@ -20,16 +20,20 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.WorkerThread;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import java.util.concurrent.Executor;
@@ -45,59 +49,102 @@ import java.util.concurrent.Executor;
@SystemApi
public abstract class RoleControllerService extends Service {
private static final String LOG_TAG = RoleControllerService.class.getSimpleName();
/**
* The {@link Intent} that must be declared as handled by the service.
*/
public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
private HandlerThread mWorkerThread;
private Handler mWorkerHandler;
@Override
public void onCreate() {
super.onCreate();
mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName());
mWorkerThread.start();
mWorkerHandler = new Handler(mWorkerThread.getLooper());
}
@Override
public void onDestroy() {
super.onDestroy();
mWorkerThread.quitSafely();
}
@Nullable
@Override
public final IBinder onBind(@Nullable Intent intent) {
return new IRoleController.Stub() {
@Override
public void onGrantDefaultRoles(IRoleManagerCallback callback) {
public void grantDefaultRoles(RemoteCallback callback) {
enforceCallerSystemUid("grantDefaultRoles");
Preconditions.checkNotNull(callback, "callback cannot be null");
RoleControllerService.this.onGrantDefaultRoles(new RoleManagerCallbackDelegate(
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::grantDefaultRoles, RoleControllerService.this,
callback));
}
@Override
public void onAddRoleHolder(String roleName, String packageName, int flags,
IRoleManagerCallback callback) {
RemoteCallback callback) {
enforceCallerSystemUid("onAddRoleHolder");
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");
RoleControllerService.this.onAddRoleHolder(roleName, packageName, flags,
new RoleManagerCallbackDelegate(callback));
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onAddRoleHolder, RoleControllerService.this,
roleName, packageName, flags, callback));
}
@Override
public void onRemoveRoleHolder(String roleName, String packageName, int flags,
IRoleManagerCallback callback) {
RemoteCallback callback) {
enforceCallerSystemUid("onRemoveRoleHolder");
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");
RoleControllerService.this.onRemoveRoleHolder(roleName, packageName, flags,
new RoleManagerCallbackDelegate(callback));
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onRemoveRoleHolder, RoleControllerService.this,
roleName, packageName, flags, callback));
}
@Override
public void onClearRoleHolders(String roleName, int flags,
IRoleManagerCallback callback) {
public void onClearRoleHolders(String roleName, int flags, RemoteCallback callback) {
enforceCallerSystemUid("onClearRoleHolders");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
RoleControllerService.this.onClearRoleHolders(roleName, flags,
new RoleManagerCallbackDelegate(callback));
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onClearRoleHolders, RoleControllerService.this,
roleName, flags, callback));
}
@Override
public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) {
RoleControllerService.this.onSmsKillSwitchToggled(smsRestrictionEnabled);
public void onSmsKillSwitchToggled(boolean enabled) {
enforceCallerSystemUid("onSmsKillSwitchToggled");
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onSmsKillSwitchToggled, RoleControllerService.this,
enabled));
}
private void enforceCallerSystemUid(@NonNull String methodName) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Only the system process can call " + methodName
+ "()");
}
}
@Override
@@ -111,9 +158,7 @@ public abstract class RoleControllerService extends Service {
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);
callback.sendResult(qualified ? Bundle.EMPTY : null);
}
@Override
@@ -124,22 +169,44 @@ public abstract class RoleControllerService extends Service {
Preconditions.checkNotNull(callback, "callback cannot be null");
boolean visible = onIsRoleVisible(roleName);
Bundle result = new Bundle();
result.putBoolean(RoleControllerManager.KEY_RESULT, visible);
callback.sendResult(result);
callback.sendResult(visible ? Bundle.EMPTY : null);
}
};
}
private void grantDefaultRoles(@NonNull RemoteCallback callback) {
boolean successful = onGrantDefaultRoles();
callback.sendResult(successful ? Bundle.EMPTY : null);
}
private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
boolean successful = onAddRoleHolder(roleName, packageName, flags);
callback.sendResult(successful ? Bundle.EMPTY : null);
}
private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
boolean successful = onRemoveRoleHolder(roleName, packageName, flags);
callback.sendResult(successful ? Bundle.EMPTY : null);
}
private void onClearRoleHolders(@NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
boolean successful = onClearRoleHolders(roleName, flags);
callback.sendResult(successful ? Bundle.EMPTY : null);
}
/**
* Called by system to grant default permissions and roles.
* <p>
* This is typically when creating a new user or upgrading either system or
* permission controller package
*
* @param callback the callback for whether this call is successful
* @return whether this call was successful
*/
public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback);
@WorkerThread
public abstract boolean onGrantDefaultRoles();
/**
* Add a specific application to the holders of a role. If the role is exclusive, the previous
@@ -151,13 +218,15 @@ public abstract class RoleControllerService extends Service {
* @param roleName the name of the role to add the role holder for
* @param packageName the package name of the application to add to the role holders
* @param flags optional behavior flags
* @param callback the callback for whether this call is successful
*
* @return whether this call was successful
*
* @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor,
* RoleManagerCallback)
* RemoteCallback)
*/
public abstract void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @NonNull RoleManagerCallback callback);
@WorkerThread
public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags);
/**
* Remove a specific application from the holders of a role.
@@ -165,26 +234,29 @@ public abstract class RoleControllerService extends Service {
* @param roleName the name of the role to remove the role holder for
* @param packageName the package name of the application to remove from the role holders
* @param flags optional behavior flags
* @param callback the callback for whether this call is successful
*
* @return whether this call was successful
*
* @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor,
* RoleManagerCallback)
* RemoteCallback)
*/
public abstract void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @NonNull RoleManagerCallback callback);
@WorkerThread
public abstract boolean onRemoveRoleHolder(@NonNull String roleName,
@NonNull String packageName, @RoleManager.ManageHoldersFlags int flags);
/**
* Remove all holders of a role.
*
* @param roleName the name of the role to remove role holders for
* @param flags optional behavior flags
* @param callback the callback for whether this call is successful
*
* @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor,
* RoleManagerCallback)
* @return whether this call was successful
*
* @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback)
*/
public abstract void onClearRoleHolders(@NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags, @NonNull RoleManagerCallback callback);
@WorkerThread
public abstract boolean onClearRoleHolders(@NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags);
/**
* Cleanup appop/permissions state in response to sms kill switch toggle
@@ -192,6 +264,7 @@ public abstract class RoleControllerService extends Service {
* @param enabled whether kill switch was turned on
*/
//STOPSHIP: remove this api before shipping a final version
@WorkerThread
public abstract void onSmsKillSwitchToggled(boolean enabled);
/**
@@ -213,31 +286,4 @@ public abstract class RoleControllerService extends Service {
* @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;
RoleManagerCallbackDelegate(IRoleManagerCallback callback) {
mCallback = callback;
}
@Override
public void onSuccess() {
try {
mCallback.onSuccess();
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onSuccess() callback");
}
}
@Override
public void onFailure() {
try {
mCallback.onFailure();
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error calling onFailure() callback");
}
}
}
}

View File

@@ -30,6 +30,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -42,6 +43,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* This class provides information about and manages roles.
@@ -315,9 +317,9 @@ public final class RoleManager {
*
* @return a list of package names of the role holders, or an empty list if none.
*
* @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
* @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
* @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, RoleManagerCallback)
* @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
* @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
* @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -351,8 +353,8 @@ public final class RoleManager {
* @param callback the callback for whether this call is successful
*
* @see #getRoleHoldersAsUser(String, UserHandle)
* @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
* @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, RoleManagerCallback)
* @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
* @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -361,7 +363,7 @@ public final class RoleManager {
@TestApi
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@ManageHoldersFlags int flags, @NonNull UserHandle user,
@CallbackExecutor @NonNull Executor executor, @NonNull RoleManagerCallback callback) {
@CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(user, "user cannot be null");
@@ -369,7 +371,7 @@ public final class RoleManager {
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
mService.addRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(),
new RoleManagerCallbackDelegate(executor, callback));
createRemoteCallback(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -390,8 +392,8 @@ public final class RoleManager {
* @param callback the callback for whether this call is successful
*
* @see #getRoleHoldersAsUser(String, UserHandle)
* @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
* @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, RoleManagerCallback)
* @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
* @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -400,7 +402,7 @@ public final class RoleManager {
@TestApi
public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@ManageHoldersFlags int flags, @NonNull UserHandle user,
@CallbackExecutor @NonNull Executor executor, @NonNull RoleManagerCallback callback) {
@CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(user, "user cannot be null");
@@ -408,7 +410,7 @@ public final class RoleManager {
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
mService.removeRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(),
new RoleManagerCallbackDelegate(executor, callback));
createRemoteCallback(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -428,8 +430,8 @@ public final class RoleManager {
* @param callback the callback for whether this call is successful
*
* @see #getRoleHoldersAsUser(String, UserHandle)
* @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
* @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
* @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
* @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -438,19 +440,33 @@ public final class RoleManager {
@TestApi
public void clearRoleHoldersAsUser(@NonNull String roleName, @ManageHoldersFlags int flags,
@NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
@NonNull RoleManagerCallback callback) {
@NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(user, "user cannot be null");
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
mService.clearRoleHoldersAsUser(roleName, flags, user.getIdentifier(),
new RoleManagerCallbackDelegate(executor, callback));
createRemoteCallback(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@NonNull
private static RemoteCallback createRemoteCallback(@NonNull Executor executor,
@NonNull Consumer<Boolean> callback) {
return new RemoteCallback(result -> executor.execute(() -> {
boolean successful = result != null;
long token = Binder.clearCallingIdentity();
try {
callback.accept(successful);
} finally {
Binder.restoreCallingIdentity(token);
}
}));
}
/**
* Add a listener to observe role holder changes
* <p>
@@ -669,40 +685,6 @@ public final class RoleManager {
}
}
private static class RoleManagerCallbackDelegate extends IRoleManagerCallback.Stub {
@NonNull
private final Executor mExecutor;
@NonNull
private final RoleManagerCallback mCallback;
RoleManagerCallbackDelegate(@NonNull Executor executor,
@NonNull RoleManagerCallback callback) {
mExecutor = executor;
mCallback = callback;
}
@Override
public void onSuccess() {
long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(mCallback::onSuccess);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onFailure() {
long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(mCallback::onFailure);
} finally {
Binder.restoreCallingIdentity(token);
}
}
}
private static class OnRoleHoldersChangedListenerDelegate
extends IOnRoleHoldersChangedListener.Stub {

View File

@@ -1,56 +0,0 @@
/*
* Copyright (C) 2018 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 android.app.role;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import java.util.concurrent.CompletableFuture;
/**
* Callback for a {@link RoleManager} request.
*
* @hide
*/
@SystemApi
@TestApi
public interface RoleManagerCallback {
/**
* Signals a success.
*/
void onSuccess();
/**
* Signals a failure.
*/
void onFailure();
/** @hide */
class Future extends CompletableFuture<Void> implements RoleManagerCallback {
@Override
public void onSuccess() {
complete(null);
}
@Override
public void onFailure() {
completeExceptionally(new RuntimeException());
}
}
}

View File

@@ -27,7 +27,6 @@ import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.role.IOnRoleHoldersChangedListener;
import android.app.role.IRoleManager;
import android.app.role.IRoleManagerCallback;
import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
@@ -245,14 +244,11 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
// Run grants again
Slog.i(LOG_TAG, "Granting default permissions...");
CompletableFuture<Void> result = new CompletableFuture<>();
getOrCreateControllerService(userId).onGrantDefaultRoles(
new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() {
getOrCreateControllerService(userId).grantDefaultRoles(FgThread.getExecutor(),
successful -> {
if (successful) {
result.complete(null);
}
@Override
public void onFailure() {
} else {
result.completeExceptionally(new RuntimeException());
}
});
@@ -434,11 +430,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public boolean isRoleHeld(@NonNull String roleName, @NonNull String packageName) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
int callingUid = getCallingUid();
mAppOpsManager.checkPackage(callingUid, packageName);
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
int userId = UserHandle.getUserId(callingUid);
ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
if (roleHolders == null) {
@@ -450,7 +447,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@NonNull
@Override
public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return Collections.emptyList();
@@ -459,6 +455,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"getRoleHoldersAsUser");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
if (roleHolders == null) {
return Collections.emptyList();
@@ -469,10 +467,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
@NonNull IRoleManagerCallback callback) {
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");
@NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -481,6 +476,10 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"addRoleHolderAsUser");
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");
getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
}
@@ -488,10 +487,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
@NonNull IRoleManagerCallback callback) {
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");
@NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -500,6 +496,10 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"removeRoleHolderAsUser");
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");
getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName, flags,
callback);
}
@@ -507,9 +507,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void clearRoleHoldersAsUser(@NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
@NonNull IRoleManagerCallback callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
@NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -518,13 +516,15 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"clearRoleHoldersAsUser");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
getOrCreateControllerService(userId).onClearRoleHolders(roleName, flags, callback);
}
@Override
public void addOnRoleHoldersChangedListenerAsUser(
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
Preconditions.checkNotNull(listener, "listener cannot be null");
if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -533,6 +533,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"addOnRoleHoldersChangedListenerAsUser");
Preconditions.checkNotNull(listener, "listener cannot be null");
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
userId);
listeners.register(listener);
@@ -541,7 +543,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void removeOnRoleHoldersChangedListenerAsUser(
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
Preconditions.checkNotNull(listener, "listener cannot be null");
if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -550,6 +551,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"removeOnRoleHoldersChangedListenerAsUser");
Preconditions.checkNotNull(listener, "listener cannot be null");
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
if (listener == null) {
return;
@@ -559,11 +562,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void setRoleNamesFromController(@NonNull List<String> roleNames) {
Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"setRoleNamesFromController");
Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
int userId = UserHandle.getCallingUserId();
getOrCreateUserState(userId).setRoleNames(roleNames);
}
@@ -571,12 +575,13 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public boolean addRoleHolderFromController(@NonNull String roleName,
@NonNull String packageName) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"addRoleHolderFromController");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
int userId = UserHandle.getCallingUserId();
return getOrCreateUserState(userId).addRoleHolder(roleName, packageName);
}
@@ -584,23 +589,25 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public boolean removeRoleHolderFromController(@NonNull String roleName,
@NonNull String packageName) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"removeRoleHolderFromController");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
int userId = UserHandle.getCallingUserId();
return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName);
}
@Override
public List<String> getHeldRolesFromController(@NonNull String packageName) {
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"getRolesHeldFromController");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
int userId = UserHandle.getCallingUserId();
return getOrCreateUserState(userId).getHeldRoles(packageName);
}
@@ -728,16 +735,14 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
CompletableFuture<Void> future = new CompletableFuture<>();
IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() {
RemoteCallback callback = new RemoteCallback(result -> {
boolean successful = result != null;
if (successful) {
future.complete(null);
}
@Override
public void onFailure() {
} else {
future.completeExceptionally(new RuntimeException());
}
};
});
if (packageName != null) {
getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
@@ -756,14 +761,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId) {
IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() {}
@Override
public void onFailure() {
RemoteCallback callback = new RemoteCallback(result -> {
boolean successful = result != null;
if (!successful) {
Slog.e(LOG_TAG, "Failed to set default browser: " + packageName);
}
};
});
if (packageName != null) {
getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
@@ -785,14 +788,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId) {
IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() {}
@Override
public void onFailure() {
RemoteCallback callback = new RemoteCallback(result -> {
boolean successful = result != null;
if (!successful) {
Slog.e(LOG_TAG, "Failed to set default home: " + packageName);
}
};
});
if (packageName != null) {
getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
packageName, 0, callback);

View File

@@ -19,7 +19,7 @@ package com.android.server.role;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.role.IRoleManager;
import android.app.role.IRoleManagerCallback;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -38,14 +38,23 @@ class RoleManagerShellCommand extends ShellCommand {
mRoleManager = roleManager;
}
private class Callback extends IRoleManagerCallback.Stub {
private class CallbackFuture extends CompletableFuture<Void> {
@NonNull
private final CompletableFuture<Void> mResult = new CompletableFuture<>();
public RemoteCallback createCallback() {
return new RemoteCallback(result -> {
boolean successful = result != null;
if (successful) {
complete(null);
} else {
completeExceptionally(new RuntimeException("Failed"));
}
});
}
public int waitForResult() {
try {
mResult.get(5, TimeUnit.SECONDS);
get(5, TimeUnit.SECONDS);
return 0;
} catch (Exception e) {
getErrPrintWriter().println("Error: see logcat for details.\n"
@@ -53,16 +62,6 @@ class RoleManagerShellCommand extends ShellCommand {
return -1;
}
}
@Override
public void onSuccess() {
mResult.complete(null);
}
@Override
public void onFailure() {
mResult.completeExceptionally(new RuntimeException("Failed"));
}
}
@Override
@@ -112,9 +111,10 @@ class RoleManagerShellCommand extends ShellCommand {
String packageName = getNextArgRequired();
int flags = getFlagsMaybe();
Callback callback = new Callback();
mRoleManager.addRoleHolderAsUser(roleName, packageName, flags, userId, callback);
return callback.waitForResult();
CallbackFuture future = new CallbackFuture();
mRoleManager.addRoleHolderAsUser(roleName, packageName, flags, userId,
future.createCallback());
return future.waitForResult();
}
private int runRemoveRoleHolder() throws RemoteException {
@@ -123,9 +123,10 @@ class RoleManagerShellCommand extends ShellCommand {
String packageName = getNextArgRequired();
int flags = getFlagsMaybe();
Callback callback = new Callback();
mRoleManager.removeRoleHolderAsUser(roleName, packageName, flags, userId, callback);
return callback.waitForResult();
CallbackFuture future = new CallbackFuture();
mRoleManager.removeRoleHolderAsUser(roleName, packageName, flags, userId,
future.createCallback());
return future.waitForResult();
}
private int runClearRoleHolders() throws RemoteException {
@@ -133,9 +134,9 @@ class RoleManagerShellCommand extends ShellCommand {
String roleName = getNextArgRequired();
int flags = getFlagsMaybe();
Callback callback = new Callback();
mRoleManager.clearRoleHoldersAsUser(roleName, flags, userId, callback);
return callback.waitForResult();
CallbackFuture future = new CallbackFuture();
mRoleManager.clearRoleHoldersAsUser(roleName, flags, userId, future.createCallback());
return future.waitForResult();
}
@Override

View File

@@ -16,7 +16,6 @@ package android.telecom;
import android.app.ActivityManager;
import android.app.role.RoleManager;
import android.app.role.RoleManagerCallback;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -34,9 +33,11 @@ import com.android.internal.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
/**
* Class for managing the default dialer application that will receive incoming calls, and be
@@ -75,11 +76,18 @@ public class DefaultDialerManager {
int user) {
long identity = Binder.clearCallingIdentity();
try {
RoleManagerCallback.Future cb = new RoleManagerCallback.Future();
CompletableFuture<Void> future = new CompletableFuture<>();
Consumer<Boolean> callback = successful -> {
if (successful) {
future.complete(null);
} else {
future.completeExceptionally(new RuntimeException());
}
};
context.getSystemService(RoleManager.class).addRoleHolderAsUser(
RoleManager.ROLE_DIALER, packageName, 0, UserHandle.of(user),
AsyncTask.THREAD_POOL_EXECUTOR, cb);
cb.get(5, TimeUnit.SECONDS);
AsyncTask.THREAD_POOL_EXECUTOR, callback);
future.get(5, TimeUnit.SECONDS);
return true;
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Slog.e(TAG, "Failed to set default dialer to " + packageName + " for user " + user, e);

View File

@@ -25,7 +25,6 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.role.RoleManagerCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -1221,8 +1220,8 @@ public class TelecomManager {
*
* @hide
* @deprecated Use
* {@link android.app.role.RoleManager#addRoleHolderAsUser(String, String, UserHandle, Executor,
* RoleManagerCallback)} instead.
* {@link android.app.role.RoleManager#addRoleHolderAsUser(String, String, int, UserHandle,
* Executor, java.util.function.Consumer)} instead.
*/
@SystemApi
@Deprecated

View File

@@ -19,7 +19,6 @@ package com.android.internal.telephony;
import android.Manifest.permission;
import android.app.AppOpsManager;
import android.app.role.RoleManager;
import android.app.role.RoleManagerCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -51,9 +50,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
/**
* Class for managing the primary application that we will deliver SMS/MMS messages to
@@ -634,12 +635,19 @@ public final class SmsApplication {
}
// Update the setting.
RoleManagerCallback.Future res = new RoleManagerCallback.Future();
CompletableFuture<Void> future = new CompletableFuture<>();
Consumer<Boolean> callback = successful -> {
if (successful) {
future.complete(null);
} else {
future.completeExceptionally(new RuntimeException());
}
};
context.getSystemService(RoleManager.class).addRoleHolderAsUser(
RoleManager.ROLE_SMS, applicationData.mPackageName, 0, UserHandle.of(userId),
AsyncTask.THREAD_POOL_EXECUTOR, res);
AsyncTask.THREAD_POOL_EXECUTOR, callback);
try {
res.get(5, TimeUnit.SECONDS);
future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.e(LOG_TAG, "Exception while adding sms role holder " + applicationData, e);
return;