Refactor RoleManagerService to use system API when possible.
Changes include but not limited to: - Use DataOutputStream for computePackageStateHash(), as OutputStream.write(int) only writes one byte, so it's better to use a proper built-in mechanism and drop dependency on another util class in the meantime. - Use a simplified enforceCrossUserPermission() similar to other system services, instead of the non-API ActivityManager.handleIncomingUser(). - Use the module library BasicShellCommandHandler to implement RoleManagerShellCommand. - Dump the existing user states, instead of for all users which potentially creates empty states. This makes the dump more truthful and saves an API. - Use a local copy of checkDumpPermission() instead of depending on the entire DumpUtils class. - Use the XmlPullParser API instead of the new non-API TypedXmlPullParser, because the legacy file can only be written before R, and thus can't be the new binary XML format. - Other small changes to use system APIs. Bug: 158736025 Test: CtsRoleTestCases Change-Id: I97d74aadfa2ccd264929c45226367b65a47f6435
This commit is contained in:
@@ -18,13 +18,11 @@ package com.android.server.role;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.AnyThread;
|
||||
import android.annotation.CheckResult;
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.annotation.WorkerThread;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.role.IOnRoleHoldersChangedListener;
|
||||
import android.app.role.IRoleManager;
|
||||
@@ -34,20 +32,22 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.Signature;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
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.PackageUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -57,11 +57,7 @@ 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.BitUtils;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.FunctionalUtils;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.dump.DualDumpOutputStream;
|
||||
import com.android.internal.util.function.pooled.PooledLambda;
|
||||
@@ -71,7 +67,10 @@ import com.android.server.SystemService;
|
||||
import com.android.server.pm.UserManagerInternal;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -87,17 +86,18 @@ import java.util.concurrent.TimeoutException;
|
||||
* @see RoleManager
|
||||
*/
|
||||
public class RoleManagerService extends SystemService implements RoleUserState.Callback {
|
||||
|
||||
private static final String LOG_TAG = RoleManagerService.class.getSimpleName();
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final long GRANT_DEFAULT_ROLES_INTERVAL_MILLIS = 1000;
|
||||
|
||||
@NonNull
|
||||
private final UserManagerInternal mUserManagerInternal;
|
||||
@NonNull
|
||||
private final AppOpsManager mAppOpsManager;
|
||||
@NonNull
|
||||
private final PackageManagerInternal mPackageManagerInternal;
|
||||
@NonNull
|
||||
private final UserManagerInternal mUserManagerInternal;
|
||||
|
||||
@NonNull
|
||||
private final Object mLock = new Object();
|
||||
@@ -146,8 +146,9 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
|
||||
RoleControllerManager.initializeRemoteServiceComponentName(context);
|
||||
|
||||
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
|
||||
mAppOpsManager = context.getSystemService(AppOpsManager.class);
|
||||
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
|
||||
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
|
||||
|
||||
LocalServices.addService(RoleManagerInternal.class, new Internal());
|
||||
|
||||
@@ -157,15 +158,16 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
private void registerUserRemovedReceiver() {
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
|
||||
getContext().registerReceiverAsUser(new BroadcastReceiver() {
|
||||
getContext().registerReceiverForAllUsers(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
|
||||
if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) {
|
||||
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
|
||||
int userId = intent.<UserHandle>getParcelableExtra(Intent.EXTRA_USER)
|
||||
.getIdentifier();
|
||||
onRemoveUser(userId);
|
||||
}
|
||||
}
|
||||
}, UserHandle.ALL, intentFilter, null, null);
|
||||
}, intentFilter, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,7 +180,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
intentFilter.addDataScheme("package");
|
||||
intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
|
||||
getContext().registerReceiverAsUser(new BroadcastReceiver() {
|
||||
getContext().registerReceiverForAllUsers(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1));
|
||||
@@ -193,12 +195,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
}
|
||||
maybeGrantDefaultRolesAsync(userId);
|
||||
}
|
||||
}, UserHandle.ALL, intentFilter, null, null);
|
||||
}, intentFilter, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserStarting(@NonNull TargetUser user) {
|
||||
maybeGrantDefaultRolesSync(user.getUserIdentifier());
|
||||
maybeGrantDefaultRolesSync(user.getUserHandle().getIdentifier());
|
||||
}
|
||||
|
||||
@MainThread
|
||||
@@ -230,7 +232,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
private AndroidFuture<Void> maybeGrantDefaultRolesInternal(@UserIdInt int userId) {
|
||||
RoleUserState userState = getOrCreateUserState(userId);
|
||||
String oldPackagesHash = userState.getPackagesHash();
|
||||
String newPackagesHash = computeComponentStateHash(userId);
|
||||
String newPackagesHash = computePackageStateHash(userId);
|
||||
if (Objects.equals(oldPackagesHash, newPackagesHash)) {
|
||||
if (DEBUG) {
|
||||
Slog.i(LOG_TAG, "Already granted default roles for packages hash "
|
||||
@@ -282,35 +284,42 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String computeComponentStateHash(@UserIdInt int userId) {
|
||||
PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
private String computePackageStateHash(@UserIdInt int userId) {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
|
||||
|
||||
pm.forEachInstalledPackage(FunctionalUtils.uncheckExceptions(pkg -> {
|
||||
out.write(pkg.getPackageName().getBytes());
|
||||
out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
|
||||
out.write(pm.getApplicationEnabledState(pkg.getPackageName(), userId));
|
||||
mPackageManagerInternal.forEachInstalledPackage(pkg -> {
|
||||
try {
|
||||
dataOutputStream.writeUTF(pkg.getPackageName());
|
||||
dataOutputStream.writeLong(pkg.getLongVersionCode());
|
||||
dataOutputStream.writeInt(mPackageManagerInternal.getApplicationEnabledState(
|
||||
pkg.getPackageName(), userId));
|
||||
|
||||
ArraySet<String> enabledComponents =
|
||||
pm.getEnabledComponents(pkg.getPackageName(), userId);
|
||||
int numComponents = CollectionUtils.size(enabledComponents);
|
||||
out.write(numComponents);
|
||||
for (int i = 0; i < numComponents; i++) {
|
||||
out.write(enabledComponents.valueAt(i).getBytes());
|
||||
ArraySet<String> enabledComponents =
|
||||
mPackageManagerInternal.getEnabledComponents(pkg.getPackageName(), userId);
|
||||
int numComponents = CollectionUtils.size(enabledComponents);
|
||||
dataOutputStream.writeInt(numComponents);
|
||||
for (int i = 0; i < numComponents; i++) {
|
||||
dataOutputStream.writeUTF(enabledComponents.valueAt(i));
|
||||
}
|
||||
|
||||
ArraySet<String> disabledComponents =
|
||||
mPackageManagerInternal.getDisabledComponents(pkg.getPackageName(), userId);
|
||||
numComponents = CollectionUtils.size(disabledComponents);
|
||||
for (int i = 0; i < numComponents; i++) {
|
||||
dataOutputStream.writeUTF(disabledComponents.valueAt(i));
|
||||
}
|
||||
|
||||
for (Signature signature : pkg.getSigningDetails().signatures) {
|
||||
dataOutputStream.write(signature.toByteArray());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Never happens for ByteArrayOutputStream and DataOutputStream.
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}, userId);
|
||||
|
||||
ArraySet<String> disabledComponents =
|
||||
pm.getDisabledComponents(pkg.getPackageName(), userId);
|
||||
numComponents = CollectionUtils.size(disabledComponents);
|
||||
for (int i = 0; i < numComponents; i++) {
|
||||
out.write(disabledComponents.valueAt(i).getBytes());
|
||||
}
|
||||
for (Signature signature : pkg.getSigningDetails().signatures) {
|
||||
out.write(signature.toByteArray());
|
||||
}
|
||||
}), userId);
|
||||
|
||||
return PackageUtils.computeSha256Digest(out.toByteArray());
|
||||
return PackageUtils.computeSha256Digest(byteArrayOutputStream.toByteArray());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -335,7 +344,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
try {
|
||||
context = systemContext.createPackageContextAsUser(
|
||||
systemContext.getPackageName(), 0, UserHandle.of(userId));
|
||||
} catch (NameNotFoundException e) {
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName(
|
||||
@@ -371,9 +380,11 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
RoleUserState userState;
|
||||
synchronized (mLock) {
|
||||
mGrantDefaultRolesThrottledRunnables.remove(userId);
|
||||
listeners = mListeners.removeReturnOld(userId);
|
||||
listeners = mListeners.get(userId);
|
||||
mListeners.remove(userId);
|
||||
mControllers.remove(userId);
|
||||
userState = mUserStates.removeReturnOld(userId);
|
||||
userState = mUserStates.get(userId);
|
||||
mUserStates.remove(userId);
|
||||
}
|
||||
if (listeners != null) {
|
||||
listeners.kill();
|
||||
@@ -455,7 +466,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
userId = handleIncomingUser(userId, false, "getRoleHoldersAsUser");
|
||||
enforceCrossUserPermission(userId, false, "getRoleHoldersAsUser");
|
||||
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
|
||||
"getRoleHoldersAsUser");
|
||||
|
||||
@@ -476,7 +487,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
||||
return;
|
||||
}
|
||||
userId = handleIncomingUser(userId, false, "addRoleHolderAsUser");
|
||||
enforceCrossUserPermission(userId, false, "addRoleHolderAsUser");
|
||||
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
|
||||
"addRoleHolderAsUser");
|
||||
|
||||
@@ -496,7 +507,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
||||
return;
|
||||
}
|
||||
userId = handleIncomingUser(userId, false, "removeRoleHolderAsUser");
|
||||
enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser");
|
||||
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
|
||||
"removeRoleHolderAsUser");
|
||||
|
||||
@@ -516,7 +527,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
||||
return;
|
||||
}
|
||||
userId = handleIncomingUser(userId, false, "clearRoleHoldersAsUser");
|
||||
enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser");
|
||||
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
|
||||
"clearRoleHoldersAsUser");
|
||||
|
||||
@@ -533,7 +544,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
||||
return;
|
||||
}
|
||||
userId = handleIncomingUser(userId, true, "addOnRoleHoldersChangedListenerAsUser");
|
||||
enforceCrossUserPermission(userId, true, "addOnRoleHoldersChangedListenerAsUser");
|
||||
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
|
||||
"addOnRoleHoldersChangedListenerAsUser");
|
||||
|
||||
@@ -551,7 +562,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
Slog.e(LOG_TAG, "user " + userId + " does not exist");
|
||||
return;
|
||||
}
|
||||
userId = handleIncomingUser(userId, true, "removeOnRoleHoldersChangedListenerAsUser");
|
||||
enforceCrossUserPermission(userId, true, "removeOnRoleHoldersChangedListenerAsUser");
|
||||
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
|
||||
"removeOnRoleHoldersChangedListenerAsUser");
|
||||
|
||||
@@ -572,7 +583,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
|
||||
Objects.requireNonNull(roleNames, "roleNames cannot be null");
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||
getOrCreateUserState(userId).setRoleNames(roleNames);
|
||||
}
|
||||
|
||||
@@ -586,7 +597,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.getCallingUserId();
|
||||
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||
return getOrCreateUserState(userId).addRoleHolder(roleName, packageName);
|
||||
}
|
||||
|
||||
@@ -600,7 +611,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.getCallingUserId();
|
||||
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||
return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName);
|
||||
}
|
||||
|
||||
@@ -612,23 +623,36 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
|
||||
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
|
||||
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||
return getOrCreateUserState(userId).getHeldRoles(packageName);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
private int handleIncomingUser(@UserIdInt int userId, boolean allowAll,
|
||||
@NonNull String name) {
|
||||
return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
|
||||
allowAll, true, name, null);
|
||||
private void enforceCrossUserPermission(@UserIdInt int userId, boolean allowAll,
|
||||
@NonNull String message) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||
if (userId == callingUserId) {
|
||||
return;
|
||||
}
|
||||
Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM
|
||||
|| (allowAll && userId == UserHandle.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)) {
|
||||
throw new SecurityException("Shell does not have permission to access user "
|
||||
+ userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
|
||||
@Nullable FileDescriptor err, @NonNull String[] args,
|
||||
@Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) {
|
||||
new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback,
|
||||
resultReceiver);
|
||||
public int handleShellCommand(@NonNull ParcelFileDescriptor in,
|
||||
@NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
|
||||
@NonNull String[] args) {
|
||||
return new RoleManagerShellCommand(this).exec(this, in.getFileDescriptor(),
|
||||
out.getFileDescriptor(), err.getFileDescriptor(), args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -639,9 +663,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
getContext().enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||
}
|
||||
final PackageManagerInternal packageManager = LocalServices.getService(
|
||||
PackageManagerInternal.class);
|
||||
if (packageManager.getInstantAppPackageName(callingUid) != null) {
|
||||
if (mPackageManagerInternal.getInstantAppPackageName(callingUid) != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -659,7 +681,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
final Context context = getContext();
|
||||
context.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
|
||||
if (UserHandle.getCallingUserId() != userId) {
|
||||
if (UserHandle.getUserId(Binder.getCallingUid()) != userId) {
|
||||
context.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||
}
|
||||
@@ -711,35 +733,48 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
@Override
|
||||
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
|
||||
@Nullable String[] args) {
|
||||
if (!DumpUtils.checkDumpPermission(getContext(), LOG_TAG, fout)) {
|
||||
if (!checkDumpPermission("role", fout)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
|
||||
DualDumpOutputStream dumpOutputStream;
|
||||
if (dumpAsProto) {
|
||||
dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(fd));
|
||||
dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(
|
||||
new FileOutputStream(fd)));
|
||||
} else {
|
||||
fout.println("ROLE MANAGER STATE (dumpsys role):");
|
||||
dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " "));
|
||||
}
|
||||
|
||||
int[] userIds = mUserManagerInternal.getUserIds();
|
||||
int userIdsLength = userIds.length;
|
||||
for (int i = 0; i < userIdsLength; i++) {
|
||||
int userId = userIds[i];
|
||||
synchronized (mLock) {
|
||||
final int userStatesSize = mUserStates.size();
|
||||
for (int i = 0; i < userStatesSize; i++) {
|
||||
final RoleUserState userState = mUserStates.valueAt(i);
|
||||
|
||||
RoleUserState userState = getOrCreateUserState(userId);
|
||||
userState.dump(dumpOutputStream, "user_states",
|
||||
RoleManagerServiceDumpProto.USER_STATES);
|
||||
userState.dump(dumpOutputStream, "user_states",
|
||||
RoleManagerServiceDumpProto.USER_STATES);
|
||||
}
|
||||
}
|
||||
|
||||
dumpOutputStream.flush();
|
||||
}
|
||||
|
||||
private boolean checkDumpPermission(@NonNull String serviceName,
|
||||
@NonNull PrintWriter writer) {
|
||||
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
writer.println("Permission Denial: can't dump " + serviceName + " from from pid="
|
||||
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
|
||||
+ " due to missing " + android.Manifest.permission.DUMP + " permission");
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Internal extends RoleManagerInternal {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayMap<String, ArraySet<String>> getRolesAndHolders(@UserIdInt int userId) {
|
||||
|
||||
@@ -21,16 +21,15 @@ import android.annotation.Nullable;
|
||||
import android.app.role.IRoleManager;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.modules.utils.BasicShellCommandHandler;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
class RoleManagerShellCommand extends ShellCommand {
|
||||
|
||||
class RoleManagerShellCommand extends BasicShellCommandHandler {
|
||||
@NonNull
|
||||
private final IRoleManager mRoleManager;
|
||||
|
||||
@@ -39,7 +38,6 @@ class RoleManagerShellCommand extends ShellCommand {
|
||||
}
|
||||
|
||||
private class CallbackFuture extends CompletableFuture<Void> {
|
||||
|
||||
@NonNull
|
||||
public RemoteCallback createCallback() {
|
||||
return new RemoteCallback(result -> {
|
||||
@@ -57,8 +55,7 @@ class RoleManagerShellCommand extends ShellCommand {
|
||||
get(5, TimeUnit.SECONDS);
|
||||
return 0;
|
||||
} catch (Exception e) {
|
||||
getErrPrintWriter().println("Error: see logcat for details.\n"
|
||||
+ Log.getStackTraceString(e));
|
||||
getErrPrintWriter().println("Error: see logcat for details.\n" + e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -92,7 +89,7 @@ class RoleManagerShellCommand extends ShellCommand {
|
||||
int userId = UserHandle.USER_SYSTEM;
|
||||
String option = getNextOption();
|
||||
if (option != null && option.equals("--user")) {
|
||||
userId = UserHandle.parseUserArg(getNextArgRequired());
|
||||
userId = Integer.parseInt(getNextArgRequired());
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
@@ -143,7 +140,7 @@ class RoleManagerShellCommand extends ShellCommand {
|
||||
public void onHelp() {
|
||||
PrintWriter pw = getOutPrintWriter();
|
||||
pw.println("Role manager (role) commands:");
|
||||
pw.println(" help");
|
||||
pw.println(" help or -h");
|
||||
pw.println(" Print this help text.");
|
||||
pw.println();
|
||||
pw.println(" add-role-holder [--user USER_ID] ROLE PACKAGE [FLAGS]");
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
import android.util.TypedXmlPullParser;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -55,8 +54,7 @@ import java.util.Set;
|
||||
/**
|
||||
* Stores the state of roles for a user.
|
||||
*/
|
||||
public class RoleUserState {
|
||||
|
||||
class RoleUserState {
|
||||
private static final String LOG_TAG = RoleUserState.class.getSimpleName();
|
||||
|
||||
public static final int VERSION_UNDEFINED = -1;
|
||||
@@ -104,7 +102,7 @@ public class RoleUserState {
|
||||
private boolean mDestroyed;
|
||||
|
||||
@NonNull
|
||||
private final Handler mWriteHandler = new Handler(BackgroundThread.getHandler().getLooper());
|
||||
private final Handler mWriteHandler = new Handler(BackgroundThread.get().getLooper());
|
||||
|
||||
/**
|
||||
* Create a new user state, and read its state from disk if previously persisted.
|
||||
@@ -392,7 +390,8 @@ public class RoleUserState {
|
||||
private void readLegacyFileLocked() {
|
||||
File file = getFile(mUserId);
|
||||
try (FileInputStream in = new AtomicFile(file).openRead()) {
|
||||
TypedXmlPullParser parser = Xml.resolvePullParser(in);
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setInput(in, null);
|
||||
parseXmlLocked(parser);
|
||||
Slog.i(LOG_TAG, "Read roles.xml successfully");
|
||||
} catch (FileNotFoundException e) {
|
||||
@@ -402,7 +401,7 @@ public class RoleUserState {
|
||||
}
|
||||
}
|
||||
|
||||
private void parseXmlLocked(@NonNull TypedXmlPullParser parser) throws IOException,
|
||||
private void parseXmlLocked(@NonNull XmlPullParser parser) throws IOException,
|
||||
XmlPullParserException {
|
||||
int type;
|
||||
int depth;
|
||||
@@ -421,9 +420,9 @@ public class RoleUserState {
|
||||
Slog.w(LOG_TAG, "Missing <" + TAG_ROLES + "> in roles.xml");
|
||||
}
|
||||
|
||||
private void parseRolesLocked(@NonNull TypedXmlPullParser parser) throws IOException,
|
||||
private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
|
||||
XmlPullParserException {
|
||||
mVersion = parser.getAttributeInt(null, ATTRIBUTE_VERSION);
|
||||
mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
|
||||
mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
|
||||
mRoles.clear();
|
||||
|
||||
@@ -445,7 +444,7 @@ public class RoleUserState {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ArraySet<String> parseRoleHoldersLocked(@NonNull TypedXmlPullParser parser)
|
||||
private ArraySet<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
|
||||
throws IOException, XmlPullParserException {
|
||||
ArraySet<String> roleHolders = new ArraySet<>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user