Merge "Cache the UserInfo for the system user on UserManagerService."

This commit is contained in:
TreeHugger Robot
2020-08-19 00:54:31 +00:00
committed by Android (Google) Code Review

View File

@@ -84,6 +84,7 @@ import android.os.storage.StorageManager;
import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -141,7 +142,6 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Service for {@link UserManager}.
@@ -159,6 +159,10 @@ public class UserManagerService extends IUserManager.Stub {
private static final String LOG_TAG = "UserManagerService";
static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE
// TODO(b/164159026): remove once owner_name issue on automotive is fixed
// Can be used to track getUsers() / userWithNameLU() behavior
public static final boolean DBG_CACHED_USERINFOS = false; // DO NOT SUBMIT WITH TRUE
// Can be used for manual testing of id recycling
private static final boolean RELEASE_DELETED_USER_ID = false; // DO NOT SUBMIT WITH TRUE
@@ -271,6 +275,25 @@ public class UserManagerService extends IUserManager.Stub {
private PackageManagerInternal mPmInternal;
private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
/**
* Reference to the {@link UserHandle#SYSTEM} user's UserInfo; it's {@code name} was either
* manually set, or it's {@code null}.
*
* <p>The reference is set just once, but it's {@code name} is updated when it's manually set.
*/
@GuardedBy("mUsersLock")
private UserInfo mSystemUserInfo;
/**
* Reference to the {@link UserHandle#SYSTEM} user's UserInfo, with its {@code name} set to
* the localized value of {@code owner_name}.
*
* <p>The reference is set just once, but it's {@code name} is updated everytime the reference
* is used and the locale changed.
*/
@GuardedBy("mUsersLock")
private UserInfo mSystemUserInfoWithName;
/**
* Internal non-parcelable wrapper for UserInfo that is not exposed to other system apps.
*/
@@ -444,11 +467,6 @@ public class UserManagerService extends IUserManager.Stub {
}
};
// TODO(b/161915546): remove once userWithName() is fixed / removed
// Use to debug / dump when user 0 is allocated at userWithName()
public static final boolean DBG_ALLOCATION = false; // DO NOT SUBMIT WITH TRUE
public final AtomicInteger mUser0Allocations;
/**
* Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
*
@@ -638,7 +656,6 @@ public class UserManagerService extends IUserManager.Stub {
LocalServices.addService(UserManagerInternal.class, mLocalService);
mLockPatternUtils = new LockPatternUtils(mContext);
mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
mUser0Allocations = DBG_ALLOCATION ? new AtomicInteger() : null;
}
void systemReady() {
@@ -784,7 +801,7 @@ public class UserManagerService extends IUserManager.Stub {
|| (excludePreCreated && ui.preCreated)) {
continue;
}
users.add(userWithName(ui));
users.add(userWithNameLU(ui));
}
return users;
}
@@ -853,7 +870,7 @@ public class UserManagerService extends IUserManager.Stub {
userInfo.name = null;
userInfo.iconPath = null;
} else {
userInfo = userWithName(userInfo);
userInfo = userWithNameLU(userInfo);
}
users.add(userInfo);
}
@@ -1310,26 +1327,57 @@ public class UserManagerService extends IUserManager.Stub {
public UserInfo getUserInfo(@UserIdInt int userId) {
checkManageOrCreateUsersPermission("query user");
synchronized (mUsersLock) {
return userWithName(getUserInfoLU(userId));
return userWithNameLU(getUserInfoLU(userId));
}
}
/**
* Returns a UserInfo object with the name filled in, for Owner, or the original
* if the name is already set.
*
* <p>Note:</p> the Owner name is localized, so the current value must be checked every time
* this method is called.
*/
private UserInfo userWithName(UserInfo orig) {
if (orig != null && orig.name == null && orig.id == UserHandle.USER_SYSTEM) {
if (DBG_ALLOCATION) {
final int number = mUser0Allocations.incrementAndGet();
Slog.w(LOG_TAG, "System user instantiated at least " + number + " times");
private UserInfo userWithNameLU(UserInfo orig) {
// Only the system user uses the owner_name string.
if (orig == null || orig.id != UserHandle.USER_SYSTEM) return orig;
if (mSystemUserInfo == null) {
mSystemUserInfo = orig;
if (DBG_CACHED_USERINFOS) {
Slog.d(LOG_TAG, "Set mSystemUserInfo:" + mSystemUserInfo.toFullString());
}
UserInfo withName = new UserInfo(orig);
withName.name = getOwnerName();
return withName;
} else {
return orig;
}
if (mSystemUserInfo.name != null) {
if (DBG_CACHED_USERINFOS) {
Slog.v(LOG_TAG, "Returning mSystemUserInfo: " + mSystemUserInfo.toFullString());
}
return mSystemUserInfo;
}
final String ownerName = getOwnerName();
if (mSystemUserInfoWithName == null) {
mSystemUserInfoWithName = new UserInfo(orig);
mSystemUserInfoWithName.name = ownerName;
if (DBG_CACHED_USERINFOS) {
Slog.d(LOG_TAG, "Set mSystemUserInfoWithName: "
+ mSystemUserInfoWithName.toFullString());
}
} else if (!TextUtils.equals(ownerName, mSystemUserInfoWithName.name)) {
if (DBG_CACHED_USERINFOS) {
Slog.d(LOG_TAG, "Updating mSystemUserInfoWithName.name from "
+ mSystemUserInfoWithName.name + " to " + ownerName);
}
mSystemUserInfoWithName.name = ownerName;
}
if (DBG_CACHED_USERINFOS) {
Slog.v(LOG_TAG, "Returning mSystemUserInfoWithName:"
+ mSystemUserInfoWithName.toFullString());
}
return mSystemUserInfoWithName;
}
/** Returns whether the given user type is one of the FULL user types. */
@@ -1482,7 +1530,7 @@ public class UserManagerService extends IUserManager.Stub {
}
final int userId = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mUsersLock) {
UserInfo userInfo = userWithName(getUserInfoLU(userId));
UserInfo userInfo = userWithNameLU(getUserInfoLU(userId));
return userInfo == null ? "" : userInfo.name;
}
}
@@ -1597,6 +1645,13 @@ public class UserManagerService extends IUserManager.Stub {
Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
return null;
}
if (DBG_CACHED_USERINFOS && userId == UserHandle.USER_SYSTEM && userData != null
&& userData.info != mSystemUserInfo) {
Slog.wtf(LOG_TAG, "getUserInfoLU(): system user on userData (" + userData.info
+ ") is not the same as mSystemUserInfo (" + mSystemUserInfo + ")");
}
return userData != null ? userData.info : null;
}
@@ -4855,8 +4910,15 @@ public class UserManagerService extends IUserManager.Stub {
pw.println(" Is headless-system mode: " + UserManager.isHeadlessSystemUserMode());
pw.println(" User version: " + mUserVersion);
pw.println(" Owner name: " + getOwnerName());
if (DBG_ALLOCATION) {
pw.println(" System user allocations: " + mUser0Allocations.get());
if (mSystemUserInfo == null) {
pw.println(" (mSystemUserInfo not set)");
} else {
pw.println(" System user: " + mSystemUserInfo.toFullString());
}
if (mSystemUserInfoWithName == null) {
pw.println(" (mSystemUserInfoWithName not set)");
} else {
pw.println(" System user (with name): " + mSystemUserInfoWithName.toFullString());
}
// Dump UserTypes