Loading core/java/android/rolecontrollerservice/IRoleControllerService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -30,4 +30,6 @@ oneway interface IRoleControllerService { in IRoleManagerCallback callback); void onClearRoleHolders(in String roleName, in IRoleManagerCallback callback); void onGrantDefaultRoles(in IRoleManagerCallback callback); } core/java/android/rolecontrollerservice/RoleControllerService.java +17 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ public abstract class RoleControllerService extends Service { RoleControllerService.this.onClearRoleHolders(roleName, new RoleManagerCallbackDelegate(callback)); } @Override public void onGrantDefaultRoles(IRoleManagerCallback callback) { Preconditions.checkNotNull(callback, "callback cannot be null"); RoleControllerService.this.onGrantDefaultRoles( new RoleManagerCallbackDelegate(callback)); } }; } Loading Loading @@ -133,6 +140,16 @@ public abstract class RoleControllerService extends Service { public abstract void onClearRoleHolders(@NonNull String roleName, @NonNull RoleManagerCallback callback); /** * 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 */ public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback); private static class RoleManagerCallbackDelegate implements RoleManagerCallback { private IRoleManagerCallback mCallback; Loading services/core/java/com/android/server/role/RemoteRoleControllerService.java +56 −27 Original line number Diff line number Diff line Loading @@ -16,10 +16,10 @@ package com.android.server.role; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.annotation.WorkerThread; import android.app.role.IRoleManagerCallback; import android.app.role.RoleManagerCallback; import android.content.ComponentName; Loading @@ -34,6 +34,7 @@ import android.rolecontrollerservice.IRoleControllerService; import android.rolecontrollerservice.RoleControllerService; import android.util.Slog; import com.android.internal.os.BackgroundThread; import com.android.internal.util.function.pooled.PooledLambda; import java.util.ArrayDeque; Loading @@ -44,8 +45,12 @@ import java.util.Queue; */ public class RemoteRoleControllerService { static final boolean DEBUG = false; private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName(); @NonNull private static final Handler sCallbackHandler = BackgroundThread.getHandler(); @NonNull private final Connection mConnection; Loading Loading @@ -87,6 +92,16 @@ public class RemoteRoleControllerService { service.onClearRoleHolders(roleName, callbackDelegate), callback)); } /** * Performs granting of default roles and permissions and appops * * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback) */ public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) { mConnection.enqueueCall( new Connection.Call(IRoleControllerService::onGrantDefaultRoles, callback)); } private static final class Connection implements ServiceConnection { private static final long UNBIND_DELAY_MILLIS = 15 * 1000; Loading @@ -105,9 +120,6 @@ public class RemoteRoleControllerService { @NonNull private final Queue<Call> mPendingCalls = new ArrayDeque<>(); @NonNull private final Handler mMainHandler = Handler.getMain(); @NonNull private final Runnable mUnbindRunnable = this::unbind; Loading @@ -116,14 +128,14 @@ public class RemoteRoleControllerService { mContext = context; } @MainThread @Override @WorkerThread public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) { mService = IRoleControllerService.Stub.asInterface(service); executePendingCalls(); } @MainThread @WorkerThread private void executePendingCalls() { while (!mPendingCalls.isEmpty()) { Call call = mPendingCalls.poll(); Loading @@ -132,26 +144,33 @@ public class RemoteRoleControllerService { scheduleUnbind(); } @MainThread @Override @WorkerThread public void onServiceDisconnected(@NonNull ComponentName name) { mService = null; } @MainThread @Override @WorkerThread public void onBindingDied(@NonNull ComponentName name) { unbind(); } public void enqueueCall(@NonNull Call call) { mMainHandler.post(PooledLambda.obtainRunnable(this::executeCall, call)); if (DEBUG) { Slog.i(LOG_TAG, "Enqueue " + call); } sCallbackHandler.executeOrSendMessage(PooledLambda.obtainMessage( Connection::executeCall, this, call)); } @MainThread @WorkerThread private void executeCall(@NonNull Call call) { ensureBound(); if (mService == null) { if (DEBUG) { Slog.i(LOG_TAG, "Delaying until service connected: " + call); } mPendingCalls.offer(call); return; } Loading @@ -159,24 +178,28 @@ public class RemoteRoleControllerService { scheduleUnbind(); } @MainThread @WorkerThread private void ensureBound() { mMainHandler.removeCallbacks(mUnbindRunnable); sCallbackHandler.removeCallbacks(mUnbindRunnable); if (!mBound) { Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); intent.setPackage(mContext.getPackageManager() .getPermissionControllerPackageName()); // Use direct handler to ensure onServiceConnected callback happens in the same // call frame, as required by onGrantDefaultRoles // // Note that as a result, onServiceConnected may happen not on main thread! mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE, UserHandle.of(mUserId)); sCallbackHandler, UserHandle.of(mUserId)); } } private void scheduleUnbind() { mMainHandler.removeCallbacks(mUnbindRunnable); mMainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); sCallbackHandler.removeCallbacks(mUnbindRunnable); sCallbackHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); } @MainThread @WorkerThread private void unbind() { if (mBound) { mService = null; Loading @@ -195,9 +218,6 @@ public class RemoteRoleControllerService { @NonNull private final IRoleManagerCallback mCallback; @NonNull private final Handler mMainHandler = Handler.getMain(); @NonNull private final Runnable mTimeoutRunnable = () -> notifyCallback(false); Loading @@ -209,10 +229,13 @@ public class RemoteRoleControllerService { mCallback = callback; } @MainThread @WorkerThread public void execute(IRoleControllerService service) { if (DEBUG) { Slog.i(LOG_TAG, "Executing " + this); } try { mMainHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS); sCallbackHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS); mCallExecutor.execute(service, new CallbackDelegate()); } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling RoleControllerService", e); Loading @@ -220,13 +243,13 @@ public class RemoteRoleControllerService { } } @MainThread @WorkerThread private void notifyCallback(boolean success) { if (mCallbackNotified) { return; } mCallbackNotified = true; mMainHandler.removeCallbacks(mTimeoutRunnable); sCallbackHandler.removeCallbacks(mTimeoutRunnable); try { if (success) { mCallback.onSuccess(); Loading @@ -239,10 +262,15 @@ public class RemoteRoleControllerService { } } @Override public String toString() { return "Call with callback: " + mCallback; } @FunctionalInterface public interface CallExecutor { @MainThread @WorkerThread void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate) throws RemoteException; } Loading @@ -251,13 +279,14 @@ public class RemoteRoleControllerService { @Override public void onSuccess() throws RemoteException { mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, true)); sCallbackHandler.sendMessage(PooledLambda.obtainMessage( Call::notifyCallback, Call.this, true)); } @Override public void onFailure() throws RemoteException { mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, false)); sCallbackHandler.sendMessage(PooledLambda.obtainMessage( Call::notifyCallback, Call.this, false)); } } } Loading services/core/java/com/android/server/role/RoleManagerService.java +27 −3 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ import com.android.server.SystemService; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Service for role management. Loading Loading @@ -105,17 +109,37 @@ public class RoleManagerService extends SystemService { public void onStart() { publishBinderService(Context.ROLE_SERVICE, new Stub()); //TODO add watch for new user creation and run default grants for them //TODO add package update watch to detect PermissionController upgrade and run def. grants } @Override public void onStartUser(@UserIdInt int userId) { synchronized (mLock) { //TODO only call into PermissionController if it or system upgreaded (for boot time) // (add package changes watch; // we can detect upgrade using build fingerprint and app version) getUserStateLocked(userId); //TODO call permission grant policy here } //TODO consider calling grants only when certain conditions are met // such as OS or PermissionController upgrade if (RemoteRoleControllerService.DEBUG) { Slog.i(LOG_TAG, "Granting default permissions..."); CompletableFuture<Void> result = new CompletableFuture<>(); getControllerService(userId).onGrantDefaultRoles( new IRoleManagerCallback.Stub() { @Override public void onSuccess() { result.complete(null); } @Override public void onFailure() { result.completeExceptionally(new RuntimeException()); } }); try { result.get(5, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e); } } } Loading Loading
core/java/android/rolecontrollerservice/IRoleControllerService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -30,4 +30,6 @@ oneway interface IRoleControllerService { in IRoleManagerCallback callback); void onClearRoleHolders(in String roleName, in IRoleManagerCallback callback); void onGrantDefaultRoles(in IRoleManagerCallback callback); }
core/java/android/rolecontrollerservice/RoleControllerService.java +17 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ public abstract class RoleControllerService extends Service { RoleControllerService.this.onClearRoleHolders(roleName, new RoleManagerCallbackDelegate(callback)); } @Override public void onGrantDefaultRoles(IRoleManagerCallback callback) { Preconditions.checkNotNull(callback, "callback cannot be null"); RoleControllerService.this.onGrantDefaultRoles( new RoleManagerCallbackDelegate(callback)); } }; } Loading Loading @@ -133,6 +140,16 @@ public abstract class RoleControllerService extends Service { public abstract void onClearRoleHolders(@NonNull String roleName, @NonNull RoleManagerCallback callback); /** * 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 */ public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback); private static class RoleManagerCallbackDelegate implements RoleManagerCallback { private IRoleManagerCallback mCallback; Loading
services/core/java/com/android/server/role/RemoteRoleControllerService.java +56 −27 Original line number Diff line number Diff line Loading @@ -16,10 +16,10 @@ package com.android.server.role; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.annotation.WorkerThread; import android.app.role.IRoleManagerCallback; import android.app.role.RoleManagerCallback; import android.content.ComponentName; Loading @@ -34,6 +34,7 @@ import android.rolecontrollerservice.IRoleControllerService; import android.rolecontrollerservice.RoleControllerService; import android.util.Slog; import com.android.internal.os.BackgroundThread; import com.android.internal.util.function.pooled.PooledLambda; import java.util.ArrayDeque; Loading @@ -44,8 +45,12 @@ import java.util.Queue; */ public class RemoteRoleControllerService { static final boolean DEBUG = false; private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName(); @NonNull private static final Handler sCallbackHandler = BackgroundThread.getHandler(); @NonNull private final Connection mConnection; Loading Loading @@ -87,6 +92,16 @@ public class RemoteRoleControllerService { service.onClearRoleHolders(roleName, callbackDelegate), callback)); } /** * Performs granting of default roles and permissions and appops * * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback) */ public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) { mConnection.enqueueCall( new Connection.Call(IRoleControllerService::onGrantDefaultRoles, callback)); } private static final class Connection implements ServiceConnection { private static final long UNBIND_DELAY_MILLIS = 15 * 1000; Loading @@ -105,9 +120,6 @@ public class RemoteRoleControllerService { @NonNull private final Queue<Call> mPendingCalls = new ArrayDeque<>(); @NonNull private final Handler mMainHandler = Handler.getMain(); @NonNull private final Runnable mUnbindRunnable = this::unbind; Loading @@ -116,14 +128,14 @@ public class RemoteRoleControllerService { mContext = context; } @MainThread @Override @WorkerThread public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) { mService = IRoleControllerService.Stub.asInterface(service); executePendingCalls(); } @MainThread @WorkerThread private void executePendingCalls() { while (!mPendingCalls.isEmpty()) { Call call = mPendingCalls.poll(); Loading @@ -132,26 +144,33 @@ public class RemoteRoleControllerService { scheduleUnbind(); } @MainThread @Override @WorkerThread public void onServiceDisconnected(@NonNull ComponentName name) { mService = null; } @MainThread @Override @WorkerThread public void onBindingDied(@NonNull ComponentName name) { unbind(); } public void enqueueCall(@NonNull Call call) { mMainHandler.post(PooledLambda.obtainRunnable(this::executeCall, call)); if (DEBUG) { Slog.i(LOG_TAG, "Enqueue " + call); } sCallbackHandler.executeOrSendMessage(PooledLambda.obtainMessage( Connection::executeCall, this, call)); } @MainThread @WorkerThread private void executeCall(@NonNull Call call) { ensureBound(); if (mService == null) { if (DEBUG) { Slog.i(LOG_TAG, "Delaying until service connected: " + call); } mPendingCalls.offer(call); return; } Loading @@ -159,24 +178,28 @@ public class RemoteRoleControllerService { scheduleUnbind(); } @MainThread @WorkerThread private void ensureBound() { mMainHandler.removeCallbacks(mUnbindRunnable); sCallbackHandler.removeCallbacks(mUnbindRunnable); if (!mBound) { Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); intent.setPackage(mContext.getPackageManager() .getPermissionControllerPackageName()); // Use direct handler to ensure onServiceConnected callback happens in the same // call frame, as required by onGrantDefaultRoles // // Note that as a result, onServiceConnected may happen not on main thread! mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE, UserHandle.of(mUserId)); sCallbackHandler, UserHandle.of(mUserId)); } } private void scheduleUnbind() { mMainHandler.removeCallbacks(mUnbindRunnable); mMainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); sCallbackHandler.removeCallbacks(mUnbindRunnable); sCallbackHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); } @MainThread @WorkerThread private void unbind() { if (mBound) { mService = null; Loading @@ -195,9 +218,6 @@ public class RemoteRoleControllerService { @NonNull private final IRoleManagerCallback mCallback; @NonNull private final Handler mMainHandler = Handler.getMain(); @NonNull private final Runnable mTimeoutRunnable = () -> notifyCallback(false); Loading @@ -209,10 +229,13 @@ public class RemoteRoleControllerService { mCallback = callback; } @MainThread @WorkerThread public void execute(IRoleControllerService service) { if (DEBUG) { Slog.i(LOG_TAG, "Executing " + this); } try { mMainHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS); sCallbackHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS); mCallExecutor.execute(service, new CallbackDelegate()); } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling RoleControllerService", e); Loading @@ -220,13 +243,13 @@ public class RemoteRoleControllerService { } } @MainThread @WorkerThread private void notifyCallback(boolean success) { if (mCallbackNotified) { return; } mCallbackNotified = true; mMainHandler.removeCallbacks(mTimeoutRunnable); sCallbackHandler.removeCallbacks(mTimeoutRunnable); try { if (success) { mCallback.onSuccess(); Loading @@ -239,10 +262,15 @@ public class RemoteRoleControllerService { } } @Override public String toString() { return "Call with callback: " + mCallback; } @FunctionalInterface public interface CallExecutor { @MainThread @WorkerThread void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate) throws RemoteException; } Loading @@ -251,13 +279,14 @@ public class RemoteRoleControllerService { @Override public void onSuccess() throws RemoteException { mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, true)); sCallbackHandler.sendMessage(PooledLambda.obtainMessage( Call::notifyCallback, Call.this, true)); } @Override public void onFailure() throws RemoteException { mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, false)); sCallbackHandler.sendMessage(PooledLambda.obtainMessage( Call::notifyCallback, Call.this, false)); } } } Loading
services/core/java/com/android/server/role/RoleManagerService.java +27 −3 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ import com.android.server.SystemService; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Service for role management. Loading Loading @@ -105,17 +109,37 @@ public class RoleManagerService extends SystemService { public void onStart() { publishBinderService(Context.ROLE_SERVICE, new Stub()); //TODO add watch for new user creation and run default grants for them //TODO add package update watch to detect PermissionController upgrade and run def. grants } @Override public void onStartUser(@UserIdInt int userId) { synchronized (mLock) { //TODO only call into PermissionController if it or system upgreaded (for boot time) // (add package changes watch; // we can detect upgrade using build fingerprint and app version) getUserStateLocked(userId); //TODO call permission grant policy here } //TODO consider calling grants only when certain conditions are met // such as OS or PermissionController upgrade if (RemoteRoleControllerService.DEBUG) { Slog.i(LOG_TAG, "Granting default permissions..."); CompletableFuture<Void> result = new CompletableFuture<>(); getControllerService(userId).onGrantDefaultRoles( new IRoleManagerCallback.Stub() { @Override public void onSuccess() { result.complete(null); } @Override public void onFailure() { result.completeExceptionally(new RuntimeException()); } }); try { result.get(5, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e); } } } Loading