Use Java synchronize instead serial tasks

This commit is contained in:
topjohnwu 2017-06-06 03:06:23 +08:00
parent ff6938280e
commit efeddda328
17 changed files with 143 additions and 146 deletions

View File

@ -24,7 +24,7 @@ import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.SerialTask; import com.topjohnwu.magisk.asyncs.RootTask;
import com.topjohnwu.magisk.components.Fragment; import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.components.SnackbarMaker; import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Shell;
@ -127,14 +127,14 @@ public class MagiskLogFragment extends Fragment {
} }
} }
public class LogManager extends SerialTask<Object, Void, Object> { private class LogManager extends RootTask<Object, Void, Object> {
int mode; int mode;
File targetFile; File targetFile;
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
@Override @Override
protected Object doInBackground(Object... params) { protected Object doInRoot(Object... params) {
mode = (int) params[0]; mode = (int) params[0];
switch (mode) { switch (mode) {
case 0: case 0:

View File

@ -12,7 +12,6 @@ import android.support.v7.widget.Toolbar;
import android.widget.Toast; import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.MagiskHide; import com.topjohnwu.magisk.asyncs.MagiskHide;
import com.topjohnwu.magisk.asyncs.SerialTask;
import com.topjohnwu.magisk.components.Activity; import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder; import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.database.SuDatabaseHelper; import com.topjohnwu.magisk.database.SuDatabaseHelper;
@ -140,18 +139,11 @@ public class SettingsActivity extends Activity {
break; break;
case "disable": case "disable":
enabled = prefs.getBoolean("disable", false); enabled = prefs.getBoolean("disable", false);
new SerialTask<Void, Void, Void>() { if (enabled) {
private boolean enable = enabled; Utils.createFile(MagiskManager.MAGISK_DISABLE_FILE);
@Override } else {
protected Void doInBackground(Void... voids) { Utils.removeItem(MagiskManager.MAGISK_DISABLE_FILE);
if (enable) { }
Utils.createFile(MagiskManager.MAGISK_DISABLE_FILE);
} else {
Utils.removeItem(MagiskManager.MAGISK_DISABLE_FILE);
}
return null;
}
}.exec();
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show(); Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
break; break;
case "magiskhide": case "magiskhide":
@ -173,20 +165,15 @@ public class SettingsActivity extends Activity {
break; break;
case "hosts": case "hosts":
enabled = prefs.getBoolean("hosts", false); enabled = prefs.getBoolean("hosts", false);
new SerialTask<Void, Void, Void>() { if (enabled) {
private boolean enable = enabled; Shell.su_async(null,
@Override "cp -af /system/etc/hosts /magisk/.core/hosts",
protected Void doInBackground(Void... voids) { "mount -o bind /magisk/.core/hosts /system/etc/hosts");
if (enable) { } else {
Shell.su("cp -af /system/etc/hosts /magisk/.core/hosts", Shell.su_async(null,
"mount -o bind /magisk/.core/hosts /system/etc/hosts"); "umount -l /system/etc/hosts",
} else { "rm -f /magisk/.core/hosts");
Shell.su("umount -l /system/etc/hosts", }
"rm -f /magisk/.core/hosts");
}
return null;
}
}.exec();
break; break;
case "su_access": case "su_access":
magiskManager.suAccessState = Utils.getPrefsInt(prefs, "su_access", 3); magiskManager.suAccessState = Utils.getPrefsInt(prefs, "su_access", 3);

View File

@ -25,28 +25,18 @@ public class SplashActivity extends Activity{
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
MagiskManager magiskManager = getApplicationContext();
// Init the info and configs and root shell // Init the info and configs and root shell
magiskManager.init(); getApplicationContext().init();
// Now fire all async tasks // Now fire all async tasks
new GetBootBlocks(this).exec(); new GetBootBlocks(this).exec();
new LoadModules(this) { new LoadModules(this).setCallBack(() -> new LoadRepos(this).exec()).exec();
@Override
protected void onPostExecute(Void v) {
super.onPostExecute(v);
if (Utils.checkNetworkStatus(activity)) {
new LoadRepos(activity).exec();
}
}
}.exec();
new LoadApps(this).exec(); new LoadApps(this).exec();
if (Utils.checkNetworkStatus(this)) { if (Utils.checkNetworkStatus(this)) {
// Initialize the update check service, notify every 12 hours // Initialize the update check service, notify every 12 hours
if (!TextUtils.equals("install", getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) { if (!TextUtils.equals("install", getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
ComponentName service = new ComponentName(magiskManager, UpdateCheckService.class); ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service) JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true) .setPersisted(true)
@ -57,7 +47,7 @@ public class SplashActivity extends Activity{
} }
} }
Intent intent = new Intent(magiskManager, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION); String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
if (section != null) { if (section != null) {
intent.putExtra(MagiskManager.INTENT_SECTION, section); intent.putExtra(MagiskManager.INTENT_SECTION, section);

View File

@ -12,7 +12,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.SerialTask;
import com.topjohnwu.magisk.components.SnackbarMaker; import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Shell;
@ -53,44 +52,31 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
holder.checkBox.setOnCheckedChangeListener(null); holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setChecked(module.isEnabled()); holder.checkBox.setChecked(module.isEnabled());
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> new SerialTask<Void, Void, Void>() { holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
@Override int snack;
protected Void doInBackground(Void... voids) { if (isChecked) {
if (isChecked) { module.removeDisableFile();
module.removeDisableFile(); snack = R.string.disable_file_removed;
} else { } else {
module.createDisableFile(); module.createDisableFile();
} snack = R.string.disable_file_created;
return null;
} }
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
});
@Override holder.delete.setOnClickListener(v -> {
protected void onPostExecute(Void v) { boolean removed = module.willBeRemoved();
int snack = isChecked ? R.string.disable_file_removed : R.string.disable_file_created; int snack;
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show(); if (removed) {
module.deleteRemoveFile();
snack = R.string.remove_file_deleted;
} else {
module.createRemoveFile();
snack = R.string.remove_file_created;
} }
}.exec()); SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
updateDeleteButton(holder, module);
holder.delete.setOnClickListener(v -> new SerialTask<Void, Void, Void>() { });
private final boolean removed = module.willBeRemoved();
@Override
protected Void doInBackground(Void... voids) {
if (removed) {
module.deleteRemoveFile();
} else {
module.createRemoveFile();
}
return null;
}
@Override
protected void onPostExecute(Void v) {
int snack = removed ? R.string.remove_file_deleted : R.string.remove_file_created;
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
updateDeleteButton(holder, module);
}
}.exec());
if (module.isUpdated()) { if (module.isUpdated()) {
holder.notice.setVisibility(View.VISIBLE); holder.notice.setVisibility(View.VISIBLE);

View File

@ -68,5 +68,6 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
notificationManager.notify(NOTIFICATION_ID, builder.build()); notificationManager.notify(NOTIFICATION_ID, builder.build());
} }
magiskManager.updateCheckDone.trigger(); magiskManager.updateCheckDone.trigger();
super.onPostExecute(v);
} }
} }

View File

@ -21,7 +21,7 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List; import java.util.List;
public class FlashZip extends SerialTask<Void, String, Integer> { public class FlashZip extends RootTask<Void, String, Integer> {
private Uri mUri; private Uri mUri;
private File mCachedFile, mScriptFile, mCheckFile; private File mCachedFile, mScriptFile, mCheckFile;
@ -96,7 +96,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
} }
@Override @Override
protected Integer doInBackground(Void... voids) { protected Integer doInRoot(Void... voids) {
Logger.dev("FlashZip Running... " + mFilename); Logger.dev("FlashZip Running... " + mFilename);
List<String> ret; List<String> ret;
try { try {
@ -124,7 +124,6 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
// -1 = error, manual install; 0 = invalid zip; 1 = success // -1 = error, manual install; 0 = invalid zip; 1 = success
@Override @Override
protected void onPostExecute(Integer result) { protected void onPostExecute(Integer result) {
super.onPostExecute(result);
progress.dismiss(); progress.dismiss();
switch (result) { switch (result) {
case -1: case -1:
@ -138,6 +137,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
onSuccess(); onSuccess();
break; break;
} }
super.onPostExecute(result);
} }
protected void onSuccess() { protected void onSuccess() {

View File

@ -5,15 +5,17 @@ import android.app.Activity;
import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
public class GetBootBlocks extends SerialTask<Void, Void, Void> { public class GetBootBlocks extends RootTask<Void, Void, Void> {
public GetBootBlocks(Activity context) { public GetBootBlocks(Activity context) {
super(context); super(context);
} }
@Override @Override
protected Void doInBackground(Void... params) { protected Void doInRoot(Void... params) {
magiskManager.blockList = Shell.su("ls /dev/block | grep mmc"); magiskManager.blockList = Shell.su(
"find /dev/block -type b -maxdepth 1 | grep -v -E \"loop|ram|dm-0\""
);
if (magiskManager.bootBlock == null) { if (magiskManager.bootBlock == null) {
magiskManager.bootBlock = Utils.detectBootImage(); magiskManager.bootBlock = Utils.detectBootImage();
} }
@ -23,5 +25,6 @@ public class GetBootBlocks extends SerialTask<Void, Void, Void> {
@Override @Override
protected void onPostExecute(Void v) { protected void onPostExecute(Void v) {
magiskManager.blockDetectionDone.trigger(); magiskManager.blockDetectionDone.trigger();
super.onPostExecute(v);
} }
} }

View File

@ -9,14 +9,14 @@ import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ValueSortedMap; import com.topjohnwu.magisk.utils.ValueSortedMap;
public class LoadModules extends SerialTask<Void, Void, Void> { public class LoadModules extends RootTask<Void, Void, Void> {
public LoadModules(Activity context) { public LoadModules(Activity context) {
super(context); super(context);
} }
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInRoot(Void... voids) {
Logger.dev("LoadModules: Loading modules"); Logger.dev("LoadModules: Loading modules");
magiskManager.moduleMap = new ValueSortedMap<>(); magiskManager.moduleMap = new ValueSortedMap<>();
@ -37,5 +37,6 @@ public class LoadModules extends SerialTask<Void, Void, Void> {
@Override @Override
protected void onPostExecute(Void v) { protected void onPostExecute(Void v) {
magiskManager.moduleLoadDone.trigger(); magiskManager.moduleLoadDone.trigger();
super.onPostExecute(v);
} }
} }

View File

@ -184,5 +184,6 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
@Override @Override
protected void onPostExecute(Void v) { protected void onPostExecute(Void v) {
magiskManager.repoLoadDone.trigger(); magiskManager.repoLoadDone.trigger();
super.onPostExecute(v);
} }
} }

View File

@ -6,7 +6,7 @@ import com.topjohnwu.magisk.utils.Shell;
import java.util.List; import java.util.List;
public class MagiskHide extends SerialTask<Object, Void, Void> { public class MagiskHide extends RootTask<Object, Void, Void> {
private boolean isList = false; private boolean isList = false;
@ -17,7 +17,7 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
} }
@Override @Override
protected Void doInBackground(Object... params) { protected Void doInRoot(Object... params) {
String command = (String) params[0]; String command = (String) params[0];
List<String> ret = Shell.su("magiskhide --" + command); List<String> ret = Shell.su("magiskhide --" + command);
if (isList) { if (isList) {
@ -31,6 +31,7 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
if (isList) { if (isList) {
magiskManager.magiskHideDone.trigger(); magiskManager.magiskHideDone.trigger();
} }
super.onPostExecute(v);
} }
public void add(CharSequence packageName) { public void add(CharSequence packageName) {

View File

@ -7,9 +7,12 @@ import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
protected Activity activity; protected Activity activity;
protected MagiskManager magiskManager; protected MagiskManager magiskManager;
private Runnable callback = null;
public ParallelTask() {} public ParallelTask() {}
public ParallelTask(Activity context) { public ParallelTask(Activity context) {
@ -17,8 +20,18 @@ public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<P
magiskManager = Utils.getMagiskManager(context); magiskManager = Utils.getMagiskManager(context);
} }
@SafeVarargs @SuppressWarnings("unchecked")
public final void exec(Params... params) { public void exec(Params... params) {
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} }
@Override
protected void onPostExecute(Result result) {
if (callback != null) callback.run();
}
public ParallelTask<Params, Progress, Result> setCallBack(Runnable next) {
callback = next;
return this;
}
} }

View File

@ -33,13 +33,13 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
@Override @Override
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
if (Shell.rootAccess()) { if (Shell.rootAccess()) {
// Running in parallel mode, open new shell synchronized (Shell.lock) {
Shell.su(true, Shell.su("rm -f /dev/.magisk",
"rm -f /dev/.magisk", (mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "",
(mBoot != null) ? "echo \"BOOTIMAGE=/dev/block/" + mBoot + "\" >> /dev/.magisk" : "", "echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk", "echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk"
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk" );
); }
return true; return true;
} }
return false; return false;
@ -53,5 +53,6 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
} else { } else {
Utils.showUriSnack(activity, mUri); Utils.showUriSnack(activity, mUri);
} }
super.onPostExecute(result);
} }
} }

View File

@ -0,0 +1,33 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import com.topjohnwu.magisk.utils.Shell;
public abstract class RootTask <Params, Progress, Result> extends ParallelTask<Params, Progress, Result> {
public RootTask() {}
public RootTask(Activity context) {
super(context);
}
@SafeVarargs
@Override
final protected Result doInBackground(Params... params) {
synchronized (Shell.lock) {
return doInRoot(params);
}
}
@SuppressWarnings("unchecked")
abstract protected Result doInRoot(Params... params);
@SuppressWarnings("unchecked")
@Override
public void exec(Params... params) {
if (Shell.rootAccess()) {
super.exec(params);
}
}
}

View File

@ -1,30 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.os.AsyncTask;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
/**
* This class is only used for running root commands
**/
public abstract class SerialTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
protected Activity activity;
protected MagiskManager magiskManager;
public SerialTask() {}
public SerialTask(Activity context) {
activity = context;
magiskManager = Utils.getMagiskManager(context);
}
@SafeVarargs
public final void exec(Params... params) {
if (!Shell.rootAccess()) return;
executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);
}
}

View File

@ -33,11 +33,13 @@ public class Module extends BaseModule {
} }
public void createDisableFile() { public void createDisableFile() {
mEnable = !Utils.createFile(mDisableFile); mEnable = false;
Utils.createFile(mDisableFile);
} }
public void removeDisableFile() { public void removeDisableFile() {
mEnable = Utils.removeItem(mDisableFile); mEnable = true;
Utils.removeItem(mDisableFile);
} }
public boolean isEnabled() { public boolean isEnabled() {
@ -45,11 +47,13 @@ public class Module extends BaseModule {
} }
public void createRemoveFile() { public void createRemoveFile() {
mRemove = Utils.createFile(mRemoveFile); mRemove = true;
Utils.createFile(mRemoveFile);
} }
public void deleteRemoveFile() { public void deleteRemoveFile() {
mRemove = !Utils.removeItem(mRemoveFile); mRemove = false;
Utils.removeItem(mRemoveFile);
} }
public boolean willBeRemoved() { public boolean willBeRemoved() {

View File

@ -1,5 +1,7 @@
package com.topjohnwu.magisk.utils; package com.topjohnwu.magisk.utils;
import com.topjohnwu.magisk.asyncs.RootTask;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -14,6 +16,7 @@ public class Shell {
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted // -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
public static int rootStatus; public static int rootStatus;
public static final Object lock = new Object();
private static boolean isInit = false; private static boolean isInit = false;
private static Process rootShell; private static Process rootShell;
@ -212,4 +215,15 @@ public class Shell {
return new ArrayList<>(res); return new ArrayList<>(res);
} }
public static void su_async(List<String> result, String... commands) {
new RootTask<Void, Void, Void>() {
@Override
protected Void doInRoot(Void... params) {
List<String> ret = Shell.su(commands);
if (result != null) result.addAll(ret);
return null;
}
}.exec();
}
} }

View File

@ -39,23 +39,15 @@ public class Utils {
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0)); return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
} }
public static boolean commandExists(String s) { public static void createFile(String path) {
String command = "if [ -z $(which " + s + ") ]; then echo false; else echo true; fi";
List<String> ret = Shell.sh(command);
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
}
public static boolean createFile(String path) {
String folder = path.substring(0, path.lastIndexOf('/')); String folder = path.substring(0, path.lastIndexOf('/'));
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi"; String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi";
List<String> ret = Shell.su(command); Shell.su_async(null, command);
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
} }
public static boolean removeItem(String path) { public static void removeItem(String path) {
String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi"; String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi";
List<String> ret = Shell.su(command); Shell.su_async(null, command);
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
} }
public static List<String> getModList(String path) { public static List<String> getModList(String path) {
@ -116,7 +108,7 @@ public class Utils {
"BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`", "BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`",
"if [ ! -z \"$BOOTIMAGE\" ]; then break; fi", "if [ ! -z \"$BOOTIMAGE\" ]; then break; fi",
"done", "done",
"echo \"${BOOTIMAGE##*/}\"" "echo \"$BOOTIMAGE\""
}; };
List<String> ret = Shell.su(commands); List<String> ret = Shell.su(commands);
if (isValidShellResponse(ret)) { if (isValidShellResponse(ret)) {