Merge "Prepare role code for modularization."
This commit is contained in:
@@ -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;
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @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)
|
||||
|
||||
@@ -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<RoleManager>() {
|
||||
@Override
|
||||
public RoleManager createService(ContextImpl ctx)
|
||||
throws ServiceNotFoundException {
|
||||
return new RoleManager(ctx.getOuterContext());
|
||||
}});
|
||||
|
||||
registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
|
||||
new CachedServiceFetcher<DynamicSystemManager>() {
|
||||
@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...
|
||||
|
||||
@@ -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<IRoleController> remoteService = sRemoteServices.get(userId);
|
||||
if (remoteService == null) {
|
||||
remoteService = new ServiceConnector.Impl<IRoleController>(
|
||||
ActivityThread.currentApplication(),
|
||||
remoteService = new ServiceConnector.Impl<IRoleController>(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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
43
core/java/android/app/role/RoleFrameworkInitializer.java
Normal file
43
core/java/android/app/role/RoleFrameworkInitializer.java
Normal file
@@ -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.
|
||||
*
|
||||
* <p>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)));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, ArraySet<String>> getRolesAndHolders(
|
||||
@UserIdInt int userId);
|
||||
Map<String, Set<String>> getRolesAndHolders(@UserIdInt int userId);
|
||||
}
|
||||
@@ -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<ThrottledRunnable> 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<Void> 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<IOnRoleHoldersChangedListener> 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<String> 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<String> 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<String, ArraySet<String>> getRolesAndHolders(@UserIdInt int userId) {
|
||||
return getOrCreateUserState(userId).getRolesAndHolders();
|
||||
public Map<String, Set<String>> getRolesAndHolders(@UserIdInt int userId) {
|
||||
// Convert ArrayMap<String, ArraySet<String>> to Map<String, Set<String>> for the API.
|
||||
//noinspection unchecked
|
||||
return (Map<String, Set<String>>) (Map<String, ?>)
|
||||
getOrCreateUserState(userId).getRolesAndHolders();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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<String> 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<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 <T> 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 <T> the type of the elements of the array
|
||||
* @return first element of an array, or {@code null} if none
|
||||
*/
|
||||
public static <T> T firstOrNull(@Nullable T[] array) {
|
||||
return !isEmpty(array) ? array[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#indexOf(Object)
|
||||
*/
|
||||
public static <T> 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 <T> boolean isEmpty(@Nullable T[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <E> the element type of the {@link List}
|
||||
* @return the first element of the {@link List}, or {@code 0} if none
|
||||
*/
|
||||
@Nullable
|
||||
public static <E> E firstOrNull(@Nullable List<E> 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<UserInfo> 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<String, ArraySet<String>> roles = rmi.getRolesAndHolders(userId);
|
||||
Map<String, Set<String>> roles = roleManagerLocal.getRolesAndHolders(userId);
|
||||
|
||||
int numRoles = roles.size();
|
||||
for (int roleNum = 0; roleNum < numRoles; roleNum++) {
|
||||
String roleName = roles.keyAt(roleNum);
|
||||
ArraySet<String> holders = roles.valueAt(roleNum);
|
||||
|
||||
int numHolders = holders.size();
|
||||
for (int holderNum = 0; holderNum < numHolders; holderNum++) {
|
||||
String holderName = holders.valueAt(holderNum);
|
||||
for (Map.Entry<String, Set<String>> roleEntry : roles.entrySet()) {
|
||||
String roleName = roleEntry.getKey();
|
||||
Set<String> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user