Rewrite FlashZip in Kotlin

This commit is contained in:
topjohnwu 2019-05-03 04:42:57 -04:00
parent 8b7144c986
commit a0cfce7cbc
6 changed files with 100 additions and 108 deletions

View File

@ -1,85 +0,0 @@
package com.topjohnwu.magisk.tasks;
import android.net.Uri;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtilsKt;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
import com.topjohnwu.superuser.internal.UiThreadHandler;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public abstract class FlashZip {
private Uri mUri;
private File tmpFile;
private List<String> console, logs;
public FlashZip(Uri uri, List<String> out, List<String> err) {
mUri = uri;
console = out;
logs = err;
tmpFile = new File(App.self.getCacheDir(), "install.zip");
}
private boolean unzipAndCheck() throws IOException {
ZipUtilsKt.unzip(tmpFile, tmpFile.getParentFile(), "META-INF/com/google/android", true);
return Shell.su("grep -q '#MAGISK' " + new File(tmpFile.getParentFile(), "updater-script"))
.exec().isSuccess();
}
private boolean flash() throws IOException {
console.add("- Copying zip to temp directory");
try (InputStream in = App.self.getContentResolver().openInputStream(mUri);
OutputStream out = new BufferedOutputStream(new FileOutputStream(tmpFile))) {
if (in == null) throw new FileNotFoundException();
InputStream buf= new BufferedInputStream(in);
ShellUtils.pump(buf, out);
} catch (FileNotFoundException e) {
console.add("! Invalid Uri");
throw e;
} catch (IOException e) {
console.add("! Cannot copy to cache");
throw e;
}
try {
if (!unzipAndCheck()) {
console.add("! This zip is not a Magisk Module!");
return false;
}
} catch (IOException e) {
console.add("! Unzip error");
throw e;
}
console.add("- Installing " + Utils.getNameFromUri(App.self, mUri));
return Shell.su("cd " + tmpFile.getParent(),
"BOOTMODE=true sh update-binary dummy 1 " + tmpFile)
.to(console, logs)
.exec().isSuccess();
}
public void exec() {
App.THREAD_POOL.execute(() -> {
boolean success = false;
try {
success = flash();
} catch (IOException ignored) {}
Shell.su("cd /", "rm -rf " + tmpFile.getParent() + " " + Const.TMP_FOLDER_PATH).submit();
boolean finalSuccess = success;
UiThreadHandler.run(() -> onResult(finalSuccess));
});
}
protected abstract void onResult(boolean success);
}

View File

@ -0,0 +1,73 @@
package com.topjohnwu.magisk.tasks
import android.net.Uri
import com.topjohnwu.magisk.App
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.utils.*
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.internal.UiThreadHandler
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
abstract class FlashZip(private val mUri: Uri,
private val console: MutableList<String>,
private val logs: MutableList<String>) {
private val tmpFile: File = File(App.self.cacheDir, "install.zip")
@Throws(IOException::class)
private fun unzipAndCheck(): Boolean {
unzip(tmpFile, tmpFile.parentFile!!, "META-INF/com/google/android", true)
return Shell.su("grep -q '#MAGISK' ${File(tmpFile.parentFile, "updater-script")}")
.exec().isSuccess
}
@Throws(IOException::class)
private fun flash(): Boolean {
console.add("- Copying zip to temp directory")
try {
App.self.readUri(mUri).use { input ->
tmpFile.outputStream().use { out -> input.copyTo(out) }
}
} catch (e: FileNotFoundException) {
console.add("! Invalid Uri")
throw e
} catch (e: IOException) {
console.add("! Cannot copy to cache")
throw e
}
try {
if (!unzipAndCheck()) {
console.add("! This zip is not a Magisk Module!")
return false
}
} catch (e: IOException) {
console.add("! Unzip error")
throw e
}
console.add("- Installing ${mUri.fileName}")
return Shell.su("cd " + tmpFile.parent!!,
"BOOTMODE=true sh update-binary dummy 1 $tmpFile")
.to(console, logs)
.exec().isSuccess
}
fun exec() {
App.THREAD_POOL.execute {
val success = try {
flash()
} catch (e: IOException) {
false
}
Shell.su("cd /", "rm -rf ${tmpFile.parent} ${Const.TMP_FOLDER_PATH}").submit()
UiThreadHandler.run { onResult(success) }
}
}
protected abstract fun onResult(success: Boolean)
}

View File

@ -58,24 +58,6 @@ public class Utils {
return getPrefsInt(prefs, key, 0); return getPrefsInt(prefs, key, 0);
} }
public static String getNameFromUri(Context context, Uri uri) {
String name = null;
try (Cursor c = context.getContentResolver().query(uri, null, null, null, null)) {
if (c != null) {
int nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (nameIndex != -1) {
c.moveToFirst();
name = c.getString(nameIndex);
}
}
}
if (name == null) {
int idx = uri.getPath().lastIndexOf('/');
name = uri.getPath().substring(idx + 1);
}
return name;
}
public static int dpInPx(int dp) { public static int dpInPx(int dp) {
float scale = App.self.getResources().getDisplayMetrics().density; float scale = App.self.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5); return (int) (dp * scale + 0.5);

View File

@ -6,6 +6,10 @@ import android.content.pm.ComponentInfo
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.PackageManager.* import android.content.pm.PackageManager.*
import android.net.Uri
import android.provider.OpenableColumns
import com.topjohnwu.magisk.App
import java.io.FileNotFoundException
val PackageInfo.processes val PackageInfo.processes
get() = activities?.processNames.orEmpty() + get() = activities?.processNames.orEmpty() +
@ -38,6 +42,22 @@ val ApplicationInfo.packageInfo: PackageInfo?
} }
} }
val Uri.fileName: String get() {
var name: String? = null
App.self.contentResolver.query(this, null, null, null, null)?.use { c ->
val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (nameIndex != -1) {
c.moveToFirst()
name = c.getString(nameIndex)
}
}
if (name == null && path != null) {
val idx = path!!.lastIndexOf('/')
name = path!!.substring(idx + 1)
}
return name.orEmpty()
}
fun PackageManager.activities(packageName: String) = fun PackageManager.activities(packageName: String) =
getPackageInfo(packageName, GET_ACTIVITIES) getPackageInfo(packageName, GET_ACTIVITIES)
@ -51,3 +71,6 @@ fun PackageManager.providers(packageName: String) =
getPackageInfo(packageName, GET_PROVIDERS).providers getPackageInfo(packageName, GET_PROVIDERS).providers
fun Context.rawResource(id: Int) = resources.openRawResource(id) fun Context.rawResource(id: Int) = resources.openRawResource(id)
fun Context.readUri(uri: Uri) = contentResolver.openInputStream(uri) ?: throw FileNotFoundException()

View File

@ -9,7 +9,6 @@ import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
@Throws(IOException::class) @Throws(IOException::class)
@JvmOverloads
fun unzip(zip: File, folder: File, path: String = "", junkPath: Boolean = false) { fun unzip(zip: File, folder: File, path: String = "", junkPath: Boolean = false) {
zip.inputStream().buffered().use { zip.inputStream().buffered().use {
unzip(it, folder, path, junkPath) unzip(it, folder, path, junkPath)

View File

@ -5,11 +5,11 @@ import android.net.Uri;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.StringRes;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.XAndroidKt;
import androidx.annotation.StringRes;
public class SnackbarMaker { public class SnackbarMaker {
@ -41,7 +41,7 @@ public class SnackbarMaker {
public static void showUri(Activity activity, Uri uri) { public static void showUri(Activity activity, Uri uri) {
make(activity, activity.getString(R.string.internal_storage, make(activity, activity.getString(R.string.internal_storage,
"/Download/" + Utils.getNameFromUri(activity, uri)), "/Download/" + XAndroidKt.getFileName(uri)),
Snackbar.LENGTH_LONG) Snackbar.LENGTH_LONG)
.setAction(R.string.ok, (v)->{}).show(); .setAction(R.string.ok, (v)->{}).show();
} }