Loading core/proto/android/os/incident.proto +6 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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; } core/proto/android/server/rolemanagerservice.proto 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * 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; } services/core/java/com/android/server/role/RoleManagerService.java +42 −5 Original line number Diff line number Diff line Loading @@ -42,17 +42,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; Loading Loading @@ -154,11 +160,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 Loading @@ -178,7 +184,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); Loading Loading @@ -246,7 +252,7 @@ public class RoleManagerService extends SystemService { mControllerServices.remove(userId); RoleUserState userState = mUserStates.removeReturnOld(userId); if (userState != null) { userState.destroySyncLocked(); userState.destroyLocked(); } } } Loading Loading @@ -417,5 +423,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(); } } } services/core/java/com/android/server/role/RoleUserState.java +49 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -99,7 +100,7 @@ public class RoleUserState { private RoleUserState(@UserIdInt int userId) { mUserId = userId; readSyncLocked(); readLocked(); } /** Loading Loading @@ -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(); } Loading Loading @@ -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"); } Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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(); Loading Loading
core/proto/android/os/incident.proto +6 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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; }
core/proto/android/server/rolemanagerservice.proto 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * 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; }
services/core/java/com/android/server/role/RoleManagerService.java +42 −5 Original line number Diff line number Diff line Loading @@ -42,17 +42,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; Loading Loading @@ -154,11 +160,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 Loading @@ -178,7 +184,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); Loading Loading @@ -246,7 +252,7 @@ public class RoleManagerService extends SystemService { mControllerServices.remove(userId); RoleUserState userState = mUserStates.removeReturnOld(userId); if (userState != null) { userState.destroySyncLocked(); userState.destroyLocked(); } } } Loading Loading @@ -417,5 +423,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(); } } }
services/core/java/com/android/server/role/RoleUserState.java +49 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -99,7 +100,7 @@ public class RoleUserState { private RoleUserState(@UserIdInt int userId) { mUserId = userId; readSyncLocked(); readLocked(); } /** Loading Loading @@ -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(); } Loading Loading @@ -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"); } Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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(); Loading