-
Notifications
You must be signed in to change notification settings - Fork 566
Expand file tree
/
Copy pathMonoPackageManager.java
More file actions
177 lines (155 loc) · 6.22 KB
/
MonoPackageManager.java
File metadata and controls
177 lines (155 loc) · 6.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package mono;
import java.io.*;
import java.lang.String;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Locale;
import java.util.HashSet;
import java.util.zip.*;
import java.util.Arrays;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.res.AssetManager;
import android.os.Build;
import android.util.Log;
import mono.android.Runtime;
import mono.android.DebugRuntime;
import mono.android.BuildConfig;
import net.dot.android.ApplicationRegistration;
public class MonoPackageManager {
static Object lock = new Object ();
static boolean initialized;
public static void LoadApplication (Context context)
{
synchronized (lock) {
android.content.pm.ApplicationInfo runtimePackage = context.getApplicationInfo ();
String[] apks = null;
String[] splitApks = runtimePackage.splitSourceDirs;
if (splitApks != null && splitApks.length > 0) {
apks = new String[splitApks.length + 1];
apks [0] = runtimePackage.sourceDir;
System.arraycopy (splitApks, 0, apks, 1, splitApks.length);
} else {
apks = new String[] { runtimePackage.sourceDir };
}
if (context instanceof android.app.Application) {
ApplicationRegistration.Context = context;
}
if (!initialized) {
android.content.IntentFilter timezoneChangedFilter = new android.content.IntentFilter (
android.content.Intent.ACTION_TIMEZONE_CHANGED
);
context.registerReceiver (new mono.android.app.NotifyTimeZoneChanges (), timezoneChangedFilter);
Locale locale = Locale.getDefault ();
String language = locale.getLanguage () + "-" + locale.getCountry ();
String filesDir = context.getFilesDir ().getAbsolutePath ();
String cacheDir = context.getCacheDir ().getAbsolutePath ();
String dataDir = getNativeLibraryPath (context);
ClassLoader loader = context.getClassLoader ();
String runtimeDir = getNativeLibraryPath (runtimePackage);
int localDateTimeOffset;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
localDateTimeOffset = OffsetDateTime.now().getOffset().getTotalSeconds();
}
else {
localDateTimeOffset = (Calendar.getInstance ().get (Calendar.ZONE_OFFSET) + Calendar.getInstance ().get (Calendar.DST_OFFSET)) / 1000;
}
//
// Should the order change here, src/mono/native/runtime-base/shared-constants.hh and
// src/native/clr/include/constants.hh must be updated accordingly
//
String[] appDirs = new String[] {filesDir, cacheDir, dataDir};
boolean haveSplitApks = runtimePackage.splitSourceDirs != null && runtimePackage.splitSourceDirs.length > 0;
//
// Preload DSOs libmonodroid.so depends on so that the dynamic
// linker can resolve them when loading monodroid. This is not
// needed in the latest Android versions but is required in at least
// API 16 and since there's no inherent negative effect of doing it,
// we can do it unconditionally.
//
// Additionally, we need to load all the DSOs which depend on libmonosgen-2.0. The reason is that on
// some 64-bit devices running Android 5.{0,1} the dynamic linker fails to find `libmonosgen-2.0.so`
// even though it is in the same directory as the DSO depending on it *and* libmonosgen-2.0 is already
// in memory. This was seen on some devices (Huawei P8) and the x86_64 Android emulator. See the
// following issues:
//
// https://github.com/xamarin/xamarin-android/issues/4772
// https://github.com/xamarin/xamarin-android/issues/4852
//
// We could limit the preloading to only 64-bit 5.x Android versions but it appears to be more effort
// than necessary as preloading won't hurt performance (much - some libraries might not be needed
// immediately during startup) and there might be other Android builds out there with similar problems.
//
// We need to use our own `BuildConfig` class to detect debug builds here because,
// it seems, ApplicationInfo.flags information is not reliable - in the debug builds
// (with `android:debuggable=true` present on the `<application>` element in the
// manifest) using shared runtime, the `runtimePackage.flags` field does NOT have
// the FLAGS_DEBUGGABLE (0x00000002) set and thus we'd revert to the `else` clause
// below, leading to an error locating the Mono runtime
//
if (BuildConfig.Debug) {
System.loadLibrary ("xamarin-debug-app-helper");
DebugRuntime.init (apks, runtimeDir, appDirs, haveSplitApks);
} else {
System.loadLibrary("monosgen-2.0");
}
System.loadLibrary("xamarin-app");
if (!BuildConfig.DotNetRuntime) {
// .net5+ APKs don't contain `libmono-native.so`
System.loadLibrary("mono-native");
}
System.loadLibrary("monodroid");
Runtime.initInternal (
language,
apks,
runtimeDir,
appDirs,
localDateTimeOffset,
loader,
MonoPackageManager_Resources.Assemblies,
isEmulator (),
haveSplitApks
);
ApplicationRegistration.registerApplications ();
initialized = true;
}
}
}
// We need to detect the emulator in order to determine the maximum gref count.
// The official Android emulator requires a much lower maximum than actual
// devices. Hopefully other emulators don't need the treatment. If they do, we
// can add their detection here. We should perform the absolute minimum of
// checking in order to save time.
static boolean isEmulator()
{
String val = Build.HARDWARE;
// This detects the official Android emulator
if (val.contains ("ranchu") || val.contains ("goldfish"))
return true;
return false;
}
public static void setContext (Context context)
{
// Ignore; vestigial
}
static String getNativeLibraryPath (Context context)
{
return getNativeLibraryPath (context.getApplicationInfo ());
}
static String getNativeLibraryPath (ApplicationInfo ainfo)
{
if (android.os.Build.VERSION.SDK_INT >= 9)
return ainfo.nativeLibraryDir;
return ainfo.dataDir + "/lib";
}
public static String[] getAssemblies ()
{
return MonoPackageManager_Resources.Assemblies;
}
public static String[] getDependencies ()
{
return MonoPackageManager_Resources.Dependencies;
}
}