Loading services/core/java/com/android/server/location/FakeLocationResolver.java +89 −1 Original line number Diff line number Diff line Loading @@ -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"; Loading @@ -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, Loading Loading @@ -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; } Loading @@ -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); Loading @@ -113,6 +176,8 @@ public class FakeLocationResolver { } } catch(Exception e) { Log.w(TAG, "Can't getFakeLocation", e); } finally { Binder.restoreCallingIdentity(ident); } return null; } Loading @@ -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; } } services/core/java/com/android/server/location/provider/LocationProviderManager.java +41 −10 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ public class LocationProviderManager extends AbstractLocationProvider.State newState); } protected interface LocationTransport { public interface LocationTransport { void deliverOnLocationChanged(LocationResult locationResult, @Nullable IRemoteCallback onCompleteCallback) throws Exception; Loading Loading @@ -1681,15 +1681,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 Loading Loading @@ -1832,6 +1836,15 @@ public class LocationProviderManager extends .build(); } if (FakeLocationResolver.deliverFakeLocationQuickly( mContext, identity, new GetCurrentLocationTransport(callback), request.getProvider() )) { return CancellationSignal.createTransport(); } GetCurrentLocationListenerRegistration registration = new GetCurrentLocationListenerRegistration( request, Loading Loading @@ -1889,6 +1902,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, Loading @@ -1908,6 +1930,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, Loading Loading
services/core/java/com/android/server/location/FakeLocationResolver.java +89 −1 Original line number Diff line number Diff line Loading @@ -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"; Loading @@ -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, Loading Loading @@ -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; } Loading @@ -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); Loading @@ -113,6 +176,8 @@ public class FakeLocationResolver { } } catch(Exception e) { Log.w(TAG, "Can't getFakeLocation", e); } finally { Binder.restoreCallingIdentity(ident); } return null; } Loading @@ -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; } }
services/core/java/com/android/server/location/provider/LocationProviderManager.java +41 −10 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ public class LocationProviderManager extends AbstractLocationProvider.State newState); } protected interface LocationTransport { public interface LocationTransport { void deliverOnLocationChanged(LocationResult locationResult, @Nullable IRemoteCallback onCompleteCallback) throws Exception; Loading Loading @@ -1681,15 +1681,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 Loading Loading @@ -1832,6 +1836,15 @@ public class LocationProviderManager extends .build(); } if (FakeLocationResolver.deliverFakeLocationQuickly( mContext, identity, new GetCurrentLocationTransport(callback), request.getProvider() )) { return CancellationSignal.createTransport(); } GetCurrentLocationListenerRegistration registration = new GetCurrentLocationListenerRegistration( request, Loading Loading @@ -1889,6 +1902,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, Loading @@ -1908,6 +1930,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, Loading