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..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 @@ -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) { @@ -73,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); } @@ -87,11 +89,25 @@ public void getApplicationsList(PackageManager packageManager) { public void selectAll() { allowAllPackages(); menuHandler.selectAll(); + reloadDisallowedApps(); } public void deselectAll() { - disallowAllApps(new HashSet<>(apps)); + ObservableArrayList allApps = new ObservableArrayList<>(); + allApps.addAll(apps); + allApps.addAll(systemApps); + disallowAllApps(new HashSet<>(allApps)); menuHandler.deselectAll(); + reloadDisallowedApps(); + } + + private void reloadDisallowedApps() { + disallowedApps.clear(); + disallowedApps.addAll(getDisallowedPackages()); + } + + private void toggleSystemApps(Boolean value) { + showSystemApps.set(value); } private void disallowAllApps(Set applicationItems) { @@ -145,15 +161,24 @@ 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) || - 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, + 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) && + (info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) + ) { + 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))); } } @@ -161,13 +186,15 @@ protected List doInBackground(Void... voids) { 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 ab3637cfd..40e6a235e 100644 --- a/core/src/main/res/layout/content_split_tunneling.xml +++ b/core/src/main/res/layout/content_split_tunneling.xml @@ -48,19 +48,55 @@ 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"> + + + + + + + + + + diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index a5f1a4074..faab9c78a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -189,6 +189,7 @@ 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