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

Commit 157749ed authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

fix:8489: Quick return fake location, fix calling package and uid doesn't...

fix:8489: Quick return fake location, fix calling package and uid doesn't match to resolve fakeLocationProvider

fix:8489: Fix unavailable isMyProcess method on CallerIdentity
parent e93b54fa
Loading
Loading
Loading
Loading
+89 −1
Original line number Diff line number Diff line
@@ -17,18 +17,29 @@

package com.android.server.location;

import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.location.Location;
import android.location.LocationResult;
import android.location.LocationManager;
import android.location.util.identity.CallerIdentity;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Process;
import android.os.SystemClock;
import android.util.Log;


import com.android.server.FgThread;
import com.android.server.location.provider.LocationProviderManager;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

public class FakeLocationResolver {
    public static final String TAG = "FakeLocationResolver";
@@ -39,6 +50,8 @@ public class FakeLocationResolver {
    private static final String PARAM_LATITUDE = "latitude";
    private static final String PARAM_LONGITUDE = "longitude";

    private static final String FAKE_LOCATION_PROVIDER = LocationManager.FUSED_PROVIDER;

    public static @Nullable LocationResult fakeLocations(
            @NonNull Context context,
            @Nullable LocationResult baseLocations,
@@ -82,7 +95,54 @@ public class FakeLocationResolver {
            return false;
        }
        final FakeLocation latLon = getFakeLocation(context, packageName, uid);
        if (latLon == null) return false;
        if (latLon == null) {
            return false;
        }

        return true;
    }

    public static @Nullable Location buildFakeLocation(
            @NonNull Context context,
            @NonNull CallerIdentity identity,
            @Nullable String provider
    ){
        final int uid = identity.getUid();
        final String packageName = identity.getPackageName();
        if (packageName == null || uid < 0) {
            Log.w(TAG, "FakeLocationResolver::buildFakeLocation invalid parameters");
            return null;
        }

        final FakeLocation latLon = getFakeLocation(context, packageName, uid);
        if (latLon == null) {
            return null;
        }

        final String fakeProvider = (provider != null) ? provider : FAKE_LOCATION_PROVIDER;
        return buildFakeLocationObject(latLon, fakeProvider);
    }

    public static boolean deliverFakeLocationQuickly(
            @NonNull Context context,
            @NonNull CallerIdentity identity,
            @NonNull LocationProviderManager.LocationTransport transport,
            @Nullable String provider
    ) {
        Location fakeLocation = buildFakeLocation(context, identity, provider);
        if (fakeLocation == null) {
            return false;
        }

        // Take the same executor as in all LocationRegistration constructor
        Executor executor = (identity.getPid() == Process.myPid()) ? FgThread.getExecutor() : DIRECT_EXECUTOR;
        executor.execute(() -> {
            try {
                transport.deliverOnLocationChanged(LocationResult.wrap(fakeLocation), null);
            } catch (Exception e) {
                Log.e(TAG, "FakeLocationResolver::deliverFakeLocationQuickly can't deliver fakelocation to "  + identity.getPackageName());
            }
        });

        return true;
    }
@@ -98,6 +158,9 @@ public class FakeLocationResolver {
    }

    private static @Nullable FakeLocation getFakeLocation(@NonNull Context context, @NonNull String packageName, int uid) {
        // getContentResolver requires that
        // binder.getCallingUId() and context.getOpPackageName() are coherent.
        final long ident = Binder.clearCallingIdentity();
        try {
            final Bundle extra = new Bundle();
            extra.putInt(PARAM_UID, uid);
@@ -113,6 +176,8 @@ public class FakeLocationResolver {
            }
        } catch(Exception e) {
            Log.w(TAG, "Can't getFakeLocation", e);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        return null;
    }
@@ -136,4 +201,27 @@ public class FakeLocationResolver {

        return fakedLocation;
    }

    private static @NonNull Location buildFakeLocationObject(
            @NonNull FakeLocation latLon,
            @NonNull String provider
    ) {
        Location fakedLocation = new Location(provider);
        fakedLocation.setLatitude(latLon.latitude);
        fakedLocation.setLongitude(latLon.longitude);

        // Set default value for all the other required fields.
        fakedLocation.setAccuracy(3f);
        fakedLocation.setAltitude(3.0);
        fakedLocation.setBearing(1f);
        fakedLocation.setSpeed(0.01f);
        fakedLocation.setTime(System.currentTimeMillis());
        fakedLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());

        fakedLocation.setBearingAccuracyDegrees(0.1f);
        fakedLocation.setVerticalAccuracyMeters(0.1f);
        fakedLocation.setSpeedAccuracyMetersPerSecond(0.01f);

        return fakedLocation;
    }
}
+41 −10
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ public class LocationProviderManager extends
                AbstractLocationProvider.State newState);
    }

    protected interface LocationTransport {
    public interface LocationTransport {

        void deliverOnLocationChanged(LocationResult locationResult,
                @Nullable IRemoteCallback onCompleteCallback) throws Exception;
@@ -1653,15 +1653,19 @@ public class LocationProviderManager extends
            return null;
        }

        Location location = getPermittedLocation(
        Location fakeLocation = FakeLocationResolver.buildFakeLocation(mContext, identity, null);
        Location location = null;
        if (fakeLocation != null) {
            location = fakeLocation;
        } else {
            location = getPermittedLocation(
                    getLastLocationUnsafe(
                            identity.getUserId(),
                            permissionLevel,
                            request.isBypass(),
                            Long.MAX_VALUE),
                    permissionLevel);

        location = FakeLocationResolver.fakeLocation(mContext, location, identity);
        }

        if (location != null && identity.getPid() == Process.myPid()) {
            // if delivering to the same process, make a copy of the location first (since
@@ -1768,6 +1772,15 @@ public class LocationProviderManager extends
                    .build();
        }

        if (FakeLocationResolver.deliverFakeLocationQuickly(
                mContext,
                identity,
                new GetCurrentLocationTransport(callback),
                request.getProvider()
        )) {
            return CancellationSignal.createTransport();
        }

        GetCurrentLocationListenerRegistration registration =
                new GetCurrentLocationListenerRegistration(
                        request,
@@ -1811,6 +1824,15 @@ public class LocationProviderManager extends

    public void registerLocationRequest(LocationRequest request, CallerIdentity identity,
            @PermissionLevel int permissionLevel, ILocationListener listener) {
        if (FakeLocationResolver.deliverFakeLocationQuickly(
                mContext,
                identity,
                new LocationListenerTransport(listener),
                request.getProvider()
        )) {
            return;
        }

        LocationListenerRegistration registration = new LocationListenerRegistration(
                request,
                identity,
@@ -1830,6 +1852,15 @@ public class LocationProviderManager extends

    public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity,
            @PermissionLevel int permissionLevel, PendingIntent pendingIntent) {
        if (FakeLocationResolver.deliverFakeLocationQuickly(
                mContext,
                callerIdentity,
                new LocationPendingIntentTransport(mContext, pendingIntent),
                request.getProvider()
        )) {
            return;
        }

        LocationPendingIntentRegistration registration = new LocationPendingIntentRegistration(
                request,
                callerIdentity,