Merge "Add elapsed time to user journey report and user lifecycle journey (from create to delete)" into udc-dev

This commit is contained in:
Anna Bauza
2023-05-12 05:47:28 +00:00
committed by Android (Google) Code Review
3 changed files with 96 additions and 9 deletions

View File

@@ -99,6 +99,8 @@ public class UserJourneyLogger {
FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN;
public static final int USER_JOURNEY_REVOKE_ADMIN =
FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN;
public static final int USER_JOURNEY_USER_LIFECYCLE =
FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_LIFECYCLE;
@IntDef(prefix = {"USER_JOURNEY"}, value = {
USER_JOURNEY_UNKNOWN,
@@ -109,7 +111,8 @@ public class UserJourneyLogger {
USER_JOURNEY_USER_CREATE,
USER_JOURNEY_USER_REMOVE,
USER_JOURNEY_GRANT_ADMIN,
USER_JOURNEY_REVOKE_ADMIN
USER_JOURNEY_REVOKE_ADMIN,
USER_JOURNEY_USER_LIFECYCLE
})
public @interface UserJourney {
}
@@ -272,11 +275,12 @@ public class UserJourneyLogger {
int userType, int userFlags, @UserJourneyErrorCode int errorCode) {
if (session == null) {
writeUserLifecycleJourneyReported(-1, journey, originalUserId, targetUserId,
userType, userFlags, ERROR_CODE_INVALID_SESSION_ID);
userType, userFlags, ERROR_CODE_INVALID_SESSION_ID, -1);
} else {
final long elapsedTime = System.currentTimeMillis() - session.mStartTimeInMills;
writeUserLifecycleJourneyReported(
session.mSessionId, journey, originalUserId, targetUserId, userType, userFlags,
errorCode);
errorCode, elapsedTime);
}
}
@@ -285,10 +289,10 @@ public class UserJourneyLogger {
*/
@VisibleForTesting
public void writeUserLifecycleJourneyReported(long sessionId, int journey, int originalUserId,
int targetUserId, int userType, int userFlags, int errorCode) {
int targetUserId, int userType, int userFlags, int errorCode, long elapsedTime) {
FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED,
sessionId, journey, originalUserId, targetUserId, userType, userFlags,
errorCode);
errorCode, elapsedTime);
}
/**
@@ -451,6 +455,29 @@ public class UserJourneyLogger {
return null;
}
/**
* Log user journey event and report finishing with error
*/
public UserJourneySession logDelayedUserJourneyFinishWithError(@UserIdInt int originalUserId,
UserInfo targetUser, @UserJourney int journey, @UserJourneyErrorCode int errorCode) {
synchronized (mLock) {
final int key = getUserJourneyKey(targetUser.id, journey);
final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(key);
if (userJourneySession != null) {
logUserLifecycleJourneyReported(
userJourneySession,
journey, originalUserId, targetUser.id,
getUserTypeForStatsd(targetUser.userType),
targetUser.flags,
errorCode);
mUserIdToUserJourneyMap.remove(key);
return userJourneySession;
}
}
return null;
}
/**
* Log event and report finish when user is null. This is edge case when UserInfo
* can not be passed because it is null, therefore all information are passed as arguments.
@@ -532,6 +559,23 @@ public class UserJourneyLogger {
}
}
/**
* This keeps the start time when finishing extensively long journey was began.
* For instance full user lifecycle ( from creation to deletion )when user is about to delete
* we need to get user creation time before it was deleted.
*/
public UserJourneySession startSessionForDelayedJourney(@UserIdInt int targetId,
@UserJourney int journey, long startTime) {
final long newSessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE);
synchronized (mLock) {
final int key = getUserJourneyKey(targetId, journey);
final UserJourneySession userJourneySession =
new UserJourneySession(newSessionId, journey, startTime);
mUserIdToUserJourneyMap.append(key, userJourneySession);
return userJourneySession;
}
}
/**
* Helper class to store user journey and session id.
*
@@ -542,11 +586,19 @@ public class UserJourneyLogger {
public final long mSessionId;
@UserJourney
public final int mJourney;
public long mStartTimeInMills;
@VisibleForTesting
public UserJourneySession(long sessionId, @UserJourney int journey) {
mJourney = journey;
mSessionId = sessionId;
mStartTimeInMills = System.currentTimeMillis();
}
@VisibleForTesting
public UserJourneySession(long sessionId, @UserJourney int journey, long startTimeInMills) {
mJourney = journey;
mSessionId = sessionId;
mStartTimeInMills = startTimeInMills;
}
}
}
}

View File

@@ -30,6 +30,7 @@ import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_USER_IS_NOT_AN_
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_GRANT_ADMIN;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_REVOKE_ADMIN;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_CREATE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_LIFECYCLE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_REMOVE;
import android.Manifest;
@@ -3332,7 +3333,7 @@ public class UserManagerService extends IUserManager.Stub {
}
/**
* Enforces that only the system UID or root's UID or apps that have the
* Enforces that only the system UID or root's UID or apps that have the
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
* can make certain calls to the UserManager.
@@ -5535,6 +5536,8 @@ public class UserManagerService extends IUserManager.Stub {
}
mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_USER_REMOVE);
mUserJourneyLogger.startSessionForDelayedJourney(userId,
USER_JOURNEY_USER_LIFECYCLE, userData.info.creationTime);
try {
mAppOpsService.removeUser(userId);
@@ -5560,6 +5563,10 @@ public class UserManagerService extends IUserManager.Stub {
mUserJourneyLogger.logUserJourneyFinishWithError(originUserId,
userData.info, USER_JOURNEY_USER_REMOVE,
ERROR_CODE_UNSPECIFIED);
mUserJourneyLogger
.logDelayedUserJourneyFinishWithError(originUserId,
userData.info, USER_JOURNEY_USER_LIFECYCLE,
ERROR_CODE_UNSPECIFIED);
}
@Override
public void userStopAborted(int userIdParam) {
@@ -5567,6 +5574,10 @@ public class UserManagerService extends IUserManager.Stub {
mUserJourneyLogger.logUserJourneyFinishWithError(originUserId,
userData.info, USER_JOURNEY_USER_REMOVE,
ERROR_CODE_ABORTED);
mUserJourneyLogger
.logDelayedUserJourneyFinishWithError(originUserId,
userData.info, USER_JOURNEY_USER_LIFECYCLE,
ERROR_CODE_ABORTED);
}
});
} catch (RemoteException e) {

View File

@@ -27,6 +27,7 @@ import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_FINISH;
import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_NONE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_GRANT_ADMIN;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_CREATE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_LIFECYCLE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_REMOVE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_START;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_STOP;
@@ -499,6 +500,27 @@ public class UserJourneyLoggerTest {
0x00000402, ERROR_CODE_UNSPECIFIED, 3);
}
@Test
public void testUserLifecycleJourney() {
final long startTime = System.currentTimeMillis();
final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
.startSessionForDelayedJourney(10, USER_JOURNEY_USER_LIFECYCLE, startTime);
final UserLifecycleJourneyReportedCaptor report = new UserLifecycleJourneyReportedCaptor();
final UserInfo targetUser = new UserInfo(10, "test target user",
UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
mUserJourneyLogger.logDelayedUserJourneyFinishWithError(0, targetUser,
USER_JOURNEY_USER_LIFECYCLE, ERROR_CODE_UNSPECIFIED);
report.captureAndAssert(mUserJourneyLogger, session.mSessionId,
USER_JOURNEY_USER_LIFECYCLE, 0, 10,
FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
0x00000402, ERROR_CODE_UNSPECIFIED, 1);
assertThat(report.mElapsedTime.getValue() > 0L).isTrue();
}
static class UserLifecycleJourneyReportedCaptor {
ArgumentCaptor<Long> mSessionId = ArgumentCaptor.forClass(Long.class);
ArgumentCaptor<Integer> mJourney = ArgumentCaptor.forClass(Integer.class);
@@ -507,6 +529,7 @@ public class UserJourneyLoggerTest {
ArgumentCaptor<Integer> mUserType = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Integer> mUserFlags = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Integer> mErrorCode = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Long> mElapsedTime = ArgumentCaptor.forClass(Long.class);
public void captureAndAssert(UserJourneyLogger mUserJourneyLogger,
long sessionId, int journey, int originalUserId,
@@ -518,7 +541,8 @@ public class UserJourneyLoggerTest {
mTargetUserId.capture(),
mUserType.capture(),
mUserFlags.capture(),
mErrorCode.capture());
mErrorCode.capture(),
mElapsedTime.capture());
assertThat(mSessionId.getValue()).isEqualTo(sessionId);
assertThat(mJourney.getValue()).isEqualTo(journey);
@@ -577,4 +601,4 @@ public class UserJourneyLoggerTest {
state, errorCode, 1);
}
}
}
}