Loading services/core/java/com/android/server/location/LocationManagerService.java +53 −22 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ import static android.os.PowerManager.locationPowerSaveModeToString; import static com.android.server.location.CallerIdentity.PERMISSION_COARSE; import static com.android.server.location.CallerIdentity.PERMISSION_FINE; import static com.android.server.location.UserInfoHelper.UserListener.CURRENT_USER_CHANGED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STARTED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STOPPED; import static java.util.concurrent.TimeUnit.NANOSECONDS; Loading Loading @@ -101,7 +104,7 @@ import com.android.server.location.AbstractLocationProvider.State; import com.android.server.location.CallerIdentity.PermissionLevel; import com.android.server.location.LocationRequestStatistics.PackageProviderKey; import com.android.server.location.LocationRequestStatistics.PackageStatistics; import com.android.server.location.UserInfoHelper.UserListener; import com.android.server.location.UserInfoHelper.UserListener.UserChange; import com.android.server.location.gnss.GnssManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; Loading Loading @@ -132,11 +135,13 @@ public class LocationManagerService extends ILocationManager.Stub { */ public static class Lifecycle extends SystemService { private final UserInfoHelper mUserInfoHelper; private final LocationManagerService mService; public Lifecycle(Context context) { super(context); mService = new LocationManagerService(context); mUserInfoHelper = new SystemUserInfoHelper(context); mService = new LocationManagerService(context, mUserInfoHelper); } @Override Loading @@ -161,6 +166,29 @@ public class LocationManagerService extends ILocationManager.Stub { mService.onSystemThirdPartyAppsCanStart(); } } @Override public void onUserStarting(TargetUser user) { mUserInfoHelper.dispatchOnUserStarted(user.getUserIdentifier()); } @Override public void onUserSwitching(TargetUser from, TargetUser to) { mUserInfoHelper.dispatchOnCurrentUserChanged(from.getUserIdentifier(), to.getUserIdentifier()); } @Override public void onUserStopped(TargetUser user) { mUserInfoHelper.dispatchOnUserStopped(user.getUserIdentifier()); } private static class SystemUserInfoHelper extends UserInfoHelper { SystemUserInfoHelper(Context context) { super(context); } } } public static final String TAG = "LocationManagerService"; Loading Loading @@ -232,7 +260,7 @@ public class LocationManagerService extends ILocationManager.Stub { @PowerManager.LocationPowerSaveMode private int mBatterySaverMode; private LocationManagerService(Context context) { private LocationManagerService(Context context, UserInfoHelper userInfoHelper) { mContext = context.createAttributionContext(ATTRIBUTION_TAG); mHandler = FgThread.getHandler(); mLocalService = new LocalService(); Loading @@ -240,7 +268,7 @@ public class LocationManagerService extends ILocationManager.Stub { LocalServices.addService(LocationManagerInternal.class, mLocalService); mAppOpsHelper = new AppOpsHelper(mContext); mUserInfoHelper = new UserInfoHelper(mContext); mUserInfoHelper = userInfoHelper; mSettingsHelper = new SettingsHelper(mContext, mHandler); mAppForegroundHelper = new AppForegroundHelper(mContext); mLocationUsageLogger = new LocationUsageLogger(); Loading Loading @@ -342,7 +370,7 @@ public class LocationManagerService extends ILocationManager.Stub { // initialize the current users. we would get the user started notifications for these // users eventually anyways, but this takes care of it as early as possible. for (int userId: mUserInfoHelper.getCurrentUserIds()) { onUserChanged(userId, UserListener.USER_STARTED); onUserChanged(userId, USER_STARTED); } } } Loading Loading @@ -596,32 +624,23 @@ public class LocationManagerService extends ILocationManager.Stub { } } private void onUserChanged(@UserIdInt int userId, @UserListener.UserChange int change) { private void onUserChanged(@UserIdInt int userId, @UserChange int change) { switch (change) { case UserListener.USER_SWITCHED: if (D) { Log.d(TAG, "user " + userId + " current status changed"); } case CURRENT_USER_CHANGED: synchronized (mLock) { for (LocationProviderManager manager : mProviderManagers) { manager.onEnabledChangedLocked(userId); } } break; case UserListener.USER_STARTED: if (D) { Log.d(TAG, "user " + userId + " started"); } case USER_STARTED: synchronized (mLock) { for (LocationProviderManager manager : mProviderManagers) { manager.onUserStarted(userId); } } break; case UserListener.USER_STOPPED: if (D) { Log.d(TAG, "user " + userId + " stopped"); } case USER_STOPPED: synchronized (mLock) { for (LocationProviderManager manager : mProviderManagers) { manager.onUserStopped(userId); Loading Loading @@ -957,10 +976,22 @@ public class LocationManagerService extends ILocationManager.Stub { pw.increaseIndent(); // for now we only dump for the parent user int userId = mUserInfoHelper.getCurrentUserIds()[0]; int[] userIds = mUserInfoHelper.getCurrentUserIds(); if (userIds.length == 1) { int userId = userIds[0]; pw.println("last location=" + mLastLocation.get(userId)); pw.println("last coarse location=" + mLastCoarseLocation.get(userId)); pw.println("enabled=" + isEnabled(userId)); } else { for (int userId : userIds) { pw.println("user " + userId + ":"); pw.increaseIndent(); pw.println("last location=" + mLastLocation.get(userId)); pw.println("last coarse location=" + mLastCoarseLocation.get(userId)); pw.println("enabled=" + isEnabled(userId)); pw.decreaseIndent(); } } } mProvider.dump(fd, pw, args); Loading services/core/java/com/android/server/location/UserInfoHelper.java +82 −131 Original line number Diff line number Diff line Loading @@ -20,48 +20,48 @@ import static android.os.UserManager.DISALLOW_SHARE_LOCATION; import static com.android.server.location.LocationManagerService.D; import static com.android.server.location.LocationManagerService.TAG; import static com.android.server.location.UserInfoHelper.UserListener.CURRENT_USER_CHANGED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STARTED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STOPPED; import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.app.ActivityManagerInternal; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.Build; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; import com.android.server.FgThread; import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; /** * Provides accessors and listeners for all user info. */ public class UserInfoHelper { public abstract class UserInfoHelper { /** * Listener for current user changes. */ public interface UserListener { int USER_SWITCHED = 1; int CURRENT_USER_CHANGED = 1; int USER_STARTED = 2; int USER_STOPPED = 3; @IntDef({USER_SWITCHED, USER_STARTED, USER_STOPPED}) @IntDef({CURRENT_USER_CHANGED, USER_STARTED, USER_STOPPED}) @Retention(RetentionPolicy.SOURCE) @interface UserChange {} Loading @@ -75,143 +75,101 @@ public class UserInfoHelper { private final CopyOnWriteArrayList<UserListener> mListeners; @GuardedBy("this") @Nullable private UserManager mUserManager; @UserIdInt private volatile int mCurrentUserId; @GuardedBy("this") @UserIdInt private int mCachedParentUserId; @Nullable private ActivityManagerInternal mActivityManagerInternal; @GuardedBy("this") private int[] mCachedProfileUserIds; @Nullable private UserManager mUserManager; public UserInfoHelper(Context context) { mContext = context; mListeners = new CopyOnWriteArrayList<>(); mCurrentUserId = UserHandle.USER_NULL; mCachedParentUserId = UserHandle.USER_NULL; mCachedProfileUserIds = new int[]{UserHandle.USER_NULL}; } /** Called when system is ready. */ @CallSuper public synchronized void onSystemReady() { if (mUserManager != null) { if (mActivityManagerInternal != null) { return; } mActivityManagerInternal = Objects.requireNonNull( LocalServices.getService(ActivityManagerInternal.class)); mUserManager = mContext.getSystemService(UserManager.class); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_USER_SWITCHED); intentFilter.addAction(Intent.ACTION_USER_STARTED); intentFilter.addAction(Intent.ACTION_USER_STOPPED); intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); mContext.registerReceiverAsUser(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == null) { return; } int userId; switch (action) { case Intent.ACTION_USER_SWITCHED: userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { onCurrentUserChanged(userId); } break; case Intent.ACTION_USER_STARTED: userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { onUserStarted(userId); } break; case Intent.ACTION_USER_STOPPED: userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { onUserStopped(userId); } break; case Intent.ACTION_MANAGED_PROFILE_ADDED: case Intent.ACTION_MANAGED_PROFILE_REMOVED: onUserProfilesChanged(); break; } } }, UserHandle.ALL, intentFilter, null, FgThread.getHandler()); mCurrentUserId = ActivityManager.getCurrentUser(); } /** * Adds a listener for user changed events. Callbacks occur on an unspecified thread. */ public void addListener(UserListener listener) { public final void addListener(UserListener listener) { mListeners.add(listener); } /** * Removes a listener for user changed events. */ public void removeListener(UserListener listener) { public final void removeListener(UserListener listener) { mListeners.remove(listener); } private void onCurrentUserChanged(@UserIdInt int newUserId) { if (newUserId == mCurrentUserId) { return; } protected void dispatchOnUserStarted(@UserIdInt int userId) { if (D) { Log.d(TAG, "current user switched from u" + mCurrentUserId + " to u" + newUserId); Log.d(TAG, "u" + userId + " started"); } int oldUserId = mCurrentUserId; mCurrentUserId = newUserId; onUserChanged(oldUserId, UserListener.USER_SWITCHED); onUserChanged(newUserId, UserListener.USER_SWITCHED); for (UserListener listener : mListeners) { listener.onUserChanged(userId, USER_STARTED); } } private void onUserStarted(@UserIdInt int userId) { protected void dispatchOnUserStopped(@UserIdInt int userId) { if (D) { Log.d(TAG, "u" + userId + " started"); Log.d(TAG, "u" + userId + " stopped"); } onUserChanged(userId, UserListener.USER_STARTED); for (UserListener listener : mListeners) { listener.onUserChanged(userId, USER_STOPPED); } private void onUserStopped(@UserIdInt int userId) { if (D) { Log.d(TAG, "u" + userId + " stopped"); } onUserChanged(userId, UserListener.USER_STOPPED); protected void dispatchOnCurrentUserChanged(@UserIdInt int fromUserId, @UserIdInt int toUserId) { int[] fromUserIds = getProfileIds(fromUserId); int[] toUserIds = getProfileIds(toUserId); if (D) { Log.d(TAG, "current user changed from u" + Arrays.toString(fromUserIds) + " to u" + Arrays.toString(toUserIds)); } private void onUserChanged(@UserIdInt int userId, @UserListener.UserChange int change) { for (UserListener listener : mListeners) { listener.onUserChanged(userId, change); for (int userId : fromUserIds) { listener.onUserChanged(userId, CURRENT_USER_CHANGED); } } private synchronized void onUserProfilesChanged() { // this intent is only sent to the current user if (mCachedParentUserId == mCurrentUserId) { mCachedParentUserId = UserHandle.USER_NULL; mCachedProfileUserIds = new int[]{UserHandle.USER_NULL}; for (UserListener listener : mListeners) { for (int userId : toUserIds) { listener.onUserChanged(userId, CURRENT_USER_CHANGED); } } } /** * Returns an array of current user ids. This will always include the current user, and will * also include any profiles of the current user. * also include any profiles of the current user. The caller must never mutate the returned * array. */ public int[] getCurrentUserIds() { return getProfileUserIdsForParentUser(mCurrentUserId); synchronized (this) { if (mActivityManagerInternal == null) { return new int[] {}; } } long identity = Binder.clearCallingIdentity(); try { return mActivityManagerInternal.getCurrentProfileIds(); } finally { Binder.restoreCallingIdentity(identity); } } /** Loading @@ -219,54 +177,47 @@ public class UserInfoHelper { * user. */ public boolean isCurrentUserId(@UserIdInt int userId) { int currentUserId = mCurrentUserId; return userId == currentUserId || ArrayUtils.contains( getProfileUserIdsForParentUser(currentUserId), userId); synchronized (this) { if (mActivityManagerInternal == null) { return false; } } @GuardedBy("this") private synchronized int[] getProfileUserIdsForParentUser(@UserIdInt int parentUserId) { if (parentUserId != mCachedParentUserId) { long identity = Binder.clearCallingIdentity(); try { Preconditions.checkState(mUserManager != null); return mActivityManagerInternal.isCurrentProfile(userId); } finally { Binder.restoreCallingIdentity(identity); } } // more expensive check - check that argument really is a parent user id if (Build.IS_DEBUGGABLE) { Preconditions.checkArgument( mUserManager.getProfileParent(parentUserId) == null); private int[] getProfileIds(@UserIdInt int userId) { synchronized (this) { Preconditions.checkState(mUserManager != null); } mCachedParentUserId = parentUserId; mCachedProfileUserIds = mUserManager.getProfileIdsWithDisabled(parentUserId); long identity = Binder.clearCallingIdentity(); try { return mUserManager.getEnabledProfileIds(userId); } finally { Binder.restoreCallingIdentity(identity); } } return mCachedProfileUserIds; } /** * Dump info for debugging. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { boolean systemRunning; synchronized (this) { systemRunning = mUserManager != null; } if (systemRunning) { int[] currentUserIds = getProfileUserIdsForParentUser(mCurrentUserId); pw.println("current users: " + Arrays.toString(currentUserIds)); for (int userId : currentUserIds) { if (mUserManager.hasUserRestrictionForUser(DISALLOW_SHARE_LOCATION, int[] currentUserProfiles = getCurrentUserIds(); pw.println("current users: " + Arrays.toString(currentUserProfiles)); UserManager userManager = mContext.getSystemService(UserManager.class); if (userManager != null) { for (int userId : currentUserProfiles) { if (userManager.hasUserRestrictionForUser(DISALLOW_SHARE_LOCATION, UserHandle.of(userId))) { pw.println(" u" + userId + " restricted"); } } } else { pw.println("current user: " + mCurrentUserId); } } } services/tests/mockingservicestests/src/com/android/server/location/UserInfoHelperTest.java +52 −93 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/location/LocationManagerService.java +53 −22 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ import static android.os.PowerManager.locationPowerSaveModeToString; import static com.android.server.location.CallerIdentity.PERMISSION_COARSE; import static com.android.server.location.CallerIdentity.PERMISSION_FINE; import static com.android.server.location.UserInfoHelper.UserListener.CURRENT_USER_CHANGED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STARTED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STOPPED; import static java.util.concurrent.TimeUnit.NANOSECONDS; Loading Loading @@ -101,7 +104,7 @@ import com.android.server.location.AbstractLocationProvider.State; import com.android.server.location.CallerIdentity.PermissionLevel; import com.android.server.location.LocationRequestStatistics.PackageProviderKey; import com.android.server.location.LocationRequestStatistics.PackageStatistics; import com.android.server.location.UserInfoHelper.UserListener; import com.android.server.location.UserInfoHelper.UserListener.UserChange; import com.android.server.location.gnss.GnssManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; Loading Loading @@ -132,11 +135,13 @@ public class LocationManagerService extends ILocationManager.Stub { */ public static class Lifecycle extends SystemService { private final UserInfoHelper mUserInfoHelper; private final LocationManagerService mService; public Lifecycle(Context context) { super(context); mService = new LocationManagerService(context); mUserInfoHelper = new SystemUserInfoHelper(context); mService = new LocationManagerService(context, mUserInfoHelper); } @Override Loading @@ -161,6 +166,29 @@ public class LocationManagerService extends ILocationManager.Stub { mService.onSystemThirdPartyAppsCanStart(); } } @Override public void onUserStarting(TargetUser user) { mUserInfoHelper.dispatchOnUserStarted(user.getUserIdentifier()); } @Override public void onUserSwitching(TargetUser from, TargetUser to) { mUserInfoHelper.dispatchOnCurrentUserChanged(from.getUserIdentifier(), to.getUserIdentifier()); } @Override public void onUserStopped(TargetUser user) { mUserInfoHelper.dispatchOnUserStopped(user.getUserIdentifier()); } private static class SystemUserInfoHelper extends UserInfoHelper { SystemUserInfoHelper(Context context) { super(context); } } } public static final String TAG = "LocationManagerService"; Loading Loading @@ -232,7 +260,7 @@ public class LocationManagerService extends ILocationManager.Stub { @PowerManager.LocationPowerSaveMode private int mBatterySaverMode; private LocationManagerService(Context context) { private LocationManagerService(Context context, UserInfoHelper userInfoHelper) { mContext = context.createAttributionContext(ATTRIBUTION_TAG); mHandler = FgThread.getHandler(); mLocalService = new LocalService(); Loading @@ -240,7 +268,7 @@ public class LocationManagerService extends ILocationManager.Stub { LocalServices.addService(LocationManagerInternal.class, mLocalService); mAppOpsHelper = new AppOpsHelper(mContext); mUserInfoHelper = new UserInfoHelper(mContext); mUserInfoHelper = userInfoHelper; mSettingsHelper = new SettingsHelper(mContext, mHandler); mAppForegroundHelper = new AppForegroundHelper(mContext); mLocationUsageLogger = new LocationUsageLogger(); Loading Loading @@ -342,7 +370,7 @@ public class LocationManagerService extends ILocationManager.Stub { // initialize the current users. we would get the user started notifications for these // users eventually anyways, but this takes care of it as early as possible. for (int userId: mUserInfoHelper.getCurrentUserIds()) { onUserChanged(userId, UserListener.USER_STARTED); onUserChanged(userId, USER_STARTED); } } } Loading Loading @@ -596,32 +624,23 @@ public class LocationManagerService extends ILocationManager.Stub { } } private void onUserChanged(@UserIdInt int userId, @UserListener.UserChange int change) { private void onUserChanged(@UserIdInt int userId, @UserChange int change) { switch (change) { case UserListener.USER_SWITCHED: if (D) { Log.d(TAG, "user " + userId + " current status changed"); } case CURRENT_USER_CHANGED: synchronized (mLock) { for (LocationProviderManager manager : mProviderManagers) { manager.onEnabledChangedLocked(userId); } } break; case UserListener.USER_STARTED: if (D) { Log.d(TAG, "user " + userId + " started"); } case USER_STARTED: synchronized (mLock) { for (LocationProviderManager manager : mProviderManagers) { manager.onUserStarted(userId); } } break; case UserListener.USER_STOPPED: if (D) { Log.d(TAG, "user " + userId + " stopped"); } case USER_STOPPED: synchronized (mLock) { for (LocationProviderManager manager : mProviderManagers) { manager.onUserStopped(userId); Loading Loading @@ -957,10 +976,22 @@ public class LocationManagerService extends ILocationManager.Stub { pw.increaseIndent(); // for now we only dump for the parent user int userId = mUserInfoHelper.getCurrentUserIds()[0]; int[] userIds = mUserInfoHelper.getCurrentUserIds(); if (userIds.length == 1) { int userId = userIds[0]; pw.println("last location=" + mLastLocation.get(userId)); pw.println("last coarse location=" + mLastCoarseLocation.get(userId)); pw.println("enabled=" + isEnabled(userId)); } else { for (int userId : userIds) { pw.println("user " + userId + ":"); pw.increaseIndent(); pw.println("last location=" + mLastLocation.get(userId)); pw.println("last coarse location=" + mLastCoarseLocation.get(userId)); pw.println("enabled=" + isEnabled(userId)); pw.decreaseIndent(); } } } mProvider.dump(fd, pw, args); Loading
services/core/java/com/android/server/location/UserInfoHelper.java +82 −131 Original line number Diff line number Diff line Loading @@ -20,48 +20,48 @@ import static android.os.UserManager.DISALLOW_SHARE_LOCATION; import static com.android.server.location.LocationManagerService.D; import static com.android.server.location.LocationManagerService.TAG; import static com.android.server.location.UserInfoHelper.UserListener.CURRENT_USER_CHANGED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STARTED; import static com.android.server.location.UserInfoHelper.UserListener.USER_STOPPED; import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.app.ActivityManagerInternal; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.Build; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; import com.android.server.FgThread; import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; /** * Provides accessors and listeners for all user info. */ public class UserInfoHelper { public abstract class UserInfoHelper { /** * Listener for current user changes. */ public interface UserListener { int USER_SWITCHED = 1; int CURRENT_USER_CHANGED = 1; int USER_STARTED = 2; int USER_STOPPED = 3; @IntDef({USER_SWITCHED, USER_STARTED, USER_STOPPED}) @IntDef({CURRENT_USER_CHANGED, USER_STARTED, USER_STOPPED}) @Retention(RetentionPolicy.SOURCE) @interface UserChange {} Loading @@ -75,143 +75,101 @@ public class UserInfoHelper { private final CopyOnWriteArrayList<UserListener> mListeners; @GuardedBy("this") @Nullable private UserManager mUserManager; @UserIdInt private volatile int mCurrentUserId; @GuardedBy("this") @UserIdInt private int mCachedParentUserId; @Nullable private ActivityManagerInternal mActivityManagerInternal; @GuardedBy("this") private int[] mCachedProfileUserIds; @Nullable private UserManager mUserManager; public UserInfoHelper(Context context) { mContext = context; mListeners = new CopyOnWriteArrayList<>(); mCurrentUserId = UserHandle.USER_NULL; mCachedParentUserId = UserHandle.USER_NULL; mCachedProfileUserIds = new int[]{UserHandle.USER_NULL}; } /** Called when system is ready. */ @CallSuper public synchronized void onSystemReady() { if (mUserManager != null) { if (mActivityManagerInternal != null) { return; } mActivityManagerInternal = Objects.requireNonNull( LocalServices.getService(ActivityManagerInternal.class)); mUserManager = mContext.getSystemService(UserManager.class); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_USER_SWITCHED); intentFilter.addAction(Intent.ACTION_USER_STARTED); intentFilter.addAction(Intent.ACTION_USER_STOPPED); intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); mContext.registerReceiverAsUser(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == null) { return; } int userId; switch (action) { case Intent.ACTION_USER_SWITCHED: userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { onCurrentUserChanged(userId); } break; case Intent.ACTION_USER_STARTED: userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { onUserStarted(userId); } break; case Intent.ACTION_USER_STOPPED: userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { onUserStopped(userId); } break; case Intent.ACTION_MANAGED_PROFILE_ADDED: case Intent.ACTION_MANAGED_PROFILE_REMOVED: onUserProfilesChanged(); break; } } }, UserHandle.ALL, intentFilter, null, FgThread.getHandler()); mCurrentUserId = ActivityManager.getCurrentUser(); } /** * Adds a listener for user changed events. Callbacks occur on an unspecified thread. */ public void addListener(UserListener listener) { public final void addListener(UserListener listener) { mListeners.add(listener); } /** * Removes a listener for user changed events. */ public void removeListener(UserListener listener) { public final void removeListener(UserListener listener) { mListeners.remove(listener); } private void onCurrentUserChanged(@UserIdInt int newUserId) { if (newUserId == mCurrentUserId) { return; } protected void dispatchOnUserStarted(@UserIdInt int userId) { if (D) { Log.d(TAG, "current user switched from u" + mCurrentUserId + " to u" + newUserId); Log.d(TAG, "u" + userId + " started"); } int oldUserId = mCurrentUserId; mCurrentUserId = newUserId; onUserChanged(oldUserId, UserListener.USER_SWITCHED); onUserChanged(newUserId, UserListener.USER_SWITCHED); for (UserListener listener : mListeners) { listener.onUserChanged(userId, USER_STARTED); } } private void onUserStarted(@UserIdInt int userId) { protected void dispatchOnUserStopped(@UserIdInt int userId) { if (D) { Log.d(TAG, "u" + userId + " started"); Log.d(TAG, "u" + userId + " stopped"); } onUserChanged(userId, UserListener.USER_STARTED); for (UserListener listener : mListeners) { listener.onUserChanged(userId, USER_STOPPED); } private void onUserStopped(@UserIdInt int userId) { if (D) { Log.d(TAG, "u" + userId + " stopped"); } onUserChanged(userId, UserListener.USER_STOPPED); protected void dispatchOnCurrentUserChanged(@UserIdInt int fromUserId, @UserIdInt int toUserId) { int[] fromUserIds = getProfileIds(fromUserId); int[] toUserIds = getProfileIds(toUserId); if (D) { Log.d(TAG, "current user changed from u" + Arrays.toString(fromUserIds) + " to u" + Arrays.toString(toUserIds)); } private void onUserChanged(@UserIdInt int userId, @UserListener.UserChange int change) { for (UserListener listener : mListeners) { listener.onUserChanged(userId, change); for (int userId : fromUserIds) { listener.onUserChanged(userId, CURRENT_USER_CHANGED); } } private synchronized void onUserProfilesChanged() { // this intent is only sent to the current user if (mCachedParentUserId == mCurrentUserId) { mCachedParentUserId = UserHandle.USER_NULL; mCachedProfileUserIds = new int[]{UserHandle.USER_NULL}; for (UserListener listener : mListeners) { for (int userId : toUserIds) { listener.onUserChanged(userId, CURRENT_USER_CHANGED); } } } /** * Returns an array of current user ids. This will always include the current user, and will * also include any profiles of the current user. * also include any profiles of the current user. The caller must never mutate the returned * array. */ public int[] getCurrentUserIds() { return getProfileUserIdsForParentUser(mCurrentUserId); synchronized (this) { if (mActivityManagerInternal == null) { return new int[] {}; } } long identity = Binder.clearCallingIdentity(); try { return mActivityManagerInternal.getCurrentProfileIds(); } finally { Binder.restoreCallingIdentity(identity); } } /** Loading @@ -219,54 +177,47 @@ public class UserInfoHelper { * user. */ public boolean isCurrentUserId(@UserIdInt int userId) { int currentUserId = mCurrentUserId; return userId == currentUserId || ArrayUtils.contains( getProfileUserIdsForParentUser(currentUserId), userId); synchronized (this) { if (mActivityManagerInternal == null) { return false; } } @GuardedBy("this") private synchronized int[] getProfileUserIdsForParentUser(@UserIdInt int parentUserId) { if (parentUserId != mCachedParentUserId) { long identity = Binder.clearCallingIdentity(); try { Preconditions.checkState(mUserManager != null); return mActivityManagerInternal.isCurrentProfile(userId); } finally { Binder.restoreCallingIdentity(identity); } } // more expensive check - check that argument really is a parent user id if (Build.IS_DEBUGGABLE) { Preconditions.checkArgument( mUserManager.getProfileParent(parentUserId) == null); private int[] getProfileIds(@UserIdInt int userId) { synchronized (this) { Preconditions.checkState(mUserManager != null); } mCachedParentUserId = parentUserId; mCachedProfileUserIds = mUserManager.getProfileIdsWithDisabled(parentUserId); long identity = Binder.clearCallingIdentity(); try { return mUserManager.getEnabledProfileIds(userId); } finally { Binder.restoreCallingIdentity(identity); } } return mCachedProfileUserIds; } /** * Dump info for debugging. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { boolean systemRunning; synchronized (this) { systemRunning = mUserManager != null; } if (systemRunning) { int[] currentUserIds = getProfileUserIdsForParentUser(mCurrentUserId); pw.println("current users: " + Arrays.toString(currentUserIds)); for (int userId : currentUserIds) { if (mUserManager.hasUserRestrictionForUser(DISALLOW_SHARE_LOCATION, int[] currentUserProfiles = getCurrentUserIds(); pw.println("current users: " + Arrays.toString(currentUserProfiles)); UserManager userManager = mContext.getSystemService(UserManager.class); if (userManager != null) { for (int userId : currentUserProfiles) { if (userManager.hasUserRestrictionForUser(DISALLOW_SHARE_LOCATION, UserHandle.of(userId))) { pw.println(" u" + userId + " restricted"); } } } else { pw.println("current user: " + mCurrentUserId); } } }
services/tests/mockingservicestests/src/com/android/server/location/UserInfoHelperTest.java +52 −93 File changed.Preview size limit exceeded, changes collapsed. Show changes