Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix vm incompatible #170

Merged
merged 1 commit into from
Apr 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
fix vm incompatible
  • Loading branch information
JackCho committed Apr 22, 2016
commit 88fa9841978fed96cb49976b36bd87186d1af864
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