summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/UserJourneyLogger.java64
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java28
3 files changed, 96 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/pm/UserJourneyLogger.java b/services/core/java/com/android/server/pm/UserJourneyLogger.java
index f48a1669c259..895edce093b5 100644
--- a/services/core/java/com/android/server/pm/UserJourneyLogger.java
+++ b/services/core/java/com/android/server/pm/UserJourneyLogger.java
@@ -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);
}
/**
@@ -452,6 +456,29 @@ public class UserJourneyLogger {
}
/**
+ * 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.
*/
@@ -533,6 +560,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.
*
* <p> User journey tracks a chain of user lifecycle events occurring during different user
@@ -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;
}
}
-}
+} \ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4ef68d8f5aaf..4e043aae4f09 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -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) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java
index 20e2692cb747..bfd407216c3b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java
@@ -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);
}
}
-}
+} \ No newline at end of file