Android O compatibility

This commit is contained in:
M66B 2017-04-02 12:47:59 +02:00
parent 5f3e12404e
commit 02cc7d41af
2 changed files with 161 additions and 167 deletions

View File

@ -19,20 +19,13 @@ package eu.faircode.netguard;
Copyright 2015-2017 by Marcel Bokhorst (M66B)
*/
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import java.util.Map;
@ -44,160 +37,22 @@ public class Receiver extends BroadcastReceiver {
Log.i(TAG, "Received " + intent);
Util.logExtras(intent);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Upgrade settings
upgrade(true, context);
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
// Application added
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// Show notification
if (IAB.isPurchased(ActivityPro.SKU_NOTIFY, context) && prefs.getBoolean("install", true)) {
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
notifyNewApplication(uid, context);
}
}
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
// Application removed
Rule.clearCache(context);
if (intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false)) {
// Remove settings
String packageName = intent.getData().getSchemeSpecificPart();
Log.i(TAG, "Deleting settings package=" + packageName);
context.getSharedPreferences("wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("other", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("screen_other", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("roaming", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("lockdown", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("apply", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("notify", Context.MODE_PRIVATE).edit().remove(packageName).apply();
int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
if (uid > 0) {
DatabaseHelper dh = DatabaseHelper.getInstance(context);
dh.clearLog(uid);
dh.clearAccess(uid, false);
dh.close();
NotificationManagerCompat.from(context).cancel(uid); // installed notification
NotificationManagerCompat.from(context).cancel(uid + 10000); // access notification
}
}
} else {
// Upgrade settings
upgrade(true, context);
// Start service
try {
if (prefs.getBoolean("enabled", false))
ServiceSinkhole.start("receiver", context);
else if (prefs.getBoolean("show_stats", false))
ServiceSinkhole.run("receiver", context);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
if (Util.isInteractive(context))
ServiceSinkhole.reloadStats("receiver", context);
}
}
public static void notifyNewApplication(int uid, Context context) {
if (uid < 0)
return;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Start service
try {
// Get application info
String name = TextUtils.join(", ", Util.getApplicationNames(uid, context));
// Get application info
PackageManager pm = context.getPackageManager();
String[] packages = pm.getPackagesForUid(uid);
if (packages == null || packages.length < 1)
throw new PackageManager.NameNotFoundException(Integer.toString(uid));
boolean internet = Util.hasInternet(uid, context);
// Build notification
Intent main = new Intent(context, ActivityMain.class);
main.putExtra(ActivityMain.EXTRA_REFRESH, true);
main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
PendingIntent pi = PendingIntent.getActivity(context, uid, main, PendingIntent.FLAG_UPDATE_CURRENT);
Util.setTheme(context);
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_security_white_24dp)
.setContentIntent(pi)
.setColor(tv.data)
.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
builder.setContentTitle(name)
.setContentText(context.getString(R.string.msg_installed_n));
else
builder.setContentTitle(context.getString(R.string.app_name))
.setContentText(context.getString(R.string.msg_installed, name));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setCategory(Notification.CATEGORY_STATUS)
.setVisibility(Notification.VISIBILITY_SECRET);
}
// Get defaults
SharedPreferences prefs_wifi = context.getSharedPreferences("wifi", Context.MODE_PRIVATE);
SharedPreferences prefs_other = context.getSharedPreferences("other", Context.MODE_PRIVATE);
boolean wifi = prefs_wifi.getBoolean(packages[0], prefs.getBoolean("whitelist_wifi", true));
boolean other = prefs_other.getBoolean(packages[0], prefs.getBoolean("whitelist_other", true));
// Build Wi-Fi action
Intent riWifi = new Intent(context, ServiceSinkhole.class);
riWifi.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
riWifi.putExtra(ServiceSinkhole.EXTRA_NETWORK, "wifi");
riWifi.putExtra(ServiceSinkhole.EXTRA_UID, uid);
riWifi.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
riWifi.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !wifi);
PendingIntent piWifi = PendingIntent.getService(context, uid, riWifi, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(
wifi ? R.drawable.wifi_on : R.drawable.wifi_off,
context.getString(wifi ? R.string.title_allow : R.string.title_block),
piWifi
);
// Build mobile action
Intent riOther = new Intent(context, ServiceSinkhole.class);
riOther.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
riOther.putExtra(ServiceSinkhole.EXTRA_NETWORK, "other");
riOther.putExtra(ServiceSinkhole.EXTRA_UID, uid);
riOther.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
riOther.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !other);
PendingIntent piOther = PendingIntent.getService(context, uid + 10000, riOther, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(
other ? R.drawable.other_on : R.drawable.other_off,
context.getString(other ? R.string.title_allow : R.string.title_block),
piOther
);
// Show notification
if (internet)
NotificationManagerCompat.from(context).notify(uid, builder.build());
else {
NotificationCompat.BigTextStyle expanded = new NotificationCompat.BigTextStyle(builder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
expanded.bigText(context.getString(R.string.msg_installed_n));
else
expanded.bigText(context.getString(R.string.msg_installed, name));
expanded.setSummaryText(context.getString(R.string.title_internet));
NotificationManagerCompat.from(context).notify(uid, expanded.build());
}
} catch (PackageManager.NameNotFoundException ex) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.getBoolean("enabled", false))
ServiceSinkhole.start("receiver", context);
else if (prefs.getBoolean("show_stats", false))
ServiceSinkhole.run("receiver", context);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
if (Util.isInteractive(context))
ServiceSinkhole.reloadStats("receiver", context);
}
public static void upgrade(boolean initialized, Context context) {

View File

@ -113,7 +113,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
private boolean registeredUser = false;
private boolean registeredIdleState = false;
private boolean registeredConnectivityChanged = false;
private boolean registeredPackageAdded = false;
private boolean registeredPackageChanged = false;
private State state = State.none;
private boolean user_foreground = true;
@ -1907,16 +1907,154 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
}
};
private BroadcastReceiver packageAddedReceiver = new BroadcastReceiver() {
private BroadcastReceiver packageChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received " + intent);
Util.logExtras(intent);
Rule.clearCache(ServiceSinkhole.this);
reload("package added", ServiceSinkhole.this);
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
// Application added
Rule.clearCache(context);
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// Show notification
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (IAB.isPurchased(ActivityPro.SKU_NOTIFY, context) && prefs.getBoolean("install", true)) {
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
notifyNewApplication(uid);
}
}
reload("package added", context);
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
// Application removed
Rule.clearCache(context);
if (intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false)) {
// Remove settings
String packageName = intent.getData().getSchemeSpecificPart();
Log.i(TAG, "Deleting settings package=" + packageName);
context.getSharedPreferences("wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("other", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("screen_other", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("roaming", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("lockdown", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("apply", Context.MODE_PRIVATE).edit().remove(packageName).apply();
context.getSharedPreferences("notify", Context.MODE_PRIVATE).edit().remove(packageName).apply();
int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
if (uid > 0) {
DatabaseHelper dh = DatabaseHelper.getInstance(context);
dh.clearLog(uid);
dh.clearAccess(uid, false);
NotificationManagerCompat.from(context).cancel(uid); // installed notification
NotificationManagerCompat.from(context).cancel(uid + 10000); // access notification
}
}
reload("package deleted", context);
}
}
};
public void notifyNewApplication(int uid) {
if (uid < 0)
return;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
try {
// Get application name
String name = TextUtils.join(", ", Util.getApplicationNames(uid, this));
// Get application info
PackageManager pm = getPackageManager();
String[] packages = pm.getPackagesForUid(uid);
if (packages == null || packages.length < 1)
throw new PackageManager.NameNotFoundException(Integer.toString(uid));
boolean internet = Util.hasInternet(uid, this);
// Build notification
Intent main = new Intent(this, ActivityMain.class);
main.putExtra(ActivityMain.EXTRA_REFRESH, true);
main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
PendingIntent pi = PendingIntent.getActivity(this, uid, main, PendingIntent.FLAG_UPDATE_CURRENT);
TypedValue tv = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_security_white_24dp)
.setContentIntent(pi)
.setColor(tv.data)
.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
builder.setContentTitle(name)
.setContentText(getString(R.string.msg_installed_n));
else
builder.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.msg_installed, name));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
builder.setCategory(Notification.CATEGORY_STATUS)
.setVisibility(Notification.VISIBILITY_SECRET);
// Get defaults
SharedPreferences prefs_wifi = getSharedPreferences("wifi", Context.MODE_PRIVATE);
SharedPreferences prefs_other = getSharedPreferences("other", Context.MODE_PRIVATE);
boolean wifi = prefs_wifi.getBoolean(packages[0], prefs.getBoolean("whitelist_wifi", true));
boolean other = prefs_other.getBoolean(packages[0], prefs.getBoolean("whitelist_other", true));
// Build Wi-Fi action
Intent riWifi = new Intent(this, ServiceSinkhole.class);
riWifi.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
riWifi.putExtra(ServiceSinkhole.EXTRA_NETWORK, "wifi");
riWifi.putExtra(ServiceSinkhole.EXTRA_UID, uid);
riWifi.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
riWifi.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !wifi);
PendingIntent piWifi = PendingIntent.getService(this, uid, riWifi, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(
wifi ? R.drawable.wifi_on : R.drawable.wifi_off,
getString(wifi ? R.string.title_allow : R.string.title_block),
piWifi
);
// Build mobile action
Intent riOther = new Intent(this, ServiceSinkhole.class);
riOther.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
riOther.putExtra(ServiceSinkhole.EXTRA_NETWORK, "other");
riOther.putExtra(ServiceSinkhole.EXTRA_UID, uid);
riOther.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
riOther.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !other);
PendingIntent piOther = PendingIntent.getService(this, uid + 10000, riOther, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(
other ? R.drawable.other_on : R.drawable.other_off,
getString(other ? R.string.title_allow : R.string.title_block),
piOther
);
// Show notification
if (internet)
NotificationManagerCompat.from(this).notify(uid, builder.build());
else {
NotificationCompat.BigTextStyle expanded = new NotificationCompat.BigTextStyle(builder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
expanded.bigText(getString(R.string.msg_installed_n));
else
expanded.bigText(getString(R.string.msg_installed, name));
expanded.setSummaryText(getString(R.string.title_internet));
NotificationManagerCompat.from(this).notify(uid, expanded.build());
}
} catch (PackageManager.NameNotFoundException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
private PhoneStateListener phoneStateListener = new PhoneStateListener() {
private String last_generation = null;
private int last_international = -1;
@ -2025,9 +2163,10 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
// Listen for added applications
IntentFilter ifPackage = new IntentFilter();
ifPackage.addAction(Intent.ACTION_PACKAGE_ADDED);
ifPackage.addAction(Intent.ACTION_PACKAGE_REMOVED);
ifPackage.addDataScheme("package");
registerReceiver(packageAddedReceiver, ifPackage);
registeredPackageAdded = true;
registerReceiver(packageChangedReceiver, ifPackage);
registeredPackageChanged = true;
// Setup house holding
Intent alarmIntent = new Intent(this, ServiceSinkhole.class);
@ -2123,7 +2262,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
ServiceSinkhole.reload("notification", ServiceSinkhole.this);
// Update notification
Receiver.notifyNewApplication(uid, ServiceSinkhole.this);
notifyNewApplication(uid);
// Update UI
Intent ruleset = new Intent(ActivityMain.ACTION_RULES_CHANGED);
@ -2173,9 +2312,9 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
unregisterReceiver(connectivityChangedReceiver);
registeredConnectivityChanged = false;
}
if (registeredPackageAdded) {
unregisterReceiver(packageAddedReceiver);
registeredPackageAdded = false;
if (registeredPackageChanged) {
unregisterReceiver(packageChangedReceiver);
registeredPackageChanged = false;
}
if (phone_state) {