Add dual dumping for RoleManagerService.
This change adds dual dumping for RoleManagerService. Bug: 110557011 Test: adb shell dumpsys role Change-Id: I2782cd896df5d79274963785e46d04a295d83f7f
This commit is contained in:
@@ -34,6 +34,7 @@ import "frameworks/base/core/proto/android/server/alarmmanagerservice.proto";
|
||||
import "frameworks/base/core/proto/android/server/fingerprint.proto";
|
||||
import "frameworks/base/core/proto/android/server/jobscheduler.proto";
|
||||
import "frameworks/base/core/proto/android/server/powermanagerservice.proto";
|
||||
import "frameworks/base/core/proto/android/server/rolemanagerservice.proto";
|
||||
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
|
||||
import "frameworks/base/core/proto/android/service/appwidget.proto";
|
||||
import "frameworks/base/core/proto/android/service/battery.proto";
|
||||
@@ -308,6 +309,11 @@ message IncidentProto {
|
||||
(section).userdebug_and_eng_only = true
|
||||
];
|
||||
|
||||
optional com.android.server.role.RoleManagerServiceDumpProto role = 3024 [
|
||||
(section).type = SECTION_DUMPSYS,
|
||||
(section).args = "role --proto"
|
||||
];
|
||||
|
||||
// Reserved for OEMs.
|
||||
extensions 50000 to 100000;
|
||||
}
|
||||
|
||||
56
core/proto/android/server/rolemanagerservice.proto
Normal file
56
core/proto/android/server/rolemanagerservice.proto
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package com.android.server.role;
|
||||
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "frameworks/base/libs/incident/proto/android/privacy.proto";
|
||||
|
||||
message RoleManagerServiceDumpProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
|
||||
// List of per-user states for all users.
|
||||
repeated RoleUserStateProto user_states = 1;
|
||||
}
|
||||
|
||||
message RoleUserStateProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
|
||||
// The user id of this state.
|
||||
optional int32 user_id = 1;
|
||||
|
||||
// The version of this state.
|
||||
optional int32 version = 2;
|
||||
|
||||
// The hash of packages for this state.
|
||||
optional string packages_hash = 3;
|
||||
|
||||
// The set of roles in this state.
|
||||
repeated RoleProto roles = 4;
|
||||
}
|
||||
|
||||
message RoleProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
|
||||
// The name of this role, e.g. "android.app.role.DIALER".
|
||||
optional string name = 1;
|
||||
|
||||
// The package names of the holders of this role.
|
||||
repeated string holders = 2;
|
||||
}
|
||||
@@ -41,17 +41,23 @@ import android.util.ArraySet;
|
||||
import android.util.PackageUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
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.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -130,11 +136,11 @@ public class RoleManagerService extends SystemService {
|
||||
userState = getUserStateLocked(userId);
|
||||
}
|
||||
String packagesHash = computeComponentStateHash(userId);
|
||||
String lastGrantPackagesHash;
|
||||
String oldPackagesHash;
|
||||
synchronized (mLock) {
|
||||
lastGrantPackagesHash = userState.getLastGrantPackagesHashLocked();
|
||||
oldPackagesHash = userState.getPackagesHashLocked();
|
||||
}
|
||||
boolean needGrant = !Objects.equals(packagesHash, lastGrantPackagesHash);
|
||||
boolean needGrant = !Objects.equals(packagesHash, oldPackagesHash);
|
||||
if (needGrant) {
|
||||
// Some vital packages state has changed since last role grant
|
||||
// Run grants again
|
||||
@@ -154,7 +160,7 @@ public class RoleManagerService extends SystemService {
|
||||
try {
|
||||
result.get(5, TimeUnit.SECONDS);
|
||||
synchronized (mLock) {
|
||||
userState.setLastGrantPackagesHashLocked(packagesHash);
|
||||
userState.setPackagesHashLocked(packagesHash);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
|
||||
@@ -222,7 +228,7 @@ public class RoleManagerService extends SystemService {
|
||||
mControllerServices.remove(userId);
|
||||
RoleUserState userState = mUserStates.removeReturnOld(userId);
|
||||
if (userState != null) {
|
||||
userState.destroySyncLocked();
|
||||
userState.destroyLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,5 +399,36 @@ public class RoleManagerService extends SystemService {
|
||||
new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback,
|
||||
resultReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
|
||||
@Nullable String[] args) {
|
||||
if (!DumpUtils.checkDumpPermission(getContext(), LOG_TAG, fout)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
|
||||
DualDumpOutputStream dumpOutputStream;
|
||||
if (dumpAsProto) {
|
||||
dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(fd));
|
||||
} else {
|
||||
fout.println("ROLE MANAGER STATE (dumpsys role):");
|
||||
dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " "));
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
int[] userIds = mUserManagerInternal.getUserIds();
|
||||
int userIdsLength = userIds.length;
|
||||
for (int i = 0; i < userIdsLength; i++) {
|
||||
int userId = userIds[i];
|
||||
|
||||
RoleUserState userState = getUserStateLocked(userId);
|
||||
userState.dumpLocked(dumpOutputStream, "user_states",
|
||||
RoleManagerServiceDumpProto.USER_STATES);
|
||||
}
|
||||
}
|
||||
|
||||
dumpOutputStream.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.util.Xml;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.internal.util.dump.DualDumpOutputStream;
|
||||
import com.android.internal.util.function.pooled.PooledLambda;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
@@ -78,7 +79,7 @@ public class RoleUserState {
|
||||
|
||||
@GuardedBy("RoleManagerService.mLock")
|
||||
@Nullable
|
||||
private String mLastGrantPackagesHash;
|
||||
private String mPackagesHash;
|
||||
|
||||
/**
|
||||
* Maps role names to its holders' package names. The values should never be null.
|
||||
@@ -99,7 +100,7 @@ public class RoleUserState {
|
||||
private RoleUserState(@UserIdInt int userId) {
|
||||
mUserId = userId;
|
||||
|
||||
readSyncLocked();
|
||||
readLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,22 +145,22 @@ public class RoleUserState {
|
||||
* @return the hash representing the state of packages
|
||||
*/
|
||||
@GuardedBy("RoleManagerService.mLock")
|
||||
public String getLastGrantPackagesHashLocked() {
|
||||
return mLastGrantPackagesHash;
|
||||
public String getPackagesHashLocked() {
|
||||
return mPackagesHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hash representing the state of packages during the last time initial grants was run.
|
||||
*
|
||||
* @param lastGrantPackagesHash the hash representing the state of packages
|
||||
* @param packagesHash the hash representing the state of packages
|
||||
*/
|
||||
@GuardedBy("RoleManagerService.mLock")
|
||||
public void setLastGrantPackagesHashLocked(@Nullable String lastGrantPackagesHash) {
|
||||
public void setPackagesHashLocked(@Nullable String packagesHash) {
|
||||
throwIfDestroyedLocked();
|
||||
if (Objects.equals(mLastGrantPackagesHash, lastGrantPackagesHash)) {
|
||||
if (Objects.equals(mPackagesHash, packagesHash)) {
|
||||
return;
|
||||
}
|
||||
mLastGrantPackagesHash = lastGrantPackagesHash;
|
||||
mPackagesHash = packagesHash;
|
||||
writeAsyncLocked();
|
||||
}
|
||||
|
||||
@@ -311,7 +312,7 @@ public class RoleUserState {
|
||||
}
|
||||
|
||||
mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeSync, this,
|
||||
mVersion, mLastGrantPackagesHash, roles), writeDelayMillis);
|
||||
mVersion, mPackagesHash, roles), writeDelayMillis);
|
||||
Slog.i(LOG_TAG, "Scheduled writing roles.xml");
|
||||
}
|
||||
|
||||
@@ -385,7 +386,7 @@ public class RoleUserState {
|
||||
* Read the state from file.
|
||||
*/
|
||||
@GuardedBy("RoleManagerService.mLock")
|
||||
private void readSyncLocked() {
|
||||
private void readLocked() {
|
||||
File file = getFile(mUserId);
|
||||
try (FileInputStream in = new AtomicFile(file).openRead()) {
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
@@ -421,7 +422,7 @@ public class RoleUserState {
|
||||
private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
|
||||
XmlPullParserException {
|
||||
mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
|
||||
mLastGrantPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
|
||||
mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
|
||||
mRoles.clear();
|
||||
|
||||
int type;
|
||||
@@ -464,12 +465,48 @@ public class RoleUserState {
|
||||
return roleHolders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump this user state.
|
||||
*
|
||||
* @param dumpOutputStream the output stream to dump to
|
||||
*/
|
||||
@GuardedBy("RoleManagerService.mLock")
|
||||
public void dumpLocked(@NonNull DualDumpOutputStream dumpOutputStream,
|
||||
@NonNull String fieldName, long fieldId) {
|
||||
throwIfDestroyedLocked();
|
||||
|
||||
long fieldToken = dumpOutputStream.start(fieldName, fieldId);
|
||||
dumpOutputStream.write("user_id", RoleUserStateProto.USER_ID, mUserId);
|
||||
dumpOutputStream.write("version", RoleUserStateProto.VERSION, mVersion);
|
||||
dumpOutputStream.write("packages_hash", RoleUserStateProto.PACKAGES_HASH, mPackagesHash);
|
||||
|
||||
int rolesSize = mRoles.size();
|
||||
for (int rolesIndex = 0; rolesIndex < rolesSize; rolesIndex++) {
|
||||
String roleName = mRoles.keyAt(rolesIndex);
|
||||
ArraySet<String> roleHolders = mRoles.valueAt(rolesIndex);
|
||||
|
||||
long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES);
|
||||
dumpOutputStream.write("name", RoleProto.NAME, roleName);
|
||||
|
||||
int roleHoldersSize = roleHolders.size();
|
||||
for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) {
|
||||
String roleHolder = roleHolders.valueAt(roleHoldersIndex);
|
||||
|
||||
dumpOutputStream.write("holders", RoleProto.HOLDERS, roleHolder);
|
||||
}
|
||||
|
||||
dumpOutputStream.end(rolesToken);
|
||||
}
|
||||
|
||||
dumpOutputStream.end(fieldToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy this state and delete the corresponding file. Any pending writes to the file will be
|
||||
* cancelled and any future interaction with this state will throw an exception.
|
||||
*/
|
||||
@GuardedBy("RoleManagerService.mLock")
|
||||
public void destroySyncLocked() {
|
||||
public void destroyLocked() {
|
||||
throwIfDestroyedLocked();
|
||||
mWriteHandler.removeCallbacksAndMessages(null);
|
||||
getFile(mUserId).delete();
|
||||
|
||||
Reference in New Issue
Block a user