2017-08-31 03:07:33 +08:00
|
|
|
package com.topjohnwu.magisk.asyncs;
|
|
|
|
|
|
|
|
import android.app.Activity;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.Environment;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
|
|
|
|
import com.topjohnwu.magisk.MagiskManager;
|
|
|
|
import com.topjohnwu.magisk.utils.AdaptiveList;
|
2017-09-03 17:24:05 +08:00
|
|
|
import com.topjohnwu.magisk.utils.Shell;
|
|
|
|
import com.topjohnwu.magisk.utils.TarEntry;
|
2017-08-31 03:07:33 +08:00
|
|
|
import com.topjohnwu.magisk.utils.ZipUtils;
|
|
|
|
|
2017-09-03 17:24:05 +08:00
|
|
|
import org.kamranzafar.jtar.TarOutputStream;
|
|
|
|
|
2017-08-31 03:07:33 +08:00
|
|
|
import java.io.BufferedInputStream;
|
2017-09-03 17:24:05 +08:00
|
|
|
import java.io.BufferedOutputStream;
|
2017-08-31 03:07:33 +08:00
|
|
|
import java.io.File;
|
2017-09-03 17:24:05 +08:00
|
|
|
import java.io.FileInputStream;
|
2017-08-31 03:07:33 +08:00
|
|
|
import java.io.FileNotFoundException;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.List;
|
|
|
|
|
2017-09-03 00:10:14 +08:00
|
|
|
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
|
|
|
|
|
|
|
private static final int PATCH_MODE = 0;
|
|
|
|
private static final int DIRECT_MODE = 1;
|
2017-08-31 03:07:33 +08:00
|
|
|
|
|
|
|
private Uri mBootImg, mZip;
|
|
|
|
private AdaptiveList<String> mList;
|
2017-09-03 00:10:14 +08:00
|
|
|
private String mBootLocation;
|
|
|
|
private boolean mKeepEnc, mKeepVerity;
|
|
|
|
private int mode;
|
2017-08-31 03:07:33 +08:00
|
|
|
|
2017-09-03 00:10:14 +08:00
|
|
|
private InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity) {
|
2017-08-31 03:07:33 +08:00
|
|
|
super(context);
|
|
|
|
mList = list;
|
|
|
|
mZip = zip;
|
2017-09-03 00:10:14 +08:00
|
|
|
mKeepEnc = enc;
|
|
|
|
mKeepVerity = verity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, Uri boot) {
|
|
|
|
this(context, list, zip, enc, verity);
|
|
|
|
mBootImg = boot;
|
|
|
|
mode = PATCH_MODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, String boot) {
|
|
|
|
this(context, list, zip, enc, verity);
|
|
|
|
mBootLocation = boot;
|
|
|
|
mode = DIRECT_MODE;
|
2017-08-31 03:07:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPreExecute() {
|
|
|
|
// UI updates must run in the UI thread
|
|
|
|
mList.setCallback(this::publishProgress);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onProgressUpdate(Void... values) {
|
|
|
|
mList.updateView();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Boolean doInBackground(Void... voids) {
|
2017-09-03 15:35:14 +08:00
|
|
|
MagiskManager mm = getMagiskManager();
|
|
|
|
if (mm == null) return false;
|
2017-08-31 03:07:33 +08:00
|
|
|
|
2017-09-03 15:35:14 +08:00
|
|
|
File install = new File(mm.getApplicationInfo().dataDir, "install");
|
2017-08-31 03:07:33 +08:00
|
|
|
getShell().sh_raw("rm -rf " + install);
|
|
|
|
|
|
|
|
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
|
|
|
|
String arch;
|
|
|
|
if (abis.contains("x86_64")) arch = "x64";
|
|
|
|
else if (abis.contains("arm64-v8a")) arch = "arm64";
|
|
|
|
else if (abis.contains("x86")) arch = "x86";
|
|
|
|
else arch = "arm";
|
|
|
|
mList.add("- Device platform: " + arch);
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Unzip files
|
|
|
|
mList.add("- Extracting files");
|
2017-09-03 15:35:14 +08:00
|
|
|
try (InputStream in = mm.getContentResolver().openInputStream(mZip)) {
|
2017-08-31 03:07:33 +08:00
|
|
|
if (in == null) throw new FileNotFoundException();
|
|
|
|
BufferedInputStream buf = new BufferedInputStream(in);
|
|
|
|
buf.mark(Integer.MAX_VALUE);
|
2017-09-03 21:05:57 +08:00
|
|
|
ZipUtils.unzip(buf, install, arch + "/", true);
|
2017-08-31 03:07:33 +08:00
|
|
|
buf.reset();
|
2017-09-03 21:05:57 +08:00
|
|
|
ZipUtils.unzip(buf, install, "common/", true);
|
2017-08-31 03:07:33 +08:00
|
|
|
buf.reset();
|
2017-09-03 21:05:57 +08:00
|
|
|
ZipUtils.unzip(buf, install, "chromeos/", false);
|
2017-08-31 03:07:33 +08:00
|
|
|
buf.reset();
|
|
|
|
ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
|
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
mList.add("! Invalid Uri");
|
|
|
|
throw e;
|
|
|
|
} catch (Exception e) {
|
|
|
|
mList.add("! Cannot unzip zip");
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
|
2017-09-03 00:10:14 +08:00
|
|
|
File boot;
|
|
|
|
switch (mode) {
|
|
|
|
case PATCH_MODE:
|
|
|
|
boot = new File(install, "boot.img");
|
|
|
|
// Copy boot image to local
|
|
|
|
try (
|
2017-09-03 15:35:14 +08:00
|
|
|
InputStream in = mm.getContentResolver().openInputStream(mBootImg);
|
2017-09-03 00:10:14 +08:00
|
|
|
OutputStream out = new FileOutputStream(boot);
|
|
|
|
) {
|
|
|
|
if (in == null) throw new FileNotFoundException();
|
|
|
|
byte buffer[] = new byte[1024];
|
|
|
|
int length;
|
|
|
|
while ((length = in.read(buffer)) > 0)
|
|
|
|
out.write(buffer, 0, length);
|
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
mList.add("! Invalid Uri");
|
|
|
|
throw e;
|
|
|
|
} catch (IOException e) {
|
|
|
|
mList.add("! Copy failed");
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DIRECT_MODE:
|
|
|
|
boot = new File(mBootLocation);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
2017-08-31 03:07:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mList.add("- Use boot image: " + boot);
|
|
|
|
|
|
|
|
// Patch boot image
|
|
|
|
getShell().sh(mList,
|
|
|
|
"cd " + install,
|
2017-09-03 00:10:14 +08:00
|
|
|
"KEEPFORCEENCRYPT=" + mKeepEnc + " KEEPVERITY=" + mKeepVerity + " sh " +
|
2017-09-03 17:24:05 +08:00
|
|
|
"update-binary indep boot_patch.sh " + boot +
|
2017-08-31 03:07:33 +08:00
|
|
|
" && echo 'Success!' || echo 'Failed!'"
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
|
|
|
|
return false;
|
|
|
|
|
2017-09-03 00:10:14 +08:00
|
|
|
File patched_boot = new File(install, "new-boot.img");
|
|
|
|
mList.add("");
|
|
|
|
switch (mode) {
|
|
|
|
case PATCH_MODE:
|
2017-09-03 17:24:05 +08:00
|
|
|
File dest = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/patched_boot" + mm.bootFormat);
|
2017-09-03 00:10:14 +08:00
|
|
|
dest.getParentFile().mkdirs();
|
2017-09-03 17:24:05 +08:00
|
|
|
switch (mm.bootFormat) {
|
|
|
|
case ".img":
|
|
|
|
getShell().sh_raw("cp -f " + patched_boot + " " + dest);
|
|
|
|
break;
|
|
|
|
case ".img.tar":
|
|
|
|
// Workaround root shell issues so we can access the file through Java
|
|
|
|
if (Shell.rootAccess()) {
|
|
|
|
// Get non-root UID
|
|
|
|
int uid = mm.getApplicationInfo().uid;
|
|
|
|
// Get app selabel
|
|
|
|
String selabel = getShell().su("/system/bin/ls -dZ " + install + " | cut -d' ' -f1").get(0);
|
|
|
|
getShell().su(
|
|
|
|
"chcon " + selabel + " " + patched_boot,
|
|
|
|
"chown " + uid + "." + uid + " " + patched_boot);
|
|
|
|
}
|
|
|
|
TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
|
|
|
|
tar.putNextEntry(new TarEntry(patched_boot, "boot.img"));
|
|
|
|
byte buffer[] = new byte[4096];
|
|
|
|
BufferedInputStream in = new BufferedInputStream(new FileInputStream(patched_boot));
|
|
|
|
int len;
|
|
|
|
while ((len = in.read(buffer)) != -1) {
|
|
|
|
tar.write(buffer, 0, len);
|
|
|
|
}
|
|
|
|
tar.flush();
|
|
|
|
tar.close();
|
|
|
|
in.close();
|
|
|
|
break;
|
|
|
|
}
|
2017-09-03 00:10:14 +08:00
|
|
|
mList.add("*********************************");
|
|
|
|
mList.add(" Patched Boot Image is placed in ");
|
|
|
|
mList.add(" " + dest + " ");
|
|
|
|
mList.add("*********************************");
|
|
|
|
break;
|
|
|
|
case DIRECT_MODE:
|
|
|
|
// Direct flash boot image
|
|
|
|
getShell().su_raw("cat " + patched_boot + " /dev/zero | dd of=" + mBootLocation + " bs=4096");
|
|
|
|
mList.add("Flashing patched boot to " + mBootLocation);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-31 03:07:33 +08:00
|
|
|
|
|
|
|
// Finals
|
|
|
|
getShell().sh_raw(
|
|
|
|
"mv bin/busybox busybox",
|
|
|
|
"rm -rf bin *.img update-binary");
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(Boolean result) {
|
|
|
|
super.onPostExecute(result);
|
|
|
|
}
|
|
|
|
}
|