Skip to content

Commit

Permalink
Merge pull request #170 from JackCho/bugfix/fix_vm_incompatible
Browse files Browse the repository at this point in the history
fix vm incompatible
  • Loading branch information
Lody committed Apr 22, 2016
2 parents 6bebbee + 88fa984 commit e8b6f98
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,11 @@ public int installPackage(String filepath, int flags) throws RemoteException {
// Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion());
// }
// }
copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0));
if (copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0)) < 0) {
new File(apkfile).delete();
return PackageManagerCompat.INSTALL_FAILED_NOT_SUPPORT_ABI;
}

dexOpt(mContext, apkfile, parser);
mPluginCache.put(parser.getPackageName(), parser);
mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName());
Expand Down Expand Up @@ -895,7 +899,11 @@ public int installPackage(String filepath, int flags) throws RemoteException {
// }
// }

copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0));
if (copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0)) < 0) {
new File(apkfile).delete();
return PackageManagerCompat.INSTALL_FAILED_NOT_SUPPORT_ABI;
}

dexOpt(mContext, apkfile, parser);
mPluginCache.put(parser.getPackageName(), parser);
mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName());
Expand Down Expand Up @@ -978,9 +986,9 @@ private void sendUninstalledBroadcast(String packageName) {
mContext.sendBroadcast(intent);
}

private void copyNativeLibs(Context context, String apkfile, ApplicationInfo applicationInfo) throws Exception {
private int copyNativeLibs(Context context, String apkfile, ApplicationInfo applicationInfo) throws Exception {
String nativeLibraryDir = PluginDirHelper.getPluginNativeLibraryDir(context, applicationInfo.packageName);
NativeLibraryHelperCompat.copyNativeBinaries(new File(apkfile), new File(nativeLibraryDir));
return NativeLibraryHelperCompat.copyNativeBinaries(new File(apkfile), new File(nativeLibraryDir));
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@

import android.annotation.TargetApi;
import android.os.Build;

import com.morgoo.droidplugin.pm.PluginManager;
import com.morgoo.droidplugin.reflect.MethodUtils;
import com.morgoo.helper.Log;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class NativeLibraryHelperCompat {

private static final String TAG = NativeLibraryHelperCompat.class.getSimpleName();

private static final Class nativeLibraryHelperClass() throws ClassNotFoundException {
return Class.forName("com.android.internal.content.NativeLibraryHelper");
Expand All @@ -19,20 +29,19 @@ private static final Class handleClass() throws ClassNotFoundException {

public static final int copyNativeBinaries(File apkFile, File sharedLibraryDir) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return copyNativeBinariesAfterM(apkFile, sharedLibraryDir);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return copyNativeBinariesAfterL(apkFile, sharedLibraryDir);
} else {
return copyNativeBinariesBeforeM(apkFile, sharedLibraryDir);
return copyNativeBinariesBeforeL(apkFile, sharedLibraryDir);
}

}

private static int copyNativeBinariesBeforeM(File apkFile, File sharedLibraryDir) {
private static int copyNativeBinariesBeforeL(File apkFile, File sharedLibraryDir) {
try {
Object[] args = new Object[2];
args[0] = apkFile;
args[1] = sharedLibraryDir;

return (int) MethodUtils.invokeStaticMethod(nativeLibraryHelperClass(), "copyNativeBinariesIfNeededLI", args);
} catch (NoSuchMethodException e) {
e.printStackTrace();
Expand All @@ -47,27 +56,44 @@ private static int copyNativeBinariesBeforeM(File apkFile, File sharedLibraryDir
return -1;
}

@TargetApi(Build.VERSION_CODES.M)
private static int copyNativeBinariesAfterM(File apkFile, File sharedLibraryDir) {

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static int copyNativeBinariesAfterL(File apkFile, File sharedLibraryDir) {
try {
Object handleInstance = MethodUtils.invokeStaticMethod(handleClass(), "create", apkFile);
if (handleInstance == null) {
return -1;
}

String abi = null;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
int abiIndex = (int) MethodUtils.invokeStaticMethod(nativeLibraryHelperClass(), "findSupportedAbi", handleInstance, Build.SUPPORTED_32_BIT_ABIS);
abi = Build.SUPPORTED_32_BIT_ABIS[abiIndex];
}

if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
int abiIndex = (int) MethodUtils.invokeStaticMethod(nativeLibraryHelperClass(), "findSupportedAbi", handleInstance, Build.SUPPORTED_64_BIT_ABIS);
if (abiIndex >= 0) {
abi = Build.SUPPORTED_64_BIT_ABIS[abiIndex];
if (isVM64()) {
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
Set<String> abis = getAbisFromApk(apkFile.getAbsolutePath());
if (abis == null || abis.isEmpty()) {
return 0;
}
int abiIndex = (int) MethodUtils.invokeStaticMethod(nativeLibraryHelperClass(), "findSupportedAbi", handleInstance, Build.SUPPORTED_64_BIT_ABIS);
if (abiIndex >= 0) {
abi = Build.SUPPORTED_64_BIT_ABIS[abiIndex];
}
}
} else {
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
Set<String> abis = getAbisFromApk(apkFile.getAbsolutePath());
if (abis == null || abis.isEmpty()) {
return 0;
}
int abiIndex = (int) MethodUtils.invokeStaticMethod(nativeLibraryHelperClass(), "findSupportedAbi", handleInstance, Build.SUPPORTED_32_BIT_ABIS);
if (abiIndex >= 0) {
abi = Build.SUPPORTED_32_BIT_ABIS[abiIndex];
}
}
}

if (abi == null) {
return -1;
}

Object[] args = new Object[3];
args[0] = handleInstance;
args[1] = sharedLibraryDir;
Expand All @@ -85,4 +111,53 @@ private static int copyNativeBinariesAfterM(File apkFile, File sharedLibraryDir)

return -1;
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean isVM64() {
Set<String> supportedAbis = getAbisFromApk(getHostApk());
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<>();
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);
}
}
Log.d(TAG, "supportedAbis : %s", supportedAbis);
return supportedAbis;
} catch (Exception e) {
Log.e(TAG, "get supportedAbis failure", e);
}

return null;
}

private static String getHostApk() {
return PluginManager.getInstance().getHostContext().getApplicationInfo().sourceDir;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ public class PackageManagerCompat {
public static final int INSTALL_FAILED_INVALID_APK = -2;
public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
}
public static final int INSTALL_FAILED_NOT_SUPPORT_ABI = -3;}
18 changes: 16 additions & 2 deletions project/TestPlugin/src/com/example/TestPlugin/ApkFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@
import android.widget.Toast;

import com.morgoo.droidplugin.pm.PluginManager;
import com.morgoo.helper.compat.PackageManagerCompat;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static com.morgoo.helper.compat.PackageManagerCompat.*;

public class ApkFragment extends ListFragment implements ServiceConnection {
private ArrayAdapter<ApkItem> adapter;
final Handler handler = new Handler();
Expand Down Expand Up @@ -290,8 +293,19 @@ public void run() {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getActivity(), re == PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION ? "安装失败,文件请求的权限太多" : "安装完成", Toast.LENGTH_SHORT).show();
adapter.notifyDataSetChanged();
switch (re) {
case PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION:
Toast.makeText(getActivity(), "安装失败,文件请求的权限太多", Toast.LENGTH_SHORT).show();
break;
case INSTALL_FAILED_NOT_SUPPORT_ABI:
Toast.makeText(getActivity(), "宿主不支持插件的abi环境,可能宿主运行时为64位,但插件只支持32位", Toast.LENGTH_SHORT).show();
break;
case INSTALL_SUCCEEDED:
Toast.makeText(getActivity(), "安装完成", Toast.LENGTH_SHORT).show();
adapter.notifyDataSetChanged();
break;
}

}
});
} catch (RemoteException e) {
Expand Down

0 comments on commit e8b6f98

Please sign in to comment.