Support patching second slot
This commit is contained in:
parent
b80ba13cb4
commit
4c9f5f4655
@ -229,6 +229,7 @@ public class MagiskManager extends Application {
|
|||||||
"export PATH=" + BUSYBOXPATH + ":$PATH",
|
"export PATH=" + BUSYBOXPATH + ":$PATH",
|
||||||
". " + utils,
|
". " + utils,
|
||||||
"mount_partitions",
|
"mount_partitions",
|
||||||
|
"BOOTIMAGE=",
|
||||||
"find_boot_image",
|
"find_boot_image",
|
||||||
"migrate_boot_backup"
|
"migrate_boot_backup"
|
||||||
);
|
);
|
||||||
|
@ -332,101 +332,137 @@ public class Utils {
|
|||||||
MagiskManager mm = getMagiskManager(fragment.getActivity());
|
MagiskManager mm = getMagiskManager(fragment.getActivity());
|
||||||
String filename = getLegalFilename("Magisk-v" + mm.remoteMagiskVersionString + ".zip");
|
String filename = getLegalFilename("Magisk-v" + mm.remoteMagiskVersionString + ".zip");
|
||||||
new AlertDialogBuilder(fragment.getActivity())
|
new AlertDialogBuilder(fragment.getActivity())
|
||||||
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.magisk)))
|
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.magisk)))
|
||||||
.setMessage(mm.getString(R.string.repo_install_msg, filename))
|
.setMessage(mm.getString(R.string.repo_install_msg, filename))
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setPositiveButton(R.string.install, (d, i) -> {
|
.setPositiveButton(R.string.install, (d, i) -> {
|
||||||
List<String> options = new ArrayList<>();
|
List<String> options = new ArrayList<>();
|
||||||
options.add(mm.getString(R.string.download_zip_only));
|
options.add(mm.getString(R.string.download_zip_only));
|
||||||
options.add(mm.getString(R.string.patch_boot_file));
|
options.add(mm.getString(R.string.patch_boot_file));
|
||||||
if (Shell.rootAccess()) {
|
if (Shell.rootAccess()) {
|
||||||
options.add(mm.getString(R.string.direct_install));
|
options.add(mm.getString(R.string.direct_install));
|
||||||
}
|
}
|
||||||
new AlertDialog.Builder(fragment.getActivity())
|
List<String> res = Shell.getShell(mm).su("echo $SLOT");
|
||||||
.setTitle(R.string.select_method)
|
if (isValidShellResponse(res)) {
|
||||||
.setItems(
|
options.add(mm.getString(R.string.install_second_slot));
|
||||||
options.toArray(new String [0]),
|
}
|
||||||
(dialog, idx) -> {
|
char[] slot = isValidShellResponse(res) ? res.get(0).toCharArray() : null;
|
||||||
DownloadReceiver receiver = null;
|
new AlertDialog.Builder(fragment.getActivity())
|
||||||
switch (idx) {
|
.setTitle(R.string.select_method)
|
||||||
case 1:
|
.setItems(
|
||||||
if (mm.remoteMagiskVersionCode < 1400) {
|
options.toArray(new String [0]),
|
||||||
mm.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG);
|
(dialog, idx) -> {
|
||||||
return;
|
String boot;
|
||||||
}
|
DownloadReceiver receiver = null;
|
||||||
mm.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
|
switch (idx) {
|
||||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
case 1:
|
||||||
intent.setType("*/*");
|
if (mm.remoteMagiskVersionCode < 1400) {
|
||||||
fragment.startActivityForResult(intent, SELECT_BOOT_IMG,
|
mm.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG);
|
||||||
(requestCode, resultCode, data) -> {
|
|
||||||
if (requestCode == SELECT_BOOT_IMG
|
|
||||||
&& resultCode == Activity.RESULT_OK && data != null) {
|
|
||||||
dlAndReceive(
|
|
||||||
fragment.getActivity(),
|
|
||||||
new DownloadReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onDownloadDone(Uri uri) {
|
|
||||||
Intent intent = new Intent(mm, FlashActivity.class);
|
|
||||||
intent.setData(uri)
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
.putExtra(FlashActivity.SET_BOOT, data.getData())
|
|
||||||
.putExtra(FlashActivity.SET_ENC, enc)
|
|
||||||
.putExtra(FlashActivity.SET_VERITY, verity)
|
|
||||||
.putExtra(FlashActivity.SET_ACTION, FlashActivity.PATCH_BOOT);
|
|
||||||
mm.startActivity(intent);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mm.magiskLink,
|
|
||||||
filename
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
case 0:
|
}
|
||||||
receiver = new DownloadReceiver() {
|
mm.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
|
||||||
@Override
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
public void onDownloadDone(Uri uri) {
|
intent.setType("*/*");
|
||||||
showUriSnack(fragment.getActivity(), uri);
|
fragment.startActivityForResult(intent, SELECT_BOOT_IMG,
|
||||||
|
(requestCode, resultCode, data) -> {
|
||||||
|
if (requestCode == SELECT_BOOT_IMG
|
||||||
|
&& resultCode == Activity.RESULT_OK && data != null) {
|
||||||
|
dlAndReceive(
|
||||||
|
fragment.getActivity(),
|
||||||
|
new DownloadReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onDownloadDone(Uri uri) {
|
||||||
|
Intent intent = new Intent(mm, FlashActivity.class);
|
||||||
|
intent.setData(uri)
|
||||||
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
.putExtra(FlashActivity.SET_BOOT, data.getData())
|
||||||
|
.putExtra(FlashActivity.SET_ENC, enc)
|
||||||
|
.putExtra(FlashActivity.SET_VERITY, verity)
|
||||||
|
.putExtra(FlashActivity.SET_ACTION, FlashActivity.PATCH_BOOT);
|
||||||
|
mm.startActivity(intent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mm.magiskLink,
|
||||||
|
filename
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
break;
|
return;
|
||||||
case 2:
|
case 0:
|
||||||
final String boot = fragment.getSelectedBootImage();
|
receiver = new DownloadReceiver() {
|
||||||
if (boot == null)
|
@Override
|
||||||
return;
|
public void onDownloadDone(Uri uri) {
|
||||||
receiver = new DownloadReceiver() {
|
showUriSnack(fragment.getActivity(), uri);
|
||||||
@Override
|
}
|
||||||
public void onDownloadDone(Uri uri) {
|
};
|
||||||
Intent intent = new Intent(mm, FlashActivity.class);
|
break;
|
||||||
intent.setData(uri)
|
case 2:
|
||||||
|
boot = fragment.getSelectedBootImage();
|
||||||
|
if (boot == null)
|
||||||
|
return;
|
||||||
|
receiver = new DownloadReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onDownloadDone(Uri uri) {
|
||||||
|
Intent intent = new Intent(mm, FlashActivity.class);
|
||||||
|
intent.setData(uri)
|
||||||
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
.putExtra(FlashActivity.SET_BOOT, boot)
|
||||||
|
.putExtra(FlashActivity.SET_ENC, enc)
|
||||||
|
.putExtra(FlashActivity.SET_VERITY, verity)
|
||||||
|
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
|
||||||
|
mm.startActivity(intent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
assert (slot != null);
|
||||||
|
// Choose the other slot
|
||||||
|
if (slot[1] == 'a') slot[1] = 'b';
|
||||||
|
else slot[1] = 'a';
|
||||||
|
// Then find the boot image again
|
||||||
|
List<String> ret = Shell.getShell(mm).su(
|
||||||
|
"BOOTIMAGE=",
|
||||||
|
"SLOT=" + String.valueOf(slot),
|
||||||
|
"find_boot_image",
|
||||||
|
"echo \"$BOOTIMAGE\""
|
||||||
|
);
|
||||||
|
boot = isValidShellResponse(ret) ? ret.get(ret.size() - 1) : null;
|
||||||
|
Shell.getShell(mm).su_raw("mount_partitions");
|
||||||
|
if (boot == null)
|
||||||
|
return;
|
||||||
|
receiver = new DownloadReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onDownloadDone(Uri uri) {
|
||||||
|
Intent intent = new Intent(mm, FlashActivity.class);
|
||||||
|
intent.setData(uri)
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
.putExtra(FlashActivity.SET_BOOT, boot)
|
.putExtra(FlashActivity.SET_BOOT, boot)
|
||||||
.putExtra(FlashActivity.SET_ENC, enc)
|
.putExtra(FlashActivity.SET_ENC, enc)
|
||||||
.putExtra(FlashActivity.SET_VERITY, verity)
|
.putExtra(FlashActivity.SET_VERITY, verity)
|
||||||
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
|
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
|
||||||
mm.startActivity(intent);
|
mm.startActivity(intent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
break;
|
default:
|
||||||
}
|
|
||||||
Utils.dlAndReceive(
|
|
||||||
mm,
|
|
||||||
receiver,
|
|
||||||
mm.magiskLink,
|
|
||||||
filename
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
).show();
|
Utils.dlAndReceive(
|
||||||
})
|
mm,
|
||||||
.setNeutralButton(R.string.release_notes, (d, i) -> {
|
receiver,
|
||||||
if (mm.releaseNoteLink != null) {
|
mm.magiskLink,
|
||||||
Intent openLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink));
|
filename
|
||||||
openLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
);
|
||||||
mm.startActivity(openLink);
|
}
|
||||||
}
|
).show();
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
.setNeutralButton(R.string.release_notes, (d, i) -> {
|
||||||
.show();
|
if (mm.releaseNoteLink != null) {
|
||||||
|
Intent openLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink));
|
||||||
|
openLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
mm.startActivity(openLink);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showManagerInstallDialog(Activity activity) {
|
public static void showManagerInstallDialog(Activity activity) {
|
||||||
@ -450,58 +486,58 @@ public class Utils {
|
|||||||
public static void showUninstallDialog(MagiskFragment fragment) {
|
public static void showUninstallDialog(MagiskFragment fragment) {
|
||||||
MagiskManager mm = Utils.getMagiskManager(fragment.getActivity());
|
MagiskManager mm = Utils.getMagiskManager(fragment.getActivity());
|
||||||
new AlertDialogBuilder(fragment.getActivity())
|
new AlertDialogBuilder(fragment.getActivity())
|
||||||
.setTitle(R.string.uninstall_magisk_title)
|
.setTitle(R.string.uninstall_magisk_title)
|
||||||
.setMessage(R.string.uninstall_magisk_msg)
|
.setMessage(R.string.uninstall_magisk_msg)
|
||||||
.setPositiveButton(R.string.complete_uninstall, (d, i) -> {
|
.setPositiveButton(R.string.complete_uninstall, (d, i) -> {
|
||||||
try {
|
try {
|
||||||
InputStream in = mm.getAssets().open(UNINSTALLER);
|
InputStream in = mm.getAssets().open(UNINSTALLER);
|
||||||
File uninstaller = new File(mm.getCacheDir(), UNINSTALLER);
|
File uninstaller = new File(mm.getCacheDir(), UNINSTALLER);
|
||||||
FileOutputStream out = new FileOutputStream(uninstaller);
|
FileOutputStream out = new FileOutputStream(uninstaller);
|
||||||
byte[] bytes = new byte[1024];
|
byte[] bytes = new byte[1024];
|
||||||
int read;
|
int read;
|
||||||
while ((read = in.read(bytes)) != -1) {
|
while ((read = in.read(bytes)) != -1) {
|
||||||
out.write(bytes, 0, read);
|
out.write(bytes, 0, read);
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
out.close();
|
|
||||||
in = mm.getAssets().open(UTIL_FUNCTIONS);
|
|
||||||
File utils = new File(mm.getCacheDir(), UTIL_FUNCTIONS);
|
|
||||||
out = new FileOutputStream(utils);
|
|
||||||
while ((read = in.read(bytes)) != -1) {
|
|
||||||
out.write(bytes, 0, read);
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
out.close();
|
|
||||||
ProgressDialog progress = new ProgressDialog(fragment.getActivity());
|
|
||||||
progress.setTitle(R.string.reboot);
|
|
||||||
progress.show();
|
|
||||||
new CountDownTimer(5000, 1000) {
|
|
||||||
@Override
|
|
||||||
public void onTick(long millisUntilFinished) {
|
|
||||||
progress.setMessage(mm.getString(R.string.reboot_countdown,
|
|
||||||
millisUntilFinished / 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinish() {
|
|
||||||
progress.setMessage(mm.getString(R.string.reboot_countdown, 0));
|
|
||||||
Shell.getShell(mm).su_raw(
|
|
||||||
"mv -f " + uninstaller + " /cache/" + UNINSTALLER,
|
|
||||||
"mv -f " + utils + " /data/magisk/" + UTIL_FUNCTIONS,
|
|
||||||
"reboot"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
})
|
in.close();
|
||||||
.setNeutralButton(R.string.restore_stock_boot, (d, i) -> {
|
out.close();
|
||||||
String boot = fragment.getSelectedBootImage();
|
in = mm.getAssets().open(UTIL_FUNCTIONS);
|
||||||
if (boot == null) return;
|
File utils = new File(mm.getCacheDir(), UTIL_FUNCTIONS);
|
||||||
new RestoreStockBoot(mm, boot).exec();
|
out = new FileOutputStream(utils);
|
||||||
})
|
while ((read = in.read(bytes)) != -1) {
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
out.write(bytes, 0, read);
|
||||||
.show();
|
}
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
ProgressDialog progress = new ProgressDialog(fragment.getActivity());
|
||||||
|
progress.setTitle(R.string.reboot);
|
||||||
|
progress.show();
|
||||||
|
new CountDownTimer(5000, 1000) {
|
||||||
|
@Override
|
||||||
|
public void onTick(long millisUntilFinished) {
|
||||||
|
progress.setMessage(mm.getString(R.string.reboot_countdown,
|
||||||
|
millisUntilFinished / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
progress.setMessage(mm.getString(R.string.reboot_countdown, 0));
|
||||||
|
Shell.getShell(mm).su_raw(
|
||||||
|
"mv -f " + uninstaller + " /cache/" + UNINSTALLER,
|
||||||
|
"mv -f " + utils + " /data/magisk/" + UTIL_FUNCTIONS,
|
||||||
|
"reboot"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNeutralButton(R.string.restore_stock_boot, (d, i) -> {
|
||||||
|
String boot = fragment.getSelectedBootImage();
|
||||||
|
if (boot == null) return;
|
||||||
|
new RestoreStockBoot(mm, boot).exec();
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -114,6 +114,7 @@
|
|||||||
<string name="download_zip_only">Download Zip Only</string>
|
<string name="download_zip_only">Download Zip Only</string>
|
||||||
<string name="patch_boot_file">Patch Boot Image File</string>
|
<string name="patch_boot_file">Patch Boot Image File</string>
|
||||||
<string name="direct_install">Direct Install (Recommend)</string>
|
<string name="direct_install">Direct Install (Recommend)</string>
|
||||||
|
<string name="install_second_slot">Install to Second Slot (After OTA)</string>
|
||||||
<string name="select_method">Select Method</string>
|
<string name="select_method">Select Method</string>
|
||||||
<string name="no_boot_file_patch_support">Target Magisk version doesn\'t support boot image file patching</string>
|
<string name="no_boot_file_patch_support">Target Magisk version doesn\'t support boot image file patching</string>
|
||||||
<string name="boot_file_patch_msg">Select stock boot image dump in .img or .img.tar format</string>
|
<string name="boot_file_patch_msg">Select stock boot image dump in .img or .img.tar format</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user