diff --git a/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java b/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java index 11f41f5f..ca98ad69 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java +++ b/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java @@ -195,7 +195,7 @@ public class PCAPdroid extends Application { private void removeUninstalledAppsFromAppFilter() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - Set filter = Prefs.getAppFilter(prefs); + Set filter = Prefs.getAppFilterRaw(prefs); ArrayList to_remove = new ArrayList<>(); PackageManager pm = getPackageManager(); diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java index 536a38c3..54c18b89 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java @@ -90,6 +90,7 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr private TextView mFilterDescription; private SwitchCompat mAppFilterSwitch; private Set mAppFilter; + private boolean mAppFilterEnabled; private TextView mFilterRootDecryptionWarning; private View mLastCaptureSection; private View mLastCapture; @@ -141,7 +142,8 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr mQuickSettings = view.findViewById(R.id.quick_settings); mFilterRootDecryptionWarning = view.findViewById(R.id.app_filter_root_decryption_warning); mPrefs = PreferenceManager.getDefaultSharedPreferences(mActivity); - mAppFilter = Prefs.getAppFilter(mPrefs); + mAppFilter = Prefs.getAppFilterRaw(mPrefs); + mAppFilterEnabled = Prefs.isAppFilterEnabled(mPrefs); PrefSpinner.init(view.findViewById(R.id.dump_mode_spinner), R.array.pcap_dump_modes, R.array.pcap_dump_modes_labels, R.array.pcap_dump_modes_descriptions, @@ -162,10 +164,9 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr filterTitle.setText(R.string.target_apps); - mAppFilterSwitch.setOnClickListener((buttonView) -> { - mAppFilterSwitch.setChecked(!mAppFilterSwitch.isChecked()); - openAppFilterSelector(); - }); + filterRow.setOnClickListener((v) -> openAppFilterSelector()); + + mAppFilterSwitch.setOnClickListener((buttonView) -> onAppFilterSwitchClicked()); refreshFilterInfo(); @@ -204,11 +205,11 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr } private void recheckFilterWarning() { - boolean hasFilter = ((mAppFilter != null) && (!mAppFilter.isEmpty())); + boolean hasEffectiveFilter = mAppFilterEnabled && (mAppFilter != null) && (!mAppFilter.isEmpty()); mFilterRootDecryptionWarning.setVisibility((Prefs.getTlsDecryptionEnabled(mPrefs) && Prefs.isRootCaptureEnabled(mPrefs) - && !hasFilter) ? View.VISIBLE : View.GONE); + && !hasEffectiveFilter) ? View.VISIBLE : View.GONE); } private void refreshDecryptionStatus() { @@ -226,15 +227,17 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr if(context == null) return; - if((mAppFilter == null) || (mAppFilter.isEmpty())) { + boolean hasApps = (mAppFilter != null) && (!mAppFilter.isEmpty()); + boolean effective = hasApps && mAppFilterEnabled; + + mAppFilterSwitch.setChecked(effective); + + if (!effective) { mFilterDescription.setText(R.string.capture_all_apps); mFilterIcon.setVisibility(View.GONE); - mAppFilterSwitch.setChecked(false); return; } - mAppFilterSwitch.setChecked(true); - Pair pair = getAppFilterTextAndIcon(context); mFilterDescription.setText(pair.first); @@ -245,6 +248,23 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr } } + private void onAppFilterSwitchClicked() { + boolean hasApps = (mAppFilter != null) && (!mAppFilter.isEmpty()); + + if (!hasApps) { + mAppFilterSwitch.setChecked(false); + mPrefs.edit().putBoolean(Prefs.PREF_APP_FILTER_ENABLED, true).apply(); + mAppFilterEnabled = true; + openAppFilterSelector(); + return; + } + + mAppFilterEnabled = !mAppFilterEnabled; + mPrefs.edit().putBoolean(Prefs.PREF_APP_FILTER_ENABLED, mAppFilterEnabled).apply(); + refreshFilterInfo(); + recheckFilterWarning(); + } + private void onStatsUpdate(CaptureStats stats) { Log.d("MainReceiver", "Got StatsUpdate: bytes_sent=" + stats.pkts_sent + ", bytes_rcvd=" + stats.bytes_rcvd + ", pkts_sent=" + stats.pkts_sent + ", pkts_rcvd=" + stats.pkts_rcvd); @@ -361,7 +381,8 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr mCollectorInfoLayout.setVisibility(View.GONE); mInterfaceInfo.setVisibility(View.GONE); mQuickSettings.setVisibility(View.VISIBLE); - mAppFilter = Prefs.getAppFilter(mPrefs); + mAppFilter = Prefs.getAppFilterRaw(mPrefs); + mAppFilterEnabled = Prefs.isAppFilterEnabled(mPrefs); refreshFilterInfo(); refreshLastCapture(); break; @@ -401,6 +422,7 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr mInterfaceInfo.setVisibility(View.GONE); mAppFilter = CaptureService.getAppFilter(); + mAppFilterEnabled = (mAppFilter != null) && (!mAppFilter.isEmpty()); refreshPcapDumpInfo(context); break; default: diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java b/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java index 517969f7..e7b9bc5a 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java @@ -70,6 +70,7 @@ public class Prefs { public static final String PREF_FIREWALL = "firewall"; public static final String PREF_TLS_DECRYPTION_KEY = "tls_decryption"; public static final String PREF_APP_FILTER = "app_filter"; + public static final String PREF_APP_FILTER_ENABLED = "app_filter_enabled"; public static final String PREF_HTTP_SERVER_PORT = "http_server_port"; public static final String PREF_PCAP_DUMP_MODE = "pcap_dump_mode_v2"; public static final String PREF_IP_MODE = "ip_mode"; @@ -207,7 +208,9 @@ public class Prefs { public static boolean isSocks5AuthEnabled(SharedPreferences p) { return(p.getBoolean(PREF_SOCKS5_AUTH_ENABLED_KEY, false)); } public static String getSocks5Username(SharedPreferences p) { return(p.getString(PREF_SOCKS5_USERNAME_KEY, "")); } public static String getSocks5Password(SharedPreferences p) { return(p.getString(PREF_SOCKS5_PASSWORD_KEY, "")); } - public static Set getAppFilter(SharedPreferences p) { return(getStringSet(p, PREF_APP_FILTER)); } + public static Set getAppFilter(SharedPreferences p) { return(isAppFilterEnabled(p) ? getAppFilterRaw(p) : new ArraySet<>()); } + public static Set getAppFilterRaw(SharedPreferences p) { return(getStringSet(p, PREF_APP_FILTER)); } + public static boolean isAppFilterEnabled(SharedPreferences p) { return(p.getBoolean(PREF_APP_FILTER_ENABLED, true)); } public static IpMode getIPMode(SharedPreferences p) { return(getIPMode(p.getString(PREF_IP_MODE, IP_MODE_DEFAULT))); } public static BlockQuicMode getBlockQuicMode(SharedPreferences p) { return(getBlockQuicMode(p.getString(PREF_BLOCK_QUIC, BLOCK_QUIC_MODE_DEFAULT))); } public static String getAppLocale(SharedPreferences p) { diff --git a/app/src/main/res/layout/status.xml b/app/src/main/res/layout/status.xml index 507985a4..270be3ed 100644 --- a/app/src/main/res/layout/status.xml +++ b/app/src/main/res/layout/status.xml @@ -91,34 +91,57 @@ tools:listitem="@layout/quick_settings_item" android:prompt="@string/traffic_dump"/> - + android:layout_height="wrap_content" + android:orientation="vertical"> - + android:orientation="horizontal" + android:gravity="center_vertical" + android:baselineAligned="false"> - + + + + + + + + + - +