From 151d702d332d54946939da2c0010fd38f63e167e Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 23 Nov 2023 12:53:29 +0100 Subject: [PATCH 1/5] feat(split tunneling): update content_split_tunneling.xml --- .../res/layout/content_split_tunneling.xml | 41 +++++++++++++++++-- core/src/main/res/values/strings.xml | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/src/main/res/layout/content_split_tunneling.xml b/core/src/main/res/layout/content_split_tunneling.xml index ab3637cfd..3cfeedc34 100644 --- a/core/src/main/res/layout/content_split_tunneling.xml +++ b/core/src/main/res/layout/content_split_tunneling.xml @@ -48,13 +48,48 @@ android:textSize="14sp" android:textStyle="normal" /> - + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + android:layout_marginBottom="16dp" + android:orientation="horizontal"> + + + + + + + + + + Split tunnelling allows you to control which apps use the VPN tunnel. New apps that you install will automatically use the VPN tunnel. TURN ON ALL TURN OFF ALL + Show system apps Mobile data From b2fc0902a228910310aeed9a00ca63d9ee0fc6c8 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Sun, 26 Nov 2023 18:59:54 +0100 Subject: [PATCH 2/5] feat(split tunneling): update SplitTunnelingViewModel --- .../v2/viewmodel/SplitTunnelingViewModel.java | 23 +++++++++++++++++-- .../res/layout/content_split_tunneling.xml | 7 +++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java index 661ebf830..3afc0e86f 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java @@ -22,9 +22,11 @@ along with the IVPN Android app. If not, see . */ +import android.Manifest; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.AsyncTask; +import android.widget.CompoundButton; import androidx.databinding.ObservableArrayList; import androidx.databinding.ObservableBoolean; @@ -45,10 +47,13 @@ public class SplitTunnelingViewModel { public final ObservableBoolean dataLoading = new ObservableBoolean(); + public final ObservableBoolean showSystemApps = new ObservableBoolean(); public final ObservableBoolean isAllItemsAllowed = new ObservableBoolean(); public final ObservableArrayList apps = new ObservableArrayList<>(); + public final ObservableArrayList systemApps = new ObservableArrayList<>(); public final ObservableArrayList disallowedApps = new ObservableArrayList(); public final ObservableField adapter = new ObservableField<>(); + public CompoundButton.OnCheckedChangeListener toggleSystemApps = (compoundButton, value) -> toggleSystemApps(value); public final OnApplicationItemSelectionChangedListener selectionChangedListener = new OnApplicationItemSelectionChangedListener() { @Override public void onApplicationItemSelectionChanged(ApplicationItem applicationItem, boolean isSelected) { @@ -94,6 +99,10 @@ public void deselectAll() { menuHandler.deselectAll(); } + private void toggleSystemApps(Boolean value) { + showSystemApps.set(value); + } + private void disallowAllApps(Set applicationItems) { Set disallowedPackages = new HashSet<>(); for (ApplicationItem app : applicationItems) { @@ -145,7 +154,9 @@ protected void onPreExecute() { @Override protected List doInBackground(Void... voids) { List items = new LinkedList<>(); + List systemItems = new LinkedList<>(); Set packageNames = new HashSet<>(); + Set systemPackageNames = new HashSet<>(); for (ApplicationInfo info : applicationInfoList) { try { if (null != packageManager.getLaunchIntentForPackage(info.packageName) || @@ -157,17 +168,25 @@ protected List doInBackground(Void... voids) { info.loadIcon(packageManager))); } } + if (PackageManager.PERMISSION_GRANTED == packageManager.checkPermission(Manifest.permission.INTERNET, info.packageName)) { + if (systemPackageNames.add(info.loadLabel(packageManager).toString())) { + systemItems.add(new ApplicationItem(info.loadLabel(packageManager).toString(), info.packageName, + info.loadIcon(packageManager))); + } + } } catch (Exception e) { e.printStackTrace(); } } + apps.clear(); + apps.addAll(items); + systemApps.clear(); + systemApps.addAll(systemItems); return items; } @Override protected void onPostExecute(List applicationItems) { - apps.clear(); - apps.addAll(applicationItems); dataLoading.set(false); } } diff --git a/core/src/main/res/layout/content_split_tunneling.xml b/core/src/main/res/layout/content_split_tunneling.xml index 3cfeedc34..40e6a235e 100644 --- a/core/src/main/res/layout/content_split_tunneling.xml +++ b/core/src/main/res/layout/content_split_tunneling.xml @@ -73,11 +73,12 @@ android:layout_weight="1" /> @@ -95,7 +96,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:adapter="@{viewmodel.adapter}" - app:apps="@{viewmodel.apps}" + app:apps="@{viewmodel.showSystemApps ? viewmodel.systemApps : viewmodel.apps}" app:not_allowed_apps="@{viewmodel.disallowedApps}" app:selection_listener="@{viewmodel.selectionChangedListener}"/> From daa3b81a0a5926c687fc5cc3ec7e3b8ffca389e0 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 30 Nov 2023 18:29:54 +0100 Subject: [PATCH 3/5] feat(split tunneling): update SplitTunnelingViewModel --- .../v2/viewmodel/SplitTunnelingViewModel.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java index 3afc0e86f..12b33cdb8 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java @@ -78,10 +78,7 @@ public void onItemsSelectionStateChanged(boolean isAllItemSelected) { this.adapter.set(adapter); this.menuHandler = adapter.getMenuHandler(); this.preference = preference; - - disallowedApps.clear(); - disallowedApps.addAll(getDisallowedPackages()); - + reloadDisallowedApps(); isAllItemsAllowed.set(disallowedApps.size() == 0); } @@ -92,11 +89,19 @@ public void getApplicationsList(PackageManager packageManager) { public void selectAll() { allowAllPackages(); menuHandler.selectAll(); + reloadDisallowedApps(); } public void deselectAll() { disallowAllApps(new HashSet<>(apps)); + disallowAllApps(new HashSet<>(systemApps)); menuHandler.deselectAll(); + reloadDisallowedApps(); + } + + private void reloadDisallowedApps() { + disallowedApps.clear(); + disallowedApps.addAll(getDisallowedPackages()); } private void toggleSystemApps(Boolean value) { @@ -159,16 +164,16 @@ protected List doInBackground(Void... voids) { Set systemPackageNames = new HashSet<>(); for (ApplicationInfo info : applicationInfoList) { try { - if (null != packageManager.getLaunchIntentForPackage(info.packageName) || - null != packageManager.getLeanbackLaunchIntentForPackage(info.packageName) || - null != packageManager.getInstallerPackageName(info.packageName) - ) { - if (packageNames.add(info.loadLabel(packageManager).toString())) { - items.add(new ApplicationItem(info.loadLabel(packageManager).toString(), info.packageName, - info.loadIcon(packageManager))); - } - } if (PackageManager.PERMISSION_GRANTED == packageManager.checkPermission(Manifest.permission.INTERNET, info.packageName)) { + if (null != packageManager.getLaunchIntentForPackage(info.packageName) || + null != packageManager.getLeanbackLaunchIntentForPackage(info.packageName) || + null != packageManager.getInstallerPackageName(info.packageName) + ) { + if (packageNames.add(info.loadLabel(packageManager).toString())) { + items.add(new ApplicationItem(info.loadLabel(packageManager).toString(), info.packageName, + info.loadIcon(packageManager))); + } + } if (systemPackageNames.add(info.loadLabel(packageManager).toString())) { systemItems.add(new ApplicationItem(info.loadLabel(packageManager).toString(), info.packageName, info.loadIcon(packageManager))); From 72bbb35936794e2a9b810e465df9bdfeff789ac4 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 6 Dec 2023 10:39:25 +0100 Subject: [PATCH 4/5] feat(split tunneling): update SplitTunnelingViewModel --- .../net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java index 12b33cdb8..b1ad5751b 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java @@ -165,9 +165,10 @@ protected List doInBackground(Void... voids) { for (ApplicationInfo info : applicationInfoList) { try { if (PackageManager.PERMISSION_GRANTED == packageManager.checkPermission(Manifest.permission.INTERNET, info.packageName)) { - if (null != packageManager.getLaunchIntentForPackage(info.packageName) || + if ((null != packageManager.getLaunchIntentForPackage(info.packageName) || null != packageManager.getLeanbackLaunchIntentForPackage(info.packageName) || - null != packageManager.getInstallerPackageName(info.packageName) + null != packageManager.getInstallerPackageName(info.packageName) && + (info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) ) { if (packageNames.add(info.loadLabel(packageManager).toString())) { items.add(new ApplicationItem(info.loadLabel(packageManager).toString(), info.packageName, From 5f5447b80e308bed44c22cf315c7973082fcca52 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 6 Dec 2023 20:06:57 +0100 Subject: [PATCH 5/5] feat(split tunneling): update SplitTunnelingViewModel --- .../net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java index b1ad5751b..a61d85302 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/SplitTunnelingViewModel.java @@ -93,8 +93,10 @@ public void selectAll() { } public void deselectAll() { - disallowAllApps(new HashSet<>(apps)); - disallowAllApps(new HashSet<>(systemApps)); + ObservableArrayList allApps = new ObservableArrayList<>(); + allApps.addAll(apps); + allApps.addAll(systemApps); + disallowAllApps(new HashSet<>(allApps)); menuHandler.deselectAll(); reloadDisallowedApps(); }