mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-22 13:17:43 +00:00
Update resources load
addAssetPath supports apk and directory
This commit is contained in:
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk;
|
|||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
|
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -57,12 +58,24 @@ public class StubApk {
|
|||||||
return new File(getDynDir(info), "update.apk");
|
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) {
|
public static void addAssetPath(Resources res, String path) {
|
||||||
if (SDK_INT >= Build.VERSION_CODES.R) {
|
if (SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
try (var fd = ParcelFileDescriptor.open(new File(path), MODE_READ_ONLY)) {
|
try {
|
||||||
var loader = new ResourcesLoader();
|
res.addLoaders(getResourcesLoader(new File(path)));
|
||||||
loader.addProvider(ResourcesProvider.loadFromApk(fd));
|
|
||||||
res.addLoaders(loader);
|
|
||||||
} catch (IOException ignored) {}
|
} catch (IOException ignored) {}
|
||||||
} else {
|
} else {
|
||||||
AssetManager asset = res.getAssets();
|
AssetManager asset = res.getAssets();
|
||||||
|
@@ -35,9 +35,6 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.zip.InflaterInputStream;
|
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.Cipher;
|
||||||
import javax.crypto.CipherInputStream;
|
import javax.crypto.CipherInputStream;
|
||||||
@@ -162,47 +159,36 @@ public class DownloadActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void decryptResources(OutputStream out) throws Exception {
|
private void decryptResources(OutputStream out) throws Exception {
|
||||||
try (var zip = new ZipOutputStream(out)) {
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
zip.putNextEntry(new ZipEntry("resources.arsc"));
|
SecretKey key = new SecretKeySpec(Bytes.key(), "AES");
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
IvParameterSpec iv = new IvParameterSpec(Bytes.iv());
|
||||||
SecretKey key = new SecretKeySpec(Bytes.key(), "AES");
|
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
||||||
IvParameterSpec iv = new IvParameterSpec(Bytes.iv());
|
var is = new InflaterInputStream(new CipherInputStream(
|
||||||
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
new ByteArrayInputStream(Bytes.res()), cipher));
|
||||||
var is = new InflaterInputStream(new CipherInputStream(
|
try (is; out) {
|
||||||
new ByteArrayInputStream(Bytes.res()), cipher));
|
APKInstall.transfer(is, out);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadResources() throws Exception {
|
private void loadResources() throws Exception {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
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 {
|
try {
|
||||||
decryptResources(new FileOutputStream(fd));
|
decryptResources(new FileOutputStream(fd));
|
||||||
Os.lseek(fd, 0, OsConstants.SEEK_SET);
|
Os.lseek(fd, 0, OsConstants.SEEK_SET);
|
||||||
try (var pfd = ParcelFileDescriptor.dup(fd)) {
|
var loader = new ResourcesLoader();
|
||||||
var loader = new ResourcesLoader();
|
try (var pfd = ParcelFileDescriptor.dup(fd);
|
||||||
loader.addProvider(ResourcesProvider.loadFromApk(pfd));
|
var provider = ResourcesProvider.loadFromTable(pfd, null)) {
|
||||||
|
loader.addProvider(provider);
|
||||||
getResources().addLoaders(loader);
|
getResources().addLoaders(loader);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Os.close(fd);
|
Os.close(fd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
File apk = new File(getCacheDir(), "res.apk");
|
File dir = new File(getCodeCacheDir(), "res");
|
||||||
decryptResources(new FileOutputStream(apk));
|
decryptResources(new FileOutputStream(new File(dir, "resources.arsc")));
|
||||||
StubApk.addAssetPath(getResources(), apk.getPath());
|
StubApk.addAssetPath(getResources(), dir.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user