diff options
Diffstat (limited to 'app/src/main/java/com/wireguard/android')
8 files changed, 97 insertions, 89 deletions
diff --git a/app/src/main/java/com/wireguard/android/activity/BaseActivity.java b/app/src/main/java/com/wireguard/android/activity/BaseActivity.java index eb2de5ed..6ee9ff14 100644 --- a/app/src/main/java/com/wireguard/android/activity/BaseActivity.java +++ b/app/src/main/java/com/wireguard/android/activity/BaseActivity.java @@ -49,7 +49,7 @@ public abstract class BaseActivity extends AppCompatActivity { super.onCreate(savedInstanceState); if (Application.getComponent().getBackendType() == GoBackend.class) { - Intent intent = GoBackend.VpnService.prepare(this); + final Intent intent = GoBackend.VpnService.prepare(this); if (intent != null) { startActivityForResult(intent, 0); } diff --git a/app/src/main/java/com/wireguard/android/activity/MainActivity.java b/app/src/main/java/com/wireguard/android/activity/MainActivity.java index bfb3be7e..307d0bf6 100644 --- a/app/src/main/java/com/wireguard/android/activity/MainActivity.java +++ b/app/src/main/java/com/wireguard/android/activity/MainActivity.java @@ -68,7 +68,7 @@ public class MainActivity extends BaseActivity { fragment = ((TunnelListFragment) getSupportFragmentManager().getFragments().get(0)); - } catch (ClassCastException ignored) { + } catch (final ClassCastException ignored) { } if (fragment == null || !(fragment.collapseActionMenu())) { if (!moveToState(State.ofLayer(state.layer - 1))) diff --git a/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java b/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java index fb5e7a09..46a90daa 100644 --- a/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java +++ b/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java @@ -17,28 +17,29 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Interface for changing application-global persistent settings. */ public class SettingsActivity extends AppCompatActivity { - private HashMap<Integer, PermissionRequestCallback> permissionRequestCallbacks = new HashMap<>(); - private int permissionRequestCounter = 0; + private final Map<Integer, PermissionRequestCallback> permissionRequestCallbacks = new HashMap<>(); + private int permissionRequestCounter; - public synchronized void ensurePermissions(String[] permissions, PermissionRequestCallback cb) { - List<String> needPermissions = new ArrayList<>(permissions.length); + public void ensurePermissions(final String[] permissions, final PermissionRequestCallback cb) { + final List<String> needPermissions = new ArrayList<>(permissions.length); for (final String permission : permissions) { if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) needPermissions.add(permission); } if (needPermissions.isEmpty()) { - int[] granted = new int[permissions.length]; + final int[] granted = new int[permissions.length]; Arrays.fill(granted, PackageManager.PERMISSION_GRANTED); cb.done(permissions, granted); return; } - int idx = permissionRequestCounter++; + final int idx = permissionRequestCounter++; permissionRequestCallbacks.put(idx, cb); ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), idx); } @@ -54,7 +55,7 @@ public class SettingsActivity extends AppCompatActivity { } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); @@ -65,7 +66,7 @@ public class SettingsActivity extends AppCompatActivity { } @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { final PermissionRequestCallback f = permissionRequestCallbacks.get(requestCode); if (f != null) { permissionRequestCallbacks.remove(requestCode); @@ -73,7 +74,6 @@ public class SettingsActivity extends AppCompatActivity { } } - @FunctionalInterface public interface PermissionRequestCallback { void done(String[] permissions, int[] grantResults); } diff --git a/app/src/main/java/com/wireguard/android/backend/GoBackend.java b/app/src/main/java/com/wireguard/android/backend/GoBackend.java index 519f7427..e055c353 100644 --- a/app/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/app/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -33,11 +33,11 @@ public final class GoBackend implements Backend { System.loadLibrary("wg-go"); } - private Context context; + private final Context context; private Tunnel currentTunnel; private int currentTunnelHandle = -1; - public GoBackend(Context context) { + public GoBackend(final Context context) { this.context = context; } @@ -108,14 +108,14 @@ public final class GoBackend implements Backend { if (VpnService.prepare(context) != null) throw new Exception("VPN service not authorized by user"); - VpnService service; + final VpnService service; if (!vpnService.isDone()) startVpnService(); try { service = vpnService.get(2, TimeUnit.SECONDS); - } catch (TimeoutException e) { - throw new Exception("Unable to start Android VPN service"); + } catch (final TimeoutException e) { + throw new Exception("Unable to start Android VPN service", e); } if (currentTunnelHandle != -1) { @@ -124,29 +124,32 @@ public final class GoBackend implements Backend { } // Build config - Formatter fmt = new Formatter(new StringBuilder()); final Interface iface = config.getInterface(); - fmt.format("replace_peers=true\n"); - if (iface.getPrivateKey() != null) - fmt.format("private_key=%s\n", KeyEncoding.keyToHex(KeyEncoding.keyFromBase64(iface.getPrivateKey()))); - if (iface.getListenPort() != 0) - fmt.format("listen_port=%d\n", config.getInterface().getListenPort()); - for (final Peer peer : config.getPeers()) { - if (peer.getPublicKey() != null) - fmt.format("public_key=%s\n", KeyEncoding.keyToHex(KeyEncoding.keyFromBase64(peer.getPublicKey()))); - if (peer.getPreSharedKey() != null) - fmt.format("preshared_key=%s\n", KeyEncoding.keyToHex(KeyEncoding.keyFromBase64(peer.getPreSharedKey()))); - if (peer.getEndpoint() != null) - fmt.format("endpoint=%s\n", peer.getResolvedEndpointString()); - if (peer.getPersistentKeepalive() != 0) - fmt.format("persistent_keepalive_interval=%d\n", peer.getPersistentKeepalive()); - for (final IPCidr addr : peer.getAllowedIPs()) { - fmt.format("allowed_ip=%s\n", addr.toString()); + final String goConfig; + try (Formatter fmt = new Formatter(new StringBuilder())) { + fmt.format("replace_peers=true\n"); + if (iface.getPrivateKey() != null) + fmt.format("private_key=%s\n", KeyEncoding.keyToHex(KeyEncoding.keyFromBase64(iface.getPrivateKey()))); + if (iface.getListenPort() != 0) + fmt.format("listen_port=%d\n", config.getInterface().getListenPort()); + for (final Peer peer : config.getPeers()) { + if (peer.getPublicKey() != null) + fmt.format("public_key=%s\n", KeyEncoding.keyToHex(KeyEncoding.keyFromBase64(peer.getPublicKey()))); + if (peer.getPreSharedKey() != null) + fmt.format("preshared_key=%s\n", KeyEncoding.keyToHex(KeyEncoding.keyFromBase64(peer.getPreSharedKey()))); + if (peer.getEndpoint() != null) + fmt.format("endpoint=%s\n", peer.getResolvedEndpointString()); + if (peer.getPersistentKeepalive() != 0) + fmt.format("persistent_keepalive_interval=%d\n", peer.getPersistentKeepalive()); + for (final IPCidr addr : peer.getAllowedIPs()) { + fmt.format("allowed_ip=%s\n", addr.toString()); + } } + goConfig = fmt.toString(); } // Create the vpn tunnel with android API - VpnService.Builder builder = service.getBuilder(); + final VpnService.Builder builder = service.getBuilder(); builder.setSession(tunnel.getName()); for (final IPCidr addr : config.getInterface().getAddresses()) @@ -166,13 +169,13 @@ public final class GoBackend implements Backend { builder.setMtu(mtu); builder.setBlocking(true); - ParcelFileDescriptor tun = builder.establish(); + final ParcelFileDescriptor tun = builder.establish(); if (tun == null) throw new Exception("Unable to create tun device"); - currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), fmt.toString()); + currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig); if (currentTunnelHandle < 0) - throw new Exception("Unable to turn tunnel on (wgTurnOn return " + currentTunnelHandle + ")"); + throw new Exception("Unable to turn tunnel on (wgTurnOn return " + currentTunnelHandle + ')'); currentTunnel = tunnel; diff --git a/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java b/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java index b91d8476..b9eb3461 100644 --- a/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java +++ b/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java @@ -105,14 +105,15 @@ public final class WgQuickBackend implements Backend { } final String command = String.format("wg-quick %s '%s'", state.toString().toLowerCase(), tempFile.getAbsolutePath()); final int result = rootShell.run(null, command); + // noinspection ResultOfMethodCallIgnored tempFile.delete(); if (result != 0) throw new Exception("Unable to configure tunnel (wg-quick returned " + result + ')'); } - public final static class WgQuickChangeReceiver extends BroadcastReceiver { + public static final class WgQuickChangeReceiver extends BroadcastReceiver { @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(final Context context, final Intent intent) { Log.d(TAG, "Refreshing tunnel states"); Application.getComponent().getTunnelManager().refreshTunnelStates(); } diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java index a3760ed9..f0731587 100644 --- a/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java +++ b/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java @@ -109,10 +109,10 @@ public class TunnelEditorFragment extends BaseFragment { public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case R.id.menu_action_save: - Config newConfig = new Config(); + final Config newConfig = new Config(); try { binding.getConfig().commitData(newConfig); - } catch (Exception e) { + } catch (final Exception e) { final String error = ExceptionLoggers.unwrap(e).getMessage(); final String tunnelName = tunnel == null ? binding.getConfig().getName() : tunnel.getName(); final String message = getString(R.string.config_save_error, tunnelName, error); @@ -202,8 +202,8 @@ public class TunnelEditorFragment extends BaseFragment { onSelectedTunnelChanged(null, getSelectedTunnel()); } else { tunnel = getSelectedTunnel(); - Config.Observable config = savedInstanceState.getParcelable(KEY_LOCAL_CONFIG); - String originalName = savedInstanceState.getString(KEY_ORIGINAL_NAME); + final Config.Observable config = savedInstanceState.getParcelable(KEY_LOCAL_CONFIG); + final String originalName = savedInstanceState.getString(KEY_ORIGINAL_NAME); if (tunnel != null && !tunnel.getName().equals(originalName)) onSelectedTunnelChanged(null, tunnel); else diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java index 2b81a98a..9fc7346b 100644 --- a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java +++ b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java @@ -43,6 +43,7 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.zip.ZipEntry; @@ -82,7 +83,7 @@ public class TunnelListFragment extends BaseFragment { return; final ContentResolver contentResolver = activity.getContentResolver(); - final List<CompletableFuture<Tunnel>> futureTunnels = new ArrayList<>(); + final Collection<CompletableFuture<Tunnel>> futureTunnels = new ArrayList<>(); final List<Throwable> throwables = new ArrayList<>(); asyncWorker.supplyAsync(() -> { final String[] columns = {OpenableColumns.DISPLAY_NAME}; @@ -106,31 +107,32 @@ public class TunnelListFragment extends BaseFragment { throw new IllegalArgumentException("File must be .conf or .zip"); if (isZip) { - ZipInputStream zip = new ZipInputStream(contentResolver.openInputStream(uri)); - BufferedReader reader = new BufferedReader(new InputStreamReader(zip, StandardCharsets.UTF_8)); - ZipEntry entry; - while ((entry = zip.getNextEntry()) != null) { - if (entry.isDirectory()) - continue; - name = entry.getName(); - idx = name.lastIndexOf('/'); - if (idx >= 0) { - if (idx >= name.length() - 1) + try (ZipInputStream zip = new ZipInputStream(contentResolver.openInputStream(uri))) { + BufferedReader reader = new BufferedReader(new InputStreamReader(zip, StandardCharsets.UTF_8)); + ZipEntry entry; + while ((entry = zip.getNextEntry()) != null) { + if (entry.isDirectory()) continue; - name = name.substring(name.lastIndexOf('/') + 1); - } - if (name.toLowerCase().endsWith(".conf")) - name = name.substring(0, name.length() - ".conf".length()); - else - continue; - Config config = null; - try { - config = Config.from(reader); - } catch (Exception e) { - throwables.add(e); + name = entry.getName(); + idx = name.lastIndexOf('/'); + if (idx >= 0) { + if (idx >= name.length() - 1) + continue; + name = name.substring(name.lastIndexOf('/') + 1); + } + if (name.toLowerCase().endsWith(".conf")) + name = name.substring(0, name.length() - ".conf".length()); + else + continue; + Config config = null; + try { + config = Config.from(reader); + } catch (Exception e) { + throwables.add(e); + } + if (config != null) + futureTunnels.add(tunnelManager.create(name, config).toCompletableFuture()); } - if (config != null) - futureTunnels.add(tunnelManager.create(name, config).toCompletableFuture()); } } else { futureTunnels.add(tunnelManager.create(name, Config.from(contentResolver.openInputStream(uri))).toCompletableFuture()); @@ -146,15 +148,15 @@ public class TunnelListFragment extends BaseFragment { return CompletableFuture.allOf(futureTunnels.toArray(new CompletableFuture[futureTunnels.size()])); }).whenComplete((future, exception) -> { if (exception != null) { - this.onTunnelImportFinished(Collections.emptyList(), Collections.singletonList(exception)); + onTunnelImportFinished(Collections.emptyList(), Collections.singletonList(exception)); } else { future.whenComplete((ignored1, ignored2) -> { - ArrayList<Tunnel> tunnels = new ArrayList<>(futureTunnels.size()); - for (CompletableFuture<Tunnel> futureTunnel : futureTunnels) { + final List<Tunnel> tunnels = new ArrayList<>(futureTunnels.size()); + for (final CompletableFuture<Tunnel> futureTunnel : futureTunnels) { Tunnel tunnel = null; try { tunnel = futureTunnel.getNow(null); - } catch (Exception e) { + } catch (final Exception e) { throwables.add(e); } if (tunnel != null) @@ -240,7 +242,7 @@ public class TunnelListFragment extends BaseFragment { } } - private void onTunnelImportFinished(final List<Tunnel> tunnels, final List<Throwable> throwables) { + private void onTunnelImportFinished(final List<Tunnel> tunnels, final Collection<Throwable> throwables) { String message = null; for (final Throwable throwable : throwables) { diff --git a/app/src/main/java/com/wireguard/android/preference/ZipExporterPreference.java b/app/src/main/java/com/wireguard/android/preference/ZipExporterPreference.java index b10d8388..677c56c9 100644 --- a/app/src/main/java/com/wireguard/android/preference/ZipExporterPreference.java +++ b/app/src/main/java/com/wireguard/android/preference/ZipExporterPreference.java @@ -22,6 +22,7 @@ import com.wireguard.config.Config; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -39,7 +40,7 @@ public class ZipExporterPreference extends Preference { private final AsyncWorker asyncWorker; private final TunnelManager tunnelManager; - private String exportedFilePath = null; + private String exportedFilePath; @SuppressWarnings({"SameParameterValue", "WeakerAccess"}) public ZipExporterPreference(final Context context, final AttributeSet attrs) { @@ -49,9 +50,19 @@ public class ZipExporterPreference extends Preference { tunnelManager = applicationComponent.getTunnelManager(); } + private static SettingsActivity getPrefActivity(final Preference preference) { + final Context context = preference.getContext(); + if (context instanceof ContextThemeWrapper) { + if (((ContextThemeWrapper) context).getBaseContext() instanceof SettingsActivity) { + return ((SettingsActivity) ((ContextThemeWrapper) context).getBaseContext()); + } + } + return null; + } + private void exportZip() { - List<Tunnel> tunnels = new ArrayList<>(tunnelManager.getTunnels()); - List<CompletableFuture<Config>> futureConfigs = new ArrayList<>(tunnels.size()); + final List<Tunnel> tunnels = new ArrayList<>(tunnelManager.getTunnels()); + final List<CompletableFuture<Config>> futureConfigs = new ArrayList<>(tunnels.size()); for (final Tunnel tunnel : tunnels) futureConfigs.add(tunnel.getConfigAsync().toCompletableFuture()); if (futureConfigs.isEmpty()) { @@ -65,9 +76,9 @@ public class ZipExporterPreference extends Preference { throw exception; final File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); final File file = new File(path, "wireguard-export.zip"); - try { - path.mkdirs(); - final ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file)); + if (!path.mkdirs()) + throw new IOException("Cannot create output directory"); + try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file))) { for (int i = 0; i < futureConfigs.size(); ++i) { zip.putNextEntry(new ZipEntry(tunnels.get(i).getName() + ".conf")); zip.write(futureConfigs.get(i).getNow(null). @@ -76,6 +87,7 @@ public class ZipExporterPreference extends Preference { zip.closeEntry(); zip.close(); } catch (Exception e) { + // noinspection ResultOfMethodCallIgnored file.delete(); throw e; } @@ -84,7 +96,7 @@ public class ZipExporterPreference extends Preference { }); } - private void exportZipComplete(String filePath, Throwable throwable) { + private void exportZipComplete(final String filePath, final Throwable throwable) { if (throwable != null) { final String error = ExceptionLoggers.unwrap(throwable).getMessage(); final String message = getContext().getString(R.string.export_error, error); @@ -99,16 +111,6 @@ public class ZipExporterPreference extends Preference { } } - private SettingsActivity getPrefActivity(Preference preference) { - Context context = preference.getContext(); - if (context instanceof ContextThemeWrapper) { - if (((ContextThemeWrapper) context).getBaseContext() instanceof SettingsActivity) { - return ((SettingsActivity) ((ContextThemeWrapper) context).getBaseContext()); - } - } - return null; - } - @Override public CharSequence getSummary() { if (exportedFilePath == null) |