diff --git a/core/java/android/annotation/MainThread.java b/core/java/android/annotation/MainThread.java index 556fdb4e7742d..a070246e5ef3b 100644 --- a/core/java/android/annotation/MainThread.java +++ b/core/java/android/annotation/MainThread.java @@ -21,8 +21,6 @@ import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.os.Looper; - import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -40,8 +38,7 @@ import java.lang.annotation.Target; * * * - * @memberDoc This method must be called from the - * {@linkplain Looper#getMainLooper() main thread} of your app. + * @memberDoc This method must be called from the main thread of your app. * @hide */ @Retention(SOURCE) diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index bbda871325592..5b0ad228dc436 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -31,7 +31,7 @@ import android.app.contentsuggestions.IContentSuggestionsManager; import android.app.job.JobSchedulerFrameworkInitializer; import android.app.people.PeopleManager; import android.app.prediction.AppPredictionManager; -import android.app.role.RoleManager; +import android.app.role.RoleFrameworkInitializer; import android.app.search.SearchUiManager; import android.app.slice.SliceManager; import android.app.time.TimeManager; @@ -1320,14 +1320,6 @@ public final class SystemServiceRegistry { ctx.getMainThreadHandler()); }}); - registerService(Context.ROLE_SERVICE, RoleManager.class, - new CachedServiceFetcher() { - @Override - public RoleManager createService(ContextImpl ctx) - throws ServiceNotFoundException { - return new RoleManager(ctx.getOuterContext()); - }}); - registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class, new CachedServiceFetcher() { @Override @@ -1423,6 +1415,7 @@ public final class SystemServiceRegistry { RollbackManagerFrameworkInitializer.initialize(); MediaFrameworkPlatformInitializer.registerServiceWrappers(); MediaFrameworkInitializer.registerServiceWrappers(); + RoleFrameworkInitializer.registerServiceWrappers(); } finally { // If any of the above code throws, we're in a pretty bad shape and the process // will likely crash, but we'll reset it just in case there's an exception handler... diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java index ba1f612906317..93a7ae0c82c0f 100644 --- a/core/java/android/app/role/RoleControllerManager.java +++ b/core/java/android/app/role/RoleControllerManager.java @@ -20,15 +20,15 @@ import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.RequiresPermission; -import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.RemoteCallback; import android.util.Log; import android.util.SparseArray; @@ -95,11 +95,10 @@ public class RoleControllerManager { private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName, @NonNull Handler handler, @NonNull Context context) { synchronized (sRemoteServicesLock) { - int userId = context.getUserId(); + int userId = context.getUser().getIdentifier(); ServiceConnector remoteService = sRemoteServices.get(userId); if (remoteService == null) { - remoteService = new ServiceConnector.Impl( - ActivityThread.currentApplication(), + remoteService = new ServiceConnector.Impl(context, new Intent(RoleControllerService.SERVICE_INTERFACE) .setComponent(remoteServiceComponentName), 0 /* bindingFlags */, userId, IRoleController.Stub::asInterface) { @@ -119,7 +118,7 @@ public class RoleControllerManager { * @hide */ public RoleControllerManager(@NonNull Context context) { - this(getRemoteServiceComponentName(context), context.getMainThreadHandler(), context); + this(getRemoteServiceComponentName(context), new Handler(Looper.getMainLooper()), context); } @NonNull @@ -127,8 +126,8 @@ public class RoleControllerManager { Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); PackageManager packageManager = context.getPackageManager(); intent.setPackage(packageManager.getPermissionControllerPackageName()); - ResolveInfo resolveInfo = packageManager.resolveService(intent, 0); - return resolveInfo.getComponentInfo().getComponentName(); + ServiceInfo serviceInfo = packageManager.resolveService(intent, 0).serviceInfo; + return new ComponentName(serviceInfo.packageName, serviceInfo.name); } /** diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java index d92c95691eea1..6ef9e445d1c97 100644 --- a/core/java/android/app/role/RoleControllerService.java +++ b/core/java/android/app/role/RoleControllerService.java @@ -33,7 +33,6 @@ import android.os.RemoteCallback; import android.os.UserHandle; import com.android.internal.util.Preconditions; -import com.android.internal.util.function.pooled.PooledLambda; import java.util.Objects; import java.util.concurrent.Executor; @@ -85,9 +84,7 @@ public abstract class RoleControllerService extends Service { Objects.requireNonNull(callback, "callback cannot be null"); - mWorkerHandler.sendMessage(PooledLambda.obtainMessage( - RoleControllerService::grantDefaultRoles, RoleControllerService.this, - callback)); + mWorkerHandler.post(() -> RoleControllerService.this.grantDefaultRoles(callback)); } @Override @@ -100,9 +97,8 @@ public abstract class RoleControllerService extends Service { "packageName cannot be null or empty"); Objects.requireNonNull(callback, "callback cannot be null"); - mWorkerHandler.sendMessage(PooledLambda.obtainMessage( - RoleControllerService::onAddRoleHolder, RoleControllerService.this, - roleName, packageName, flags, callback)); + mWorkerHandler.post(() -> RoleControllerService.this.onAddRoleHolder(roleName, + packageName, flags, callback)); } @Override @@ -115,9 +111,8 @@ public abstract class RoleControllerService extends Service { "packageName cannot be null or empty"); Objects.requireNonNull(callback, "callback cannot be null"); - mWorkerHandler.sendMessage(PooledLambda.obtainMessage( - RoleControllerService::onRemoveRoleHolder, RoleControllerService.this, - roleName, packageName, flags, callback)); + mWorkerHandler.post(() -> RoleControllerService.this.onRemoveRoleHolder(roleName, + packageName, flags, callback)); } @Override @@ -127,9 +122,8 @@ public abstract class RoleControllerService extends Service { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Objects.requireNonNull(callback, "callback cannot be null"); - mWorkerHandler.sendMessage(PooledLambda.obtainMessage( - RoleControllerService::onClearRoleHolders, RoleControllerService.this, - roleName, flags, callback)); + mWorkerHandler.post(() -> RoleControllerService.this.onClearRoleHolders(roleName, + flags, callback)); } private void enforceCallerSystemUid(@NonNull String methodName) { @@ -274,6 +268,7 @@ public abstract class RoleControllerService extends Service { * * @deprecated Implement {@link #onIsApplicationVisibleForRole(String, String)} instead. */ + @Deprecated public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName); diff --git a/core/java/android/app/role/RoleFrameworkInitializer.java b/core/java/android/app/role/RoleFrameworkInitializer.java new file mode 100644 index 0000000000000..15a324f050c8f --- /dev/null +++ b/core/java/android/app/role/RoleFrameworkInitializer.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 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.app.SystemServiceRegistry; +import android.content.Context; + +/** + * Class holding initialization code for role in the permission module. + * + * @hide + */ +//@SystemApi +public class RoleFrameworkInitializer { + private RoleFrameworkInitializer() {} + + /** + * Called by {@link SystemServiceRegistry}'s static initializer and registers + * {@link RoleManager} to {@link Context}, so that {@link Context#getSystemService} can return + * it. + * + *

If this is called from other places, it throws a {@link IllegalStateException). + */ + public static void registerServiceWrappers() { + SystemServiceRegistry.registerContextAwareService(Context.ROLE_SERVICE, RoleManager.class, + (context, serviceBinder) -> new RoleManager(context, + IRoleManager.Stub.asInterface(serviceBinder))); + } +} diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java index 3788257bcf171..73f9c747b074c 100644 --- a/core/java/android/app/role/RoleManager.java +++ b/core/java/android/app/role/RoleManager.java @@ -32,14 +32,12 @@ import android.os.Binder; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.util.ArrayMap; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; -import com.android.internal.util.function.pooled.PooledLambda; import java.util.List; import java.util.Objects; @@ -180,12 +178,16 @@ public final class RoleManager { private final Object mRoleControllerManagerLock = new Object(); /** + * Create a new instance of this class. + * + * @param context the {@link Context} + * @param service the {@link IRoleManager} service + * * @hide */ - public RoleManager(@NonNull Context context) throws ServiceManager.ServiceNotFoundException { + public RoleManager(@NonNull Context context, @NonNull IRoleManager service) { mContext = context; - mService = IRoleManager.Stub.asInterface(ServiceManager.getServiceOrThrow( - Context.ROLE_SERVICE)); + mService = service; } /** @@ -747,9 +749,8 @@ public final class RoleManager { public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { final long token = Binder.clearCallingIdentity(); try { - mExecutor.execute(PooledLambda.obtainRunnable( - OnRoleHoldersChangedListener::onRoleHoldersChanged, mListener, roleName, - UserHandle.of(userId))); + mExecutor.execute(() -> + mListener.onRoleHoldersChanged(roleName, UserHandle.of(userId))); } finally { Binder.restoreCallingIdentity(token); } diff --git a/core/java/android/app/role/TEST_MAPPING b/core/java/android/app/role/TEST_MAPPING index 11c28032c7cf5..f8f140dd716ed 100644 --- a/core/java/android/app/role/TEST_MAPPING +++ b/core/java/android/app/role/TEST_MAPPING @@ -9,4 +9,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/services/core/java/com/android/server/role/RoleManagerInternal.java b/services/core/java/com/android/server/role/RoleManagerLocal.java similarity index 77% rename from services/core/java/com/android/server/role/RoleManagerInternal.java rename to services/core/java/com/android/server/role/RoleManagerLocal.java index 7598bf70d77a6..f11d99d43061a 100644 --- a/services/core/java/com/android/server/role/RoleManagerInternal.java +++ b/services/core/java/com/android/server/role/RoleManagerLocal.java @@ -18,14 +18,17 @@ package com.android.server.role; import android.annotation.NonNull; import android.annotation.UserIdInt; -import android.util.ArrayMap; -import android.util.ArraySet; + +import java.util.Map; +import java.util.Set; /** - * Internal calls into {@link RoleManagerService}. + * Internal calls into {@link RoleService}. + * + * @hide */ -public abstract class RoleManagerInternal { - +//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) +public interface RoleManagerLocal { /** * Get all roles and their holders. * @@ -34,6 +37,5 @@ public abstract class RoleManagerInternal { * @return The roles and their holders */ @NonNull - public abstract ArrayMap> getRolesAndHolders( - @UserIdInt int userId); + Map> getRolesAndHolders(@UserIdInt int userId); } diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleService.java similarity index 85% rename from services/core/java/com/android/server/role/RoleManagerService.java rename to services/core/java/com/android/server/role/RoleService.java index 0fff996c9d6f1..944ebf0f77c05 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleService.java @@ -43,25 +43,23 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; -import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; -import android.util.Slog; +import android.util.Log; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ThrottledRunnable; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.CollectionUtils; import com.android.internal.util.Preconditions; import com.android.internal.util.dump.DualDumpOutputStream; -import com.android.internal.util.function.pooled.PooledLambda; -import com.android.server.FgThread; -import com.android.server.LocalServices; +import com.android.server.LocalManagerRegistry; import com.android.server.SystemService; -import com.android.server.pm.UserManagerInternal; +import com.android.server.role.compat.UserHandleCompat; +import com.android.server.role.util.ArrayUtils; +import com.android.server.role.util.CollectionUtils; +import com.android.server.role.util.ForegroundThread; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -69,7 +67,9 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -79,8 +79,8 @@ import java.util.concurrent.TimeoutException; * * @see RoleManager */ -public class RoleManagerService extends SystemService implements RoleUserState.Callback { - private static final String LOG_TAG = RoleManagerService.class.getSimpleName(); +public class RoleService extends SystemService implements RoleUserState.Callback { + private static final String LOG_TAG = RoleService.class.getSimpleName(); private static final boolean DEBUG = false; @@ -89,7 +89,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @NonNull private final AppOpsManager mAppOpsManager; @NonNull - private final UserManagerInternal mUserManagerInternal; + private final UserManager mUserManager; @NonNull private final Object mLock = new Object(); @@ -120,7 +120,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C new SparseArray<>(); @NonNull - private final Handler mListenerHandler = FgThread.getHandler(); + private final Handler mListenerHandler = ForegroundThread.getHandler(); /** * Maps user id to its throttled runnable for granting default roles. @@ -130,18 +130,17 @@ public class RoleManagerService extends SystemService implements RoleUserState.C private final SparseArray mGrantDefaultRolesThrottledRunnables = new SparseArray<>(); - public RoleManagerService(@NonNull Context context, - @NonNull RoleServicePlatformHelper platformHelper) { + public RoleService(@NonNull Context context) { super(context); - mPlatformHelper = platformHelper; + mPlatformHelper = LocalManagerRegistry.getManager(RoleServicePlatformHelper.class); RoleControllerManager.initializeRemoteServiceComponentName(context); mAppOpsManager = context.getSystemService(AppOpsManager.class); - mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); + mUserManager = context.getSystemService(UserManager.class); - LocalServices.addService(RoleManagerInternal.class, new Internal()); + LocalManagerRegistry.addManager(RoleManagerLocal.class, new Local()); registerUserRemovedReceiver(); } @@ -174,9 +173,9 @@ public class RoleManagerService extends SystemService implements RoleUserState.C getContext().registerReceiverForAllUsers(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1)); + int userId = UserHandleCompat.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1)); if (DEBUG) { - Slog.i(LOG_TAG, "Packages changed - re-running initial grants for user " + Log.i(LOG_TAG, "Packages changed - re-running initial grants for user " + userId); } if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) @@ -200,7 +199,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C try { future.get(30, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { - Slog.e(LOG_TAG, "Failed to grant default roles for user " + userId, e); + Log.e(LOG_TAG, "Failed to grant default roles for user " + userId, e); } } @@ -209,7 +208,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C synchronized (mLock) { runnable = mGrantDefaultRolesThrottledRunnables.get(userId); if (runnable == null) { - runnable = new ThrottledRunnable(FgThread.getHandler(), + runnable = new ThrottledRunnable(ForegroundThread.getHandler(), GRANT_DEFAULT_ROLES_INTERVAL_MILLIS, () -> maybeGrantDefaultRolesInternal(userId)); mGrantDefaultRolesThrottledRunnables.put(userId, runnable); @@ -226,16 +225,16 @@ public class RoleManagerService extends SystemService implements RoleUserState.C String newPackagesHash = mPlatformHelper.computePackageStateHash(userId); if (Objects.equals(oldPackagesHash, newPackagesHash)) { if (DEBUG) { - Slog.i(LOG_TAG, "Already granted default roles for packages hash " + Log.i(LOG_TAG, "Already granted default roles for packages hash " + newPackagesHash); } return AndroidFuture.completedFuture(null); } // Some package state has changed, so grant default roles again. - Slog.i(LOG_TAG, "Granting default roles..."); + Log.i(LOG_TAG, "Granting default roles..."); AndroidFuture future = new AndroidFuture<>(); - getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(), + getOrCreateController(userId).grantDefaultRoles(ForegroundThread.getExecutor(), successful -> { if (successful) { userState.setPackagesHash(newPackagesHash); @@ -273,7 +272,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C throw new RuntimeException(e); } controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName( - FgThread.getHandler(), context); + ForegroundThread.getHandler(), context); mControllers.put(userId, controller); } return controller; @@ -321,8 +320,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @Override public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { - mListenerHandler.sendMessage(PooledLambda.obtainMessage( - RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId)); + mListenerHandler.post(() -> notifyRoleHoldersChanged(roleName, userId)); } @WorkerThread @@ -333,7 +331,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } RemoteCallbackList allUsersListeners = getListeners( - UserHandle.USER_ALL); + UserHandleCompat.USER_ALL); if (allUsersListeners != null) { notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId); } @@ -350,7 +348,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C try { listener.onRoleHoldersChanged(roleName, userId); } catch (RemoteException e) { - Slog.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e); + Log.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e); } } } finally { @@ -364,7 +362,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C public boolean isRoleAvailable(@NonNull String roleName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); - int userId = UserHandle.getUserId(getCallingUid()); + int userId = UserHandleCompat.getUserId(getCallingUid()); return getOrCreateUserState(userId).isRoleAvailable(roleName); } @@ -376,7 +374,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); - int userId = UserHandle.getUserId(callingUid); + int userId = UserHandleCompat.getUserId(callingUid); ArraySet roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName); if (roleHolders == null) { return false; @@ -387,8 +385,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @NonNull @Override public List getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) { - if (!mUserManagerInternal.exists(userId)) { - Slog.e(LOG_TAG, "user " + userId + " does not exist"); + if (!isUserExistent(userId)) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); return Collections.emptyList(); } enforceCrossUserPermission(userId, false, "getRoleHoldersAsUser"); @@ -408,8 +406,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - if (!mUserManagerInternal.exists(userId)) { - Slog.e(LOG_TAG, "user " + userId + " does not exist"); + if (!isUserExistent(userId)) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); return; } enforceCrossUserPermission(userId, false, "addRoleHolderAsUser"); @@ -428,8 +426,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - if (!mUserManagerInternal.exists(userId)) { - Slog.e(LOG_TAG, "user " + userId + " does not exist"); + if (!isUserExistent(userId)) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); return; } enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser"); @@ -448,8 +446,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C public void clearRoleHoldersAsUser(@NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { - if (!mUserManagerInternal.exists(userId)) { - Slog.e(LOG_TAG, "user " + userId + " does not exist"); + if (!isUserExistent(userId)) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); return; } enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser"); @@ -465,8 +463,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @Override public void addOnRoleHoldersChangedListenerAsUser( @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) { - if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) { - Slog.e(LOG_TAG, "user " + userId + " does not exist"); + if (userId != UserHandleCompat.USER_ALL && !isUserExistent(userId)) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); return; } enforceCrossUserPermission(userId, true, "addOnRoleHoldersChangedListenerAsUser"); @@ -483,8 +481,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @Override public void removeOnRoleHoldersChangedListenerAsUser( @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) { - if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) { - Slog.e(LOG_TAG, "user " + userId + " does not exist"); + if (userId != UserHandleCompat.USER_ALL && !isUserExistent(userId)) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); return; } enforceCrossUserPermission(userId, true, "removeOnRoleHoldersChangedListenerAsUser"); @@ -508,7 +506,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Objects.requireNonNull(roleNames, "roleNames cannot be null"); - int userId = UserHandle.getUserId(Binder.getCallingUid()); + int userId = UserHandleCompat.getUserId(Binder.getCallingUid()); getOrCreateUserState(userId).setRoleNames(roleNames); } @@ -522,7 +520,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); - int userId = UserHandle.getUserId(Binder.getCallingUid()); + int userId = UserHandleCompat.getUserId(Binder.getCallingUid()); return getOrCreateUserState(userId).addRoleHolder(roleName, packageName); } @@ -536,7 +534,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); - int userId = UserHandle.getUserId(Binder.getCallingUid()); + int userId = UserHandleCompat.getUserId(Binder.getCallingUid()); return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName); } @@ -548,24 +546,30 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); - int userId = UserHandle.getUserId(Binder.getCallingUid()); + int userId = UserHandleCompat.getUserId(Binder.getCallingUid()); return getOrCreateUserState(userId).getHeldRoles(packageName); } + private boolean isUserExistent(@UserIdInt int userId) { + // FIXME: This checks whether the user is alive, but we should check for whether the + // user is existent. + return mUserManager.getUserHandles(true).contains(UserHandle.of(userId)); + } + private void enforceCrossUserPermission(@UserIdInt int userId, boolean allowAll, @NonNull String message) { final int callingUid = Binder.getCallingUid(); - final int callingUserId = UserHandle.getUserId(callingUid); + final int callingUserId = UserHandleCompat.getUserId(callingUid); if (userId == callingUserId) { return; } - Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM - || (allowAll && userId == UserHandle.USER_ALL), "Invalid user " + userId); + Preconditions.checkArgument(userId >= UserHandleCompat.USER_SYSTEM + || (allowAll && userId == UserHandleCompat.USER_ALL), "Invalid user " + userId); getContext().enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message); - if (callingUid == Process.SHELL_UID && userId >= UserHandle.USER_SYSTEM) { - if (mUserManagerInternal.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, - userId)) { + if (callingUid == Process.SHELL_UID && userId >= UserHandleCompat.USER_SYSTEM) { + if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_DEBUGGING_FEATURES, + UserHandle.of(userId))) { throw new SecurityException("Shell does not have permission to access user " + userId); } @@ -576,7 +580,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C public int handleShellCommand(@NonNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args) { - return new RoleManagerShellCommand(this).exec(this, in.getFileDescriptor(), + return new RoleShellCommand(this).exec(this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args); } @@ -584,7 +588,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @Override public String getBrowserRoleHolder(@UserIdInt int userId) { final int callingUid = Binder.getCallingUid(); - if (UserHandle.getUserId(callingUid) != userId) { + if (UserHandleCompat.getUserId(callingUid) != userId) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); } @@ -625,12 +629,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C final Context context = getContext(); context.enforceCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); - if (UserHandle.getUserId(Binder.getCallingUid()) != userId) { + if (UserHandleCompat.getUserId(Binder.getCallingUid()) != userId) { context.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); } - if (!mUserManagerInternal.exists(userId)) { + if (!isUserExistent(userId)) { return false; } @@ -653,7 +657,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C try { future.get(5, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { - Slog.e(LOG_TAG, "Exception while setting default browser: " + packageName, e); + Log.e(LOG_TAG, "Exception while setting default browser: " + packageName, e); return false; } } finally { @@ -687,7 +691,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream( new FileOutputStream(fd))); } else { - fout.println("ROLE MANAGER STATE (dumpsys role):"); + fout.println("ROLE STATE (dumpsys role):"); dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " ")); } @@ -718,11 +722,14 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } - private class Internal extends RoleManagerInternal { + private class Local implements RoleManagerLocal { @NonNull @Override - public ArrayMap> getRolesAndHolders(@UserIdInt int userId) { - return getOrCreateUserState(userId).getRolesAndHolders(); + public Map> getRolesAndHolders(@UserIdInt int userId) { + // Convert ArrayMap> to Map> for the API. + //noinspection unchecked + return (Map>) (Map) + getOrCreateUserState(userId).getRolesAndHolders(); } } } diff --git a/services/core/java/com/android/server/role/RoleManagerShellCommand.java b/services/core/java/com/android/server/role/RoleShellCommand.java similarity index 94% rename from services/core/java/com/android/server/role/RoleManagerShellCommand.java rename to services/core/java/com/android/server/role/RoleShellCommand.java index 96f3c29b93135..6e0d81a605f31 100644 --- a/services/core/java/com/android/server/role/RoleManagerShellCommand.java +++ b/services/core/java/com/android/server/role/RoleShellCommand.java @@ -21,19 +21,19 @@ import android.annotation.Nullable; import android.app.role.IRoleManager; import android.os.RemoteCallback; import android.os.RemoteException; -import android.os.UserHandle; import com.android.modules.utils.BasicShellCommandHandler; +import com.android.server.role.compat.UserHandleCompat; import java.io.PrintWriter; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -class RoleManagerShellCommand extends BasicShellCommandHandler { +class RoleShellCommand extends BasicShellCommandHandler { @NonNull private final IRoleManager mRoleManager; - RoleManagerShellCommand(@NonNull IRoleManager roleManager) { + RoleShellCommand(@NonNull IRoleManager roleManager) { mRoleManager = roleManager; } @@ -86,7 +86,7 @@ class RoleManagerShellCommand extends BasicShellCommandHandler { } private int getUserIdMaybe() { - int userId = UserHandle.USER_SYSTEM; + int userId = UserHandleCompat.USER_SYSTEM; String option = getNextOption(); if (option != null && option.equals("--user")) { userId = Integer.parseInt(getNextArgRequired()); @@ -139,7 +139,7 @@ class RoleManagerShellCommand extends BasicShellCommandHandler { @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); - pw.println("Role manager (role) commands:"); + pw.println("Role (role) commands:"); pw.println(" help or -h"); pw.println(" Print this help text."); pw.println(); diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java index 838fd9046c156..52861c5e59e46 100644 --- a/services/core/java/com/android/server/role/RoleUserState.java +++ b/services/core/java/com/android/server/role/RoleUserState.java @@ -25,15 +25,14 @@ import android.os.Handler; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.Slog; +import android.util.Log; import com.android.internal.annotations.GuardedBy; -import com.android.internal.os.BackgroundThread; -import com.android.internal.util.CollectionUtils; import com.android.internal.util.dump.DualDumpOutputStream; -import com.android.internal.util.function.pooled.PooledLambda; import com.android.role.persistence.RolesPersistence; import com.android.role.persistence.RolesState; +import com.android.server.role.util.BackgroundThread; +import com.android.server.role.util.CollectionUtils; import java.util.ArrayList; import java.util.List; @@ -197,7 +196,7 @@ class RoleUserState { synchronized (mLock) { if (!mRoles.containsKey(roleName)) { mRoles.put(roleName, new ArraySet<>()); - Slog.i(LOG_TAG, "Added new role: " + roleName); + Log.i(LOG_TAG, "Added new role: " + roleName); scheduleWriteFileLocked(); return true; } else { @@ -221,7 +220,7 @@ class RoleUserState { if (!roleNames.contains(roleName)) { ArraySet packageNames = mRoles.valueAt(i); if (!packageNames.isEmpty()) { - Slog.e(LOG_TAG, "Holders of a removed role should have been cleaned up," + Log.e(LOG_TAG, "Holders of a removed role should have been cleaned up," + " role: " + roleName + ", holders: " + packageNames); } mRoles.removeAt(i); @@ -255,7 +254,7 @@ class RoleUserState { synchronized (mLock) { ArraySet roleHolders = mRoles.get(roleName); if (roleHolders == null) { - Slog.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName + Log.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName + ", package: " + packageName); return false; } @@ -286,7 +285,7 @@ class RoleUserState { synchronized (mLock) { ArraySet roleHolders = mRoles.get(roleName); if (roleHolders == null) { - Slog.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName + Log.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName + ", package: " + packageName); return false; } @@ -330,8 +329,7 @@ class RoleUserState { } if (!mWriteScheduled) { - mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeFile, - this), WRITE_DELAY_MILLIS); + mWriteHandler.postDelayed(this::writeFile, WRITE_DELAY_MILLIS); mWriteScheduled = true; } } diff --git a/services/core/java/com/android/server/role/compat/UserHandleCompat.java b/services/core/java/com/android/server/role/compat/UserHandleCompat.java new file mode 100644 index 0000000000000..8f14c1fcfca73 --- /dev/null +++ b/services/core/java/com/android/server/role/compat/UserHandleCompat.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.role.compat; + +import android.annotation.UserIdInt; +import android.os.UserHandle; + +/** + * Helper for accessing features in {@link UserHandle}. + */ +public final class UserHandleCompat { + /** + * A user ID to indicate all users on the device. + */ + public static final int USER_ALL = UserHandle.ALL.getIdentifier(); + + /** + * A user ID to indicate the "system" user of the device. + */ + public static final int USER_SYSTEM = UserHandle.SYSTEM.getIdentifier(); + + private UserHandleCompat() {} + + /** + * Get the user ID of a given UID. + * + * @param uid the UID + * @return the user ID + */ + @UserIdInt + public static int getUserId(int uid) { + return UserHandle.getUserHandleForUid(uid).getIdentifier(); + } +} diff --git a/services/core/java/com/android/server/role/util/ArrayUtils.java b/services/core/java/com/android/server/role/util/ArrayUtils.java new file mode 100644 index 0000000000000..8b7c07b7473c4 --- /dev/null +++ b/services/core/java/com/android/server/role/util/ArrayUtils.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.role.util; + +import android.annotation.Nullable; + +import java.util.Objects; + +/** + * Array utilities. + */ +public final class ArrayUtils { + private ArrayUtils() {} + + /** + * @see java.util.List#contains(Object) + */ + public static boolean contains(@Nullable T[] array, T value) { + return indexOf(array, value) != -1; + } + + /** + * Get the first element of an array, or {@code null} if none. + * + * @param array the array + * @param the type of the elements of the array + * @return first element of an array, or {@code null} if none + */ + public static T firstOrNull(@Nullable T[] array) { + return !isEmpty(array) ? array[0] : null; + } + + /** + * @see java.util.List#indexOf(Object) + */ + public static int indexOf(@Nullable T[] array, T value) { + if (array == null) { + return -1; + } + final int length = array.length; + for (int i = 0; i < length; i++) { + final T element = array[i]; + if (Objects.equals(element, value)) { + return i; + } + } + return -1; + } + + /** + * @see java.util.List#isEmpty() + */ + public static boolean isEmpty(@Nullable T[] array) { + return array == null || array.length == 0; + } +} diff --git a/services/core/java/com/android/server/role/util/BackgroundThread.java b/services/core/java/com/android/server/role/util/BackgroundThread.java new file mode 100644 index 0000000000000..385595b950ab9 --- /dev/null +++ b/services/core/java/com/android/server/role/util/BackgroundThread.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.role.util; + +import android.annotation.NonNull; +import android.os.Handler; +import android.os.HandlerExecutor; +import android.os.HandlerThread; + +import com.android.internal.annotations.GuardedBy; + +import java.util.concurrent.Executor; + +/** + * Shared singleton background thread. + */ +public class BackgroundThread extends HandlerThread { + private static final Object sLock = new Object(); + + @GuardedBy("sLock") + private static BackgroundThread sInstance; + @GuardedBy("sLock") + private static Handler sHandler; + @GuardedBy("sLock") + private static Executor sExecutor; + + private BackgroundThread() { + super(BackgroundThread.class.getName()); + } + + @GuardedBy("sLock") + private static void ensureInstanceLocked() { + if (sInstance == null) { + sInstance = new BackgroundThread(); + sInstance.start(); + sHandler = new Handler(sInstance.getLooper()); + sExecutor = new HandlerExecutor(sHandler); + } + } + + /** + * Get the singleton instance of thi class. + * + * @return the singleton instance of thi class + */ + @NonNull + public static BackgroundThread get() { + synchronized (sLock) { + ensureInstanceLocked(); + return sInstance; + } + } + + /** + * Get the {@link Handler} for this thread. + * + * @return the {@link Handler} for this thread. + */ + @NonNull + public static Handler getHandler() { + synchronized (sLock) { + ensureInstanceLocked(); + return sHandler; + } + } + + /** + * Get the {@link Executor} for this thread. + * + * @return the {@link Executor} for this thread. + */ + @NonNull + public static Executor getExecutor() { + synchronized (sLock) { + ensureInstanceLocked(); + return sExecutor; + } + } +} diff --git a/services/core/java/com/android/server/role/util/CollectionUtils.java b/services/core/java/com/android/server/role/util/CollectionUtils.java new file mode 100644 index 0000000000000..f924fbc39177b --- /dev/null +++ b/services/core/java/com/android/server/role/util/CollectionUtils.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.role.util; + +import android.annotation.Nullable; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * {@link Collection} utilities. + */ +public class CollectionUtils { + private CollectionUtils() {} + + /** + * Get the first element of a {@link List}, or {@code null} if none. + * + * @param list the {@link List}, or {@code null} + * @param the element type of the {@link List} + * @return the first element of the {@link List}, or {@code 0} if none + */ + @Nullable + public static E firstOrNull(@Nullable List list) { + return !isEmpty(list) ? list.get(0) : null; + } + + /** + * Check whether a {@link Collection} is empty or {@code null}. + * + * @param collection the {@link Collection}, or {@code null} + * @return whether the {@link Collection} is empty or {@code null} + */ + public static boolean isEmpty(@Nullable Collection collection) { + return collection == null || collection.isEmpty(); + } + + /** + * Get the size of a {@link Collection}, or {@code 0} if {@code null}. + * + * @param collection the {@link Collection}, or {@code null} + * @return the size of the {@link Collection}, or {@code 0} if {@code null} + */ + public static int size(@Nullable Collection collection) { + return collection != null ? collection.size() : 0; + } + + /** + * Get the size of a {@link Map}, or {@code 0} if {@code null}. + * + * @param collection the {@link Map}, or {@code null} + * @return the size of the {@link Map}, or {@code 0} if {@code null} + */ + public static int size(@Nullable Map collection) { + return collection != null ? collection.size() : 0; + } +} diff --git a/services/core/java/com/android/server/role/util/ForegroundThread.java b/services/core/java/com/android/server/role/util/ForegroundThread.java new file mode 100644 index 0000000000000..05da59e7c4eff --- /dev/null +++ b/services/core/java/com/android/server/role/util/ForegroundThread.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.role.util; + +import android.annotation.NonNull; +import android.os.Handler; +import android.os.HandlerExecutor; +import android.os.HandlerThread; + +import com.android.internal.annotations.GuardedBy; + +import java.util.concurrent.Executor; + +/** + * Shared singleton foreground thread. + */ +public class ForegroundThread extends HandlerThread { + private static final Object sLock = new Object(); + + @GuardedBy("sLock") + private static ForegroundThread sInstance; + @GuardedBy("sLock") + private static Handler sHandler; + @GuardedBy("sLock") + private static Executor sExecutor; + + private ForegroundThread() { + super(ForegroundThread.class.getName()); + } + + @GuardedBy("sLock") + private static void ensureInstanceLocked() { + if (sInstance == null) { + sInstance = new ForegroundThread(); + sInstance.start(); + sHandler = new Handler(sInstance.getLooper()); + sExecutor = new HandlerExecutor(sHandler); + } + } + + /** + * Get the singleton instance of thi class. + * + * @return the singleton instance of thi class + */ + @NonNull + public static ForegroundThread get() { + synchronized (sLock) { + ensureInstanceLocked(); + return sInstance; + } + } + + /** + * Get the {@link Handler} for this thread. + * + * @return the {@link Handler} for this thread. + */ + @NonNull + public static Handler getHandler() { + synchronized (sLock) { + ensureInstanceLocked(); + return sHandler; + } + } + + /** + * Get the {@link Executor} for this thread. + * + * @return the {@link Executor} for this thread. + */ + @NonNull + public static Executor getExecutor() { + synchronized (sLock) { + ensureInstanceLocked(); + return sExecutor; + } + } +} diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index e7cda028a0b5e..14855aee29914 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -156,12 +156,13 @@ import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.server.BatteryService; import com.android.server.BinderCallsStatsService; +import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.am.MemoryStatUtil.MemoryStat; import com.android.server.notification.NotificationManagerService; -import com.android.server.role.RoleManagerInternal; +import com.android.server.role.RoleManagerLocal; import com.android.server.stats.pull.IonMemoryUtil.IonAllocations; import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot; import com.android.server.stats.pull.netstats.NetworkStatsExt; @@ -2916,7 +2917,8 @@ public class StatsPullAtomService extends SystemService { final long callingToken = Binder.clearCallingIdentity(); try { PackageManager pm = mContext.getPackageManager(); - RoleManagerInternal rmi = LocalServices.getService(RoleManagerInternal.class); + RoleManagerLocal roleManagerLocal = LocalManagerRegistry.getManager( + RoleManagerLocal.class); List users = mContext.getSystemService(UserManager.class).getUsers(); @@ -2924,27 +2926,23 @@ public class StatsPullAtomService extends SystemService { for (int userNum = 0; userNum < numUsers; userNum++) { int userId = users.get(userNum).getUserHandle().getIdentifier(); - ArrayMap> roles = rmi.getRolesAndHolders(userId); + Map> roles = roleManagerLocal.getRolesAndHolders(userId); - int numRoles = roles.size(); - for (int roleNum = 0; roleNum < numRoles; roleNum++) { - String roleName = roles.keyAt(roleNum); - ArraySet holders = roles.valueAt(roleNum); - - int numHolders = holders.size(); - for (int holderNum = 0; holderNum < numHolders; holderNum++) { - String holderName = holders.valueAt(holderNum); + for (Map.Entry> roleEntry : roles.entrySet()) { + String roleName = roleEntry.getKey(); + Set packageNames = roleEntry.getValue(); + for (String packageName : packageNames) { PackageInfo pkg; try { - pkg = pm.getPackageInfoAsUser(holderName, 0, userId); + pkg = pm.getPackageInfoAsUser(packageName, 0, userId); } catch (PackageManager.NameNotFoundException e) { - Slog.w(TAG, "Role holder " + holderName + " not found"); + Slog.w(TAG, "Role holder " + packageName + " not found"); return StatsManager.PULL_SKIP; } pulledData.add(FrameworkStatsLog.buildStatsEvent( - atomTag, pkg.applicationInfo.uid, holderName, roleName)); + atomTag, pkg.applicationInfo.uid, packageName, roleName)); } } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f81ec7802f12e..7839274904ad7 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -168,7 +168,7 @@ import com.android.server.powerstats.PowerStatsService; import com.android.server.profcollect.ProfcollectForwardingService; import com.android.server.recoverysystem.RecoverySystemService; import com.android.server.restrictions.RestrictionsManagerService; -import com.android.server.role.RoleManagerService; +import com.android.server.role.RoleServicePlatformHelper; import com.android.server.security.FileIntegrityService; import com.android.server.security.KeyAttestationApplicationIdProviderService; import com.android.server.security.KeyChainSystemService; @@ -353,6 +353,7 @@ public final class SystemServer implements Dumpable { "com.android.server.ConnectivityServiceInitializer"; private static final String IP_CONNECTIVITY_METRICS_CLASS = "com.android.server.connectivity.IpConnectivityMetrics"; + private static final String ROLE_SERVICE_CLASS = "com.android.server.role.RoleService"; private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector"; @@ -2032,8 +2033,9 @@ public final class SystemServer implements Dumpable { // Grants default permissions and defines roles t.traceBegin("StartRoleManagerService"); - mSystemServiceManager.startService(new RoleManagerService( - mSystemContext, new RoleServicePlatformHelperImpl(mSystemContext))); + LocalManagerRegistry.addManager(RoleServicePlatformHelper.class, + new RoleServicePlatformHelperImpl(mSystemContext)); + mSystemServiceManager.startService(ROLE_SERVICE_CLASS); t.traceEnd(); // We need to always start this service, regardless of whether the