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

Commit 4700428b authored by Svet Ganov's avatar Svet Ganov
Browse files

Location provider app ops remapping

The platform has the concept of a location provider which could
be a plugin implemented by another package. The implementation
of a location provider plugin can make calls to APIs that require
a location permission, e.g. fusing data from different sources.
However, such accesses are counted in app ops as a location access
but the accessor is in this case the data source. It is also
possible that the package that provides the implementation of a
location provider also hosts other funcionality which may need to
call APIs that require a location permission.

This change allows a location provider to specify app op attribution
tags which which could be used when calling location to singal to the
OS that the access is for the location providing functionality of the
location provider. For location accesses of the provider package that
are not related to providing location to the OS the provider can use
any other non delcared as location attribution tags. Accesses with
the location attribution tags would be counted in app ops but instead
of towards the OP_COARSE_LOCATION/OP_FINE_LOCATION the would be
counted towards dedicated OP_COARSE_LOCATION_PROVIDER/
OP_FINE_LOCATION_PROVIDER ops. This would allow proper classification
while enabling auditability and tracking via the standard app op APIs.

<meta-data
    android:name="android:location_allow_listed_tags"
    android:value="foo;bar;baz"/>

Test: atest android.location.cts.fine.LocationManagerFineTest#testLocationAttributionTagBlaming

Bug:179062648

Change-Id: I36739ab42cedc94e1aa7a3bfd3b9aa213f5b3e97
parent 0bf57f53
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -19660,6 +19660,7 @@ package android.location {
    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
    method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
    method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
    method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
    method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
    method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
    method @Deprecated public void clearTestProviderEnabled(@NonNull String);
    method @Deprecated public void clearTestProviderEnabled(@NonNull String);
    method @Deprecated public void clearTestProviderLocation(@NonNull String);
    method @Deprecated public void clearTestProviderLocation(@NonNull String);
    method @Deprecated public void clearTestProviderStatus(@NonNull String);
    method @Deprecated public void clearTestProviderStatus(@NonNull String);
+57 −7
Original line number Original line Diff line number Diff line
@@ -1141,23 +1141,20 @@ public class AppOpsManager {
     *
     *
     * @hide
     * @hide
     */
     */
    // TODO: Add as AppProtoEnums
    public static final int OP_PHONE_CALL_MICROPHONE = AppProtoEnums.APP_OP_PHONE_CALL_MICROPHONE;
    public static final int OP_PHONE_CALL_MICROPHONE = 100;
    /**
    /**
     * Phone call is using camera
     * Phone call is using camera
     *
     *
     * @hide
     * @hide
     */
     */
    // TODO: Add as AppProtoEnums
    public static final int OP_PHONE_CALL_CAMERA = AppProtoEnums.APP_OP_PHONE_CALL_CAMERA;
    public static final int OP_PHONE_CALL_CAMERA = 101;


    /**
    /**
     * Audio is being recorded for hotword detection.
     * Audio is being recorded for hotword detection.
     *
     *
     * @hide
     * @hide
     */
     */
    // TODO: Add as AppProtoEnums
    public static final int OP_RECORD_AUDIO_HOTWORD = AppProtoEnums.APP_OP_RECORD_AUDIO_HOTWORD;
    public static final int OP_RECORD_AUDIO_HOTWORD = 102;


    /**
    /**
     * Manage credentials in the system KeyChain.
     * Manage credentials in the system KeyChain.
@@ -1184,10 +1181,29 @@ public class AppOpsManager {
     */
     */
    public static final int OP_SCHEDULE_EXACT_ALARM = AppProtoEnums.APP_OP_SCHEDULE_EXACT_ALARM;
    public static final int OP_SCHEDULE_EXACT_ALARM = AppProtoEnums.APP_OP_SCHEDULE_EXACT_ALARM;


    /**
     * Fine location being accessed by a location source, which is
     * a component that already has location data since it is the one
     * that produces location, which is it is a data source for
     * location data.
     *
     * @hide
     */
    public static final int OP_FINE_LOCATION_SOURCE = AppProtoEnums.APP_OP_FINE_LOCATION_SOURCE;

    /**
     * Coarse location being accessed by a location source, which is
     * a component that already has location data since it is the one
     * that produces location, which is it is a data source for
     * location data.
     *
     * @hide
     */
    public static final int OP_COARSE_LOCATION_SOURCE = AppProtoEnums.APP_OP_COARSE_LOCATION_SOURCE;


    /** @hide */
    /** @hide */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static final int _NUM_OP = 108;
    public static final int _NUM_OP = 110;


    /** Access to coarse location information. */
    /** Access to coarse location information. */
    public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
    public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1567,6 +1583,24 @@ public class AppOpsManager {
     */
     */
    public static final String OPSTR_SCHEDULE_EXACT_ALARM = "android:schedule_exact_alarm";
    public static final String OPSTR_SCHEDULE_EXACT_ALARM = "android:schedule_exact_alarm";


    /**
     * Fine location being accessed by a location source, which is
     * a component that already has location since it is the one that
     * produces location.
     *
     * @hide
     */
    public static final String OPSTR_FINE_LOCATION_SOURCE = "android:fine_location_source";

    /**
     * Coarse location being accessed by a location source, which is
     * a component that already has location since it is the one that
     * produces location.
     *
     * @hide
     */
    public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source";

    /** {@link #sAppOpsToNote} not initialized yet for this op */
    /** {@link #sAppOpsToNote} not initialized yet for this op */
    private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
    private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
    /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
    /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1767,6 +1801,8 @@ public class AppOpsManager {
            OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            OP_RECORD_AUDIO_OUTPUT,             // RECORD_AUDIO_OUTPUT
            OP_RECORD_AUDIO_OUTPUT,             // RECORD_AUDIO_OUTPUT
            OP_SCHEDULE_EXACT_ALARM,            // SCHEDULE_EXACT_ALARM
            OP_SCHEDULE_EXACT_ALARM,            // SCHEDULE_EXACT_ALARM
            OP_FINE_LOCATION,                   // OP_FINE_LOCATION_SOURCE
            OP_COARSE_LOCATION,                 // OP_COARSE_LOCATION_SOURCE
    };
    };


    /**
    /**
@@ -1881,6 +1917,8 @@ public class AppOpsManager {
            OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
            OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
            OPSTR_RECORD_AUDIO_OUTPUT,
            OPSTR_RECORD_AUDIO_OUTPUT,
            OPSTR_SCHEDULE_EXACT_ALARM,
            OPSTR_SCHEDULE_EXACT_ALARM,
            OPSTR_FINE_LOCATION_SOURCE,
            OPSTR_COARSE_LOCATION_SOURCE,
    };
    };


    /**
    /**
@@ -1996,6 +2034,8 @@ public class AppOpsManager {
            "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
            "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
            "RECORD_AUDIO_OUTPUT",
            "RECORD_AUDIO_OUTPUT",
            "SCHEDULE_EXACT_ALARM",
            "SCHEDULE_EXACT_ALARM",
            "FINE_LOCATION_SOURCE",
            "COARSE_LOCATION_SOURCE",
    };
    };


    /**
    /**
@@ -2112,6 +2152,8 @@ public class AppOpsManager {
            Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
            Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
            null, // no permission for OP_RECORD_AUDIO_OUTPUT
            null, // no permission for OP_RECORD_AUDIO_OUTPUT
            Manifest.permission.SCHEDULE_EXACT_ALARM,
            Manifest.permission.SCHEDULE_EXACT_ALARM,
            null, // no permission for OP_ACCESS_FINE_LOCATION_SOURCE,
            null, // no permission for OP_ACCESS_COARSE_LOCATION_SOURCE,
    };
    };


    /**
    /**
@@ -2228,6 +2270,8 @@ public class AppOpsManager {
            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            null, // RECORD_AUDIO_OUTPUT
            null, // RECORD_AUDIO_OUTPUT
            null, // SCHEDULE_EXACT_ALARM
            null, // SCHEDULE_EXACT_ALARM
            null, // ACCESS_FINE_LOCATION_SOURCE
            null, // ACCESS_COARSE_LOCATION_SOURCE
    };
    };


    /**
    /**
@@ -2343,6 +2387,8 @@ public class AppOpsManager {
            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            null, // RECORD_AUDIO_OUTPUT
            null, // RECORD_AUDIO_OUTPUT
            null, // SCHEDULE_EXACT_ALARM
            null, // SCHEDULE_EXACT_ALARM
            null, // ACCESS_FINE_LOCATION_SOURCE
            null, // ACCESS_COARSE_LOCATION_SOURCE
    };
    };


    /**
    /**
@@ -2457,6 +2503,8 @@ public class AppOpsManager {
            AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT
            AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT
            AppOpsManager.MODE_DEFAULT, // SCHEDULE_EXACT_ALARM
            AppOpsManager.MODE_DEFAULT, // SCHEDULE_EXACT_ALARM
            AppOpsManager.MODE_ALLOWED, // ACCESS_FINE_LOCATION_SOURCE
            AppOpsManager.MODE_ALLOWED, // ACCESS_COARSE_LOCATION_SOURCE
    };
    };


    /**
    /**
@@ -2575,6 +2623,8 @@ public class AppOpsManager {
            true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
            false, // RECORD_AUDIO_OUTPUT
            false, // RECORD_AUDIO_OUTPUT
            false, // SCHEDULE_EXACT_ALARM
            false, // SCHEDULE_EXACT_ALARM
            false, // ACCESS_FINE_LOCATION_SOURCE
            false, // ACCESS_COARSE_LOCATION_SOURCE
    };
    };


    /**
    /**
+2 −1
Original line number Original line Diff line number Diff line
@@ -117,7 +117,8 @@ interface ILocationManager
    boolean isLocationEnabledForUser(int userId);
    boolean isLocationEnabledForUser(int userId);
    void setLocationEnabledForUser(boolean enabled, int userId);
    void setLocationEnabledForUser(boolean enabled, int userId);


    void addTestProvider(String name, in ProviderProperties properties, String packageName, @nullable String attributionTag);
    void addTestProvider(String name, in ProviderProperties properties,
        in List<String> locationTags, String packageName, @nullable String attributionTag);
    void removeTestProvider(String provider, String packageName, @nullable String attributionTag);
    void removeTestProvider(String provider, String packageName, @nullable String attributionTag);
    void setTestProviderLocation(String provider, in Location location, String packageName, @nullable String attributionTag);
    void setTestProviderLocation(String provider, in Location location, String packageName, @nullable String attributionTag);
    void setTestProviderEnabled(String provider, boolean enabled, String packageName, @nullable String attributionTag);
    void setTestProviderEnabled(String provider, boolean enabled, String packageName, @nullable String attributionTag);
+23 −2
Original line number Original line Diff line number Diff line
@@ -76,6 +76,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Consumer;
@@ -1957,12 +1958,32 @@ public class LocationManager {
     * allowed} for your app.
     * allowed} for your app.
     */
     */
    public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties) {
    public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties) {
        addTestProvider(provider, properties, Collections.emptySet());
    }

    /**
     * Creates a test location provider and adds it to the set of active providers. This provider
     * will replace any provider with the same name that exists prior to this call.
     *
     * @param provider the provider name
     * @param properties the provider properties
     * @param locationTags the attribution tags for accessing location from the provider
     *
     * @throws IllegalArgumentException if provider is null
     * @throws IllegalArgumentException if properties is null
     * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
     * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
     * allowed} for your app.
     */
    public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties,
            @NonNull Set<String> locationTags) {
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(properties != null, "invalid null properties");
        Preconditions.checkArgument(properties != null, "invalid null properties");
        Preconditions.checkArgument(locationTags != null, "invalid null location tags");


        try {
        try {
            mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
            mService.addTestProvider(provider, properties, new ArrayList<>(locationTags),
                    mContext.getFeatureId());
                    mContext.getOpPackageName(), mContext.getFeatureId());
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
+75 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,10 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.location.util.identity.CallerIdentity;
import android.location.util.identity.CallerIdentity;


import com.android.internal.annotations.Immutable;

import java.util.Set;

/**
/**
 * Location manager local system service interface.
 * Location manager local system service interface.
 *
 *
@@ -38,6 +42,21 @@ public abstract class LocationManagerInternal {
        void onProviderEnabledChanged(String provider, int userId, boolean enabled);
        void onProviderEnabledChanged(String provider, int userId, boolean enabled);
    }
    }


    /**
     * Interface for getting callbacks when a location provider's location tags change.
     *
     * @see LocationTagInfo
     */
    public interface OnProviderLocationTagsChangeListener {

        /**
         * Called when the location tags for a provider change.
         *
         * @param providerLocationTagInfo The tag info for a provider.
         */
        void onLocationTagsChanged(@NonNull LocationTagInfo providerLocationTagInfo);
    }

    /**
    /**
     * Returns true if the given provider is enabled for the given user.
     * Returns true if the given provider is enabled for the given user.
     *
     *
@@ -88,4 +107,60 @@ public abstract class LocationManagerInternal {
     * provider, and the elapsed nanos since boot the current time was computed at.
     * provider, and the elapsed nanos since boot the current time was computed at.
     */
     */
    public abstract @Nullable LocationTime getGnssTimeMillis();
    public abstract @Nullable LocationTime getGnssTimeMillis();

    /**
     * Sets a listener for changes in the location providers' tags. Passing
     * {@code null} clears the current listener.
     *
     * @param listener The listener.
     */
    public abstract void setOnProviderLocationTagsChangeListener(
            @Nullable OnProviderLocationTagsChangeListener listener);

    /**
     * This class represents the location permission tags used by the location provider
     * packages in a given UID. These tags are strictly used for accessing state guarded
     * by the location permission(s) by a location provider which are required for the
     * provider to fulfill its function as being a location provider.
     */
    @Immutable
    public static class LocationTagInfo {
        private final int mUid;

        @NonNull
        private final String mPackageName;

        @Nullable
        private final Set<String> mLocationTags;

        public LocationTagInfo(int uid, @NonNull String packageName,
                @Nullable Set<String> locationTags) {
            mUid = uid;
            mPackageName = packageName;
            mLocationTags = locationTags;
        }

        /**
         * @return The UID for which tags are related.
         */
        public int getUid() {
            return mUid;
        }

        /**
         * @return The package for which tags are related.
         */
        @NonNull
        public String getPackageName() {
            return mPackageName;
        }

        /**
         * @return The tags for the package used for location related accesses.
         */
        @Nullable
        public Set<String> getTags() {
            return mLocationTags;
        }
    }
}
}
Loading