Просмотр исходного кода

ToolsInstaller: Extract to its own classes

Signed-off-by: Samuel Holland <samuel@sholland.org>
master
Samuel Holland 6 лет назад
Родитель
Сommit
08cca56388
6 измененных файлов: 171 добавлений и 82 удалений
  1. +3
    -0
      app/src/main/java/com/wireguard/android/Application.java
  2. +0
    -72
      app/src/main/java/com/wireguard/android/activity/SettingsActivity.java
  3. +91
    -0
      app/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.java
  4. +70
    -0
      app/src/main/java/com/wireguard/android/util/ToolsInstaller.java
  5. +6
    -6
      app/src/main/res/values/strings.xml
  6. +1
    -4
      app/src/main/res/xml/preferences.xml

+ 3
- 0
app/src/main/java/com/wireguard/android/Application.java Просмотреть файл

@@ -15,6 +15,7 @@ import com.wireguard.android.configStore.FileConfigStore;
import com.wireguard.android.model.TunnelManager;
import com.wireguard.android.util.AsyncWorker;
import com.wireguard.android.util.RootShell;
import com.wireguard.android.util.ToolsInstaller;

import java.util.concurrent.Executor;

@@ -56,6 +57,8 @@ public class Application extends android.app.Application {

SharedPreferences getPreferences();

ToolsInstaller getToolsInstaller();

TunnelManager getTunnelManager();
}



+ 0
- 72
app/src/main/java/com/wireguard/android/activity/SettingsActivity.java Просмотреть файл

@@ -1,14 +1,10 @@
package com.wireguard.android.activity;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;

import com.wireguard.android.R;
import com.wireguard.android.util.RootShell;

/**
* Interface for changing application-global persistent settings.
@@ -30,74 +26,6 @@ public class SettingsActivity extends Activity {
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
final Preference installTools = findPreference("install_cmd_line_tools");
installTools.setOnPreferenceClickListener(preference -> {
new ToolsInstaller(preference).execute();
return true;
});
}
}

private static final class ToolsInstaller extends AsyncTask<Void, Void, Integer> {
private static final String[][] LIBRARY_NAMED_EXECUTABLES = {
{"libwg.so", "wg"},
{"libwg-quick.so", "wg-quick"}
};

private final Context context;
private final Preference preference;

private ToolsInstaller(final Preference preference) {
context = preference.getContext();
this.preference = preference;
preference.setEnabled(false);
preference.setSummary(context.getString(R.string.install_cmd_line_tools_progress));
}

@Override
protected Integer doInBackground(final Void... voids) {
final String libDir = context.getApplicationInfo().nativeLibraryDir;
final StringBuilder cmd = new StringBuilder();

cmd.append("set -ex;");

for (final String[] libraryNamedExecutable : LIBRARY_NAMED_EXECUTABLES) {
final String arg1 = '\'' + libDir + '/' + libraryNamedExecutable[0] + '\'';
final String arg2 = "'/system/xbin/" + libraryNamedExecutable[1] + '\'';

cmd.append(String.format("cmp -s %s %s && ", arg1, arg2));
}
cmd.append("exit 114;");

cmd.append("trap 'mount -o ro,remount /system' EXIT;");
cmd.append("mount -o rw,remount /system;");

for (final String[] libraryNamedExecutable : LIBRARY_NAMED_EXECUTABLES) {
final String arg1 = '\'' + libDir + '/' + libraryNamedExecutable[0] + '\'';
final String arg2 = "'/system/xbin/" + libraryNamedExecutable[1] + '\'';
cmd.append(String.format("cp %s %s; chmod 755 %s;", arg1, arg2, arg2));
}

return new RootShell(context).run(null, cmd.toString());
}

@Override
protected void onPostExecute(final Integer ret) {
final String status;

switch (ret) {
case 0:
status = context.getString(R.string.install_cmd_line_tools_success);
break;
case 114 /* OsConstants.EALREADY */:
status = context.getString(R.string.install_cmd_line_tools_already);
break;
default:
status = context.getString(R.string.install_cmd_line_tools_failure);
break;
}
preference.setSummary(status);
preference.setEnabled(true);
}
}
}

+ 91
- 0
app/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.java Просмотреть файл

@@ -0,0 +1,91 @@
package com.wireguard.android.preference;

import android.content.Context;
import android.preference.Preference;
import android.system.OsConstants;
import android.util.AttributeSet;

import com.wireguard.android.Application;
import com.wireguard.android.Application.ApplicationComponent;
import com.wireguard.android.R;
import com.wireguard.android.util.AsyncWorker;
import com.wireguard.android.util.ToolsInstaller;

/**
* Preference implementing a button that asynchronously runs {@code ToolsInstaller} and displays the
* result as the preference summary.
*/

public class ToolsInstallerPreference extends Preference {
private final AsyncWorker asyncWorker;
private final ToolsInstaller toolsInstaller;
private State state = State.INITIAL;

public ToolsInstallerPreference(final Context context, final AttributeSet attrs) {
super(context, attrs);
final ApplicationComponent applicationComponent = Application.getComponent();
asyncWorker = applicationComponent.getAsyncWorker();
toolsInstaller = applicationComponent.getToolsInstaller();
}

public ToolsInstallerPreference(final Context context) {
this(context, null);
}

private static State mapResultToState(final int scriptResult) {
if (scriptResult == OsConstants.EXIT_SUCCESS)
return State.SUCCESS;
else if (scriptResult == OsConstants.EALREADY)
return State.ALREADY;
else
return State.FAILURE;
}

@Override
public CharSequence getSummary() {
return getContext().getString(state.messageResourceId);
}

@Override
public CharSequence getTitle() {
return getContext().getString(getTitleRes());
}

@Override
public int getTitleRes() {
return R.string.tools_installer_title;
}

@Override
protected void onClick() {
setState(State.WORKING);
asyncWorker.supplyAsync(toolsInstaller::install)
.thenApply(ToolsInstallerPreference::mapResultToState)
.thenAccept(this::setState);
}

private void setState(final State state) {
if (this.state == state)
return;
this.state = state;
if (isEnabled() != state.shouldEnableView)
setEnabled(state.shouldEnableView);
notifyChanged();
}

private enum State {
ALREADY(R.string.tools_installer_already, false),
FAILURE(R.string.tools_installer_failure, true),
INITIAL(R.string.tools_installer_initial, true),
SUCCESS(R.string.tools_installer_success, false),
WORKING(R.string.tools_installer_working, false);

private final int messageResourceId;
private final boolean shouldEnableView;

State(final int messageResourceId, final boolean shouldEnableView) {
this.messageResourceId = messageResourceId;
this.shouldEnableView = shouldEnableView;
}
}
}

+ 70
- 0
app/src/main/java/com/wireguard/android/util/ToolsInstaller.java Просмотреть файл

@@ -0,0 +1,70 @@
package com.wireguard.android.util;

import android.content.Context;
import android.system.OsConstants;

import com.wireguard.android.Application.ApplicationContext;
import com.wireguard.android.Application.ApplicationScope;

import java.io.File;
import java.util.Arrays;
import java.util.List;

import javax.inject.Inject;

/**
* Helper to install WireGuard tools to the system partition.
*/

@ApplicationScope
public final class ToolsInstaller {
private static final String[][] EXECUTABLES = {
{"libwg.so", "wg"},
{"libwg-quick.so", "wg-quick"},
};
private static final File[] INSTALL_DIRS = {
new File("/system/xbin"),
new File("/system/bin"),
};

private final String nativeLibraryDir;
private final RootShell rootShell;

@Inject
public ToolsInstaller(@ApplicationContext final Context context, final RootShell rootShell) {
nativeLibraryDir = context.getApplicationInfo().nativeLibraryDir;
this.rootShell = rootShell;
}

private static File getInstallDir() {
final String path = System.getenv("PATH");
if (path == null)
return INSTALL_DIRS[0];
final List<String> paths = Arrays.asList(path.split(":"));
for (final File dir : INSTALL_DIRS)
if (paths.contains(dir.getPath()) && dir.isDirectory())
return dir;
return null;
}

public int install() {
final File installDir = getInstallDir();
if (installDir == null)
return OsConstants.ENOENT;
final StringBuilder script = new StringBuilder("set -ex; ");
for (final String[] names : EXECUTABLES) {
script.append(String.format("cmp -s '%s' '%s' && ",
new File(nativeLibraryDir, names[0]),
new File(installDir, names[1])));
}
script.append("exit ").append(OsConstants.EALREADY).append("; ");
script.append("trap 'mount -o ro,remount /system' EXIT; mount -o rw,remount /system; ");
for (final String[] names : EXECUTABLES) {
script.append(String.format("cp %s %s; chmod 755 %s; ",
new File(nativeLibraryDir, names[0]),
new File(installDir, names[1]),
new File(installDir, names[1])));
}
return rootShell.run(null, script.toString());
}
}

+ 6
- 6
app/src/main/res/values/strings.xml Просмотреть файл

@@ -58,16 +58,16 @@
<string name="public_key_description">Public key</string>
<string name="restore_on_boot">Restore on boot</string>
<string name="restore_on_boot_summary">Restore previously enabled configurations on boot</string>
<string name="install_cmd_line_tools">Install command line tools</string>
<string name="install_cmd_line_tools_summary">Install optional tools for scripting into /system/xbin</string>
<string name="install_cmd_line_tools_success">wg and wg-quick installed into /system/xbin</string>
<string name="install_cmd_line_tools_progress">Installing wg and wg-quick into /system/xbin</string>
<string name="install_cmd_line_tools_already">wg and wg-quick are already installed</string>
<string name="install_cmd_line_tools_failure">Command line tools could not be installed</string>
<string name="save">Save</string>
<string name="settings">Settings</string>
<string name="status">Status</string>
<string name="toggle">Toggle</string>
<string name="tools_installer_already">wg and wg-quick are already installed</string>
<string name="tools_installer_failure">Command line tools could not be installed (no root?)</string>
<string name="tools_installer_initial">Install optional tools for scripting into the system partition</string>
<string name="tools_installer_success">wg and wg-quick installed into the system partition</string>
<string name="tools_installer_title">Install command line tools</string>
<string name="tools_installer_working">Installing wg and wg-quick into the system partition</string>
<string name="last_change">Last change</string>
<string name="never">never</string>
</resources>

+ 1
- 4
app/src/main/res/xml/preferences.xml Просмотреть файл

@@ -5,8 +5,5 @@
android:key="restore_on_boot"
android:summary="@string/restore_on_boot_summary"
android:title="@string/restore_on_boot" />
<Preference
android:key="install_cmd_line_tools"
android:summary="@string/install_cmd_line_tools_summary"
android:title="@string/install_cmd_line_tools" />
<com.wireguard.android.preference.ToolsInstallerPreference />
</PreferenceScreen>

Загрузка…
Отмена
Сохранить