diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index f88ddb8034b6..e73e915bf88b 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1943,7 +1943,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 @@ -1952,13 +1952,14 @@ public class LocationManager { * allowed} for your app. */ public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties, - @NonNull Set locationTags) { + @NonNull Set 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(); diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index cdaffb757311..2920ddb2d76d 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -464,7 +464,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())); } } @@ -1170,7 +1170,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public void addTestProvider(String provider, ProviderProperties properties, - List locationTags, String packageName, String attributionTag) { + List 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)) { @@ -1179,7 +1179,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 diff --git a/services/core/java/com/android/server/location/LocationShellCommand.java b/services/core/java/com/android/server/location/LocationShellCommand.java index 21a9b0442b74..5dc3ed8c47bd 100644 --- a/services/core/java/com/android/server/location/LocationShellCommand.java +++ b/services/core/java/com/android/server/location/LocationShellCommand.java @@ -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()); - } else { - throw new IllegalArgumentException( - "Expected \"--user\" option, but got \"" + option + "\" instead"); - } - } + private void handleIsLocationEnabled() { + int userId = UserHandle.USER_CURRENT_OR_SELF; - return 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); + + getOutPrintWriter().println(mService.isLocationEnabledForUser(userId)); } - private ProviderProperties parseTestProviderProviderProperties() { + 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(); + 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; - String option = getNextOption(); - while (option != null) { + List extraAttributionTags = Collections.emptyList(); + + do { + String option = getNextOption(); + 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(); - - return properties; + mService.addTestProvider(provider, properties, extraAttributionTags, + mContext.getOpPackageName(), mContext.getAttributionTag()); } - private Location parseTestProviderLocation(String provider) { - boolean hasLatitude = false; - boolean hasLongitude = false; + private void handleRemoveTestProvider() { + String provider = getNextArgRequired(); + mService.removeTestProvider(provider, mContext.getOpPackageName(), + mContext.getAttributionTag()); + } + + 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()); - String option = getNextOption(); - while (option != null) { + do { + String option = getNextOption(); + 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 \",\", 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 ]"); - pw.println(" Gets the master location switch enabled state."); - pw.println(" set-location-enabled [--user ] 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 ]"); + 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 [--requiresNetwork] [--requiresSatellite]"); pw.println(" [--requiresCell] [--hasMonetaryCost] [--supportsAltitude]"); pw.println(" [--supportsSpeed] [--supportsBearing]"); pw.println(" [--powerRequirement ]"); + pw.println(" [--extraAttributionTags ,,...]"); pw.println(" Add the given test provider. Requires MOCK_LOCATION permissions which"); pw.println(" can be enabled by running \"adb shell appops set "); 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 "); pw.println(" Remove the given test provider."); pw.println(" set-test-provider-enabled true|false"); pw.println(" Sets the given test provider enabled state."); - pw.println(" set-test-provider-location [--location ,]"); + pw.println(" set-test-provider-location --location ,"); pw.println(" [--accuracy ] [--time