Skip to content

Commit

Permalink
Added location restriction for Google Play services
Browse files Browse the repository at this point in the history
See "contributing" for how to add the Google Play Services library

Refs M66B#1011
  • Loading branch information
M66B committed Dec 26, 2013
1 parent c652a67 commit 22b726b
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 9 deletions.
7 changes: 7 additions & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
android:label="@string/app_name"
android:largeHeap="true"
android:theme="@style/CustomTheme.Light" >

<!-- Xposed -->
<meta-data
android:name="xposedmodule"
android:value="true" />
Expand All @@ -42,6 +44,11 @@
android:name="xposeddescription"
android:value="The ultimate privacy manager" />

<!-- Google Play services -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<!-- Samsung multi window support -->
<meta-data
android:name="com.sec.android.support.multiwindow"
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@ Test and beta releases will have experimental functions enabled by default.

**Next test/beta release**

* Fixed getting restrictions for multi-user environments ([issue](https://github.com/M66B/XPrivacy/issues/357))
* Fixed restricting internet and storage for multi-user environments ([issue](https://github.com/M66B/XPrivacy/issues/357))
* Experimental functions enabled by default
* Added location restriction for Google Play services ([issue](https://github.com/M66B/XPrivacy/issues/1011))
* Updated German translation
* Updated Vietnamese translation

**Next stable release**

* Fixed getting restrictions for multi-user environments ([issue](https://github.com/M66B/XPrivacy/issues/357))
* Fixed restricting internet and storage for multi-user environments ([issue](https://github.com/M66B/XPrivacy/issues/357))
* Experimental functions disabled by default
* Added location restriction for Google Play services ([issue](https://github.com/M66B/XPrivacy/issues/1011))
* Updated German translation
* Updated Vietnamese translation

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ For easy usage, data is restricted by category:
* return fake supplicant disconnected state
<a name="location"></a>
* Location
* return a random or set location
* return a random or set location (also for Google Play services)
* return empty cell location
* return an empty list of (neighboring) cell info
* prevents geofences from being set
* prevents geofences from being set (also for Google Play services)
* prevents proximity alerts from being set
* prevents sending NMEA data to an application
* prevent phone state from being sent to an application
Expand Down Expand Up @@ -827,6 +827,7 @@ Using Eclipse:
* Close Eclipse and copy the project from the temporary location over the imported project
* Make sure you copy all hidden files
* Add the Xposed library to the build path as described [here](https://github.com/rovo89/XposedBridge/wiki/Development-tutorial#making-the-project-an-xposed-module)
* Add the Google Play services library as decribed [here](https://developer.android.com/google/play-services/setup.html)

Testing:

Expand Down
7 changes: 6 additions & 1 deletion assets/meta.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,12 @@
<Hook restriction="location" method="getNeighboringCellInfo" permissions="ACCESS_COARSE_UPDATES" sdk="14" />
<Hook restriction="location" method="getAllCellInfo" permissions="ACCESS_COARSE_UPDATES" sdk="17" />
<Hook restriction="location" method="getScanResults" dangerous="true" permissions="ACCESS_WIFI_STATE" sdk="14" />
<Hook restriction="location" method="connect" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" sdk="14" />
<Hook restriction="location" method="GMS.addGeofences" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" />
<Hook restriction="location" method="GMS.connect" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" dangerous="true" />
<Hook restriction="location" method="GMS.getLastLocation" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" />
<Hook restriction="location" method="GMS.removeGeofences" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" />
<Hook restriction="location" method="GMS.removeLocationUpdates" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" />
<Hook restriction="location" method="GMS.requestLocationUpdates" permissions="ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION" />

<Hook restriction="media" method="startRecording" permissions="RECORD_AUDIO" sdk="14" />
<Hook restriction="media" method="setPreviewCallback" permissions="CAMERA" sdk="14" />
Expand Down
22 changes: 21 additions & 1 deletion proguard-project.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,28 @@
# public *;
#}

#Xposed
-libraryjars XposedBridgeApi-42.jar

-keep class biz.bokhorst.xprivacy.XPrivacy { *; }
#XPrivacy
-keep class biz.bokhorst.xprivacy.XPrivacy {*; }
-keepnames class biz.bokhorst.xprivacy.X* { }
-keepclassmembers class biz.bokhorst.xprivacy.Util { public static boolean isXposedEnabled(); }

#Google Play Services
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}

-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}

-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
@com.google.android.gms.common.annotation.KeepName *;
}

-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
2 changes: 2 additions & 0 deletions project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.

# Project target.
target=android-19
android.library=false
android.library.reference.1=../google-play-services_lib
2 changes: 1 addition & 1 deletion src/biz/bokhorst/xprivacy/PrivacyManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ else if (qName.equals("Hook")) {
String dangerous = attributes.getValue("dangerous");
String restart = attributes.getValue("restart");
String permissions = attributes.getValue("permissions");
int sdk = Integer.parseInt(attributes.getValue("sdk"));
int sdk = (attributes.getValue("sdk") == null ? 0 : Integer.parseInt(attributes.getValue("sdk")));

// Add meta data
if (Build.VERSION.SDK_INT >= sdk) {
Expand Down
101 changes: 97 additions & 4 deletions src/biz/bokhorst/xprivacy/XLocationClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,140 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import android.location.Location;
import android.os.Binder;
import android.util.Log;

import com.google.android.gms.location.LocationListener;

import de.robv.android.xposed.XC_MethodHook.MethodHookParam;

public class XLocationClient extends XHook {
private Methods mMethod;
private static final Map<LocationListener, XLocationListener> mListener = new WeakHashMap<LocationListener, XLocationListener>();

private XLocationClient(Methods method, String restrictionName) {
super(restrictionName, method.name(), null);
super(restrictionName, method.name(), String.format("GMS.%s", method.name()));
mMethod = method;
}

public String getClassName() {
return "com.google.android.gms.location.LocationClient";
}

// @formatter:off

// void addGeofences(List<Geofence> geofences, PendingIntent pendingIntent, LocationClient.OnAddGeofencesResultListener listener)
// void connect()
// Location getLastLocation()
// void removeGeofences(List<String> geofenceRequestIds, LocationClient.OnRemoveGeofencesResultListener listener)
// void removeGeofences(PendingIntent pendingIntent, LocationClient.OnRemoveGeofencesResultListener listener)
// void removeLocationUpdates(LocationListener listener)
// void removeLocationUpdates(PendingIntent callbackIntent)
// void requestLocationUpdates(LocationRequest request, PendingIntent callbackIntent)
// void requestLocationUpdates(LocationRequest request, LocationListener listener)
// void requestLocationUpdates(LocationRequest request, LocationListener listener, Looper looper)
// https://developer.android.com/reference/com/google/android/gms/location/LocationClient.html

// @formatter:on

private enum Methods {
connect
addGeofences, connect, getLastLocation, removeGeofences, removeLocationUpdates, requestLocationUpdates
};

public static List<XHook> getInstances() {
List<XHook> listHook = new ArrayList<XHook>();
listHook.add(new XLocationClient(Methods.addGeofences, PrivacyManager.cLocation));
listHook.add(new XLocationClient(Methods.connect, PrivacyManager.cLocation));
listHook.add(new XLocationClient(Methods.getLastLocation, PrivacyManager.cLocation));
listHook.add(new XLocationClient(Methods.removeGeofences, PrivacyManager.cLocation));
listHook.add(new XLocationClient(Methods.removeLocationUpdates, PrivacyManager.cLocation));
listHook.add(new XLocationClient(Methods.requestLocationUpdates, PrivacyManager.cLocation));
return listHook;
}

@Override
protected void before(MethodHookParam param) throws Throwable {
if (mMethod == Methods.connect) {
if (mMethod == Methods.addGeofences || mMethod == Methods.connect || mMethod == Methods.removeGeofences) {
if (isRestricted(param))
param.setResult(null);
} else if (mMethod == Methods.getLastLocation) {
// Do nothing
} else if (mMethod == Methods.removeLocationUpdates) {
removeLocationListener(param);
} else if (mMethod == Methods.requestLocationUpdates) {
replaceLocationListener(param);
} else
Util.log(this, Log.WARN, "Unknown method=" + param.method.getName());
}

@Override
protected void after(MethodHookParam param) throws Throwable {
// Do nothing
if (mMethod == Methods.addGeofences || mMethod == Methods.connect || mMethod == Methods.removeGeofences) {
// Do nothing
} else if (mMethod == Methods.getLastLocation) {
Location location = (Location) param.getResult();
if (location != null)
if (isRestricted(param))
param.setResult(PrivacyManager.getDefacedLocation(Binder.getCallingUid(), location));
} else if (mMethod == Methods.removeLocationUpdates) {
// Do nothing
} else if (mMethod == Methods.requestLocationUpdates) {
// Do nothing
} else
Util.log(this, Log.WARN, "Unknown method=" + param.method.getName());
}

private void replaceLocationListener(MethodHookParam param) throws Throwable {
if (param.args.length >= 2 && param.args[1] != null
&& LocationListener.class.isAssignableFrom(param.args[1].getClass())) {
if (!(param.args[1] instanceof XLocationListener)) {
LocationListener listener = (LocationListener) param.args[1];
if (listener != null) {
XLocationListener xListener = new XLocationListener(listener);
synchronized (mListener) {
mListener.put(listener, xListener);
Util.log(this, Log.INFO, "Added count=" + mListener.size());
}
param.args[1] = xListener;
}
}
} else
param.setResult(null);
}

private void removeLocationListener(MethodHookParam param) {
if (param.args.length >= 1 && param.args[0] != null
&& LocationListener.class.isAssignableFrom(param.args[0].getClass())) {
LocationListener listener = (LocationListener) param.args[0];
synchronized (mListener) {
XLocationListener xlistener = mListener.get(listener);
if (xlistener == null)
Util.log(this, Log.WARN, "Not found count=" + mListener.size());
else {
param.args[0] = xlistener;
mListener.remove(listener);
}
}
} else
param.setResult(null);
}

private class XLocationListener implements LocationListener {

private LocationListener mLocationListener;

public XLocationListener(LocationListener locationListener) {
mLocationListener = locationListener;
}

@Override
public void onLocationChanged(Location location) {
mLocationListener.onLocationChanged(location == null ? location : PrivacyManager.getDefacedLocation(
Binder.getCallingUid(), location));
}
}
}

0 comments on commit 22b726b

Please sign in to comment.