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

Commit f59c623d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update location broadcast behavior"

parents 4681eba6 06e37f67
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -23277,6 +23277,8 @@ package android.location {
    method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
    method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
    method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
    field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
    field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
    field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
    field public static final String GPS_PROVIDER = "gps";
    field public static final String KEY_LOCATION_CHANGED = "location";
+31 −4
Original line number Diff line number Diff line
@@ -164,24 +164,51 @@ public class LocationManager {
     * Broadcast intent action when the set of enabled location providers changes. To check the
     * status of a provider, use {@link #isProviderEnabled(String)}. From Android Q and above, will
     * include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider
     * whose state has changed.
     * whose state has changed. From Android R and above, will include a boolean intent extra,
     * {@link #EXTRA_PROVIDER_ENABLED}, with the enabled state of the provider.
     *
     * @see #EXTRA_PROVIDER_NAME
     * @see #EXTRA_PROVIDER_ENABLED
     * @see #isProviderEnabled(String)
     */
    public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";

    /**
     * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the name
     * of the location provider that has changed, to be used with location provider APIs.
     * of the location provider that has changed.
     *
     * @see #PROVIDERS_CHANGED_ACTION
     * @see #EXTRA_PROVIDER_ENABLED
     */
    public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";

    /**
     * Broadcast intent action when the device location mode changes. To check the location mode,
     * use {@link #isLocationEnabled()}.
     * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the
     * boolean enabled state of the location provider that has changed.
     *
     * @see #PROVIDERS_CHANGED_ACTION
     * @see #EXTRA_PROVIDER_NAME
     */
    public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";

    /**
     * Broadcast intent action when the device location enabled state changes. From Android R and
     * above, will include a boolean intent extra, {@link #EXTRA_LOCATION_ENABLED}, with the enabled
     * state of location.
     *
     * @see #EXTRA_LOCATION_ENABLED
     * @see #isLocationEnabled()
     */
    public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";

    /**
     * Intent extra included with {@link #MODE_CHANGED_ACTION} broadcasts, containing the boolean
     * enabled state of location.
     *
     * @see #MODE_CHANGED_ACTION
     */
    public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";

    /**
     * Broadcast intent action indicating that a high power location requests
     * has either started or stopped being active.  The current state of
+67 −77
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;

import com.android.internal.annotations.GuardedBy;
@@ -339,7 +340,7 @@ public class LocationManagerService extends ILocationManager.Stub {

            mSettingsStore.addOnLocationEnabledChangedListener((userId) -> {
                synchronized (mLock) {
                    onLocationModeChangedLocked(userId, true);
                    onLocationModeChangedLocked(userId);
                }
            });
            mSettingsStore.addOnLocationProvidersAllowedChangedListener((userId) -> {
@@ -467,36 +468,24 @@ public class LocationManagerService extends ILocationManager.Stub {
    }

    @GuardedBy("mLock")
    private void onLocationModeChangedLocked(int userId, boolean broadcast) {
        if (!isCurrentProfileLocked(userId)) {
            return;
        }

    private void onLocationModeChangedLocked(int userId) {
        if (D) {
            Log.d(TAG, "location enabled is now " + isLocationEnabled());
            Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId));
        }

        for (LocationProvider p : mProviders) {
            p.onLocationModeChangedLocked();
        }
        Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION);
        intent.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabled());
        mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));

        if (broadcast) {
            // needs to be sent to everyone because we don't know which user may have changed
            // LOCATION_MODE state.
            mContext.sendBroadcastAsUser(
                    new Intent(LocationManager.MODE_CHANGED_ACTION),
                    UserHandle.ALL);
        for (LocationProvider p : mProviders) {
            p.onLocationModeChangedLocked(userId);
        }
    }

    @GuardedBy("mLock")
    private void onProviderAllowedChangedLocked(int userId) {
        if (!isCurrentProfileLocked(userId)) {
            return;
        }

        for (LocationProvider p : mProviders) {
            p.onAllowedChangedLocked();
            p.onAllowedChangedLocked(userId);
        }
    }

@@ -798,21 +787,14 @@ public class LocationManagerService extends ILocationManager.Stub {
            Log.d(TAG, "foreground user is changing to " + userId);
        }

        // let providers know the current user is on the way out before changing the user
        for (LocationProvider p : mProviders) {
            p.onUserChangingLocked();
        }

        int oldUserId = userId;
        mCurrentUserId = userId;
        onUserProfilesChangedLocked();

        // if the user changes, per-user settings may also have changed
        onLocationModeChangedLocked(userId, false);
        onProviderAllowedChangedLocked(userId);

        // always force useability to be rechecked, even if no per-user settings have changed
        // let providers know the current user has changed
        for (LocationProvider p : mProviders) {
            p.onUseableChangedLocked(false);
            p.onCurrentUserChangedLocked(oldUserId);
            p.onCurrentUserChangedLocked(mCurrentUserId);
        }
    }

@@ -832,7 +814,7 @@ public class LocationManagerService extends ILocationManager.Stub {
        protected AbstractLocationProvider mProvider;

        @GuardedBy("mLock")
        private boolean mUseable;  // combined state
        private SparseArray<Boolean> mUseable;  // combined state for each user id
        @GuardedBy("mLock")
        private boolean mAllowed;  // state of LOCATION_PROVIDERS_ALLOWED
        @GuardedBy("mLock")
@@ -851,7 +833,7 @@ public class LocationManagerService extends ILocationManager.Stub {
            mIsManagedBySettings = isManagedBySettings;

            mProvider = null;
            mUseable = false;
            mUseable = new SparseArray<>(1);
            mAllowed = !mIsManagedBySettings;
            mEnabled = false;
            mProperties = null;
@@ -876,7 +858,10 @@ public class LocationManagerService extends ILocationManager.Stub {
            }

            mProvider = provider;
            onUseableChangedLocked(false);

            // it would be more correct to call this for all users, but we know this can only
            // affect the current user since providers are disabled for non-current users
            onUseableChangedLocked(false, mCurrentUserId);
        }

        public String getName() {
@@ -943,8 +928,8 @@ public class LocationManagerService extends ILocationManager.Stub {

            pw.increaseIndent();

            pw.println("useable=" + mUseable);
            if (!mUseable) {
            pw.println("useable=" + isUseableLocked(mCurrentUserId));
            if (!isUseableLocked(mCurrentUserId)) {
                pw.println("attached=" + (mProvider != null));
                if (mIsManagedBySettings) {
                    pw.println("allowed=" + mAllowed);
@@ -1009,7 +994,10 @@ public class LocationManagerService extends ILocationManager.Stub {
                }

                mEnabled = enabled;
                onUseableChangedLocked(false);

                // it would be more correct to call this for all users, but we know this can only
                // affect the current user since providers are disabled for non-current users
                onUseableChangedLocked(false, mCurrentUserId);
            }
        }

@@ -1021,12 +1009,20 @@ public class LocationManagerService extends ILocationManager.Stub {
        }

        @GuardedBy("mLock")
        public void onLocationModeChangedLocked() {
            onUseableChangedLocked(false);
        public void onLocationModeChangedLocked(int userId) {
            if (!isCurrentProfileLocked(userId)) {
                return;
            }

            onUseableChangedLocked(false, userId);
        }

        @GuardedBy("mLock")
        public void onAllowedChangedLocked() {
        public void onAllowedChangedLocked(int userId) {
            if (!isCurrentProfileLocked(userId)) {
                return;
            }

            if (mIsManagedBySettings) {
                boolean allowed = mSettingsStore.getLocationProvidersAllowed(
                        mCurrentUserId).contains(mName);
@@ -1040,37 +1036,36 @@ public class LocationManagerService extends ILocationManager.Stub {
                }

                mAllowed = allowed;
                onUseableChangedLocked(true);
                onUseableChangedLocked(true, userId);
            }
        }

        @GuardedBy("mLock")
        public boolean isUseableLocked() {
            return isUseableForUserLocked(mCurrentUserId);
        public void onCurrentUserChangedLocked(int userId) {
            onUseableChangedLocked(false, userId);
        }

        @GuardedBy("mLock")
        public boolean isUseableForUserLocked(int userId) {
            return isCurrentProfileLocked(userId) && mUseable;
        public boolean isUseableLocked() {
            return isUseableLocked(mCurrentUserId);
        }

        @GuardedBy("mLock")
        private boolean isUseableIgnoringAllowedLocked() {
            return mProvider != null && mProviders.contains(this) && isLocationEnabled()
                    && mEnabled;
        public boolean isUseableLocked(int userId) {
            return mUseable.get(userId, Boolean.FALSE);
        }

        @GuardedBy("mLock")
        public void onUseableChangedLocked(boolean isAllowedChanged) {
        public void onUseableChangedLocked(boolean isAllowedChanged, int userId) {
            // if any property that contributes to "useability" here changes state, it MUST result
            // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
            // guarantee that it will always eventually reach the correct state.
            boolean useableIgnoringAllowed = isUseableIgnoringAllowedLocked();
            boolean useableIgnoringAllowed = mProvider != null && mProviders.contains(this)
                    && isCurrentProfileLocked(userId) && isLocationEnabledForUser(userId)
                    && mEnabled;
            boolean useable = useableIgnoringAllowed && mAllowed;

            // update deprecated provider allowed settings for backwards compatibility, and do this
            // even if there is no change in overall useability state. this may result in trying to
            // overwrite the same value, but Settings handles deduping this.
            // update deprecated provider allowed settings for backwards compatibility
            if (mIsManagedBySettings) {
                // a "-" change derived from the allowed setting should not be overwritten, but a
                // "+" change should be corrected if necessary
@@ -1079,33 +1074,31 @@ public class LocationManagerService extends ILocationManager.Stub {
                            mContext.getContentResolver(),
                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                            "+" + mName,
                            mCurrentUserId);
                            userId);
                } else if (!useableIgnoringAllowed) {
                    Settings.Secure.putStringForUser(
                            mContext.getContentResolver(),
                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                            "-" + mName,
                            mCurrentUserId);
                            userId);
                }

                // needs to be sent to all users because whether or not a provider is enabled for
                // a given user is complicated... we broadcast to everyone and let them figure it
                // out via isProviderEnabled()
                Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION);
                intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName);
                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
                intent.putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable);
                mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
            }

            if (useable == mUseable) {
            if (useable == isUseableLocked(userId)) {
                return;
            }
            mUseable = useable;
            mUseable.put(userId, useable);

            if (D) {
                Log.d(TAG, mName + " provider useable is now " + mUseable);
                Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
            }

            if (!mUseable) {
            if (!useable) {
                // If any provider has been disabled, clear all last locations for all
                // providers. This is to be on the safe side in case a provider has location
                // derived from this disabled provider.
@@ -1115,15 +1108,6 @@ public class LocationManagerService extends ILocationManager.Stub {

            updateProviderUseableLocked(this);
        }

        @GuardedBy("mLock")
        public void onUserChangingLocked() {
            // when the user is about to change, we set this provider to un-useable, and notify all
            // of the current user clients. when the user is finished changing, useability will be
            // updated back via onLocationModeChanged() and onAllowedChanged().
            mUseable = false;
            updateProviderUseableLocked(this);
        }
    }

    private class MockLocationProvider extends LocationProvider {
@@ -1557,14 +1541,20 @@ public class LocationManagerService extends ILocationManager.Stub {

        mProviders.add(provider);

        provider.onAllowedChangedLocked();  // allowed state may change while provider was inactive
        provider.onUseableChangedLocked(false);
        // allowed state may change while provider was inactive
        provider.onAllowedChangedLocked(mCurrentUserId);

        // it would be more correct to call this for all users, but we know this can only
        // affect the current user since providers are disabled for non-current users
        provider.onUseableChangedLocked(false, mCurrentUserId);
    }

    @GuardedBy("mLock")
    private void removeProviderLocked(LocationProvider provider) {
        if (mProviders.remove(provider)) {
            provider.onUseableChangedLocked(false);
            // it would be more correct to call this for all users, but we know this can only
            // affect the current user since providers are disabled for non-current users
            provider.onUseableChangedLocked(false, mCurrentUserId);
        }
    }

@@ -2851,7 +2841,7 @@ public class LocationManagerService extends ILocationManager.Stub {

        synchronized (mLock) {
            LocationProvider provider = getLocationProviderLocked(providerName);
            return provider != null && provider.isUseableForUserLocked(userId);
            return provider != null && provider.isUseableLocked(userId);
        }
    }