14
14
15
15
package com .google .firebase .crashlytics .ndk ;
16
16
17
+ import android .annotation .TargetApi ;
18
+ import android .content .Context ;
19
+ import android .content .pm .ApplicationInfo ;
20
+ import android .content .pm .PackageInfo ;
21
+ import android .content .pm .PackageManager ;
22
+ import android .content .pm .PackageManager .NameNotFoundException ;
17
23
import android .content .res .AssetManager ;
24
+ import android .os .Build ;
25
+ import android .text .TextUtils ;
18
26
import com .google .firebase .crashlytics .internal .Logger ;
27
+ import java .io .File ;
28
+ import java .util .ArrayList ;
29
+ import java .util .Collections ;
30
+ import java .util .List ;
19
31
20
32
/** JNI implementation of the native API interface. */
21
33
@ SuppressWarnings ("PMD.AvoidUsingNativeCode" )
22
34
class JniNativeApi implements NativeApi {
23
35
24
36
private static final boolean LIB_CRASHLYTICS_LOADED ;
37
+ private Context context ;
25
38
26
39
static {
27
40
boolean loadSuccessful = false ;
@@ -45,10 +58,87 @@ class JniNativeApi implements NativeApi {
45
58
LIB_CRASHLYTICS_LOADED = loadSuccessful ;
46
59
}
47
60
61
+ public JniNativeApi (Context context ) {
62
+ this .context = context ;
63
+ }
64
+
65
+ public static boolean isAtLeastLollipop () {
66
+ return android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .LOLLIPOP ;
67
+ }
68
+
69
+ @ TargetApi (Build .VERSION_CODES .LOLLIPOP )
70
+ public static void addSplitSourceDirs (List <String > zipPaths , ApplicationInfo applicationInfo ) {
71
+ if (applicationInfo .splitSourceDirs != null ) {
72
+ Collections .addAll (zipPaths , applicationInfo .splitSourceDirs );
73
+ }
74
+ }
75
+
76
+ public String [] makePackagePaths (String arch ) {
77
+ try {
78
+ PackageManager pm = context .getPackageManager ();
79
+ PackageInfo pi =
80
+ pm .getPackageInfo (
81
+ context .getPackageName (),
82
+ PackageManager .GET_SHARED_LIBRARY_FILES | PackageManager .MATCH_UNINSTALLED_PACKAGES );
83
+
84
+ List <String > zipPaths = new ArrayList <>(10 );
85
+ zipPaths .add (pi .applicationInfo .sourceDir );
86
+
87
+ if (isAtLeastLollipop ()) {
88
+ addSplitSourceDirs (zipPaths , pi .applicationInfo );
89
+ }
90
+
91
+ if (pi .applicationInfo .sharedLibraryFiles != null ) {
92
+ Collections .addAll (zipPaths , pi .applicationInfo .sharedLibraryFiles );
93
+ }
94
+
95
+ List <String > libPaths = new ArrayList <>(10 );
96
+ File parent = new File (pi .applicationInfo .nativeLibraryDir ).getParentFile ();
97
+ if (parent != null ) {
98
+ libPaths .add (new File (parent , arch ).getPath ());
99
+
100
+ // arch is the currently loaded library's ABI name. This is the name of the library
101
+ // directory in an APK, but may differ from the library directory extracted to the
102
+ // filesystem. ARM family abi names have a suffix specifying the architecture
103
+ // version, but may be extracted to directories named "arm64" or "arm".
104
+ // crbug.com/930342
105
+ if (arch .startsWith ("arm64" )) {
106
+ libPaths .add (new File (parent , "arm64" ).getPath ());
107
+ } else if (arch .startsWith ("arm" )) {
108
+ libPaths .add (new File (parent , "arm" ).getPath ());
109
+ }
110
+ }
111
+ for (String zip : zipPaths ) {
112
+ if (zip .endsWith (".apk" )) {
113
+ libPaths .add (zip + "!/lib/" + arch );
114
+ }
115
+ }
116
+ libPaths .add (System .getProperty ("java.library.path" ));
117
+ libPaths .add (pi .applicationInfo .nativeLibraryDir );
118
+
119
+ return new String [] {
120
+ TextUtils .join (File .pathSeparator , zipPaths ), TextUtils .join (File .pathSeparator , libPaths )
121
+ };
122
+ } catch (NameNotFoundException e ) {
123
+ Logger .getLogger ().e ("Unable to compose package paths" , e );
124
+ throw new RuntimeException (e );
125
+ }
126
+ }
127
+
48
128
@ Override
49
129
public boolean initialize (String dataPath , AssetManager assetManager ) {
50
- return LIB_CRASHLYTICS_LOADED && nativeInit (dataPath , assetManager );
130
+ String [] paths = makePackagePaths (Build .CPU_ABI );
131
+
132
+ if (paths .length < 2 ) {
133
+ return false ;
134
+ }
135
+
136
+ String classpath = paths [0 ];
137
+ String libspath = paths [1 ];
138
+
139
+ return LIB_CRASHLYTICS_LOADED
140
+ && nativeInit (new String [] {classpath , libspath , dataPath }, assetManager );
51
141
}
52
142
53
- private native boolean nativeInit (String dataPath , Object assetManager );
143
+ private native boolean nativeInit (String [] paths , Object assetManager );
54
144
}
0 commit comments