mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-22 23:09:13 +00:00
Request root access from separate thread and don't use global Shell
This should help prevent some of the ANR's reported through Google Play
This commit is contained in:
parent
ac51996896
commit
69f0bb4fbc
8 changed files with 78 additions and 23 deletions
|
@ -39,8 +39,8 @@ public abstract class AegisApplicationBase extends Application {
|
|||
private VaultManager _vaultManager;
|
||||
|
||||
static {
|
||||
// to access other app's internal storage directory, run libsu commands inside the global mount namespace
|
||||
Shell.setDefaultBuilder(Shell.Builder.create().setFlags(Shell.FLAG_MOUNT_MASTER));
|
||||
// Enable verbose libsu logging in debug builds
|
||||
Shell.enableVerboseLogging = BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
|
|||
import com.beemdevelopment.aegis.util.JsonUtils;
|
||||
import com.beemdevelopment.aegis.util.PreferenceParser;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
import com.topjohnwu.superuser.io.SuFileInputStream;
|
||||
|
||||
|
@ -67,8 +68,9 @@ public class AuthyImporter extends DatabaseImporter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State readFromApp() throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
public State readFromApp(Shell shell) throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
SuFile path = getAppPath();
|
||||
path.setShell(shell);
|
||||
|
||||
JSONArray array;
|
||||
JSONArray authyArray;
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.annotation.StringRes;
|
|||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.util.UUIDMap;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
import com.topjohnwu.superuser.io.SuFileInputStream;
|
||||
|
||||
|
@ -70,8 +71,10 @@ public abstract class DatabaseImporter {
|
|||
return read(stream, false);
|
||||
}
|
||||
|
||||
public State readFromApp() throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
public State readFromApp(Shell shell) throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
SuFile file = getAppPath();
|
||||
file.setShell(shell);
|
||||
|
||||
try (InputStream stream = SuFileInputStream.open(file)) {
|
||||
return read(stream, true);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.beemdevelopment.aegis.otp.OtpInfo;
|
|||
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
@ -31,7 +32,8 @@ public class GoogleAuthImporter extends DatabaseImporter {
|
|||
|
||||
@Override
|
||||
protected SuFile getAppPath() throws PackageManager.NameNotFoundException {
|
||||
return getAppPath(_pkgName, _subPath);
|
||||
SuFile file = getAppPath(_pkgName, _subPath);
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,8 +57,10 @@ public class GoogleAuthImporter extends DatabaseImporter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DatabaseImporter.State readFromApp() throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
public DatabaseImporter.State readFromApp(Shell shell) throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
SuFile path = getAppPath();
|
||||
path.setShell(shell);
|
||||
|
||||
final Context context = requireContext();
|
||||
SqlImporterHelper helper = new SqlImporterHelper(context);
|
||||
List<Entry> entries = helper.read(Entry.class, path, "accounts");
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.beemdevelopment.aegis.otp.OtpInfo;
|
|||
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
@ -40,8 +41,10 @@ public class MicrosoftAuthImporter extends DatabaseImporter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DatabaseImporter.State readFromApp() throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
public DatabaseImporter.State readFromApp(Shell shell) throws PackageManager.NameNotFoundException, DatabaseImporterException {
|
||||
SuFile path = getAppPath();
|
||||
path.setShell(shell);
|
||||
|
||||
SqlImporterHelper helper = new SqlImporterHelper(requireContext());
|
||||
List<Entry> entries = helper.read(Entry.class, path, "accounts");
|
||||
return new State(entries);
|
||||
|
|
|
@ -20,12 +20,12 @@ import com.beemdevelopment.aegis.importers.DatabaseImporterEntryException;
|
|||
import com.beemdevelopment.aegis.importers.DatabaseImporterException;
|
||||
import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
|
||||
import com.beemdevelopment.aegis.ui.models.ImportEntry;
|
||||
import com.beemdevelopment.aegis.ui.tasks.RootShellTask;
|
||||
import com.beemdevelopment.aegis.ui.views.ImportEntriesAdapter;
|
||||
import com.beemdevelopment.aegis.util.UUIDMap;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.beemdevelopment.aegis.vault.VaultRepository;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -118,25 +118,36 @@ public class ImportEntriesActivity extends AegisActivity {
|
|||
}
|
||||
|
||||
private void startImportApp(@NonNull DatabaseImporter importer) {
|
||||
// obtain the global root shell and close it immediately after we're done
|
||||
// TODO: find a way to use SuFileInputStream with Shell.newInstance()
|
||||
try (Shell shell = Shell.getShell()) {
|
||||
if (!shell.isRoot()) {
|
||||
RootShellTask task = new RootShellTask(this, shell -> {
|
||||
if (isFinishing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell == null || !shell.isRoot()) {
|
||||
Toast.makeText(this, R.string.root_error, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
DatabaseImporter.State state = importer.readFromApp();
|
||||
processImporterState(state);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, R.string.app_lookup_error, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
} catch (IOException | DatabaseImporterException e) {
|
||||
e.printStackTrace();
|
||||
Dialogs.showErrorDialog(this, R.string.reading_file_error, e, (dialog, which) -> finish());
|
||||
}
|
||||
try {
|
||||
DatabaseImporter.State state = importer.readFromApp(shell);
|
||||
processImporterState(state);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, R.string.app_lookup_error, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
} catch (DatabaseImporterException e) {
|
||||
e.printStackTrace();
|
||||
Dialogs.showErrorDialog(this, R.string.reading_file_error, e, (dialog, which) -> finish());
|
||||
} finally {
|
||||
try {
|
||||
shell.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
task.execute(this);
|
||||
}
|
||||
|
||||
private void processImporterState(DatabaseImporter.State state) {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.beemdevelopment.aegis.ui.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.beemdevelopment.aegis.R;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
public class RootShellTask extends ProgressDialogTask<Object, Shell> {
|
||||
private final Callback _cb;
|
||||
|
||||
public RootShellTask(Context context, Callback cb) {
|
||||
super(context, context.getString(R.string.requesting_root_access));
|
||||
_cb = cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Shell doInBackground(Object... params) {
|
||||
// To access other app's internal storage directory, run libsu commands inside the global mount namespace
|
||||
return Shell.Builder.create().setFlags(Shell.FLAG_MOUNT_MASTER).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Shell shell) {
|
||||
super.onPostExecute(shell);
|
||||
_cb.onTaskFinished(shell);
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onTaskFinished(Shell shell);
|
||||
}
|
||||
}
|
|
@ -171,6 +171,7 @@
|
|||
<string name="encrypting_vault">Encrypting the vault</string>
|
||||
<string name="exporting_vault">Exporting the vault</string>
|
||||
<string name="reading_file">Reading file</string>
|
||||
<string name="requesting_root_access">Requesting root access</string>
|
||||
<string name="analyzing_qr">Analyzing QR code</string>
|
||||
<string name="analyzing_qr_multiple">Analyzing QR code %d/%d (%s)</string>
|
||||
<plurals name="added_new_entries">
|
||||
|
@ -237,7 +238,7 @@
|
|||
<string name="reading_file_error">An error occurred while trying to read the file</string>
|
||||
<string name="app_lookup_error">Error: App is not installed</string>
|
||||
<string name="app_version_error">The version of %s that\'s installed is not supported. Recent versions have started encrypting some of the files in the internal storage directory, making Aegis unable to access the information it needs for the import. Attempting to import is likely to result in an error. Would you like to continue anyway?</string>
|
||||
<string name="root_error">Error: unable to obtain root access</string>
|
||||
<string name="root_error">Error: Unable to obtain root access</string>
|
||||
<plurals name="imported_entries_count">
|
||||
<item quantity="one">Imported %d entry</item>
|
||||
<item quantity="other">Imported %d entries</item>
|
||||
|
|
Loading…
Add table
Reference in a new issue