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

Commit 526ef1c3 authored by Eva Chen's avatar Eva Chen Committed by Android (Google) Code Review
Browse files

Merge "Add test provider commands to location shell commands."

parents 79042a6c 93f34aa1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1179,7 +1179,7 @@ public class LocationManagerService extends ILocationManager.Stub {
    @Override
    public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
            ParcelFileDescriptor err, String[] args) {
        return new LocationShellCommand(this).exec(
        return new LocationShellCommand(mContext, this).exec(
                this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(),
                args);
    }
+186 −9
Original line number Diff line number Diff line
@@ -16,21 +16,29 @@

package com.android.server.location;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.provider.ProviderProperties;
import android.os.UserHandle;

import com.android.modules.utils.BasicShellCommandHandler;

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

/**
 * Interprets and executes 'adb shell cmd location [args]'.
 */
class LocationShellCommand extends BasicShellCommandHandler {
    private static final float DEFAULT_TEST_LOCATION_ACCURACY = 100.0f;

    private final Context mContext;
    private final LocationManagerService mService;

    LocationShellCommand(LocationManagerService service) {
    LocationShellCommand(Context context, LocationManagerService service) {
        mContext = context;
        mService = Objects.requireNonNull(service);
    }

@@ -47,6 +55,44 @@ class LocationShellCommand extends BasicShellCommandHandler {
                mService.setLocationEnabledForUser(enabled, userId);
                return 0;
            }
            case "providers": {
                String command = getNextArgRequired();
                return parseProvidersCommand(command);
            }
            default:
                return handleDefaultCommands(cmd);
        }
    }

    private int parseProvidersCommand(String cmd) {
        switch (cmd) {
            case "add-test-provider": {
                String provider = getNextArgRequired();
                ProviderProperties properties = parseTestProviderProviderProperties();
                mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                return 0;
            }
            case "remove-test-provider": {
                String provider = getNextArgRequired();
                mService.removeTestProvider(provider, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                return 0;
            }
            case "set-test-provider-enabled": {
                String provider = getNextArgRequired();
                boolean enabled = Boolean.parseBoolean(getNextArgRequired());
                mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                return 0;
            }
            case "set-test-provider-location": {
                String provider = getNextArgRequired();
                Location location = parseTestProviderLocation(provider);
                mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
                        mContext.getFeatureId());
                return 0;
            }
            case "send-extra-command": {
                String provider = getNextArgRequired();
                String command = getNextArgRequired();
@@ -72,6 +118,120 @@ class LocationShellCommand extends BasicShellCommandHandler {
        return UserHandle.USER_CURRENT_OR_SELF;
    }

    private ProviderProperties parseTestProviderProviderProperties() {
        boolean requiresNetwork = false;
        boolean requiresSatellite = false;
        boolean requiresCell = false;
        boolean hasMonetaryCost = false;
        boolean supportsAltitude = false;
        boolean supportsSpeed = false;
        boolean supportsBearing = false;
        int powerRequirement = Criteria.POWER_LOW;
        int accuracy = Criteria.ACCURACY_FINE;

        String option = getNextOption();
        while (option != null) {
            switch (option) {
                case "--requiresNetwork": {
                    requiresNetwork = true;
                    break;
                }
                case "--requiresSatellite": {
                    requiresSatellite = true;
                    break;
                }
                case "--requiresCell": {
                    requiresCell = true;
                    break;
                }
                case "--hasMonetaryCost": {
                    hasMonetaryCost = true;
                    break;
                }
                case "--supportsAltitude": {
                    supportsAltitude = true;
                    break;
                }
                case "--supportsSpeed": {
                    supportsSpeed = true;
                    break;
                }
                case "--supportsBearing": {
                    supportsBearing = true;
                    break;
                }
                case "--powerRequirement": {
                    powerRequirement = Integer.parseInt(getNextArgRequired());
                    break;
                }
                case "--accuracy": {
                    accuracy = Integer.parseInt(getNextArgRequired());
                    break;
                }
                default:
                    throw new IllegalArgumentException(
                            "Received unexpected option: " + option);
            }
            option = getNextOption();
        }

        ProviderProperties properties = new ProviderProperties.Builder()
                .setHasNetworkRequirement(requiresNetwork)
                .setHasSatelliteRequirement(requiresSatellite)
                .setHasCellRequirement(requiresCell)
                .setHasMonetaryCost(hasMonetaryCost)
                .setHasAltitudeSupport(supportsAltitude)
                .setHasSpeedSupport(supportsSpeed)
                .setHasBearingSupport(supportsBearing)
                .setPowerUsage(powerRequirement)
                .setAccuracy(accuracy)
                .build();

        return properties;
    }

    private Location parseTestProviderLocation(String provider) {
        boolean hasLatitude = false;
        boolean hasLongitude = false;

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

        String option = getNextOption();
        while (option != null) {
            switch (option) {
                case "--location": {
                    String[] locationInput = getNextArgRequired().split(",");
                    if (locationInput.length != 2) {
                        throw new IllegalArgumentException(
                                "Unexpected location format: " + Arrays.toString(locationInput));
                    }

                    location.setLatitude(Double.parseDouble(locationInput[0]));
                    location.setLongitude(Double.parseDouble(locationInput[1]));
                    break;
                }
                case "--accuracy": {
                    location.setAccuracy(Float.parseFloat(getNextArgRequired()));
                    break;
                }
                case "--time": {
                    location.setTime(Long.parseLong(getNextArgRequired()));
                    break;
                }
                default:
                    throw new IllegalArgumentException(
                            "Received unexpected option: " + option);
            }
            option = getNextOption();
        }

        location.setElapsedRealtimeNanos(System.nanoTime());

        return location;
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
@@ -80,6 +240,23 @@ class LocationShellCommand extends BasicShellCommandHandler {
        pw.println("    Print this help text.");
        pw.println("  set-location-enabled [--user <USER_ID>] true|false");
        pw.println("    Sets the master location switch enabled state.");
        pw.println("  providers");
        pw.println("    add-test-provider <PROVIDER> [--requiresNetwork] [--requiresSatellite]");
        pw.println("      [--requiresCell] [--hasMonetaryCost] [--supportsAltitude]");
        pw.println("      [--supportsSpeed] [--supportsBearing]");
        pw.println("      [--powerRequirement <POWER_REQUIREMENT>]");
        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("    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("      [--accuracy <ACCURACY>] [--time <TIME>]");
        pw.println("      Set location for given test provider. Accuracy and time are optional.");
        pw.println("    send-extra-command <PROVIDER> <COMMAND>");
        pw.println("      Sends the given extra command to the given provider.");
        pw.println();