Loading services/core/java/com/android/server/location/FakeLocationResolver.java +84 −1 Original line number Diff line number Diff line Loading @@ -17,18 +17,26 @@ 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.Bundle; 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 +47,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 +92,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, provider); } 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.isMyProcess() ? 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 @@ -101,6 +158,9 @@ public class FakeLocationResolver { try { final Bundle extra = new Bundle(); extra.putInt(PARAM_UID, uid); // getContentResolver requires that // binder.getCallingUId() and context.getOpPackageName() are coherent. // which may require Binder.clearCallingIdentity() calls. final Bundle result = context.getContentResolver().call( Uri.parse(FAKE_LOCATIONS_URI), "", Loading Loading @@ -136,4 +196,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 +50 −16 Original line number Diff line number Diff line Loading @@ -188,7 +188,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 @@ -1752,13 +1752,28 @@ public class LocationProviderManager extends return null; } Location location = getPermittedLocation( Location fakeLocation = null; synchronized (mMultiplexerLock) { final long ident = Binder.clearCallingIdentity(); try { fakeLocation = FakeLocationResolver.buildFakeLocation(mContext, identity, null); } finally { Binder.restoreCallingIdentity(ident); } } Location location = null; if (fakeLocation != null) { location = fakeLocation; } else { location = getPermittedLocation( getLastLocationUnsafe( identity.getUserId(), permissionLevel, request.isBypass(), Long.MAX_VALUE), permissionLevel); } if (location != null) { // lastly - note app ops Loading @@ -1767,8 +1782,6 @@ public class LocationProviderManager extends return null; } location = FakeLocationResolver.fakeLocation(mContext, location, identity); // if delivering to the same process, make a copy of the location first (since // location is mutable) if (identity.getPid() == Process.myPid()) { Loading Loading @@ -1924,11 +1937,18 @@ public class LocationProviderManager extends Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { if (!FakeLocationResolver.deliverFakeLocationQuickly( mContext, identity, new GetCurrentLocationTransport(callback), request.getProvider() )) { putRegistration(callback.asBinder(), registration); if (!registration.isActive()) { // if the registration never activated, fail it immediately registration.deliverNull(); } } } finally { Binder.restoreCallingIdentity(ident); } Loading Loading @@ -1978,7 +1998,14 @@ public class LocationProviderManager extends Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { if (!FakeLocationResolver.deliverFakeLocationQuickly( mContext, identity, new LocationListenerTransport(listener), request.getProvider() )) { putRegistration(listener.asBinder(), registration); } } finally { Binder.restoreCallingIdentity(ident); } Loading @@ -1997,7 +2024,14 @@ public class LocationProviderManager extends Preconditions.checkState(mState != STATE_STOPPED); final long identity = Binder.clearCallingIdentity(); try { if (!FakeLocationResolver.deliverFakeLocationQuickly( mContext, callerIdentity, new LocationPendingIntentTransport(mContext, pendingIntent), request.getProvider() )) { putRegistration(pendingIntent, registration); } } finally { Binder.restoreCallingIdentity(identity); } Loading Loading
services/core/java/com/android/server/location/FakeLocationResolver.java +84 −1 Original line number Diff line number Diff line Loading @@ -17,18 +17,26 @@ 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.Bundle; 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 +47,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 +92,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, provider); } 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.isMyProcess() ? 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 @@ -101,6 +158,9 @@ public class FakeLocationResolver { try { final Bundle extra = new Bundle(); extra.putInt(PARAM_UID, uid); // getContentResolver requires that // binder.getCallingUId() and context.getOpPackageName() are coherent. // which may require Binder.clearCallingIdentity() calls. final Bundle result = context.getContentResolver().call( Uri.parse(FAKE_LOCATIONS_URI), "", Loading Loading @@ -136,4 +196,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 +50 −16 Original line number Diff line number Diff line Loading @@ -188,7 +188,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 @@ -1752,13 +1752,28 @@ public class LocationProviderManager extends return null; } Location location = getPermittedLocation( Location fakeLocation = null; synchronized (mMultiplexerLock) { final long ident = Binder.clearCallingIdentity(); try { fakeLocation = FakeLocationResolver.buildFakeLocation(mContext, identity, null); } finally { Binder.restoreCallingIdentity(ident); } } Location location = null; if (fakeLocation != null) { location = fakeLocation; } else { location = getPermittedLocation( getLastLocationUnsafe( identity.getUserId(), permissionLevel, request.isBypass(), Long.MAX_VALUE), permissionLevel); } if (location != null) { // lastly - note app ops Loading @@ -1767,8 +1782,6 @@ public class LocationProviderManager extends return null; } location = FakeLocationResolver.fakeLocation(mContext, location, identity); // if delivering to the same process, make a copy of the location first (since // location is mutable) if (identity.getPid() == Process.myPid()) { Loading Loading @@ -1924,11 +1937,18 @@ public class LocationProviderManager extends Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { if (!FakeLocationResolver.deliverFakeLocationQuickly( mContext, identity, new GetCurrentLocationTransport(callback), request.getProvider() )) { putRegistration(callback.asBinder(), registration); if (!registration.isActive()) { // if the registration never activated, fail it immediately registration.deliverNull(); } } } finally { Binder.restoreCallingIdentity(ident); } Loading Loading @@ -1978,7 +1998,14 @@ public class LocationProviderManager extends Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { if (!FakeLocationResolver.deliverFakeLocationQuickly( mContext, identity, new LocationListenerTransport(listener), request.getProvider() )) { putRegistration(listener.asBinder(), registration); } } finally { Binder.restoreCallingIdentity(ident); } Loading @@ -1997,7 +2024,14 @@ public class LocationProviderManager extends Preconditions.checkState(mState != STATE_STOPPED); final long identity = Binder.clearCallingIdentity(); try { if (!FakeLocationResolver.deliverFakeLocationQuickly( mContext, callerIdentity, new LocationPendingIntentTransport(mContext, pendingIntent), request.getProvider() )) { putRegistration(pendingIntent, registration); } } finally { Binder.restoreCallingIdentity(identity); } Loading