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

Commit 76c7af7a authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

Assorted minor cleanups

Make tag list nonnull, and rename to extraAttributionTags, and add shell
command support for adding location provider with extra attribution
tags.

Bug: 181254689
Test: presubmits
Change-Id: I52e55094c7043d0e75f902a4177f15e27b018de5
parent 3f9a7c0f
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -1967,7 +1967,7 @@ public class LocationManager {
     *
     * @param provider the provider name
     * @param properties the provider properties
     * @param locationTags the attribution tags for accessing location from the provider
     * @param extraAttributionTags additional attribution tags associated with this provider
     *
     * @throws IllegalArgumentException if provider is null
     * @throws IllegalArgumentException if properties is null
@@ -1976,13 +1976,14 @@ public class LocationManager {
     * allowed} for your app.
     */
    public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties,
            @NonNull Set<String> locationTags) {
            @NonNull Set<String> extraAttributionTags) {
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(properties != null, "invalid null properties");
        Preconditions.checkArgument(locationTags != null, "invalid null location tags");
        Preconditions.checkArgument(extraAttributionTags != null,
                "invalid null extra attribution tags");

        try {
            mService.addTestProvider(provider, properties, new ArrayList<>(locationTags),
            mService.addTestProvider(provider, properties, new ArrayList<>(extraAttributionTags),
                    mContext.getOpPackageName(), mContext.getFeatureId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
+3 −3
Original line number Diff line number Diff line
@@ -463,7 +463,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                    .build();
            final LocationProviderManager manager = getOrAddLocationProviderManager(name);
            manager.setMockProvider(new MockLocationProvider(properties,
                    CallerIdentity.fromContext(mContext), /*locationTags*/ null));
                    CallerIdentity.fromContext(mContext), Collections.emptySet()));
        }
    }

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

    @Override
    public void addTestProvider(String provider, ProviderProperties properties,
            List<String> locationTags, String packageName, String attributionTag) {
            List<String> extraAttributionTags, String packageName, String attributionTag) {
        // unsafe is ok because app ops will verify the package name
        CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag);
        if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
@@ -1162,7 +1162,7 @@ public class LocationManagerService extends ILocationManager.Stub {

        final LocationProviderManager manager = getOrAddLocationProviderManager(provider);
        manager.setMockProvider(new MockLocationProvider(properties, identity,
                (locationTags != null) ? new ArraySet<>(locationTags) : null));
                new ArraySet<>(extraAttributionTags)));
    }

    @Override
+108 −57
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import com.android.modules.utils.BasicShellCommandHandler;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
@@ -50,15 +52,11 @@ class LocationShellCommand extends BasicShellCommandHandler {

        switch (cmd) {
            case "is-location-enabled": {
                int userId = parseUserId();
                boolean enabled = mService.isLocationEnabledForUser(userId);
                getOutPrintWriter().println(enabled);
                handleIsLocationEnabled();
                return 0;
            }
            case "set-location-enabled": {
                int userId = parseUserId();
                boolean enabled = Boolean.parseBoolean(getNextArgRequired());
                mService.setLocationEnabledForUser(enabled, userId);
                handleSetLocationEnabled();
                return 0;
            }
            case "providers": {
@@ -73,36 +71,23 @@ class LocationShellCommand extends BasicShellCommandHandler {
    private int parseProvidersCommand(String cmd) {
        switch (cmd) {
            case "add-test-provider": {
                String provider = getNextArgRequired();
                ProviderProperties properties = parseTestProviderProviderProperties();
                mService.addTestProvider(provider, properties, /*locationTags*/ null,
                        mContext.getOpPackageName(), mContext.getFeatureId());
                handleAddTestProvider();
                return 0;
            }
            case "remove-test-provider": {
                String provider = getNextArgRequired();
                mService.removeTestProvider(provider, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                handleRemoveTestProvider();
                return 0;
            }
            case "set-test-provider-enabled": {
                String provider = getNextArgRequired();
                boolean enabled = Boolean.parseBoolean(getNextArgRequired());
                mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                handleSetTestProviderEnabled();
                return 0;
            }
            case "set-test-provider-location": {
                String provider = getNextArgRequired();
                Location location = parseTestProviderLocation(provider);
                mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                handleSetTestProviderLocation();
                return 0;
            }
            case "send-extra-command": {
                String provider = getNextArgRequired();
                String command = getNextArgRequired();
                mService.sendExtraCommand(provider, command, null);
                handleSendExtraCommand();
                return 0;
            }
            default:
@@ -110,21 +95,47 @@ class LocationShellCommand extends BasicShellCommandHandler {
        }
    }

    private int parseUserId() {
        final String option = getNextOption();
        if (option != null) {
            if (option.equals("--user")) {
                return UserHandle.parseUserArg(getNextArgRequired());
    private void handleIsLocationEnabled() {
        int userId = UserHandle.USER_CURRENT_OR_SELF;

        do {
            String option = getNextOption();
            if (option == null) {
                break;
            }
            if ("--user".equals(option)) {
                userId = UserHandle.parseUserArg(getNextArgRequired());
            } else {
                throw new IllegalArgumentException(
                        "Expected \"--user\" option, but got \"" + option + "\" instead");
                throw new IllegalArgumentException("Unknown option: " + option);
            }
        } while (true);

        getOutPrintWriter().println(mService.isLocationEnabledForUser(userId));
    }

        return UserHandle.USER_CURRENT_OR_SELF;
    private void handleSetLocationEnabled() {
        boolean enabled = Boolean.parseBoolean(getNextArgRequired());

        int userId = UserHandle.USER_CURRENT_OR_SELF;

        do {
            String option = getNextOption();
            if (option == null) {
                break;
            }
            if ("--user".equals(option)) {
                userId = UserHandle.parseUserArg(getNextArgRequired());
            } else {
                throw new IllegalArgumentException("Unknown option: " + option);
            }
        } while (true);

        mService.setLocationEnabledForUser(enabled, userId);
    }

    private void handleAddTestProvider() {
        String provider = getNextArgRequired();

    private ProviderProperties parseTestProviderProviderProperties() {
        boolean requiresNetwork = false;
        boolean requiresSatellite = false;
        boolean requiresCell = false;
@@ -135,8 +146,13 @@ class LocationShellCommand extends BasicShellCommandHandler {
        int powerRequirement = Criteria.POWER_LOW;
        int accuracy = Criteria.ACCURACY_FINE;

        List<String> extraAttributionTags = Collections.emptyList();

        do {
            String option = getNextOption();
        while (option != null) {
            if (option == null) {
                break;
            }
            switch (option) {
                case "--requiresNetwork": {
                    requiresNetwork = true;
@@ -174,12 +190,15 @@ class LocationShellCommand extends BasicShellCommandHandler {
                    accuracy = Integer.parseInt(getNextArgRequired());
                    break;
                }
                case "--extraAttributionTags": {
                    extraAttributionTags = Arrays.asList(getNextArgRequired().split(","));
                    break;
                }
                default:
                    throw new IllegalArgumentException(
                            "Received unexpected option: " + option);
            }
            option = getNextOption();
        }
        } while(true);

        ProviderProperties properties = new ProviderProperties.Builder()
                .setHasNetworkRequirement(requiresNetwork)
@@ -192,30 +211,50 @@ class LocationShellCommand extends BasicShellCommandHandler {
                .setPowerUsage(powerRequirement)
                .setAccuracy(accuracy)
                .build();
        mService.addTestProvider(provider, properties, extraAttributionTags,
                mContext.getOpPackageName(), mContext.getAttributionTag());
    }

        return properties;
    private void handleRemoveTestProvider() {
        String provider = getNextArgRequired();
        mService.removeTestProvider(provider, mContext.getOpPackageName(),
                mContext.getAttributionTag());
    }

    private Location parseTestProviderLocation(String provider) {
        boolean hasLatitude = false;
        boolean hasLongitude = false;
    private void handleSetTestProviderEnabled() {
        String provider = getNextArgRequired();
        boolean enabled = Boolean.parseBoolean(getNextArgRequired());
        mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
                mContext.getAttributionTag());
    }

    private void handleSetTestProviderLocation() {
        String provider = getNextArgRequired();

        boolean hasLatLng = false;

        Location location = new Location(provider);
        location.setAccuracy(DEFAULT_TEST_LOCATION_ACCURACY);
        location.setTime(System.currentTimeMillis());
        location.setElapsedRealtimeNanos(System.nanoTime());

        do {
            String option = getNextOption();
        while (option != null) {
            if (option == null) {
                break;
            }
            switch (option) {
                case "--location": {
                    String[] locationInput = getNextArgRequired().split(",");
                    if (locationInput.length != 2) {
                        throw new IllegalArgumentException(
                                "Unexpected location format: " + Arrays.toString(locationInput));
                        throw new IllegalArgumentException("Location argument must be in the form "
                                + "of \"<LATITUDE>,<LONGITUDE>\", not "
                                + Arrays.toString(locationInput));
                    }

                    location.setLatitude(Double.parseDouble(locationInput[0]));
                    location.setLongitude(Double.parseDouble(locationInput[1]));
                    hasLatLng = true;
                    break;
                }
                case "--accuracy": {
@@ -227,15 +266,22 @@ class LocationShellCommand extends BasicShellCommandHandler {
                    break;
                }
                default:
                    throw new IllegalArgumentException(
                            "Received unexpected option: " + option);
                    throw new IllegalArgumentException("Unknown option: " + option);
            }
            option = getNextOption();
        } while (true);

        if (!hasLatLng) {
            throw new IllegalArgumentException("Option \"--location\" is required");
        }

        location.setElapsedRealtimeNanos(System.nanoTime());
        mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
                mContext.getAttributionTag());
    }

        return location;
    private void handleSendExtraCommand() {
        String provider = getNextArgRequired();
        String command = getNextArgRequired();
        mService.sendExtraCommand(provider, command, null);
    }

    @Override
@@ -245,24 +291,29 @@ class LocationShellCommand extends BasicShellCommandHandler {
        pw.println("  help or -h");
        pw.println("    Print this help text.");
        pw.println("  is-location-enabled [--user <USER_ID>]");
        pw.println("    Gets the master location switch enabled state.");
        pw.println("  set-location-enabled [--user <USER_ID>] true|false");
        pw.println("    Sets the master location switch enabled state.");
        pw.println("    Gets the master location switch enabled state. If no user is specified,");
        pw.println("    the current user is assumed.");
        pw.println("  set-location-enabled true|false [--user <USER_ID>]");
        pw.println("    Sets the master location switch enabled state. If no user is specified,");
        pw.println("    the current user is assumed.");
        pw.println("  providers");
        pw.println("    The providers command is followed by a subcommand, as listed below:");
        pw.println();
        pw.println("    add-test-provider <PROVIDER> [--requiresNetwork] [--requiresSatellite]");
        pw.println("      [--requiresCell] [--hasMonetaryCost] [--supportsAltitude]");
        pw.println("      [--supportsSpeed] [--supportsBearing]");
        pw.println("      [--powerRequirement <POWER_REQUIREMENT>]");
        pw.println("      [--extraAttributionTags <TAG>,<TAG>,...]");
        pw.println("      Add the given test provider. Requires MOCK_LOCATION permissions which");
        pw.println("      can be enabled by running \"adb shell appops set <uid>");
        pw.println("      android:mock_location allow\". There are optional flags that can be");
        pw.println("      used to configure the provider properties. If no flags are included,");
        pw.println("      then default values will be used.");
        pw.println("      used to configure the provider properties and additional arguments. If");
        pw.println("      no flags are included, then default values will be used.");
        pw.println("    remove-test-provider <PROVIDER>");
        pw.println("      Remove the given test provider.");
        pw.println("    set-test-provider-enabled <PROVIDER> true|false");
        pw.println("      Sets the given test provider enabled state.");
        pw.println("    set-test-provider-location <PROVIDER> [--location <LATITUDE>,<LONGITUDE>]");
        pw.println("    set-test-provider-location <PROVIDER> --location <LATITUDE>,<LONGITUDE>");
        pw.println("      [--accuracy <ACCURACY>] [--time <TIME>]");
        pw.println("      Set location for given test provider. Accuracy and time are optional.");
        pw.println("    send-extra-command <PROVIDER> <COMMAND>");
+2 −1
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ import com.android.server.location.provider.AbstractLocationProvider;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -372,7 +373,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
    public GnssLocationProvider(Context context, Injector injector, GnssNative gnssNative,
            GnssMetrics gnssMetrics) {
        super(FgThread.getExecutor(), CallerIdentity.fromContext(context), PROPERTIES,
                /*locationTags*/ null);
                Collections.emptySet());

        mContext = context;
        mGnssNative = gnssNative;
+28 −22
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.internal.util.Preconditions;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -66,9 +67,10 @@ public abstract class AbstractLocationProvider {

        /**
         * Default state value for a location provider that is disabled with no properties and an
         * empty provider package list.
         * empty extra attribution tag set.
         */
        public static final State EMPTY_STATE = new State(false, null, null, null);
        public static final State EMPTY_STATE = new State(false, null, null,
                Collections.emptySet());

        /**
         * The provider's allowed state.
@@ -85,14 +87,18 @@ public abstract class AbstractLocationProvider {
         */
        @Nullable public final CallerIdentity identity;

        @Nullable public final Set<String> locationTags;
        /**
         * A set of attribution tags also associated with this provider - these attribution tags may
         * be afforded special privileges.
         */
        public final Set<String> extraAttributionTags;

        private State(boolean allowed, ProviderProperties properties, CallerIdentity identity,
                Set<String> locationTags) {
                Set<String> extraAttributionTags) {
            this.allowed = allowed;
            this.properties = properties;
            this.identity = identity;
            this.locationTags = locationTags;
            this.extraAttributionTags = Objects.requireNonNull(extraAttributionTags);
        }

        /**
@@ -102,7 +108,7 @@ public abstract class AbstractLocationProvider {
            if (allowed == this.allowed) {
                return this;
            } else {
                return new State(allowed, properties, identity, locationTags);
                return new State(allowed, properties, identity, extraAttributionTags);
            }
        }

@@ -113,7 +119,7 @@ public abstract class AbstractLocationProvider {
            if (Objects.equals(properties, this.properties)) {
                return this;
            } else {
                return new State(allowed, properties, identity, locationTags);
                return new State(allowed, properties, identity, extraAttributionTags);
            }
        }

@@ -124,18 +130,18 @@ public abstract class AbstractLocationProvider {
            if (Objects.equals(identity, this.identity)) {
                return this;
            } else {
                return new State(allowed, properties, identity, locationTags);
                return new State(allowed, properties, identity, extraAttributionTags);
            }
        }

        /**
         * Returns a state the same as the current but with location tags set as specified.
         * Returns a state the same as the current but with extra attribution tags set as specified.
         */
        public State withLocationTags(@Nullable Set<String> locationTags) {
            if (Objects.equals(locationTags, this.locationTags)) {
        public State withExtraAttributionTags(Set<String> extraAttributionTags) {
            if (extraAttributionTags.equals(this.extraAttributionTags)) {
                return this;
            } else {
                return new State(allowed, properties, identity, locationTags);
                return new State(allowed, properties, identity, extraAttributionTags);
            }
        }

@@ -151,12 +157,12 @@ public abstract class AbstractLocationProvider {
            State state = (State) o;
            return allowed == state.allowed && properties == state.properties
                    && Objects.equals(identity, state.identity)
                    && Objects.equals(locationTags, state.locationTags);
                    && extraAttributionTags.equals(state.extraAttributionTags);
        }

        @Override
        public int hashCode() {
            return Objects.hash(allowed, properties, identity, locationTags);
            return Objects.hash(allowed, properties, identity, extraAttributionTags);
        }
    }

@@ -213,14 +219,14 @@ public abstract class AbstractLocationProvider {
     * An optional identity and properties may be provided to initialize the location provider.
     */
    protected AbstractLocationProvider(Executor executor, @Nullable CallerIdentity identity,
            @Nullable ProviderProperties properties, @Nullable Set<String> locationTags) {
            @Nullable ProviderProperties properties, Set<String> extraAttributionTags) {
        Preconditions.checkArgument(identity == null || identity.getListenerId() == null);
        mExecutor = executor;
        mExecutor = Objects.requireNonNull(executor);
        mInternalState = new AtomicReference<>(new InternalState(null,
                State.EMPTY_STATE
                        .withIdentity(identity)
                        .withProperties(properties).withLocationTags(locationTags))
        );
                        .withProperties(properties)
                        .withExtraAttributionTags(extraAttributionTags)));
        mController = new Controller();
    }

@@ -292,7 +298,7 @@ public abstract class AbstractLocationProvider {
    }

    /**
     * Call this method to report a change in provider packages.
     * Call this method to report a change in the provider's identity.
     */
    protected void setIdentity(@Nullable CallerIdentity identity) {
        Preconditions.checkArgument(identity == null || identity.getListenerId() == null);
@@ -300,10 +306,10 @@ public abstract class AbstractLocationProvider {
    }

    /**
     * Call this method to report a change in provider location tags.
     * Call this method to report a change in the provider's extra attribution tags.
     */
    protected void setLocationTags(@Nullable Set<String> locationTags) {
        setState(state -> state.withLocationTags(locationTags));
    protected void setExtraAttributionTags(Set<String> extraAttributionTags) {
        setState(state -> state.withExtraAttributionTags(extraAttributionTags));
    }

    /**
Loading