Loading location/java/android/location/Location.java +1 −1 Original line number Diff line number Diff line Loading @@ -1305,7 +1305,7 @@ public class Location implements Parcelable { * @see LocationManager#addTestProvider */ public boolean isMock() { return false; return (mFieldsMask & HAS_MOCK_PROVIDER_MASK) != 0; } /** Loading services/core/java/com/android/server/location/FakeLocationResolver.java 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 E FOUNDATION * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package com.android.server.location; import android.content.Context; import android.location.Location; import android.location.LocationResult; import android.location.util.identity.CallerIdentity; import android.net.Uri; import android.os.Bundle; import android.telecom.Call; import android.util.Log; import java.util.ArrayList; import java.util.List; public class FakeLocationResolver { public static final String TAG = "FakeLocationResolver"; private static final String FAKE_LOCATIONS_URI = "content://foundation.e.advancedprivacy.fakelocations"; private static final String PARAM_UID = "uid"; private static final String PARAM_LATITUDE = "latitude"; private static final String PARAM_LONGITUDE = "longitude"; public static LocationResult fakeLocations(Context context, LocationResult baseLocations, CallerIdentity identity) { int uid = identity.getUid(); String packageName = identity.getPackageName(); if (baseLocations == null || context == null || packageName == null || uid < 0) { Log.w(TAG, "FakeLocationResolver::fakeLocations invalid parameters"); return baseLocations; } FakeLocation latLon = getFakeLocation(context, packageName, uid); if (latLon == null) return baseLocations; return LocationResult.wrap(overrideLatLons(baseLocations.asList(), latLon)); } public static Location fakeLocation(Context context, Location baseLocation, CallerIdentity identity) { int uid = identity.getUid(); String packageName = identity.getPackageName(); if (baseLocation == null || context == null || packageName == null || uid < 0) { Log.w(TAG, "FakeLocationResolver::fakeLocation invalid parameters"); return baseLocation; } FakeLocation latLon = getFakeLocation(context, packageName, uid); if (latLon == null) return baseLocation; return overrideLatLons(baseLocation, latLon); } public static boolean hasFakeLocation(Context context, CallerIdentity identity) { int uid = identity.getUid(); String packageName = identity.getPackageName(); if (context == null || packageName == null || uid < 0) { Log.w(TAG, "FakeLocationResolver::hasFakeLocation invalid parameters"); return false; } FakeLocation latLon = getFakeLocation(context, packageName, uid); if (latLon == null) return false; return true; } private static class FakeLocation { Double latitude; Double longitude; public FakeLocation(Double latitude, Double longitude) { this.latitude = latitude; this.longitude = longitude; } } private static FakeLocation getFakeLocation(Context context, String packageName, int uid) { try { Bundle extra = new Bundle(); extra.putInt(PARAM_UID, uid); Bundle result = context.getContentResolver().call( Uri.parse(FAKE_LOCATIONS_URI), "", packageName, extra ); if (result != null && result.containsKey(PARAM_LATITUDE) && result.containsKey(PARAM_LONGITUDE)) { return new FakeLocation(result.getDouble(PARAM_LATITUDE), result.getDouble(PARAM_LONGITUDE)); } } catch(Exception e) { Log.w("AP-FakeLocation", "Can't getFakeLocation", e); } return null; } private static List<Location> overrideLatLons(List<Location> baseLocations, FakeLocation latLon) { ArrayList<Location> fakedLocations = new ArrayList<Location>(baseLocations.size()); for (Location location: baseLocations) { Location fakedLocation = overrideLatLons(location, latLon); fakedLocations.add(fakedLocation); } return fakedLocations; } private static Location overrideLatLons(Location baseLocation, FakeLocation latLon) { Location fakedLocation = new Location(baseLocation); fakedLocation.setLatitude(latLon.latitude); fakedLocation.setLongitude(latLon.longitude); fakedLocation.setAltitude(3.0); fakedLocation.setSpeed(0.01f); return fakedLocation; } } services/core/java/com/android/server/location/geofence/GeofenceManager.java +4 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.server.PendingIntentUtils; import com.android.server.location.FakeLocationResolver; import com.android.server.location.LocationPermissions; import com.android.server.location.injector.Injector; import com.android.server.location.injector.LocationPermissionsHelper; Loading Loading @@ -298,6 +299,9 @@ public class GeofenceManager extends CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, AppOpsManager.toReceiverId(pendingIntent)); if (FakeLocationResolver.hasFakeLocation(mContext, identity)) { return; } final long ident = Binder.clearCallingIdentity(); try { Loading services/core/java/com/android/server/location/provider/LocationProviderManager.java +11 −5 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.location.FakeLocationResolver; import com.android.server.location.LocationPermissions; import com.android.server.location.LocationPermissions.PermissionLevel; import com.android.server.location.fudger.LocationFudger; Loading Loading @@ -965,13 +966,15 @@ public class LocationProviderManager extends @Override public void operate(LocationTransport listener) throws Exception { LocationResult fakedLocationResult = FakeLocationResolver.fakeLocations(mContext, locationResult, getIdentity()); // if delivering to the same process, make a copy of the location first (since // location is mutable) LocationResult deliverLocationResult; if (getIdentity().getPid() == Process.myPid()) { deliverLocationResult = locationResult.deepCopy(); deliverLocationResult = fakedLocationResult.deepCopy(); } else { deliverLocationResult = locationResult; deliverLocationResult = fakedLocationResult; } listener.deliverOnLocationChanged(deliverLocationResult, Loading Loading @@ -1268,13 +1271,14 @@ public class LocationProviderManager extends return new ListenerOperation<LocationTransport>() { @Override public void operate(LocationTransport listener) throws Exception { LocationResult fakedLocationResult = FakeLocationResolver.fakeLocations(mContext, locationResult, getIdentity()); // if delivering to the same process, make a copy of the location first (since // location is mutable) LocationResult deliverLocationResult; if (getIdentity().getPid() == Process.myPid() && locationResult != null) { deliverLocationResult = locationResult.deepCopy(); if (getIdentity().getPid() == Process.myPid() && fakedLocationResult != null) { deliverLocationResult = fakedLocationResult.deepCopy(); } else { deliverLocationResult = locationResult; deliverLocationResult = fakedLocationResult; } // we currently don't hold a wakelock for getCurrentLocation deliveries Loading Loading @@ -1656,6 +1660,8 @@ public class LocationProviderManager extends 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 // location is mutable) Loading Loading
location/java/android/location/Location.java +1 −1 Original line number Diff line number Diff line Loading @@ -1305,7 +1305,7 @@ public class Location implements Parcelable { * @see LocationManager#addTestProvider */ public boolean isMock() { return false; return (mFieldsMask & HAS_MOCK_PROVIDER_MASK) != 0; } /** Loading
services/core/java/com/android/server/location/FakeLocationResolver.java 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 E FOUNDATION * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package com.android.server.location; import android.content.Context; import android.location.Location; import android.location.LocationResult; import android.location.util.identity.CallerIdentity; import android.net.Uri; import android.os.Bundle; import android.telecom.Call; import android.util.Log; import java.util.ArrayList; import java.util.List; public class FakeLocationResolver { public static final String TAG = "FakeLocationResolver"; private static final String FAKE_LOCATIONS_URI = "content://foundation.e.advancedprivacy.fakelocations"; private static final String PARAM_UID = "uid"; private static final String PARAM_LATITUDE = "latitude"; private static final String PARAM_LONGITUDE = "longitude"; public static LocationResult fakeLocations(Context context, LocationResult baseLocations, CallerIdentity identity) { int uid = identity.getUid(); String packageName = identity.getPackageName(); if (baseLocations == null || context == null || packageName == null || uid < 0) { Log.w(TAG, "FakeLocationResolver::fakeLocations invalid parameters"); return baseLocations; } FakeLocation latLon = getFakeLocation(context, packageName, uid); if (latLon == null) return baseLocations; return LocationResult.wrap(overrideLatLons(baseLocations.asList(), latLon)); } public static Location fakeLocation(Context context, Location baseLocation, CallerIdentity identity) { int uid = identity.getUid(); String packageName = identity.getPackageName(); if (baseLocation == null || context == null || packageName == null || uid < 0) { Log.w(TAG, "FakeLocationResolver::fakeLocation invalid parameters"); return baseLocation; } FakeLocation latLon = getFakeLocation(context, packageName, uid); if (latLon == null) return baseLocation; return overrideLatLons(baseLocation, latLon); } public static boolean hasFakeLocation(Context context, CallerIdentity identity) { int uid = identity.getUid(); String packageName = identity.getPackageName(); if (context == null || packageName == null || uid < 0) { Log.w(TAG, "FakeLocationResolver::hasFakeLocation invalid parameters"); return false; } FakeLocation latLon = getFakeLocation(context, packageName, uid); if (latLon == null) return false; return true; } private static class FakeLocation { Double latitude; Double longitude; public FakeLocation(Double latitude, Double longitude) { this.latitude = latitude; this.longitude = longitude; } } private static FakeLocation getFakeLocation(Context context, String packageName, int uid) { try { Bundle extra = new Bundle(); extra.putInt(PARAM_UID, uid); Bundle result = context.getContentResolver().call( Uri.parse(FAKE_LOCATIONS_URI), "", packageName, extra ); if (result != null && result.containsKey(PARAM_LATITUDE) && result.containsKey(PARAM_LONGITUDE)) { return new FakeLocation(result.getDouble(PARAM_LATITUDE), result.getDouble(PARAM_LONGITUDE)); } } catch(Exception e) { Log.w("AP-FakeLocation", "Can't getFakeLocation", e); } return null; } private static List<Location> overrideLatLons(List<Location> baseLocations, FakeLocation latLon) { ArrayList<Location> fakedLocations = new ArrayList<Location>(baseLocations.size()); for (Location location: baseLocations) { Location fakedLocation = overrideLatLons(location, latLon); fakedLocations.add(fakedLocation); } return fakedLocations; } private static Location overrideLatLons(Location baseLocation, FakeLocation latLon) { Location fakedLocation = new Location(baseLocation); fakedLocation.setLatitude(latLon.latitude); fakedLocation.setLongitude(latLon.longitude); fakedLocation.setAltitude(3.0); fakedLocation.setSpeed(0.01f); return fakedLocation; } }
services/core/java/com/android/server/location/geofence/GeofenceManager.java +4 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.server.PendingIntentUtils; import com.android.server.location.FakeLocationResolver; import com.android.server.location.LocationPermissions; import com.android.server.location.injector.Injector; import com.android.server.location.injector.LocationPermissionsHelper; Loading Loading @@ -298,6 +299,9 @@ public class GeofenceManager extends CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, AppOpsManager.toReceiverId(pendingIntent)); if (FakeLocationResolver.hasFakeLocation(mContext, identity)) { return; } final long ident = Binder.clearCallingIdentity(); try { Loading
services/core/java/com/android/server/location/provider/LocationProviderManager.java +11 −5 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.location.FakeLocationResolver; import com.android.server.location.LocationPermissions; import com.android.server.location.LocationPermissions.PermissionLevel; import com.android.server.location.fudger.LocationFudger; Loading Loading @@ -965,13 +966,15 @@ public class LocationProviderManager extends @Override public void operate(LocationTransport listener) throws Exception { LocationResult fakedLocationResult = FakeLocationResolver.fakeLocations(mContext, locationResult, getIdentity()); // if delivering to the same process, make a copy of the location first (since // location is mutable) LocationResult deliverLocationResult; if (getIdentity().getPid() == Process.myPid()) { deliverLocationResult = locationResult.deepCopy(); deliverLocationResult = fakedLocationResult.deepCopy(); } else { deliverLocationResult = locationResult; deliverLocationResult = fakedLocationResult; } listener.deliverOnLocationChanged(deliverLocationResult, Loading Loading @@ -1268,13 +1271,14 @@ public class LocationProviderManager extends return new ListenerOperation<LocationTransport>() { @Override public void operate(LocationTransport listener) throws Exception { LocationResult fakedLocationResult = FakeLocationResolver.fakeLocations(mContext, locationResult, getIdentity()); // if delivering to the same process, make a copy of the location first (since // location is mutable) LocationResult deliverLocationResult; if (getIdentity().getPid() == Process.myPid() && locationResult != null) { deliverLocationResult = locationResult.deepCopy(); if (getIdentity().getPid() == Process.myPid() && fakedLocationResult != null) { deliverLocationResult = fakedLocationResult.deepCopy(); } else { deliverLocationResult = locationResult; deliverLocationResult = fakedLocationResult; } // we currently don't hold a wakelock for getCurrentLocation deliveries Loading Loading @@ -1656,6 +1660,8 @@ public class LocationProviderManager extends 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 // location is mutable) Loading