Reboot using sui
This commit is contained in:
parent
fd6a3f9a93
commit
5e95d0c540
|
|
@ -69,7 +69,9 @@ dependencies {
|
|||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'com.takisoft.preferencex:preferencex:1.1.0'
|
||||
implementation 'com.takisoft.preferencex:preferencex-colorpicker:1.1.0'
|
||||
implementation "rikka.shizuku:api:11.0.1"
|
||||
implementation 'tech.rectifier.preferencex-android:preferencex-simplemenu:88f93154b2'
|
||||
implementation 'me.zhanghai.android.appiconloader:appiconloader-glide:1.2.0'
|
||||
implementation 'me.zhanghai.android.fastscroll:library:1.1.5'
|
||||
compileOnly project(":hiddenapi-stubs")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import org.meowcat.edxposed.manager.adapters.AppHelper;
|
|||
import org.meowcat.edxposed.manager.ui.activity.CrashReportActivity;
|
||||
import org.meowcat.edxposed.manager.util.ModuleUtil;
|
||||
import org.meowcat.edxposed.manager.util.NotificationUtil;
|
||||
import org.meowcat.edxposed.manager.util.RebootUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
|
|
@ -28,6 +29,11 @@ import java.util.Collection;
|
|||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import rikka.shizuku.Shizuku;
|
||||
import rikka.sui.Sui;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
public class App extends Application implements Application.ActivityLifecycleCallbacks {
|
||||
public static final String TAG = "EdXposedManager";
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
|
|
@ -38,6 +44,36 @@ public class App extends Application implements Application.ActivityLifecycleCal
|
|||
//private AppCompatActivity currentActivity = null;
|
||||
private boolean isUiLoaded = false;
|
||||
|
||||
private final Shizuku.OnRequestPermissionResultListener REQUEST_PERMISSION_RESULT_LISTENER = this::onRequestPermissionsResult;
|
||||
|
||||
static {
|
||||
Sui.init(BuildConfig.APPLICATION_ID);
|
||||
}
|
||||
|
||||
private void onRequestPermissionsResult(int requestCode, int grantResult) {
|
||||
if (requestCode < 10) {
|
||||
RebootUtil.onRequestPermissionsResult(requestCode, grantResult);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkPermission(int code) {
|
||||
try {
|
||||
if (!Shizuku.isPreV11() && Shizuku.getVersion() >= 11) {
|
||||
if (Shizuku.checkSelfPermission() == PERMISSION_GRANTED) {
|
||||
return true;
|
||||
} else if (Shizuku.shouldShowRequestPermissionRationale()) {
|
||||
return false;
|
||||
} else {
|
||||
Shizuku.requestPermission(code);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static App getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
|
@ -109,6 +145,8 @@ public class App extends Application implements Application.ActivityLifecycleCal
|
|||
@SuppressLint("SimpleDateFormat") DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
|
||||
Date date = new Date();
|
||||
|
||||
Shizuku.addRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER);
|
||||
|
||||
if (!Objects.requireNonNull(pref.getString("date", "")).equals(dateFormat.format(date))) {
|
||||
pref.edit().putString("date", dateFormat.format(date)).apply();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,7 @@ import android.content.SharedPreferences;
|
|||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
|
@ -29,9 +25,8 @@ import org.meowcat.edxposed.manager.R;
|
|||
import org.meowcat.edxposed.manager.util.CustomThemeColor;
|
||||
import org.meowcat.edxposed.manager.util.CustomThemeColors;
|
||||
import org.meowcat.edxposed.manager.util.NavUtil;
|
||||
import org.meowcat.edxposed.manager.util.RebootUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
|
|
@ -157,65 +152,6 @@ public class BaseActivity extends AppCompatActivity {
|
|||
.show();
|
||||
}
|
||||
|
||||
void softReboot() {
|
||||
if (!Shell.rootAccess()) {
|
||||
showAlert(getString(R.string.root_failed));
|
||||
return;
|
||||
}
|
||||
|
||||
String command;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && ((PowerManager) getSystemService(Context.POWER_SERVICE)).isRebootingUserspaceSupported()) {
|
||||
command = "/system/bin/svc power reboot userspace";
|
||||
} else {
|
||||
command = "setprop ctl.restart surfaceflinger; setprop ctl.restart zygote";
|
||||
}
|
||||
|
||||
List<String> messages = new LinkedList<>();
|
||||
Shell.Result result = Shell.su(command).exec();
|
||||
if (result.getCode() != 0) {
|
||||
messages.add(result.getOut().toString());
|
||||
messages.add("");
|
||||
messages.add(getString(R.string.reboot_failed));
|
||||
showAlert(TextUtils.join("\n", messages).trim());
|
||||
}
|
||||
}
|
||||
|
||||
void showAlert(final String result) {
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
runOnUiThread(() -> showAlert(result));
|
||||
return;
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setMessage(result)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
void reboot(String mode) {
|
||||
if (!Shell.rootAccess()) {
|
||||
showAlert(getString(R.string.root_failed));
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> messages = new LinkedList<>();
|
||||
|
||||
String command = "/system/bin/svc power reboot";
|
||||
if (mode != null) {
|
||||
command += " " + mode;
|
||||
if (mode.equals("recovery"))
|
||||
// create a flag used by some kernels to boot into recovery
|
||||
Shell.su("touch /cache/recovery/boot").exec();
|
||||
}
|
||||
Shell.Result result = Shell.su(command).exec();
|
||||
if (result.getCode() != 0) {
|
||||
messages.add(result.getOut().toString());
|
||||
messages.add("");
|
||||
messages.add(getString(R.string.reboot_failed));
|
||||
showAlert(TextUtils.join("\n", messages).trim());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
|
|
@ -266,17 +202,17 @@ public class BaseActivity extends AppCompatActivity {
|
|||
};
|
||||
});
|
||||
} else if (itemId == R.id.reboot) {
|
||||
areYouSure(R.string.reboot, (dialog, which) -> reboot(null));
|
||||
areYouSure(R.string.reboot, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.NORMAL));
|
||||
} else if (itemId == R.id.soft_reboot) {
|
||||
areYouSure(R.string.soft_reboot, (dialog, which) -> softReboot());
|
||||
areYouSure(R.string.soft_reboot, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.USERSPACE));
|
||||
} else if (itemId == R.id.reboot_recovery) {
|
||||
areYouSure(R.string.reboot_recovery, (dialog, which) -> reboot("recovery"));
|
||||
areYouSure(R.string.reboot_recovery, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.RECOVERY));
|
||||
} else if (itemId == R.id.reboot_bootloader) {
|
||||
areYouSure(R.string.reboot_bootloader, (dialog, which) -> reboot("bootloader"));
|
||||
areYouSure(R.string.reboot_bootloader, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.BOOTLOADER));
|
||||
} else if (itemId == R.id.reboot_download) {
|
||||
areYouSure(R.string.reboot_download, (dialog, which) -> reboot("download"));
|
||||
areYouSure(R.string.reboot_download, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.DOWNLOAD));
|
||||
} else if (itemId == R.id.reboot_edl) {
|
||||
areYouSure(R.string.reboot_edl, (dialog, which) -> reboot("edl"));
|
||||
areYouSure(R.string.reboot_edl, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.EDL));
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import android.app.PendingIntent;
|
|||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
|
@ -172,21 +170,7 @@ public final class NotificationUtil {
|
|||
}
|
||||
|
||||
boolean softReboot = intent.getBooleanExtra(EXTRA_SOFT_REBOOT, false);
|
||||
String command;
|
||||
if (softReboot) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).isRebootingUserspaceSupported()) {
|
||||
command = "/system/bin/svc power reboot userspace";
|
||||
} else {
|
||||
command = "setprop ctl.restart surfaceflinger; setprop ctl.restart zygote";
|
||||
}
|
||||
} else {
|
||||
command = "/system/bin/svc power reboot";
|
||||
}
|
||||
int returnCode = Shell.su(command).exec().getCode();
|
||||
|
||||
if (returnCode != 0) {
|
||||
Log.e(App.TAG, "NotificationUtil -> Could not reboot");
|
||||
}
|
||||
RebootUtil.reboot(softReboot ? RebootUtil.RebootType.USERSPACE : RebootUtil.RebootType.NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package org.meowcat.edxposed.manager.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import org.meowcat.edxposed.manager.App;
|
||||
import org.meowcat.edxposed.manager.BuildConfig;
|
||||
|
||||
import rikka.shizuku.ShizukuBinderWrapper;
|
||||
import rikka.shizuku.ShizukuSystemProperties;
|
||||
import rikka.shizuku.SystemServiceHelper;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
public class RebootUtil {
|
||||
public enum RebootType {
|
||||
NORMAL,
|
||||
USERSPACE,
|
||||
RECOVERY,
|
||||
BOOTLOADER,
|
||||
DOWNLOAD,
|
||||
EDL;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onRequestPermissionsResult(int requestCode, int grantResult) {
|
||||
RebootType mode = RebootType.values()[requestCode];
|
||||
if (grantResult == PERMISSION_GRANTED) {
|
||||
try {
|
||||
if (mode == RebootType.USERSPACE && !supportUserspaceReboot()) {
|
||||
ShizukuSystemProperties.set("ctl.restart", "surfaceflinger");
|
||||
ShizukuSystemProperties.set("ctl.restart", "zygote");
|
||||
} else {
|
||||
POWER_MANAGER.get().reboot(BuildConfig.DEBUG, mode.toString(), false);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
rebootWithShell(mode);
|
||||
}
|
||||
} else {
|
||||
rebootWithShell(mode);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Singleton<IPowerManager> POWER_MANAGER = new Singleton<IPowerManager>() {
|
||||
@Override
|
||||
protected IPowerManager create() {
|
||||
return IPowerManager.Stub.asInterface(new ShizukuBinderWrapper(SystemServiceHelper.getSystemService(Context.POWER_SERVICE)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static void reboot(RebootType mode) {
|
||||
if (App.checkPermission(mode.ordinal())) {
|
||||
onRequestPermissionsResult(mode.ordinal(), PERMISSION_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
private static void rebootWithShell(RebootType mode) {
|
||||
if (!Shell.rootAccess()) {
|
||||
return;
|
||||
}
|
||||
String command;
|
||||
if (mode == RebootType.USERSPACE) {
|
||||
if (supportUserspaceReboot()) {
|
||||
command = "/system/bin/svc power reboot userspace";
|
||||
} else {
|
||||
command = "setprop ctl.restart surfaceflinger; setprop ctl.restart zygote";
|
||||
}
|
||||
} else if (mode == RebootType.NORMAL) {
|
||||
command = "/system/bin/svc power reboot";
|
||||
} else if (mode == RebootType.RECOVERY) {
|
||||
Shell.su("touch /cache/recovery/boot").exec();
|
||||
command = "/system/bin/svc power recovery";
|
||||
} else {
|
||||
command = "/system/bin/svc power reboot " + mode.toString();
|
||||
}
|
||||
Shell.su(command).exec();
|
||||
}
|
||||
|
||||
private static boolean supportUserspaceReboot() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && ((PowerManager) App.getInstance().getSystemService(Context.POWER_SERVICE)).isRebootingUserspaceSupported();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.meowcat.edxposed.manager.util;
|
||||
|
||||
public abstract class Singleton<T> {
|
||||
|
||||
private T mInstance;
|
||||
|
||||
protected abstract T create();
|
||||
|
||||
public final T get() {
|
||||
synchronized (this) {
|
||||
if (mInstance == null) {
|
||||
mInstance = create();
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ allprojects {
|
|||
google()
|
||||
jcenter()
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url 'https://dl.bintray.com/rikkaw/Libraries' }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package android.os;
|
||||
|
||||
public interface IPowerManager extends IInterface {
|
||||
|
||||
void reboot(boolean confirm, String reason, boolean wait) throws RemoteException;
|
||||
|
||||
abstract class Stub extends Binder implements IPowerManager {
|
||||
|
||||
public static IPowerManager asInterface(IBinder obj) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue