diff --git a/app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java b/app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java index c1ebe4d4c..5ae838856 100644 --- a/app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java +++ b/app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java @@ -3,6 +3,7 @@ package com.topjohnwu.magisk; import static android.os.Build.VERSION.SDK_INT; import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -57,12 +58,24 @@ public class StubApk { return new File(getDynDir(info), "update.apk"); } + @TargetApi(Build.VERSION_CODES.R) + private static ResourcesLoader getResourcesLoader(File path) throws IOException { + var loader = new ResourcesLoader(); + ResourcesProvider provider; + if (path.isDirectory()) { + provider = ResourcesProvider.loadFromDirectory(path.getPath(), null); + } else { + var fd = ParcelFileDescriptor.open(path, MODE_READ_ONLY); + provider = ResourcesProvider.loadFromApk(fd); + } + loader.addProvider(provider); + return loader; + } + public static void addAssetPath(Resources res, String path) { if (SDK_INT >= Build.VERSION_CODES.R) { - try (var fd = ParcelFileDescriptor.open(new File(path), MODE_READ_ONLY)) { - var loader = new ResourcesLoader(); - loader.addProvider(ResourcesProvider.loadFromApk(fd)); - res.addLoaders(loader); + try { + res.addLoaders(getResourcesLoader(new File(path))); } catch (IOException ignored) {} } else { AssetManager asset = res.getAssets(); diff --git a/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java b/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java index 4db587037..2efd98f19 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java +++ b/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java @@ -35,9 +35,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.zip.InflaterInputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; @@ -162,47 +159,36 @@ public class DownloadActivity extends Activity { } private void decryptResources(OutputStream out) throws Exception { - try (var zip = new ZipOutputStream(out)) { - zip.putNextEntry(new ZipEntry("resources.arsc")); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - SecretKey key = new SecretKeySpec(Bytes.key(), "AES"); - IvParameterSpec iv = new IvParameterSpec(Bytes.iv()); - cipher.init(Cipher.DECRYPT_MODE, key, iv); - var is = new InflaterInputStream(new CipherInputStream( - new ByteArrayInputStream(Bytes.res()), cipher)); - try (is) { - APKInstall.transfer(is, zip); - } - zip.closeEntry(); - - zip.putNextEntry(new ZipEntry("AndroidManifest.xml")); - var apk = new ZipFile(getPackageResourcePath()); - var xml = apk.getInputStream(apk.getEntry("AndroidManifest.xml")); - try (apk; xml) { - APKInstall.transfer(xml, zip); - } - zip.closeEntry(); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key = new SecretKeySpec(Bytes.key(), "AES"); + IvParameterSpec iv = new IvParameterSpec(Bytes.iv()); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + var is = new InflaterInputStream(new CipherInputStream( + new ByteArrayInputStream(Bytes.res()), cipher)); + try (is; out) { + APKInstall.transfer(is, out); } } private void loadResources() throws Exception { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - var fd = Os.memfd_create("res.apk", 0); + var fd = Os.memfd_create("res", 0); try { decryptResources(new FileOutputStream(fd)); Os.lseek(fd, 0, OsConstants.SEEK_SET); - try (var pfd = ParcelFileDescriptor.dup(fd)) { - var loader = new ResourcesLoader(); - loader.addProvider(ResourcesProvider.loadFromApk(pfd)); + var loader = new ResourcesLoader(); + try (var pfd = ParcelFileDescriptor.dup(fd); + var provider = ResourcesProvider.loadFromTable(pfd, null)) { + loader.addProvider(provider); getResources().addLoaders(loader); } } finally { Os.close(fd); } } else { - File apk = new File(getCacheDir(), "res.apk"); - decryptResources(new FileOutputStream(apk)); - StubApk.addAssetPath(getResources(), apk.getPath()); + File dir = new File(getCodeCacheDir(), "res"); + decryptResources(new FileOutputStream(new File(dir, "resources.arsc"))); + StubApk.addAssetPath(getResources(), dir.getPath()); } } }