5package io.flutter.embedding.engine.loader;
7import android.app.ActivityManager;
9import android.content.pm.ApplicationInfo;
10import android.content.pm.PackageManager;
11import android.content.res.AssetManager;
12import android.hardware.display.DisplayManager;
17import android.util.DisplayMetrics;
18import androidx.annotation.NonNull;
19import androidx.annotation.Nullable;
20import io.flutter.BuildConfig;
21import io.flutter.FlutterInjector;
23import io.flutter.embedding.engine.FlutterJNI;
24import io.flutter.util.HandlerCompat;
25import io.flutter.util.PathUtils;
26import io.flutter.util.TraceSection;
27import io.flutter.view.VsyncWaiter;
30import java.util.concurrent.Callable;
31import java.util.concurrent.ExecutorService;
32import java.util.concurrent.Future;
36 private static final String TAG =
"FlutterLoader";
38 private static final String OLD_GEN_HEAP_SIZE_META_DATA_KEY =
39 "io.flutter.embedding.android.OldGenHeapSize";
40 private static final String ENABLE_IMPELLER_META_DATA_KEY =
41 "io.flutter.embedding.android.EnableImpeller";
42 private static final String ENABLE_VULKAN_VALIDATION_META_DATA_KEY =
43 "io.flutter.embedding.android.EnableVulkanValidation";
44 private static final String IMPELLER_BACKEND_META_DATA_KEY =
45 "io.flutter.embedding.android.ImpellerBackend";
46 private static final String IMPELLER_OPENGL_GPU_TRACING_DATA_KEY =
47 "io.flutter.embedding.android.EnableOpenGLGPUTracing";
48 private static final String IMPELLER_VULKAN_GPU_TRACING_DATA_KEY =
49 "io.flutter.embedding.android.EnableVulkanGPUTracing";
62 private static final String LEAK_VM_META_DATA_KEY =
"io.flutter.embedding.android.LeakVM";
74 private static final String DEFAULT_LIBRARY =
"libflutter.so";
75 private static final String DEFAULT_KERNEL_BLOB =
"kernel_blob.bin";
76 private static final String VMSERVICE_SNAPSHOT_LIBRARY =
"libvmservice_snapshot.so";
106 this.flutterJNI = flutterJNI;
107 this.executorService = executorService;
110 private boolean initialized =
false;
111 @Nullable
private Settings settings;
112 private long initStartTimestampMillis;
115 private ExecutorService executorService;
117 private static class InitResult {
118 final String appStoragePath;
119 final String engineCachesPath;
120 final String dataDirPath;
122 private InitResult(String appStoragePath, String engineCachesPath, String dataDirPath) {
123 this.appStoragePath = appStoragePath;
124 this.engineCachesPath = engineCachesPath;
125 this.dataDirPath = dataDirPath;
153 if (this.settings !=
null) {
156 if (Looper.myLooper() != Looper.getMainLooper()) {
157 throw new IllegalStateException(
"startInitialization must be called on the main thread");
162 final Context appContext = applicationContext.getApplicationContext();
164 this.settings = settings;
166 initStartTimestampMillis = SystemClock.uptimeMillis();
169 final DisplayManager dm =
170 (DisplayManager) appContext.getSystemService(Context.DISPLAY_SERVICE);
175 Callable<InitResult> initTask =
176 new Callable<InitResult>() {
178 public InitResult
call() {
184 }
catch (UnsatisfiedLinkError unsatisfiedLinkError) {
185 String couldntFindVersion =
"couldn't find \"libflutter.so\"";
186 String notFoundVersion =
"dlopen failed: library \"libflutter.so\" not found";
188 if (unsatisfiedLinkError.toString().contains(couldntFindVersion)
189 || unsatisfiedLinkError.toString().contains(notFoundVersion)) {
195 String cpuArch = System.getProperty(
"os.arch");
197 String[] nativeLibsContents = nativeLibsDir.list();
199 throw new UnsupportedOperationException(
200 "Could not load libflutter.so this is possibly because the application"
201 +
" is running on an architecture that Flutter Android does not support (e.g. x86)"
202 +
" see https://docs.flutter.dev/deployment/android#what-are-the-supported-target-architectures"
203 +
" for more detail.\n"
204 +
"App is using cpu architecture: "
206 +
", and the native libraries directory (with path "
207 + nativeLibsDir.getAbsolutePath()
208 +
") contains the following files: "
209 + Arrays.toString(nativeLibsContents),
210 unsatisfiedLinkError);
213 throw unsatisfiedLinkError;
222 if (resourceExtractor !=
null) {
226 return new InitResult(
246 @NonNull Context applicationContext, @Nullable String[]
args) {
250 if (Looper.myLooper() != Looper.getMainLooper()) {
251 throw new IllegalStateException(
252 "ensureInitializationComplete must be called on the main thread");
254 if (settings ==
null) {
255 throw new IllegalStateException(
256 "ensureInitializationComplete must be called after startInitialization");
263 shellArgs.add(
"--icu-symbol-prefix=_binary_icudtl_dat");
266 "--icu-native-lib-path="
271 Collections.addAll(shellArgs,
args);
274 String kernelPath =
null;
276 String snapshotAssetPath =
277 result.dataDirPath + File.separator + flutterApplicationInfo.
flutterAssetsDir;
278 kernelPath = snapshotAssetPath + File.separator + DEFAULT_KERNEL_BLOB;
306 shellArgs.add(
"--cache-dir-path=" +
result.engineCachesPath);
310 if (settings.getLogTag() !=
null) {
311 shellArgs.add(
"--log-tag=" + settings.getLogTag());
314 ApplicationInfo applicationInfo =
318 applicationContext.getPackageName(), PackageManager.GET_META_DATA);
319 Bundle metaData = applicationInfo.metaData;
320 int oldGenHeapSizeMegaBytes =
321 metaData !=
null ? metaData.getInt(OLD_GEN_HEAP_SIZE_META_DATA_KEY) : 0;
322 if (oldGenHeapSizeMegaBytes == 0) {
324 ActivityManager activityManager =
325 (ActivityManager) applicationContext.getSystemService(Context.ACTIVITY_SERVICE);
326 ActivityManager.MemoryInfo memInfo =
new ActivityManager.MemoryInfo();
327 activityManager.getMemoryInfo(memInfo);
328 oldGenHeapSizeMegaBytes = (
int) (memInfo.totalMem / 1e6 / 2);
330 shellArgs.add(
"--old-gen-heap-size=" + oldGenHeapSizeMegaBytes);
332 DisplayMetrics displayMetrics = applicationContext.getResources().getDisplayMetrics();
333 int screenWidth = displayMetrics.widthPixels;
334 int screenHeight = displayMetrics.heightPixels;
337 int resourceCacheMaxBytesThreshold = screenWidth * screenHeight * 12 * 4;
338 shellArgs.add(
"--resource-cache-max-bytes-threshold=" + resourceCacheMaxBytesThreshold);
340 shellArgs.add(
"--prefetched-default-font-manager");
342 if (metaData !=
null) {
343 if (metaData.getBoolean(ENABLE_IMPELLER_META_DATA_KEY,
false)) {
344 shellArgs.add(
"--enable-impeller");
346 if (metaData.getBoolean(ENABLE_VULKAN_VALIDATION_META_DATA_KEY,
false)) {
347 shellArgs.add(
"--enable-vulkan-validation");
349 if (metaData.getBoolean(IMPELLER_OPENGL_GPU_TRACING_DATA_KEY,
false)) {
350 shellArgs.add(
"--enable-opengl-gpu-tracing");
352 if (metaData.getBoolean(IMPELLER_VULKAN_GPU_TRACING_DATA_KEY,
false)) {
353 shellArgs.add(
"--enable-vulkan-gpu-tracing");
355 String
backend = metaData.getString(IMPELLER_BACKEND_META_DATA_KEY);
357 shellArgs.add(
"--impeller-backend=" +
backend);
361 final String leakVM = isLeakVM(metaData) ?
"true" :
"false";
362 shellArgs.add(
"--leak-vm=" + leakVM);
364 long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
368 shellArgs.toArray(
new String[0]),
375 }
catch (Exception
e) {
376 Log.
e(
TAG,
"Flutter initialization failed.",
e);
377 throw new RuntimeException(
e);
381 private static boolean isLeakVM(@Nullable Bundle metaData) {
382 final boolean leakVMDefaultValue =
true;
383 if (metaData ==
null) {
384 return leakVMDefaultValue;
386 return metaData.getBoolean(LEAK_VM_META_DATA_KEY, leakVMDefaultValue);
394 @NonNull Context applicationContext,
395 @Nullable String[]
args,
396 @NonNull Handler callbackHandler,
398 if (Looper.myLooper() != Looper.getMainLooper()) {
399 throw new IllegalStateException(
400 "ensureInitializationComplete must be called on the main thread");
402 if (settings ==
null) {
403 throw new IllegalStateException(
404 "ensureInitializationComplete must be called after startInitialization");
410 executorService.execute(
415 }
catch (Exception
e) {
416 Log.
e(
TAG,
"Flutter initialization failed.",
e);
417 throw new RuntimeException(
e);
438 final String packageName = applicationContext.getPackageName();
439 final PackageManager packageManager = applicationContext.getPackageManager();
440 final AssetManager assetManager = applicationContext.getResources().getAssets();
449 .
addResource(fullAssetPathFrom(DEFAULT_KERNEL_BLOB));
451 resourceExtractor.
start();
453 return resourceExtractor;
470 return fullAssetPathFrom(asset);
484 return getLookupKeyForAsset(
"packages" + File.separator + packageName + File.separator + asset);
494 private String fullAssetPathFrom(@NonNull String filePath) {
495 return flutterApplicationInfo.flutterAssetsDir + File.separator + filePath;
499 private String logTag;
static final boolean DEBUG
static final boolean PROFILE
static final boolean JIT_RELEASE
FlutterJNI.Factory getFlutterJNIFactory()
static void e(@NonNull String tag, @NonNull String message)
void init( @NonNull Context context, @NonNull String[] args, @Nullable String bundlePath, @NonNull String appStoragePath, @NonNull String engineCachesPath, long initTimeMillis)
void prefetchDefaultFontManager()
static FlutterApplicationInfo load(@NonNull Context applicationContext)
final boolean automaticallyRegisterPlugins
final String flutterAssetsDir
final String isolateSnapshotData
final String domainNetworkPolicy
final String nativeLibraryDir
final String vmSnapshotData
final String aotSharedLibraryName
void setLogTag(String tag)
FlutterLoader(@NonNull FlutterJNI flutterJNI, @NonNull ExecutorService executorService)
String getLookupKeyForAsset(@NonNull String asset)
boolean automaticallyRegisterPlugins()
void ensureInitializationComplete( @NonNull Context applicationContext, @Nullable String[] args)
static final String VM_SNAPSHOT_DATA_KEY
static final String ISOLATE_SNAPSHOT_DATA_KEY
void startInitialization(@NonNull Context applicationContext)
String getLookupKeyForAsset(@NonNull String asset, @NonNull String packageName)
static final String AOT_SHARED_LIBRARY_NAME
void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings)
String findAppBundlePath()
static final String AUTOMATICALLY_REGISTER_PLUGINS_KEY
static final String AOT_VMSERVICE_SHARED_LIBRARY_NAME
FlutterLoader(@NonNull FlutterJNI flutterJNI)
void ensureInitializationCompleteAsync( @NonNull Context applicationContext, @Nullable String[] args, @NonNull Handler callbackHandler, @NonNull Runnable callback)
static final String SNAPSHOT_ASSET_PATH_KEY
Future< InitResult > initResultFuture
static final String FLUTTER_ASSETS_DIR_KEY
static Handler createAsyncHandler(Looper looper)
static String getDataDirectory(@NonNull Context applicationContext)
static String getCacheDirectory(@NonNull Context applicationContext)
static String getFilesDir(@NonNull Context applicationContext)
static TraceSection scoped(String name)
static VsyncWaiter getInstance(float fps, @NonNull FlutterJNI flutterJNI)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback