22
33import android .annotation .TargetApi ;
44import android .os .Build ;
5+
6+ import com .morgoo .droidplugin .pm .PluginManager ;
57import com .morgoo .droidplugin .reflect .MethodUtils ;
8+ import com .morgoo .helper .Log ;
9+
610import java .io .File ;
711import java .lang .reflect .InvocationTargetException ;
12+ import java .util .Enumeration ;
13+ import java .util .HashSet ;
14+ import java .util .Set ;
15+ import java .util .zip .ZipEntry ;
16+ import java .util .zip .ZipFile ;
817
918public class NativeLibraryHelperCompat {
1019
20+ private static final String TAG = NativeLibraryHelperCompat .class .getSimpleName ();
1121
1222 private static final Class nativeLibraryHelperClass () throws ClassNotFoundException {
1323 return Class .forName ("com.android.internal.content.NativeLibraryHelper" );
@@ -19,20 +29,19 @@ private static final Class handleClass() throws ClassNotFoundException {
1929
2030 public static final int copyNativeBinaries (File apkFile , File sharedLibraryDir ) {
2131
22- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .M ) {
23- return copyNativeBinariesAfterM (apkFile , sharedLibraryDir );
32+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
33+ return copyNativeBinariesAfterL (apkFile , sharedLibraryDir );
2434 } else {
25- return copyNativeBinariesBeforeM (apkFile , sharedLibraryDir );
35+ return copyNativeBinariesBeforeL (apkFile , sharedLibraryDir );
2636 }
2737
2838 }
2939
30- private static int copyNativeBinariesBeforeM (File apkFile , File sharedLibraryDir ) {
40+ private static int copyNativeBinariesBeforeL (File apkFile , File sharedLibraryDir ) {
3141 try {
3242 Object [] args = new Object [2 ];
3343 args [0 ] = apkFile ;
3444 args [1 ] = sharedLibraryDir ;
35-
3645 return (int ) MethodUtils .invokeStaticMethod (nativeLibraryHelperClass (), "copyNativeBinariesIfNeededLI" , args );
3746 } catch (NoSuchMethodException e ) {
3847 e .printStackTrace ();
@@ -47,27 +56,44 @@ private static int copyNativeBinariesBeforeM(File apkFile, File sharedLibraryDir
4756 return -1 ;
4857 }
4958
50- @ TargetApi (Build .VERSION_CODES .M )
51- private static int copyNativeBinariesAfterM (File apkFile , File sharedLibraryDir ) {
52-
59+ @ TargetApi (Build .VERSION_CODES .LOLLIPOP )
60+ private static int copyNativeBinariesAfterL (File apkFile , File sharedLibraryDir ) {
5361 try {
5462 Object handleInstance = MethodUtils .invokeStaticMethod (handleClass (), "create" , apkFile );
5563 if (handleInstance == null ) {
5664 return -1 ;
5765 }
66+
5867 String abi = null ;
59- if (Build .SUPPORTED_32_BIT_ABIS .length > 0 ) {
60- int abiIndex = (int ) MethodUtils .invokeStaticMethod (nativeLibraryHelperClass (), "findSupportedAbi" , handleInstance , Build .SUPPORTED_32_BIT_ABIS );
61- abi = Build .SUPPORTED_32_BIT_ABIS [abiIndex ];
62- }
6368
64- if (Build .SUPPORTED_64_BIT_ABIS .length > 0 ) {
65- int abiIndex = (int ) MethodUtils .invokeStaticMethod (nativeLibraryHelperClass (), "findSupportedAbi" , handleInstance , Build .SUPPORTED_64_BIT_ABIS );
66- if (abiIndex >= 0 ) {
67- abi = Build .SUPPORTED_64_BIT_ABIS [abiIndex ];
69+ if (isVM64 ()) {
70+ if (Build .SUPPORTED_64_BIT_ABIS .length > 0 ) {
71+ Set <String > abis = getAbisFromApk (apkFile .getAbsolutePath ());
72+ if (abis == null || abis .isEmpty ()) {
73+ return 0 ;
74+ }
75+ int abiIndex = (int ) MethodUtils .invokeStaticMethod (nativeLibraryHelperClass (), "findSupportedAbi" , handleInstance , Build .SUPPORTED_64_BIT_ABIS );
76+ if (abiIndex >= 0 ) {
77+ abi = Build .SUPPORTED_64_BIT_ABIS [abiIndex ];
78+ }
79+ }
80+ } else {
81+ if (Build .SUPPORTED_32_BIT_ABIS .length > 0 ) {
82+ Set <String > abis = getAbisFromApk (apkFile .getAbsolutePath ());
83+ if (abis == null || abis .isEmpty ()) {
84+ return 0 ;
85+ }
86+ int abiIndex = (int ) MethodUtils .invokeStaticMethod (nativeLibraryHelperClass (), "findSupportedAbi" , handleInstance , Build .SUPPORTED_32_BIT_ABIS );
87+ if (abiIndex >= 0 ) {
88+ abi = Build .SUPPORTED_32_BIT_ABIS [abiIndex ];
89+ }
6890 }
6991 }
7092
93+ if (abi == null ) {
94+ return -1 ;
95+ }
96+
7197 Object [] args = new Object [3 ];
7298 args [0 ] = handleInstance ;
7399 args [1 ] = sharedLibraryDir ;
@@ -85,4 +111,53 @@ private static int copyNativeBinariesAfterM(File apkFile, File sharedLibraryDir)
85111
86112 return -1 ;
87113 }
114+
115+ @ TargetApi (Build .VERSION_CODES .LOLLIPOP )
116+ private static boolean isVM64 () {
117+ Set <String > supportedAbis = getAbisFromApk (getHostApk ());
118+ if (Build .SUPPORTED_64_BIT_ABIS .length == 0 ) {
119+ return false ;
120+ }
121+
122+ if (supportedAbis == null || supportedAbis .isEmpty ()) {
123+ return true ;
124+ }
125+
126+ for (String supportedAbi : supportedAbis ) {
127+ if ("arm64-v8a" .endsWith (supportedAbi ) || "x86_64" .equals (supportedAbi ) || "mips64" .equals (supportedAbi )) {
128+ return true ;
129+ }
130+ }
131+
132+ return false ;
133+ }
134+
135+ private static Set <String > getAbisFromApk (String apk ) {
136+ try {
137+ ZipFile apkFile = new ZipFile (apk );
138+ Enumeration <? extends ZipEntry > entries = apkFile .entries ();
139+ Set <String > supportedAbis = new HashSet <>();
140+ while (entries .hasMoreElements ()) {
141+ ZipEntry entry = entries .nextElement ();
142+ String name = entry .getName ();
143+ if (name .contains ("../" )) {
144+ continue ;
145+ }
146+ if (name .startsWith ("lib/" ) && !entry .isDirectory () && name .endsWith (".so" )) {
147+ String supportedAbi = name .substring (name .indexOf ("/" ) + 1 , name .lastIndexOf ("/" ));
148+ supportedAbis .add (supportedAbi );
149+ }
150+ }
151+ Log .d (TAG , "supportedAbis : %s" , supportedAbis );
152+ return supportedAbis ;
153+ } catch (Exception e ) {
154+ Log .e (TAG , "get supportedAbis failure" , e );
155+ }
156+
157+ return null ;
158+ }
159+
160+ private static String getHostApk () {
161+ return PluginManager .getInstance ().getHostContext ().getApplicationInfo ().sourceDir ;
162+ }
88163}
0 commit comments