Option to block only when device unused

This commit is contained in:
M66B 2015-10-29 08:48:28 +01:00
parent 947e06390f
commit e96f54b5df
7 changed files with 157 additions and 49 deletions

View File

@ -19,9 +19,10 @@ public class Rule implements Comparable<Rule> {
public boolean disabled;
public boolean wifi_blocked;
public boolean other_blocked;
public boolean unused;
public boolean changed;
private Rule(PackageInfo info, boolean wifi_blocked, boolean other_blocked, boolean changed, Context context) {
private Rule(PackageInfo info, boolean wifi_blocked, boolean other_blocked, boolean unused, boolean changed, Context context) {
PackageManager pm = context.getPackageManager();
this.info = info;
this.name = info.applicationInfo.loadLabel(pm).toString();
@ -35,6 +36,7 @@ public class Rule implements Comparable<Rule> {
this.wifi_blocked = wifi_blocked;
this.other_blocked = other_blocked;
this.unused = unused;
this.changed = changed;
}
@ -42,6 +44,7 @@ public class Rule implements Comparable<Rule> {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences wifi = context.getSharedPreferences("wifi", Context.MODE_PRIVATE);
SharedPreferences other = context.getSharedPreferences("other", Context.MODE_PRIVATE);
SharedPreferences punused = context.getSharedPreferences("unused", Context.MODE_PRIVATE);
boolean wlWifi = prefs.getBoolean("whitelist_wifi", true);
boolean wlOther = prefs.getBoolean("whitelist_other", true);
@ -50,8 +53,9 @@ public class Rule implements Comparable<Rule> {
for (PackageInfo info : context.getPackageManager().getInstalledPackages(0)) {
boolean blWifi = wifi.getBoolean(info.packageName, wlWifi);
boolean blOther = other.getBoolean(info.packageName, wlOther);
boolean unused = punused.getBoolean(info.packageName, false);
boolean changed = (blWifi != wlWifi || blOther != wlOther);
listRules.add(new Rule(info, blWifi, blOther, changed, context));
listRules.add(new Rule(info, blWifi, blOther, unused, changed, context));
}
Collections.sort(listRules);

View File

@ -16,6 +16,7 @@ import android.widget.CompoundButton;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
@ -32,20 +33,28 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
public static class ViewHolder extends RecyclerView.ViewHolder {
public View view;
public LinearLayout llApplication;
public ImageView ivIcon;
public TextView tvName;
public TextView tvPackage;
public CheckBox cbWifi;
public CheckBox cbOther;
public ImageView ivUnused;
public LinearLayout llAttributes;
public CheckBox cbUnused;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
llApplication = (LinearLayout) itemView.findViewById(R.id.llApplication);
ivIcon = (ImageView) itemView.findViewById(R.id.ivIcon);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvPackage = (TextView) itemView.findViewById(R.id.tvPackage);
cbWifi = (CheckBox) itemView.findViewById(R.id.cbWifi);
cbOther = (CheckBox) itemView.findViewById(R.id.cbOther);
ivUnused = (ImageView) itemView.findViewById(R.id.ivUnused);
llAttributes = (LinearLayout) itemView.findViewById(R.id.llAttributes);
cbUnused = (CheckBox) itemView.findViewById(R.id.cbUnused);
}
}
@ -113,6 +122,32 @@ public class RuleAdapter extends RecyclerView.Adapter<RuleAdapter.ViewHolder> im
holder.cbOther.setOnCheckedChangeListener(null);
holder.cbOther.setChecked(rule.other_blocked);
holder.cbOther.setOnCheckedChangeListener(cbListener);
holder.ivUnused.setVisibility(rule.unused ? View.VISIBLE : View.INVISIBLE);
holder.llAttributes.setVisibility(View.GONE);
holder.cbUnused.setOnCheckedChangeListener(null);
holder.cbUnused.setChecked(rule.unused);
holder.llApplication.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.llAttributes.setVisibility(holder.llAttributes.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
}
});
holder.cbUnused.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
rule.unused = isChecked;
SharedPreferences punused = context.getSharedPreferences("unused", Context.MODE_PRIVATE);
punused.edit().putBoolean(rule.info.packageName, rule.unused).apply();
holder.ivUnused.setVisibility(rule.unused ? View.VISIBLE : View.INVISIBLE);
SinkholeService.reload(null, context);
}
});
}
@Override

View File

@ -69,6 +69,10 @@ public class SinkholeService extends VpnService {
boolean wifi = Util.isWifiActive(this);
Log.i(TAG, "wifi=" + wifi);
// Check if interactive
boolean interactive = Util.isInteractive(this);
Log.i(TAG, "interactive=" + interactive);
// Build VPN service
final Builder builder = new Builder();
builder.setSession(getString(R.string.app_name));
@ -79,7 +83,7 @@ public class SinkholeService extends VpnService {
// Add list of allowed applications
for (Rule rule : Rule.getRules(this))
if (!(wifi ? rule.wifi_blocked : rule.other_blocked)) {
if (!(wifi ? rule.wifi_blocked : rule.other_blocked) && (!rule.unused || interactive)) {
Log.i(TAG, "Allowing " + rule.info.packageName);
try {
builder.addDisallowedApplication(rule.info.packageName);
@ -120,6 +124,15 @@ public class SinkholeService extends VpnService {
}
}
private BroadcastReceiver packageAddedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received " + intent);
Util.logExtras(TAG, intent);
reload(null, SinkholeService.this);
}
};
private BroadcastReceiver connectivityChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@ -131,7 +144,7 @@ public class SinkholeService extends VpnService {
}
};
private BroadcastReceiver packageAddedReceiver = new BroadcastReceiver() {
private BroadcastReceiver interactiveStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received " + intent);
@ -145,16 +158,22 @@ public class SinkholeService extends VpnService {
super.onCreate();
Log.i(TAG, "Create");
// Listen for connectivity updates
IntentFilter ifConnectivity = new IntentFilter();
ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(connectivityChangedReceiver, ifConnectivity);
// Listen for added applications
IntentFilter ifPackage = new IntentFilter();
ifPackage.addAction(Intent.ACTION_PACKAGE_ADDED);
ifPackage.addDataScheme("package");
registerReceiver(packageAddedReceiver, ifPackage);
// Listen for connectivity updates
IntentFilter ifConnectivity = new IntentFilter();
ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(connectivityChangedReceiver, ifConnectivity);
// Listen for interactive state changes
IntentFilter ifInteractive = new IntentFilter();
ifInteractive.addAction(Intent.ACTION_SCREEN_ON);
ifInteractive.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(interactiveStateReceiver, ifInteractive);
}
@Override
@ -166,8 +185,9 @@ public class SinkholeService extends VpnService {
vpn = null;
}
unregisterReceiver(connectivityChangedReceiver);
unregisterReceiver(packageAddedReceiver);
unregisterReceiver(connectivityChangedReceiver);
unregisterReceiver(interactiveStateReceiver);
super.onDestroy();
}

View File

@ -9,6 +9,7 @@ import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.util.Log;
import android.widget.Toast;
@ -31,6 +32,11 @@ public class Util {
}
public static boolean isInteractive(Context context) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return pm.isInteractive();
}
public static void toast(final String text, final int length, final Context context) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override

View File

@ -3,53 +3,92 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="4dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="?android:attr/listPreferredItemHeightSmall"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:layout_gravity="center_vertical" />
android:orientation="vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:orientation="vertical">
android:orientation="horizontal">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/llApplication"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="@+id/tvPackage"
<ImageView
android:id="@+id/ivIcon"
android:layout_width="?android:attr/listPreferredItemHeightSmall"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:layout_gravity="center_vertical" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
android:textStyle="bold" />
<TextView
android:id="@+id/tvPackage"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="start"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Small" />
</LinearLayout>
</LinearLayout>
<CheckBox
android:id="@+id/cbWifi"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="start"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Small" />
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:button="@drawable/wifi" />
<CheckBox
android:id="@+id/cbOther"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:button="@drawable/other" />
<ImageView
android:id="@+id/ivUnused"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:src="@drawable/unused" />
</LinearLayout>
<CheckBox
android:id="@+id/cbWifi"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/llAttributes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:button="@drawable/wifi" />
android:layout_marginStart="8dp"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemHeightSmall"
android:paddingTop="0dp"
android:visibility="gone">
<CheckBox
android:id="@+id/cbOther"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:button="@drawable/other" />
<CheckBox
android:id="@+id/cbUnused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_unused"
android:textAppearance="@android:style/TextAppearance.Material.Small" />
</LinearLayout>
</LinearLayout>

View File

@ -14,4 +14,6 @@
<string name="menu_about">À propos</string>
<string name="msg_sure">Etes-vous sûr ?</string>
<string name="title_unused">Block only when device unused</string>
</resources>

View File

@ -15,4 +15,6 @@
<string name="menu_about">About</string>
<string name="msg_sure">Are you sure?</string>
<string name="title_unused">Block only when device unused</string>
</resources>