5package io.flutter.embedding.engine.loader;
7import static android.os.Looper.getMainLooper;
8import static io.flutter.Build.API_LEVELS;
9import static junit.framework.TestCase.assertFalse;
10import static junit.framework.TestCase.assertTrue;
11import static org.mockito.Mockito.any;
12import static org.mockito.Mockito.anyLong;
13import static org.mockito.Mockito.anyString;
14import static org.mockito.Mockito.eq;
15import static org.mockito.Mockito.mock;
16import static org.mockito.Mockito.never;
17import static org.mockito.Mockito.spy;
18import static org.mockito.Mockito.times;
19import static org.mockito.Mockito.verify;
20import static org.robolectric.Shadows.shadowOf;
22import android.annotation.TargetApi;
23import android.app.ActivityManager;
26import android.util.DisplayMetrics;
27import androidx.test.core.app.ApplicationProvider;
28import androidx.test.ext.junit.runners.AndroidJUnit4;
29import io.flutter.embedding.engine.FlutterJNI;
30import java.util.Arrays;
32import java.util.concurrent.Callable;
33import java.util.concurrent.ExecutorService;
35import org.junit.runner.RunWith;
36import org.mockito.ArgumentCaptor;
37import org.robolectric.annotation.Config;
40@RunWith(AndroidJUnit4.class)
42 private final Context ctx = ApplicationProvider.getApplicationContext();
47 assertFalse(flutterLoader.initialized());
55 assertFalse(flutterLoader.initialized());
58 shadowOf(getMainLooper()).idle();
59 assertTrue(flutterLoader.initialized());
60 verify(mockFlutterJNI,
times(1)).loadLibrary();
61 verify(mockFlutterJNI,
times(1)).updateRefreshRate();
69 assertFalse(flutterLoader.initialized());
72 shadowOf(getMainLooper()).idle();
74 ActivityManager activityManager =
75 (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
76 ActivityManager.MemoryInfo memInfo =
new ActivityManager.MemoryInfo();
77 activityManager.getMemoryInfo(memInfo);
78 int oldGenHeapSizeMegaBytes = (
int) (memInfo.totalMem / 1e6 / 2);
79 final String oldGenHeapArg =
"--old-gen-heap-size=" + oldGenHeapSizeMegaBytes;
80 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
81 verify(mockFlutterJNI,
times(1))
82 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
83 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
84 assertTrue(arguments.contains(oldGenHeapArg));
92 assertFalse(flutterLoader.initialized());
95 shadowOf(getMainLooper()).idle();
97 DisplayMetrics displayMetrics = ctx.getResources().getDisplayMetrics();
98 int screenWidth = displayMetrics.widthPixels;
99 int screenHeight = displayMetrics.heightPixels;
100 int resourceCacheMaxBytesThreshold = screenWidth * screenHeight * 12 * 4;
101 final String resourceCacheMaxBytesThresholdArg =
102 "--resource-cache-max-bytes-threshold=" + resourceCacheMaxBytesThreshold;
103 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
104 verify(mockFlutterJNI,
times(1))
105 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
106 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
107 assertTrue(arguments.contains(resourceCacheMaxBytesThresholdArg));
115 assertFalse(flutterLoader.initialized());
118 shadowOf(getMainLooper()).idle();
120 final String leakVMArg =
"--leak-vm=true";
121 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
122 verify(mockFlutterJNI,
times(1))
123 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
124 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
125 assertTrue(arguments.contains(leakVMArg));
132 Bundle metaData =
new Bundle();
133 metaData.putBoolean(
"io.flutter.embedding.android.LeakVM",
false);
134 ctx.getApplicationInfo().metaData = metaData;
137 assertFalse(flutterLoader.initialized());
140 shadowOf(getMainLooper()).idle();
142 final String leakVMArg =
"--leak-vm=false";
143 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
144 verify(mockFlutterJNI,
times(1))
145 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
146 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
147 assertTrue(arguments.contains(leakVMArg));
153 ExecutorService mockExecutorService = mock(ExecutorService.class);
156 assertFalse(flutterLoader.initialized());
158 verify(mockExecutorService,
times(1)).submit(
any(Callable.class));
166 assertFalse(flutterLoader.initialized());
169 shadowOf(getMainLooper()).idle();
171 final String enableImpellerArg =
"--enable-impeller";
172 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
173 verify(mockFlutterJNI,
times(1))
174 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
175 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
176 assertFalse(arguments.contains(enableImpellerArg));
184 assertFalse(flutterLoader.initialized());
187 shadowOf(getMainLooper()).idle();
189 final String enableVulkanValidationArg =
"--enable-vulkan-validation";
190 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
191 verify(mockFlutterJNI,
times(1))
192 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
193 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
194 assertFalse(arguments.contains(enableVulkanValidationArg));
201 Bundle metaData =
new Bundle();
202 metaData.putBoolean(
"io.flutter.embedding.android.EnableImpeller",
true);
203 ctx.getApplicationInfo().metaData = metaData;
206 assertFalse(flutterLoader.initialized());
209 shadowOf(getMainLooper()).idle();
211 final String enableImpellerArg =
"--enable-impeller";
212 ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].
class);
213 verify(mockFlutterJNI,
times(1))
214 .init(
eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
215 List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
216 assertTrue(arguments.contains(enableImpellerArg));
222 public
void itReportsFpsToVsyncWaiterAndroidM() {
226 Context appContextSpy = spy(ctx);
228 assertFalse(flutterLoader.initialized());
230 verify(appContextSpy, never()).getSystemService(anyString());
static SkISize times(const SkISize &size, float factor)
static bool eq(const SkM44 &a, const SkM44 &b, float tol)
void itUsesCorrectExecutorService()
void itDoesNotSetEnableImpellerByDefault()
void itDoesNotSetEnableVulkanValidationByDefault()
void itDefaultsTheOldGenHeapSizeAppropriately()
void itSetsEnableImpellerFromMetaData()
void itReportsInitializedAfterInitializing()
void itReportsUninitializedAfterCreating()
void itSetsLeakVMToTrueByDefault()
void itSetsTheLeakVMFromMetaData()
void itDefaultsTheResourceCacheMaxBytesThresholdAppropriately()
void ensureInitializationComplete( @NonNull Context applicationContext, @Nullable String[] args)
void startInitialization(@NonNull Context applicationContext)
SIT bool any(const Vec< 1, T > &x)