diff options
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerInternal.java | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 43 |
2 files changed, 62 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index 47d0a3d561b1..c182d685c247 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -57,6 +57,20 @@ public abstract class UserManagerInternal { } /** + * Listener for user lifecycle events. + * + * <p><b>NOTE: </b>implementations MUST not block the current thread. + */ + public interface UserLifecycleListener { + + /** Called when a new user is created. */ + default void onUserCreated(UserInfo user) {} + + /** Called when an existing user is removed. */ + default void onUserRemoved(UserInfo user) {} + } + + /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set * restrictions enforced by the user. * @@ -97,6 +111,12 @@ public abstract class UserManagerInternal { /** Remove a {@link UserRestrictionsListener}. */ public abstract void removeUserRestrictionsListener(UserRestrictionsListener listener); + /** Adds a {@link UserLifecycleListener}. */ + public abstract void addUserLifecycleListener(UserLifecycleListener listener); + + /** Removes a {@link UserLifecycleListener}. */ + public abstract void removeUserLifecycleListener(UserLifecycleListener listener); + /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update * whether the device is managed by device owner. diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index cc814bcc7760..0597ea54e28a 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -110,6 +110,7 @@ import com.android.server.LocalServices; import com.android.server.LockGuard; import com.android.server.SystemService; import com.android.server.am.UserState; +import com.android.server.pm.UserManagerInternal.UserLifecycleListener; import com.android.server.pm.UserManagerInternal.UserRestrictionsListener; import com.android.server.storage.DeviceStorageMonitorInternal; import com.android.server.utils.TimingsTraceAndSlog; @@ -438,6 +439,9 @@ public class UserManagerService extends IUserManager.Stub { private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners = new ArrayList<>(); + @GuardedBy("mUserRemovedListeners") + private final ArrayList<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>(); + private final LockPatternUtils mLockPatternUtils; private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK = @@ -3645,6 +3649,14 @@ public class UserManagerService extends IUserManager.Stub { } private void dispatchUserAdded(@NonNull UserInfo userInfo) { + // Notify internal listeners first... + synchronized (mUserLifecycleListeners) { + for (int i = 0; i < mUserLifecycleListeners.size(); i++) { + mUserLifecycleListeners.get(i).onUserCreated(userInfo); + } + } + + //...then external ones Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id); // Also, add the UserHandle for mainline modules which can't use the @hide @@ -4030,13 +4042,19 @@ public class UserManagerService extends IUserManager.Stub { user = getUserInfoLU(userId); } if (user != null && user.preCreated) { - Slog.i(LOG_TAG, "Removing a precreated user with user id: " + userId); + Slog.i(LOG_TAG, "Removing a pre-created user with user id: " + userId); // Don't want to fire ACTION_USER_REMOVED, so cleanup the state and exit early. LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId); removeUserState(userId); return; } + synchronized (mUserLifecycleListeners) { + for (int i = 0; i < mUserLifecycleListeners.size(); i++) { + mUserLifecycleListeners.get(i).onUserRemoved(user); + } + } + // Let other services shutdown any activity and clean up their state before completely // wiping the user's system directory and removing from the user list final long ident = Binder.clearCallingIdentity(); @@ -4973,6 +4991,15 @@ public class UserManagerService extends IUserManager.Stub { pw.println(" System user allocations: " + mUser0Allocations.get()); } + pw.println(); + pw.println("Number of listeners for"); + synchronized (mUserRestrictionsListeners) { + pw.println(" restrictions: " + mUserRestrictionsListeners.size()); + } + synchronized (mUserLifecycleListeners) { + pw.println(" user lifecycle events: " + mUserLifecycleListeners.size()); + } + // Dump UserTypes pw.println(); pw.println("User types version: " + mUserTypeVersion); @@ -5091,6 +5118,20 @@ public class UserManagerService extends IUserManager.Stub { } @Override + public void addUserLifecycleListener(UserLifecycleListener listener) { + synchronized (mUserLifecycleListeners) { + mUserLifecycleListeners.add(listener); + } + } + + @Override + public void removeUserLifecycleListener(UserLifecycleListener listener) { + synchronized (mUserLifecycleListeners) { + mUserLifecycleListeners.remove(listener); + } + } + + @Override public void setDeviceManaged(boolean isManaged) { synchronized (mUsersLock) { mIsDeviceManaged = isManaged; |