Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 61 additions & 38 deletions shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ public class FlutterJNI {
// platform thread and doesn't require locking.
private ReentrantReadWriteLock shellHolderLock = new ReentrantReadWriteLock();

// Prefer using the FlutterJNI.Factory so it's easier to test.
public FlutterJNI() {
// We cache the main looper so that we can ensure calls are made on the main thread
// without consistently paying the synchronization cost of getMainLooper().
mainLooper = Looper.getMainLooper();
}

/**
* A factory for creating {@code FlutterJNI} instances. Useful for FlutterJNI injections during
* tests.
*/
public static class Factory {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the changes to this file are for consistency purposes.

  1. Put private methods right above the public ones.
  2. Move constructor and factory to the top. (It's weird that it's at the end)
  3. Move annotation after the javadoc.

I think this file still needs some additional clean ups.

/** @return a {@link FlutterJNI} instance. */
public FlutterJNI provideFlutterJNI() {
return new FlutterJNI();
}
}

// BEGIN Methods related to loading for FlutterLoader.
/**
* Loads the libflutter.so C++ library.
Expand All @@ -126,6 +144,8 @@ public void loadLibrary() {

private static boolean loadLibraryCalled = false;

private static native void nativePrefetchDefaultFontManager();

/**
* Prefetch the default font manager provided by SkFontMgr::RefDefault() which is a process-wide
* singleton owned by Skia. Note that, the first call to SkFontMgr::RefDefault() will take
Expand All @@ -142,10 +162,16 @@ public void prefetchDefaultFontManager() {
FlutterJNI.prefetchDefaultFontManagerCalled = true;
}

private static native void nativePrefetchDefaultFontManager();

private static boolean prefetchDefaultFontManagerCalled = false;

private static native void nativeInit(
@NonNull Context context,
@NonNull String[] args,
@Nullable String bundlePath,
@NonNull String appStoragePath,
@NonNull String engineCachesPath,
long initTimeMillis);

/**
* Perform one time initialization of the Dart VM and Flutter engine.
*
Expand Down Expand Up @@ -174,14 +200,6 @@ public void init(
FlutterJNI.initCalled = true;
}

private static native void nativeInit(
@NonNull Context context,
@NonNull String[] args,
@Nullable String bundlePath,
@NonNull String appStoragePath,
@NonNull String engineCachesPath,
long initTimeMillis);

private static boolean initCalled = false;
// END methods related to FlutterLoader

Expand All @@ -201,23 +219,23 @@ private static native void nativeInit(

private native boolean nativeGetIsSoftwareRenderingEnabled();

@UiThread
/**
* Checks launch settings for whether software rendering is requested.
*
* <p>The value is the same per program.
*/
@UiThread
public boolean getIsSoftwareRenderingEnabled() {
return nativeGetIsSoftwareRenderingEnabled();
}

@Nullable
/**
* Observatory URI for the VM instance.
*
* <p>Its value is set by the native engine once {@link #init(Context, String[], String, String,
* String, long)} is run.
*/
@Nullable
public static String getObservatoryUri() {
return observatoryUri;
}
Expand Down Expand Up @@ -245,7 +263,7 @@ public void setRefreshRateFPS(float refreshRateFPS) {
* The Android vsync waiter implementation in C++ needs to know when a vsync signal arrives, which
* is obtained via Java API. The delegate set here is called on the C++ side when the engine is
* ready to wait for the next vsync signal. The delegate is expected to add a postFrameCallback to
* the {@link android.view.Choreographer}, and call {@link nativeOnVsync} to notify the engine.
* the {@link android.view.Choreographer}, and call {@link onVsync} to notify the engine.
*
* @param delegate The delegate that will call the engine back on the next vsync signal.
*/
Expand All @@ -264,6 +282,8 @@ private static void asyncWaitForVsync(final long cookie) {
}
}

private native void nativeOnVsync(long frameDelayNanos, long refreshPeriodNanos, long cookie);

/**
* Notifies the engine that the Choreographer has signaled a vsync.
*
Expand All @@ -272,23 +292,44 @@ private static void asyncWaitForVsync(final long cookie) {
* @param refreshPeriodNanos The display refresh period in nanoseconds.
* @param cookie An opaque handle to the C++ VSyncWaiter object.
*/
public native void nativeOnVsync(long frameDelayNanos, long refreshPeriodNanos, long cookie);
public void onVsync(long frameDelayNanos, long refreshPeriodNanos, long cookie) {
nativeOnVsync(frameDelayNanos, refreshPeriodNanos, cookie);
}

// TODO(mattcarroll): add javadocs
@NonNull
@Deprecated
public static native FlutterCallbackInformation nativeLookupCallbackInformation(long handle);

// ----- Start FlutterTextUtils Methods ----
private native boolean nativeFlutterTextUtilsIsEmoji(int codePoint);

public native boolean nativeFlutterTextUtilsIsEmoji(int codePoint);
public boolean isCodePointEmoji(int codePoint) {
return nativeFlutterTextUtilsIsEmoji(codePoint);
}

private native boolean nativeFlutterTextUtilsIsEmojiModifier(int codePoint);

public native boolean nativeFlutterTextUtilsIsEmojiModifier(int codePoint);
public boolean isCodePointEmojiModifier(int codePoint) {
return nativeFlutterTextUtilsIsEmojiModifier(codePoint);
}

public native boolean nativeFlutterTextUtilsIsEmojiModifierBase(int codePoint);
private native boolean nativeFlutterTextUtilsIsEmojiModifierBase(int codePoint);

public boolean isCodePointEmojiModifierBase(int codePoint) {
return nativeFlutterTextUtilsIsEmojiModifierBase(codePoint);
}

public native boolean nativeFlutterTextUtilsIsVariationSelector(int codePoint);
private native boolean nativeFlutterTextUtilsIsVariationSelector(int codePoint);

public native boolean nativeFlutterTextUtilsIsRegionalIndicator(int codePoint);
public boolean isCodePointVariantSelector(int codePoint) {
return nativeFlutterTextUtilsIsVariationSelector(codePoint);
}

private native boolean nativeFlutterTextUtilsIsRegionalIndicator(int codePoint);

public boolean isCodePointRegionalIndicator(int codePoint) {
return nativeFlutterTextUtilsIsRegionalIndicator(codePoint);
}

// ----- End Engine FlutterTextUtils Methods ----

Expand All @@ -312,13 +353,6 @@ private static void asyncWaitForVsync(final long cookie) {

@NonNull private final Looper mainLooper; // cached to avoid synchronization on repeat access.

// Prefer using the FlutterJNI.Factory so it's easier to test.
public FlutterJNI() {
// We cache the main looper so that we can ensure calls are made on the main thread
// without consistently paying the synchronization cost of getMainLooper().
mainLooper = Looper.getMainLooper();
}

// ------ Start Native Attach/Detach Support ----
/**
* Returns true if this instance of {@code FlutterJNI} is connected to Flutter's native engine via
Expand Down Expand Up @@ -1402,15 +1436,4 @@ void updateSemantics(
public interface AsyncWaitForVsyncDelegate {
void asyncWaitForVsync(final long cookie);
}

/**
* A factory for creating {@code FlutterJNI} instances. Useful for FlutterJNI injections during
* tests.
*/
public static class Factory {
/** @return a {@link FlutterJNI} instance. */
public FlutterJNI provideFlutterJNI() {
return new FlutterJNI();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ public FlutterTextUtils(FlutterJNI flutterJNI) {
}

public boolean isEmoji(int codePoint) {
return flutterJNI.nativeFlutterTextUtilsIsEmoji(codePoint);
return flutterJNI.isCodePointEmoji(codePoint);
}

public boolean isEmojiModifier(int codePoint) {
return flutterJNI.nativeFlutterTextUtilsIsEmojiModifier(codePoint);
return flutterJNI.isCodePointEmojiModifier(codePoint);
}

public boolean isEmojiModifierBase(int codePoint) {
return flutterJNI.nativeFlutterTextUtilsIsEmojiModifierBase(codePoint);
return flutterJNI.isCodePointEmojiModifierBase(codePoint);
}

public boolean isVariationSelector(int codePoint) {
return flutterJNI.nativeFlutterTextUtilsIsVariationSelector(codePoint);
return flutterJNI.isCodePointVariantSelector(codePoint);
}

public boolean isRegionalIndicatorSymbol(int codePoint) {
return flutterJNI.nativeFlutterTextUtilsIsRegionalIndicator(codePoint);
return flutterJNI.isCodePointRegionalIndicator(codePoint);
}

public boolean isTagSpecChar(int codePoint) {
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/android/io/flutter/view/VsyncWaiter.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public void doFrame(long frameTimeNanos) {
if (delay < 0) {
delay = 0;
}
flutterJNI.nativeOnVsync(delay, refreshPeriodNanos, cookie);
flutterJNI.onVsync(delay, refreshPeriodNanos, cookie);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class FlutterInjectorTest {
public void setUp() {
// Since the intent is to have a convenient static class to use for production.
FlutterInjector.reset();
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
}

@After
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Matchers.notNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
Expand Down Expand Up @@ -230,7 +230,7 @@ public void itGivesHostAnOpportunityToConfigureFlutterSurfaceView() {
delegate.onCreateView(null, null, null, 0, true);

// Verify that the host was asked to configure a FlutterSurfaceView.
verify(mockHost, times(1)).onFlutterSurfaceViewCreated(notNull(FlutterSurfaceView.class));
verify(mockHost, times(1)).onFlutterSurfaceViewCreated(isNotNull());
}

@Test
Expand Down Expand Up @@ -259,7 +259,7 @@ public void itGivesHostAnOpportunityToConfigureFlutterTextureView() {
delegate.onCreateView(null, null, null, 0, false);

// Verify that the host was asked to configure a FlutterTextureView.
verify(customMockHost, times(1)).onFlutterTextureViewCreated(notNull(FlutterTextureView.class));
verify(customMockHost, times(1)).onFlutterTextureViewCreated(isNotNull());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.flutter.embedding.android;

import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.isNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -76,7 +76,7 @@ public class FlutterViewTest {

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
when(mockFlutterJni.isAttached()).thenReturn(true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class KeyChannelResponderTest {

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
channelResponder = new KeyChannelResponder(keyEventChannel);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private FlutterEngine mockFlutterEngine() {

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
when(mockFlutterJni.isAttached()).thenReturn(true);
mockEngine = mockFlutterEngine();
mockKeyEventChannel = mockEngine.getKeyEventChannel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class FlutterEngineGroupComponentTest {
public void setUp() {
FlutterInjector.reset();

MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
jniAttached = false;
when(mockflutterJNI.isAttached()).thenAnswer(invocation -> jniAttached);
doAnswer(invocation -> jniAttached = true).when(mockflutterJNI).attachToNative();
Expand Down Expand Up @@ -165,7 +165,7 @@ public void canCreateAndRunCustomEntrypoints() {
.runBundleAndSnapshotFromLibrary(
eq("some/path/to/flutter_assets"),
eq("other entrypoint"),
isNull(String.class),
isNull(),
any(AssetManager.class),
nullable(List.class));
}
Expand Down Expand Up @@ -215,7 +215,7 @@ public void canCreateAndRunWithCustomEntrypointArgs() {
.runBundleAndSnapshotFromLibrary(
nullable(String.class),
nullable(String.class),
isNull(String.class),
isNull(),
any(AssetManager.class),
eq(firstDartEntrypointArgs));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class FlutterEngineTest {

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
jniAttached = false;
when(flutterJNI.isAttached()).thenAnswer(invocation -> jniAttached);
doAnswer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -32,7 +32,7 @@ public class DartExecutorTest {
@Before
public void setUp() {
FlutterInjector.reset();
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
Expand Down
Loading