Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 361e4106 authored by Grace Cheng's avatar Grace Cheng
Browse files

Updates location services to support concurrent multi user.

Allows users that run on multi display to control MLS independently by
redefining whether a registration is currently active or not. For an
registration to be considered active, one of the necessary conditions
is the caller being a current user. With this change, the condition is
changed to be the caller being a visible user.

Bug: 236139244
Bug: 241604546

Test: atest FrameworksMockingServicesTests:LocationProviderManagerTest
Test: atest FrameworksMockingServicesTests:SystemUserInfoHelperTest
Test: manual test in emulator

Change-Id: I8cf1d6148a0465fe85953edc92273cc926f7f40a
parent f6396c68
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -140,9 +140,7 @@ import com.android.server.location.provider.StationaryThrottlingLocationProvider
import com.android.server.location.provider.proxy.ProxyLocationProvider;
import com.android.server.location.settings.LocationSettings;
import com.android.server.location.settings.LocationUserSettings;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.utils.Slogf;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -310,10 +308,6 @@ public class LocationManagerService extends ILocationManager.Stub implements
        permissionManagerInternal.setLocationExtraPackagesProvider(
                userId -> mContext.getResources().getStringArray(
                        com.android.internal.R.array.config_locationExtraPackageNames));

        // TODO(b/241604546): properly handle this callback
        LocalServices.getService(UserManagerInternal.class).addUserVisibilityListener(
                (u, v) -> Slogf.i(TAG, "onUserVisibilityChanged(): %d -> %b", u, v));
    }

    @Nullable
@@ -1702,7 +1696,7 @@ public class LocationManagerService extends ILocationManager.Stub implements

        private final Context mContext;

        private final UserInfoHelper mUserInfoHelper;
        private final SystemUserInfoHelper mUserInfoHelper;
        private final LocationSettings mLocationSettings;
        private final AlarmHelper mAlarmHelper;
        private final SystemAppOpsHelper mAppOpsHelper;
@@ -1725,7 +1719,7 @@ public class LocationManagerService extends ILocationManager.Stub implements
        @GuardedBy("this")
        private boolean mSystemReady;

        SystemInjector(Context context, UserInfoHelper userInfoHelper) {
        SystemInjector(Context context, SystemUserInfoHelper userInfoHelper) {
            mContext = context;

            mUserInfoHelper = userInfoHelper;
@@ -1745,6 +1739,7 @@ public class LocationManagerService extends ILocationManager.Stub implements
        }

        synchronized void onSystemReady() {
            mUserInfoHelper.onSystemReady();
            mAppOpsHelper.onSystemReady();
            mLocationPermissionsHelper.onSystemReady();
            mSettingsHelper.onSystemReady();
+21 −0
Original line number Diff line number Diff line
@@ -110,6 +110,11 @@ public class LocationEventLog extends LocalEventLog<Object> {
        addLog(new UserSwitchedEvent(userIdFrom, userIdTo));
    }

    /** Logs a user visibility changed event. */
    public void logUserVisibilityChanged(int userId, boolean visible) {
        addLog(new UserVisibilityChangedEvent(userId, visible));
    }

    /** Logs a location enabled/disabled event. */
    public void logLocationEnabled(int userId, boolean enabled) {
        addLog(new LocationEnabledEvent(userId, enabled));
@@ -475,6 +480,22 @@ public class LocationEventLog extends LocalEventLog<Object> {
        }
    }

    private static final class UserVisibilityChangedEvent {

        private final int mUserId;
        private final boolean mVisible;

        UserVisibilityChangedEvent(int userId, boolean visible) {
            mUserId = userId;
            mVisible = visible;
        }

        @Override
        public String toString() {
            return "[u" + mUserId + "] " + (mVisible ? "visible" : "invisible");
        }
    }

    private static final class LocationEnabledEvent {

        private final int mUserId;
+5 −2
Original line number Diff line number Diff line
@@ -387,7 +387,7 @@ public class GeofenceManager extends
            if (!mSettingsHelper.isLocationEnabled(identity.getUserId())) {
                return false;
            }
            if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
            if (!mUserInfoHelper.isVisibleUserId(identity.getUserId())) {
                return false;
            }
            if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
@@ -534,7 +534,10 @@ public class GeofenceManager extends
    }

    void onUserChanged(int userId, int change) {
        if (change == UserListener.CURRENT_USER_CHANGED) {
        // current user changes affect whether system server location requests are allowed to access
        // location, and visibility changes affect whether any given user may access location.
        if (change == UserListener.CURRENT_USER_CHANGED
                || change == UserListener.USER_VISIBILITY_CHANGED) {
            updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
        }
    }
+5 −2
Original line number Diff line number Diff line
@@ -317,7 +317,7 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
                    identity.getUserId())) {
                return false;
            }
            if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
            if (!mUserInfoHelper.isVisibleUserId(identity.getUserId())) {
                return false;
            }
            if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
@@ -394,7 +394,10 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
    }

    private void onUserChanged(int userId, int change) {
        if (change == UserListener.CURRENT_USER_CHANGED) {
        // current user changes affect whether system server location requests are allowed to access
        // location, and visibility changes affect whether any given user may access location.
        if (change == UserListener.CURRENT_USER_CHANGED
                || change == UserListener.USER_VISIBILITY_CHANGED) {
            updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
        }
    }
+30 −0
Original line number Diff line number Diff line
@@ -33,9 +33,11 @@ import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;

import java.io.FileDescriptor;
import java.util.Arrays;
import java.util.Objects;

/**
 * Provides accessors and listeners for all user info.
@@ -50,11 +52,21 @@ public class SystemUserInfoHelper extends UserInfoHelper {
    @Nullable private IActivityManager mActivityManager;
    @GuardedBy("this")
    @Nullable private UserManager mUserManager;
    @GuardedBy("this")
    @Nullable private UserManagerInternal mUserManagerInternal;

    public SystemUserInfoHelper(Context context) {
        mContext = context;
    }

    /** The function should be called when PHASE_SYSTEM_SERVICES_READY. */
    public synchronized void onSystemReady() {
        mUserManagerInternal =
                Objects.requireNonNull(LocalServices.getService(UserManagerInternal.class));
        mUserManagerInternal.addUserVisibilityListener(
                (userId, visible) -> dispatchOnVisibleUserChanged(userId, visible));
    }

    @Nullable
    protected final ActivityManagerInternal getActivityManagerInternal() {
        synchronized (this) {
@@ -135,6 +147,24 @@ public class SystemUserInfoHelper extends UserInfoHelper {
        }
    }

    @Override
    public boolean isVisibleUserId(@UserIdInt int userId) {
        synchronized (this) {
            // if you're hitting this precondition then you are invoking this before the system is
            // ready
            Preconditions.checkState(mUserManagerInternal != null);
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
                return mUserManagerInternal.isUserVisible(userId);
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    protected int[] getProfileIds(@UserIdInt int userId) {
        UserManager userManager = getUserManager();
Loading