Prepare role code for modularization.
- PooledLambda: PoolLambda is replaced with plain lambdas, to avoid adding ~20 classes to boot classpath (for each module that uses lambda). - SystemServiceRegistry: RoleFrameworkInitializer is added to add ROLE_SERVICE, similar to other modules. - RoleService: RoleManagerService is renamed to RoleService to better reflect the manager/service relationship. - @MainThread: import for Looper is removed because it's only used in javadoc and triggers package not exist error during build. @linkplain in the javadoc is also removed because it triggers an error in Metalava parsing and isn't critical. - Added small utilities: These utilities has their full version in platform, but is too large and contains too many internal references in methods unreferenced by role, whereas actually role only needs 1 or 2 methods from them. So just create a small copy of the used methods for role modularization, and they will be moved into APEX with role. Bug: 158736025 Test: manual Change-Id: I74f20b37d23370e258e7fc7130e28c5312abf46c
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.ElementType.TYPE;
|
||||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||||
|
|
||||||
import android.os.Looper;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@@ -40,8 +38,7 @@ import java.lang.annotation.Target;
|
|||||||
* </code>
|
* </code>
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @memberDoc This method must be called from the
|
* @memberDoc This method must be called from the main thread of your app.
|
||||||
* {@linkplain Looper#getMainLooper() main thread} of your app.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@Retention(SOURCE)
|
@Retention(SOURCE)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import android.app.contentsuggestions.IContentSuggestionsManager;
|
|||||||
import android.app.job.JobSchedulerFrameworkInitializer;
|
import android.app.job.JobSchedulerFrameworkInitializer;
|
||||||
import android.app.people.PeopleManager;
|
import android.app.people.PeopleManager;
|
||||||
import android.app.prediction.AppPredictionManager;
|
import android.app.prediction.AppPredictionManager;
|
||||||
import android.app.role.RoleManager;
|
import android.app.role.RoleFrameworkInitializer;
|
||||||
import android.app.search.SearchUiManager;
|
import android.app.search.SearchUiManager;
|
||||||
import android.app.slice.SliceManager;
|
import android.app.slice.SliceManager;
|
||||||
import android.app.time.TimeManager;
|
import android.app.time.TimeManager;
|
||||||
@@ -1320,14 +1320,6 @@ public final class SystemServiceRegistry {
|
|||||||
ctx.getMainThreadHandler());
|
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,
|
registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
|
||||||
new CachedServiceFetcher<DynamicSystemManager>() {
|
new CachedServiceFetcher<DynamicSystemManager>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -1423,6 +1415,7 @@ public final class SystemServiceRegistry {
|
|||||||
RollbackManagerFrameworkInitializer.initialize();
|
RollbackManagerFrameworkInitializer.initialize();
|
||||||
MediaFrameworkPlatformInitializer.registerServiceWrappers();
|
MediaFrameworkPlatformInitializer.registerServiceWrappers();
|
||||||
MediaFrameworkInitializer.registerServiceWrappers();
|
MediaFrameworkInitializer.registerServiceWrappers();
|
||||||
|
RoleFrameworkInitializer.registerServiceWrappers();
|
||||||
} finally {
|
} finally {
|
||||||
// If any of the above code throws, we're in a pretty bad shape and the process
|
// 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...
|
// 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.CallbackExecutor;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.app.ActivityThread;
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
@@ -95,11 +95,10 @@ public class RoleControllerManager {
|
|||||||
private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName,
|
private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName,
|
||||||
@NonNull Handler handler, @NonNull Context context) {
|
@NonNull Handler handler, @NonNull Context context) {
|
||||||
synchronized (sRemoteServicesLock) {
|
synchronized (sRemoteServicesLock) {
|
||||||
int userId = context.getUserId();
|
int userId = context.getUser().getIdentifier();
|
||||||
ServiceConnector<IRoleController> remoteService = sRemoteServices.get(userId);
|
ServiceConnector<IRoleController> remoteService = sRemoteServices.get(userId);
|
||||||
if (remoteService == null) {
|
if (remoteService == null) {
|
||||||
remoteService = new ServiceConnector.Impl<IRoleController>(
|
remoteService = new ServiceConnector.Impl<IRoleController>(context,
|
||||||
ActivityThread.currentApplication(),
|
|
||||||
new Intent(RoleControllerService.SERVICE_INTERFACE)
|
new Intent(RoleControllerService.SERVICE_INTERFACE)
|
||||||
.setComponent(remoteServiceComponentName),
|
.setComponent(remoteServiceComponentName),
|
||||||
0 /* bindingFlags */, userId, IRoleController.Stub::asInterface) {
|
0 /* bindingFlags */, userId, IRoleController.Stub::asInterface) {
|
||||||
@@ -119,7 +118,7 @@ public class RoleControllerManager {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public RoleControllerManager(@NonNull Context context) {
|
public RoleControllerManager(@NonNull Context context) {
|
||||||
this(getRemoteServiceComponentName(context), context.getMainThreadHandler(), context);
|
this(getRemoteServiceComponentName(context), new Handler(Looper.getMainLooper()), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -127,8 +126,8 @@ public class RoleControllerManager {
|
|||||||
Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
|
Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
|
||||||
PackageManager packageManager = context.getPackageManager();
|
PackageManager packageManager = context.getPackageManager();
|
||||||
intent.setPackage(packageManager.getPermissionControllerPackageName());
|
intent.setPackage(packageManager.getPermissionControllerPackageName());
|
||||||
ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
|
ServiceInfo serviceInfo = packageManager.resolveService(intent, 0).serviceInfo;
|
||||||
return resolveInfo.getComponentInfo().getComponentName();
|
return new ComponentName(serviceInfo.packageName, serviceInfo.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import android.os.RemoteCallback;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.function.pooled.PooledLambda;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -85,9 +84,7 @@ public abstract class RoleControllerService extends Service {
|
|||||||
|
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
Objects.requireNonNull(callback, "callback cannot be null");
|
||||||
|
|
||||||
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
|
mWorkerHandler.post(() -> RoleControllerService.this.grantDefaultRoles(callback));
|
||||||
RoleControllerService::grantDefaultRoles, RoleControllerService.this,
|
|
||||||
callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -100,9 +97,8 @@ public abstract class RoleControllerService extends Service {
|
|||||||
"packageName cannot be null or empty");
|
"packageName cannot be null or empty");
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
Objects.requireNonNull(callback, "callback cannot be null");
|
||||||
|
|
||||||
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
|
mWorkerHandler.post(() -> RoleControllerService.this.onAddRoleHolder(roleName,
|
||||||
RoleControllerService::onAddRoleHolder, RoleControllerService.this,
|
packageName, flags, callback));
|
||||||
roleName, packageName, flags, callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,9 +111,8 @@ public abstract class RoleControllerService extends Service {
|
|||||||
"packageName cannot be null or empty");
|
"packageName cannot be null or empty");
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
Objects.requireNonNull(callback, "callback cannot be null");
|
||||||
|
|
||||||
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
|
mWorkerHandler.post(() -> RoleControllerService.this.onRemoveRoleHolder(roleName,
|
||||||
RoleControllerService::onRemoveRoleHolder, RoleControllerService.this,
|
packageName, flags, callback));
|
||||||
roleName, packageName, flags, callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,9 +122,8 @@ public abstract class RoleControllerService extends Service {
|
|||||||
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
|
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
Objects.requireNonNull(callback, "callback cannot be null");
|
||||||
|
|
||||||
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
|
mWorkerHandler.post(() -> RoleControllerService.this.onClearRoleHolders(roleName,
|
||||||
RoleControllerService::onClearRoleHolders, RoleControllerService.this,
|
flags, callback));
|
||||||
roleName, flags, callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enforceCallerSystemUid(@NonNull String methodName) {
|
private void enforceCallerSystemUid(@NonNull String methodName) {
|
||||||
@@ -274,6 +268,7 @@ public abstract class RoleControllerService extends Service {
|
|||||||
*
|
*
|
||||||
* @deprecated Implement {@link #onIsApplicationVisibleForRole(String, String)} instead.
|
* @deprecated Implement {@link #onIsApplicationVisibleForRole(String, String)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
|
public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
|
||||||
@NonNull String packageName);
|
@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.Process;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.function.pooled.PooledLambda;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -180,12 +178,16 @@ public final class RoleManager {
|
|||||||
private final Object mRoleControllerManagerLock = new Object();
|
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
|
* @hide
|
||||||
*/
|
*/
|
||||||
public RoleManager(@NonNull Context context) throws ServiceManager.ServiceNotFoundException {
|
public RoleManager(@NonNull Context context, @NonNull IRoleManager service) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mService = IRoleManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
|
mService = service;
|
||||||
Context.ROLE_SERVICE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -747,9 +749,8 @@ public final class RoleManager {
|
|||||||
public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
|
public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mExecutor.execute(PooledLambda.obtainRunnable(
|
mExecutor.execute(() ->
|
||||||
OnRoleHoldersChangedListener::onRoleHoldersChanged, mListener, roleName,
|
mListener.onRoleHoldersChanged(roleName, UserHandle.of(userId)));
|
||||||
UserHandle.of(userId)));
|
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(token);
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,17 @@ package com.android.server.role;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.UserIdInt;
|
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.
|
* Get all roles and their holders.
|
||||||
*
|
*
|
||||||
@@ -34,6 +37,5 @@ public abstract class RoleManagerInternal {
|
|||||||
* @return The roles and their holders
|
* @return The roles and their holders
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract ArrayMap<String, ArraySet<String>> getRolesAndHolders(
|
Map<String, Set<String>> getRolesAndHolders(@UserIdInt int userId);
|
||||||
@UserIdInt int userId);
|
|
||||||
}
|
}
|
||||||
@@ -43,25 +43,23 @@ import android.os.RemoteException;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArrayMap;
|
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.Slog;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.proto.ProtoOutputStream;
|
import android.util.proto.ProtoOutputStream;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.infra.AndroidFuture;
|
import com.android.internal.infra.AndroidFuture;
|
||||||
import com.android.internal.infra.ThrottledRunnable;
|
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.Preconditions;
|
||||||
import com.android.internal.util.dump.DualDumpOutputStream;
|
import com.android.internal.util.dump.DualDumpOutputStream;
|
||||||
import com.android.internal.util.function.pooled.PooledLambda;
|
import com.android.server.LocalManagerRegistry;
|
||||||
import com.android.server.FgThread;
|
|
||||||
import com.android.server.LocalServices;
|
|
||||||
import com.android.server.SystemService;
|
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.FileDescriptor;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -69,7 +67,9 @@ import java.io.PrintWriter;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
@@ -79,8 +79,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
*
|
*
|
||||||
* @see RoleManager
|
* @see RoleManager
|
||||||
*/
|
*/
|
||||||
public class RoleManagerService extends SystemService implements RoleUserState.Callback {
|
public class RoleService extends SystemService implements RoleUserState.Callback {
|
||||||
private static final String LOG_TAG = RoleManagerService.class.getSimpleName();
|
private static final String LOG_TAG = RoleService.class.getSimpleName();
|
||||||
|
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final AppOpsManager mAppOpsManager;
|
private final AppOpsManager mAppOpsManager;
|
||||||
@NonNull
|
@NonNull
|
||||||
private final UserManagerInternal mUserManagerInternal;
|
private final UserManager mUserManager;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
@@ -120,7 +120,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
new SparseArray<>();
|
new SparseArray<>();
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Handler mListenerHandler = FgThread.getHandler();
|
private final Handler mListenerHandler = ForegroundThread.getHandler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps user id to its throttled runnable for granting default roles.
|
* 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 =
|
private final SparseArray<ThrottledRunnable> mGrantDefaultRolesThrottledRunnables =
|
||||||
new SparseArray<>();
|
new SparseArray<>();
|
||||||
|
|
||||||
public RoleManagerService(@NonNull Context context,
|
public RoleService(@NonNull Context context) {
|
||||||
@NonNull RoleServicePlatformHelper platformHelper) {
|
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
mPlatformHelper = platformHelper;
|
mPlatformHelper = LocalManagerRegistry.getManager(RoleServicePlatformHelper.class);
|
||||||
|
|
||||||
RoleControllerManager.initializeRemoteServiceComponentName(context);
|
RoleControllerManager.initializeRemoteServiceComponentName(context);
|
||||||
|
|
||||||
mAppOpsManager = context.getSystemService(AppOpsManager.class);
|
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();
|
registerUserRemovedReceiver();
|
||||||
}
|
}
|
||||||
@@ -174,9 +173,9 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
getContext().registerReceiverForAllUsers(new BroadcastReceiver() {
|
getContext().registerReceiverForAllUsers(new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
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) {
|
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);
|
+ userId);
|
||||||
}
|
}
|
||||||
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|
||||||
@@ -200,7 +199,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
try {
|
try {
|
||||||
future.get(30, TimeUnit.SECONDS);
|
future.get(30, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
} 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) {
|
synchronized (mLock) {
|
||||||
runnable = mGrantDefaultRolesThrottledRunnables.get(userId);
|
runnable = mGrantDefaultRolesThrottledRunnables.get(userId);
|
||||||
if (runnable == null) {
|
if (runnable == null) {
|
||||||
runnable = new ThrottledRunnable(FgThread.getHandler(),
|
runnable = new ThrottledRunnable(ForegroundThread.getHandler(),
|
||||||
GRANT_DEFAULT_ROLES_INTERVAL_MILLIS,
|
GRANT_DEFAULT_ROLES_INTERVAL_MILLIS,
|
||||||
() -> maybeGrantDefaultRolesInternal(userId));
|
() -> maybeGrantDefaultRolesInternal(userId));
|
||||||
mGrantDefaultRolesThrottledRunnables.put(userId, runnable);
|
mGrantDefaultRolesThrottledRunnables.put(userId, runnable);
|
||||||
@@ -226,16 +225,16 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
String newPackagesHash = mPlatformHelper.computePackageStateHash(userId);
|
String newPackagesHash = mPlatformHelper.computePackageStateHash(userId);
|
||||||
if (Objects.equals(oldPackagesHash, newPackagesHash)) {
|
if (Objects.equals(oldPackagesHash, newPackagesHash)) {
|
||||||
if (DEBUG) {
|
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);
|
+ newPackagesHash);
|
||||||
}
|
}
|
||||||
return AndroidFuture.completedFuture(null);
|
return AndroidFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some package state has changed, so grant default roles again.
|
// 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<>();
|
AndroidFuture<Void> future = new AndroidFuture<>();
|
||||||
getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(),
|
getOrCreateController(userId).grantDefaultRoles(ForegroundThread.getExecutor(),
|
||||||
successful -> {
|
successful -> {
|
||||||
if (successful) {
|
if (successful) {
|
||||||
userState.setPackagesHash(newPackagesHash);
|
userState.setPackagesHash(newPackagesHash);
|
||||||
@@ -273,7 +272,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName(
|
controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName(
|
||||||
FgThread.getHandler(), context);
|
ForegroundThread.getHandler(), context);
|
||||||
mControllers.put(userId, controller);
|
mControllers.put(userId, controller);
|
||||||
}
|
}
|
||||||
return controller;
|
return controller;
|
||||||
@@ -321,8 +320,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
|
public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
|
||||||
mListenerHandler.sendMessage(PooledLambda.obtainMessage(
|
mListenerHandler.post(() -> notifyRoleHoldersChanged(roleName, userId));
|
||||||
RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
@@ -333,7 +331,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoteCallbackList<IOnRoleHoldersChangedListener> allUsersListeners = getListeners(
|
RemoteCallbackList<IOnRoleHoldersChangedListener> allUsersListeners = getListeners(
|
||||||
UserHandle.USER_ALL);
|
UserHandleCompat.USER_ALL);
|
||||||
if (allUsersListeners != null) {
|
if (allUsersListeners != null) {
|
||||||
notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId);
|
notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId);
|
||||||
}
|
}
|
||||||
@@ -350,7 +348,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
try {
|
try {
|
||||||
listener.onRoleHoldersChanged(roleName, userId);
|
listener.onRoleHoldersChanged(roleName, userId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e);
|
Log.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -364,7 +362,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
public boolean isRoleAvailable(@NonNull String roleName) {
|
public boolean isRoleAvailable(@NonNull String roleName) {
|
||||||
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
|
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
|
||||||
|
|
||||||
int userId = UserHandle.getUserId(getCallingUid());
|
int userId = UserHandleCompat.getUserId(getCallingUid());
|
||||||
return getOrCreateUserState(userId).isRoleAvailable(roleName);
|
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(roleName, "roleName cannot be null or empty");
|
||||||
Preconditions.checkStringNotEmpty(packageName, "packageName 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);
|
ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
|
||||||
if (roleHolders == null) {
|
if (roleHolders == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -387,8 +385,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
|
public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
|
||||||
if (!mUserManagerInternal.exists(userId)) {
|
if (!isUserExistent(userId)) {
|
||||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
Log.e(LOG_TAG, "user " + userId + " does not exist");
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
enforceCrossUserPermission(userId, false, "getRoleHoldersAsUser");
|
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,
|
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
|
||||||
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
|
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
|
||||||
@NonNull RemoteCallback callback) {
|
@NonNull RemoteCallback callback) {
|
||||||
if (!mUserManagerInternal.exists(userId)) {
|
if (!isUserExistent(userId)) {
|
||||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
Log.e(LOG_TAG, "user " + userId + " does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
enforceCrossUserPermission(userId, false, "addRoleHolderAsUser");
|
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,
|
public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
|
||||||
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
|
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
|
||||||
@NonNull RemoteCallback callback) {
|
@NonNull RemoteCallback callback) {
|
||||||
if (!mUserManagerInternal.exists(userId)) {
|
if (!isUserExistent(userId)) {
|
||||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
Log.e(LOG_TAG, "user " + userId + " does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser");
|
enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser");
|
||||||
@@ -448,8 +446,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
public void clearRoleHoldersAsUser(@NonNull String roleName,
|
public void clearRoleHoldersAsUser(@NonNull String roleName,
|
||||||
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
|
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
|
||||||
@NonNull RemoteCallback callback) {
|
@NonNull RemoteCallback callback) {
|
||||||
if (!mUserManagerInternal.exists(userId)) {
|
if (!isUserExistent(userId)) {
|
||||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
Log.e(LOG_TAG, "user " + userId + " does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser");
|
enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser");
|
||||||
@@ -465,8 +463,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
@Override
|
@Override
|
||||||
public void addOnRoleHoldersChangedListenerAsUser(
|
public void addOnRoleHoldersChangedListenerAsUser(
|
||||||
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
|
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
|
||||||
if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
|
if (userId != UserHandleCompat.USER_ALL && !isUserExistent(userId)) {
|
||||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
Log.e(LOG_TAG, "user " + userId + " does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
enforceCrossUserPermission(userId, true, "addOnRoleHoldersChangedListenerAsUser");
|
enforceCrossUserPermission(userId, true, "addOnRoleHoldersChangedListenerAsUser");
|
||||||
@@ -483,8 +481,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
@Override
|
@Override
|
||||||
public void removeOnRoleHoldersChangedListenerAsUser(
|
public void removeOnRoleHoldersChangedListenerAsUser(
|
||||||
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
|
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
|
||||||
if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
|
if (userId != UserHandleCompat.USER_ALL && !isUserExistent(userId)) {
|
||||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
Log.e(LOG_TAG, "user " + userId + " does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
enforceCrossUserPermission(userId, true, "removeOnRoleHoldersChangedListenerAsUser");
|
enforceCrossUserPermission(userId, true, "removeOnRoleHoldersChangedListenerAsUser");
|
||||||
@@ -508,7 +506,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
|
|
||||||
Objects.requireNonNull(roleNames, "roleNames cannot be null");
|
Objects.requireNonNull(roleNames, "roleNames cannot be null");
|
||||||
|
|
||||||
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
int userId = UserHandleCompat.getUserId(Binder.getCallingUid());
|
||||||
getOrCreateUserState(userId).setRoleNames(roleNames);
|
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(roleName, "roleName cannot be null or empty");
|
||||||
Preconditions.checkStringNotEmpty(packageName, "packageName 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);
|
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(roleName, "roleName cannot be null or empty");
|
||||||
Preconditions.checkStringNotEmpty(packageName, "packageName 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);
|
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");
|
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);
|
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,
|
private void enforceCrossUserPermission(@UserIdInt int userId, boolean allowAll,
|
||||||
@NonNull String message) {
|
@NonNull String message) {
|
||||||
final int callingUid = Binder.getCallingUid();
|
final int callingUid = Binder.getCallingUid();
|
||||||
final int callingUserId = UserHandle.getUserId(callingUid);
|
final int callingUserId = UserHandleCompat.getUserId(callingUid);
|
||||||
if (userId == callingUserId) {
|
if (userId == callingUserId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM
|
Preconditions.checkArgument(userId >= UserHandleCompat.USER_SYSTEM
|
||||||
|| (allowAll && userId == UserHandle.USER_ALL), "Invalid user " + userId);
|
|| (allowAll && userId == UserHandleCompat.USER_ALL), "Invalid user " + userId);
|
||||||
getContext().enforceCallingOrSelfPermission(
|
getContext().enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
|
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
|
||||||
if (callingUid == Process.SHELL_UID && userId >= UserHandle.USER_SYSTEM) {
|
if (callingUid == Process.SHELL_UID && userId >= UserHandleCompat.USER_SYSTEM) {
|
||||||
if (mUserManagerInternal.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
|
if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_DEBUGGING_FEATURES,
|
||||||
userId)) {
|
UserHandle.of(userId))) {
|
||||||
throw new SecurityException("Shell does not have permission to access user "
|
throw new SecurityException("Shell does not have permission to access user "
|
||||||
+ userId);
|
+ userId);
|
||||||
}
|
}
|
||||||
@@ -576,7 +580,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
public int handleShellCommand(@NonNull ParcelFileDescriptor in,
|
public int handleShellCommand(@NonNull ParcelFileDescriptor in,
|
||||||
@NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
|
@NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
|
||||||
@NonNull String[] args) {
|
@NonNull String[] args) {
|
||||||
return new RoleManagerShellCommand(this).exec(this, in.getFileDescriptor(),
|
return new RoleShellCommand(this).exec(this, in.getFileDescriptor(),
|
||||||
out.getFileDescriptor(), err.getFileDescriptor(), args);
|
out.getFileDescriptor(), err.getFileDescriptor(), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,7 +588,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
@Override
|
@Override
|
||||||
public String getBrowserRoleHolder(@UserIdInt int userId) {
|
public String getBrowserRoleHolder(@UserIdInt int userId) {
|
||||||
final int callingUid = Binder.getCallingUid();
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (UserHandle.getUserId(callingUid) != userId) {
|
if (UserHandleCompat.getUserId(callingUid) != userId) {
|
||||||
getContext().enforceCallingOrSelfPermission(
|
getContext().enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||||
}
|
}
|
||||||
@@ -625,12 +629,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
context.enforceCallingOrSelfPermission(
|
context.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
|
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
|
||||||
if (UserHandle.getUserId(Binder.getCallingUid()) != userId) {
|
if (UserHandleCompat.getUserId(Binder.getCallingUid()) != userId) {
|
||||||
context.enforceCallingOrSelfPermission(
|
context.enforceCallingOrSelfPermission(
|
||||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mUserManagerInternal.exists(userId)) {
|
if (!isUserExistent(userId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,7 +657,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
try {
|
try {
|
||||||
future.get(5, TimeUnit.SECONDS);
|
future.get(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -687,7 +691,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
|||||||
dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(
|
dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(
|
||||||
new FileOutputStream(fd)));
|
new FileOutputStream(fd)));
|
||||||
} else {
|
} else {
|
||||||
fout.println("ROLE MANAGER STATE (dumpsys role):");
|
fout.println("ROLE STATE (dumpsys role):");
|
||||||
dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " "));
|
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
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ArrayMap<String, ArraySet<String>> getRolesAndHolders(@UserIdInt int userId) {
|
public Map<String, Set<String>> getRolesAndHolders(@UserIdInt int userId) {
|
||||||
return getOrCreateUserState(userId).getRolesAndHolders();
|
// 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.app.role.IRoleManager;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
|
||||||
|
|
||||||
import com.android.modules.utils.BasicShellCommandHandler;
|
import com.android.modules.utils.BasicShellCommandHandler;
|
||||||
|
import com.android.server.role.compat.UserHandleCompat;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
class RoleManagerShellCommand extends BasicShellCommandHandler {
|
class RoleShellCommand extends BasicShellCommandHandler {
|
||||||
@NonNull
|
@NonNull
|
||||||
private final IRoleManager mRoleManager;
|
private final IRoleManager mRoleManager;
|
||||||
|
|
||||||
RoleManagerShellCommand(@NonNull IRoleManager roleManager) {
|
RoleShellCommand(@NonNull IRoleManager roleManager) {
|
||||||
mRoleManager = roleManager;
|
mRoleManager = roleManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ class RoleManagerShellCommand extends BasicShellCommandHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getUserIdMaybe() {
|
private int getUserIdMaybe() {
|
||||||
int userId = UserHandle.USER_SYSTEM;
|
int userId = UserHandleCompat.USER_SYSTEM;
|
||||||
String option = getNextOption();
|
String option = getNextOption();
|
||||||
if (option != null && option.equals("--user")) {
|
if (option != null && option.equals("--user")) {
|
||||||
userId = Integer.parseInt(getNextArgRequired());
|
userId = Integer.parseInt(getNextArgRequired());
|
||||||
@@ -139,7 +139,7 @@ class RoleManagerShellCommand extends BasicShellCommandHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void onHelp() {
|
public void onHelp() {
|
||||||
PrintWriter pw = getOutPrintWriter();
|
PrintWriter pw = getOutPrintWriter();
|
||||||
pw.println("Role manager (role) commands:");
|
pw.println("Role (role) commands:");
|
||||||
pw.println(" help or -h");
|
pw.println(" help or -h");
|
||||||
pw.println(" Print this help text.");
|
pw.println(" Print this help text.");
|
||||||
pw.println();
|
pw.println();
|
||||||
@@ -25,15 +25,14 @@ import android.os.Handler;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
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.dump.DualDumpOutputStream;
|
||||||
import com.android.internal.util.function.pooled.PooledLambda;
|
|
||||||
import com.android.role.persistence.RolesPersistence;
|
import com.android.role.persistence.RolesPersistence;
|
||||||
import com.android.role.persistence.RolesState;
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -197,7 +196,7 @@ class RoleUserState {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (!mRoles.containsKey(roleName)) {
|
if (!mRoles.containsKey(roleName)) {
|
||||||
mRoles.put(roleName, new ArraySet<>());
|
mRoles.put(roleName, new ArraySet<>());
|
||||||
Slog.i(LOG_TAG, "Added new role: " + roleName);
|
Log.i(LOG_TAG, "Added new role: " + roleName);
|
||||||
scheduleWriteFileLocked();
|
scheduleWriteFileLocked();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -221,7 +220,7 @@ class RoleUserState {
|
|||||||
if (!roleNames.contains(roleName)) {
|
if (!roleNames.contains(roleName)) {
|
||||||
ArraySet<String> packageNames = mRoles.valueAt(i);
|
ArraySet<String> packageNames = mRoles.valueAt(i);
|
||||||
if (!packageNames.isEmpty()) {
|
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);
|
+ " role: " + roleName + ", holders: " + packageNames);
|
||||||
}
|
}
|
||||||
mRoles.removeAt(i);
|
mRoles.removeAt(i);
|
||||||
@@ -255,7 +254,7 @@ class RoleUserState {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
ArraySet<String> roleHolders = mRoles.get(roleName);
|
ArraySet<String> roleHolders = mRoles.get(roleName);
|
||||||
if (roleHolders == null) {
|
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);
|
+ ", package: " + packageName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -286,7 +285,7 @@ class RoleUserState {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
ArraySet<String> roleHolders = mRoles.get(roleName);
|
ArraySet<String> roleHolders = mRoles.get(roleName);
|
||||||
if (roleHolders == null) {
|
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);
|
+ ", package: " + packageName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -330,8 +329,7 @@ class RoleUserState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!mWriteScheduled) {
|
if (!mWriteScheduled) {
|
||||||
mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeFile,
|
mWriteHandler.postDelayed(this::writeFile, WRITE_DELAY_MILLIS);
|
||||||
this), WRITE_DELAY_MILLIS);
|
|
||||||
mWriteScheduled = true;
|
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.internal.util.FrameworkStatsLog;
|
||||||
import com.android.server.BatteryService;
|
import com.android.server.BatteryService;
|
||||||
import com.android.server.BinderCallsStatsService;
|
import com.android.server.BinderCallsStatsService;
|
||||||
|
import com.android.server.LocalManagerRegistry;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
import com.android.server.SystemServiceManager;
|
import com.android.server.SystemServiceManager;
|
||||||
import com.android.server.am.MemoryStatUtil.MemoryStat;
|
import com.android.server.am.MemoryStatUtil.MemoryStat;
|
||||||
import com.android.server.notification.NotificationManagerService;
|
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.IonMemoryUtil.IonAllocations;
|
||||||
import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
|
import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
|
||||||
import com.android.server.stats.pull.netstats.NetworkStatsExt;
|
import com.android.server.stats.pull.netstats.NetworkStatsExt;
|
||||||
@@ -2916,7 +2917,8 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
final long callingToken = Binder.clearCallingIdentity();
|
final long callingToken = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
PackageManager pm = mContext.getPackageManager();
|
||||||
RoleManagerInternal rmi = LocalServices.getService(RoleManagerInternal.class);
|
RoleManagerLocal roleManagerLocal = LocalManagerRegistry.getManager(
|
||||||
|
RoleManagerLocal.class);
|
||||||
|
|
||||||
List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
|
List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
|
||||||
|
|
||||||
@@ -2924,27 +2926,23 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
for (int userNum = 0; userNum < numUsers; userNum++) {
|
for (int userNum = 0; userNum < numUsers; userNum++) {
|
||||||
int userId = users.get(userNum).getUserHandle().getIdentifier();
|
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 (Map.Entry<String, Set<String>> roleEntry : roles.entrySet()) {
|
||||||
for (int roleNum = 0; roleNum < numRoles; roleNum++) {
|
String roleName = roleEntry.getKey();
|
||||||
String roleName = roles.keyAt(roleNum);
|
Set<String> packageNames = roleEntry.getValue();
|
||||||
ArraySet<String> holders = roles.valueAt(roleNum);
|
|
||||||
|
|
||||||
int numHolders = holders.size();
|
|
||||||
for (int holderNum = 0; holderNum < numHolders; holderNum++) {
|
|
||||||
String holderName = holders.valueAt(holderNum);
|
|
||||||
|
|
||||||
|
for (String packageName : packageNames) {
|
||||||
PackageInfo pkg;
|
PackageInfo pkg;
|
||||||
try {
|
try {
|
||||||
pkg = pm.getPackageInfoAsUser(holderName, 0, userId);
|
pkg = pm.getPackageInfoAsUser(packageName, 0, userId);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
Slog.w(TAG, "Role holder " + holderName + " not found");
|
Slog.w(TAG, "Role holder " + packageName + " not found");
|
||||||
return StatsManager.PULL_SKIP;
|
return StatsManager.PULL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
pulledData.add(FrameworkStatsLog.buildStatsEvent(
|
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.profcollect.ProfcollectForwardingService;
|
||||||
import com.android.server.recoverysystem.RecoverySystemService;
|
import com.android.server.recoverysystem.RecoverySystemService;
|
||||||
import com.android.server.restrictions.RestrictionsManagerService;
|
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.FileIntegrityService;
|
||||||
import com.android.server.security.KeyAttestationApplicationIdProviderService;
|
import com.android.server.security.KeyAttestationApplicationIdProviderService;
|
||||||
import com.android.server.security.KeyChainSystemService;
|
import com.android.server.security.KeyChainSystemService;
|
||||||
@@ -353,6 +353,7 @@ public final class SystemServer implements Dumpable {
|
|||||||
"com.android.server.ConnectivityServiceInitializer";
|
"com.android.server.ConnectivityServiceInitializer";
|
||||||
private static final String IP_CONNECTIVITY_METRICS_CLASS =
|
private static final String IP_CONNECTIVITY_METRICS_CLASS =
|
||||||
"com.android.server.connectivity.IpConnectivityMetrics";
|
"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";
|
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
|
// Grants default permissions and defines roles
|
||||||
t.traceBegin("StartRoleManagerService");
|
t.traceBegin("StartRoleManagerService");
|
||||||
mSystemServiceManager.startService(new RoleManagerService(
|
LocalManagerRegistry.addManager(RoleServicePlatformHelper.class,
|
||||||
mSystemContext, new RoleServicePlatformHelperImpl(mSystemContext)));
|
new RoleServicePlatformHelperImpl(mSystemContext));
|
||||||
|
mSystemServiceManager.startService(ROLE_SERVICE_CLASS);
|
||||||
t.traceEnd();
|
t.traceEnd();
|
||||||
|
|
||||||
// We need to always start this service, regardless of whether the
|
// We need to always start this service, regardless of whether the
|
||||||
|
|||||||
Reference in New Issue
Block a user