package com.lody.virtual.helper.compat;
import android.annotation.TargetApi;
import android.os.Build;
import com.lody.virtual.helper.utils.Reflect;
import com.lody.virtual.helper.utils.VLog;
import java.io.File;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import mirror.com.android.internal.content.NativeLibraryHelper;
import mirror.dalvik.system.VMRuntime;
public class NativeLibraryHelperCompat {
private static String TAG = NativeLibraryHelperCompat.class.getSimpleName();
public static int copyNativeBinaries(File apkFile, File sharedLibraryDir) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return copyNativeBinariesAfterL(apkFile, sharedLibraryDir);
} else {
return copyNativeBinariesBeforeL(apkFile, sharedLibraryDir);
}
}
private static int copyNativeBinariesBeforeL(File apkFile, File sharedLibraryDir) {
try {
return Reflect.on(NativeLibraryHelper.TYPE).call("copyNativeBinariesIfNeededLI", apkFile, sharedLibraryDir)
.get();
} catch (Throwable e) {
e.printStackTrace();
}
return -1;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static int copyNativeBinariesAfterL(File apkFile, File sharedLibraryDir) {
try {
Object handle = NativeLibraryHelper.Handle.create.call(apkFile);
if (handle == null) {
return -1;
}
String abi = null;
Set<String> abiSet = getABIsFromApk(apkFile.getAbsolutePath());
if (abiSet == null || abiSet.isEmpty()) {
return 0;
}
boolean is64Bit = VMRuntime.is64Bit.call(VMRuntime.getRuntime.call());
if (is64Bit && isVM64(abiSet)) {
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
int abiIndex = NativeLibraryHelper.findSupportedAbi.call(handle, Build.SUPPORTED_64_BIT_ABIS);
if (abiIndex >= 0) {
abi = Build.SUPPORTED_64_BIT_ABIS[abiIndex];
}
}
} else {
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
int abiIndex = NativeLibraryHelper.findSupportedAbi.call(handle, Build.SUPPORTED_32_BIT_ABIS);
if (abiIndex >= 0) {
abi = Build.SUPPORTED_32_BIT_ABIS[abiIndex];
}
}
}
if (abi == null) {
VLog.e(TAG, "Not match any abi [%s].", apkFile.getPath());
return -1;
}
return NativeLibraryHelper.copyNativeBinaries.call(handle, sharedLibraryDir, abi);
} catch (Throwable e) {
VLog.d(TAG, "copyNativeBinaries with error : %s", e.getLocalizedMessage());
e.printStackTrace();
}
return -1;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean isVM64(Set<String> supportedABIs) {
if (Build.SUPPORTED_64_BIT_ABIS.length == 0) {
return false;
}
if (supportedABIs == null || supportedABIs.isEmpty()) {
return true;
}
for (String supportedAbi : supportedABIs) {
if ("arm64-v8a".endsWith(supportedAbi) || "x86_64".equals(supportedAbi) || "mips64".equals(supportedAbi)) {
return true;
}
}
return false;
}
private static Set<String> getABIsFromApk(String apk) {
try {
ZipFile apkFile = new ZipFile(apk);
Enumeration<? extends ZipEntry> entries = apkFile.entries();
Set<String> supportedABIs = new HashSet<String>();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
if (name.contains("../")) {
continue;
}
if (name.startsWith("lib/") && !entry.isDirectory() && name.endsWith(".so")) {
String supportedAbi = name.substring(name.indexOf("/") + 1, name.lastIndexOf("/"));
supportedABIs.add(supportedAbi);
}
}
return supportedABIs;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}