diff --git a/briar-android/src/main/java/org/briarproject/briar/android/ScreenFilterMonitorImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/ScreenFilterMonitorImpl.java
index cb195108af4f941db686df4c512cb05cd6601b31..8ec4b3508fb77ad84a709427eb91eda8f03749f2 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/ScreenFilterMonitorImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/ScreenFilterMonitorImpl.java
@@ -6,10 +6,10 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.support.annotation.NonNull;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
 import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v7.preference.PreferenceManager;
@@ -19,11 +19,16 @@ import org.briarproject.bramble.api.lifecycle.ServiceException;
 import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
 import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.android.ScreenFilterMonitor;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
@@ -31,32 +36,57 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+import static android.content.Intent.ACTION_PACKAGE_ADDED;
+import static android.content.Intent.EXTRA_REPLACING;
+import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.GET_SIGNATURES;
+import static java.util.logging.Level.WARNING;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
 public class ScreenFilterMonitorImpl extends BroadcastReceiver
-		implements Service,
-		ScreenFilterMonitor {
+		implements Service, ScreenFilterMonitor {
 
 	private static final Logger LOG =
 			Logger.getLogger(ScreenFilterMonitorImpl.class.getName());
 	private static final String PREF_SCREEN_FILTER_APPS =
 			"shownScreenFilterApps";
+
+	/*
+ 	 * Ignore Play Services if it uses this package name and public key - it's
+	 * effectively a system app, but not flagged as such on older systems
+	 */
+	private static final String PLAY_SERVICES_PACKAGE =
+			"com.google.android.gms";
+	private static final String PLAY_SERVICES_PUBLIC_KEY =
+			"30820120300D06092A864886F70D01010105000382010D0030820108" +
+					"0282010100AB562E00D83BA208AE0A966F124E29DA11F2AB56D08F58" +
+					"E2CCA91303E9B754D372F640A71B1DCB130967624E4656A7776A9219" +
+					"3DB2E5BFB724A91E77188B0E6A47A43B33D9609B77183145CCDF7B2E" +
+					"586674C9E1565B1F4C6A5955BFF251A63DABF9C55C27222252E875E4" +
+					"F8154A645F897168C0B1BFC612EABF785769BB34AA7984DC7E2EA276" +
+					"4CAE8307D8C17154D7EE5F64A51A44A602C249054157DC02CD5F5C0E" +
+					"55FBEF8519FBE327F0B1511692C5A06F19D18385F5C4DBC2D6B93F68" +
+					"CC2979C70E18AB93866B3BD5DB8999552A0E3B4C99DF58FB918BEDC1" +
+					"82BA35E003C1B4B10DD244A8EE24FFFD333872AB5221985EDAB0FC0D" +
+					"0B145B6AA192858E79020103";
+
 	private final Context appContext;
 	private final AndroidExecutor androidExecutor;
-	private final LinkedList<String> appNames = new LinkedList<>();
 	private final PackageManager pm;
 	private final SharedPreferences prefs;
 	private final AtomicBoolean used = new AtomicBoolean(false);
+
+	// The following must only be accessed on the UI thread
 	private final Set<String> apps = new HashSet<>();
 	private final Set<String> shownApps;
-	// Used solely for the UiThread
 	private boolean serviceStarted = false;
 
 	@Inject
@@ -75,7 +105,7 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 			@Override
 			public Void call() {
 				IntentFilter intentFilter = new IntentFilter();
-				intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+				intentFilter.addAction(ACTION_PACKAGE_ADDED);
 				intentFilter.addDataScheme("package");
 				appContext.registerReceiver(ScreenFilterMonitorImpl.this,
 						intentFilter);
@@ -109,9 +139,8 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 	}
 
 	private Set<String> getShownScreenFilterApps() {
-		// res must not be modified
-		Set<String> s =
-				prefs.getStringSet(PREF_SCREEN_FILTER_APPS, null);
+		// Result must not be modified
+		Set<String> s = prefs.getStringSet(PREF_SCREEN_FILTER_APPS, null);
 		HashSet<String> result = new HashSet<>();
 		if (s != null) {
 			result.addAll(s);
@@ -121,7 +150,7 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 
 	@Override
 	public void onReceive(Context context, Intent intent) {
-		if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+		if (!intent.getBooleanExtra(EXTRA_REPLACING, false)) {
 			final String packageName =
 					intent.getData().getEncodedSchemeSpecificPart();
 			androidExecutor.runOnUiThread(new Runnable() {
@@ -155,7 +184,7 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 	@Override
 	@UiThread
 	public void storeAppsAsShown(Collection<String> s, boolean persistent) {
-		HashSet<String> buf = new HashSet(s);
+		HashSet<String> buf = new HashSet<>(s);
 		shownApps.addAll(buf);
 		if (persistent && !s.isEmpty()) {
 			buf.addAll(getShownScreenFilterApps());
@@ -168,7 +197,7 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 	private Set<String> getInstalledScreenFilterApps() {
 		HashSet<String> screenFilterApps = new HashSet<>();
 		List<PackageInfo> packageInfos =
-				pm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
+				pm.getInstalledPackages(GET_PERMISSIONS);
 		for (PackageInfo packageInfo : packageInfos) {
 			if (isOverlayApp(packageInfo)) {
 				String name = pkgToString(packageInfo);
@@ -180,25 +209,22 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 		return screenFilterApps;
 	}
 
-	// Checks if pkg uses the SYSTEM_ALERT_WINDOW permission and if so
+	// Checks if a package uses the SYSTEM_ALERT_WINDOW permission and if so
 	// returns the app name.
 	@Nullable
 	private String isOverlayApp(String pkg) {
 		try {
-			PackageInfo pkgInfo =
-					pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
+			PackageInfo pkgInfo = pm.getPackageInfo(pkg, GET_PERMISSIONS);
 			if (isOverlayApp(pkgInfo)) {
 				return pkgToString(pkgInfo);
 			}
-		} catch (PackageManager.NameNotFoundException ignored) {
-			if (LOG.isLoggable(Level.WARNING)) {
-				LOG.warning("Package name not found: " + pkg);
-			}
+		} catch (NameNotFoundException e) {
+			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 		}
 		return null;
 	}
 
-	// Fetch the application name for a given package.
+	// Fetches the application name for a given package.
 	@Nullable
 	private String pkgToString(PackageInfo pkgInfo) {
 		CharSequence seq = pm.getApplicationLabel(pkgInfo.applicationInfo);
@@ -208,25 +234,49 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
 		return null;
 	}
 
-	// Checks if an installed pkg is a user app using the permission.
+	// Checks if an installed package is a user app using the permission.
 	private boolean isOverlayApp(PackageInfo packageInfo) {
-		int mask = ApplicationInfo.FLAG_SYSTEM |
-				ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+		int mask = FLAG_SYSTEM | FLAG_UPDATED_SYSTEM_APP;
 		// Ignore system apps
 		if ((packageInfo.applicationInfo.flags & mask) != 0) {
 			return false;
 		}
-		//Get Permissions
-		String[] requestedPermissions =
-				packageInfo.requestedPermissions;
+		// Ignore Play Services, it's effectively a system app
+		if (isPlayServices(packageInfo.packageName)) {
+			return false;
+		}
+		// Get permissions
+		String[] requestedPermissions = packageInfo.requestedPermissions;
 		if (requestedPermissions != null) {
 			for (String requestedPermission : requestedPermissions) {
-				if (requestedPermission
-						.equals(SYSTEM_ALERT_WINDOW)) {
+				if (requestedPermission.equals(SYSTEM_ALERT_WINDOW)) {
 					return true;
 				}
 			}
 		}
 		return false;
 	}
+
+	private boolean isPlayServices(String pkg) {
+		if (!PLAY_SERVICES_PACKAGE.equals(pkg)) return false;
+		try {
+			PackageInfo sigs = pm.getPackageInfo(pkg, GET_SIGNATURES);
+			// The genuine Play Services app should have a single signature
+			Signature[] signatures = sigs.signatures;
+			if (signatures == null || signatures.length != 1) return false;
+			// Extract the public key from the signature
+			CertificateFactory certFactory =
+					CertificateFactory.getInstance("X509");
+			byte[] signatureBytes = signatures[0].toByteArray();
+			InputStream in = new ByteArrayInputStream(signatureBytes);
+			X509Certificate cert =
+					(X509Certificate) certFactory.generateCertificate(in);
+			byte[] publicKeyBytes = cert.getPublicKey().getEncoded();
+			String publicKey = StringUtils.toHexString(publicKeyBytes);
+			return PLAY_SERVICES_PUBLIC_KEY.equals(publicKey);
+		} catch (NameNotFoundException | CertificateException e) {
+			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+			return false;
+		}
+	}
 }