未验证 提交 a2db2ea6 编写于 作者: M Matt Carroll 提交者: GitHub

Android Embedding Refactor PR35: Ensure all JNI methods are in FlutterJNI (#34751). (#9391)

上级 0c874c62
......@@ -176,7 +176,7 @@ bool FlutterMain::Register(JNIEnv* env) {
},
};
jclass clazz = env->FindClass("io/flutter/view/FlutterMain");
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
if (clazz == nullptr) {
return false;
......
......@@ -4,6 +4,7 @@
package io.flutter.embedding.engine;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
......@@ -18,14 +19,14 @@ import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set;
import io.flutter.BuildConfig;
import io.flutter.Log;
import io.flutter.embedding.engine.dart.PlatformMessageHandler;
import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener;
import io.flutter.embedding.engine.dart.PlatformMessageHandler;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.view.AccessibilityBridge;
import io.flutter.view.FlutterCallbackInformation;
/**
* Interface between Flutter embedding's Java code and Flutter engine's C/C++ code.
......@@ -93,18 +94,64 @@ import io.flutter.view.AccessibilityBridge;
public class FlutterJNI {
private static final String TAG = "FlutterJNI";
@Nullable
private static AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate;
// This should also be updated by FlutterView when it is attached to a Display.
// The initial value of 0.0 indicates unknown refresh rate.
private static float refreshRateFPS = 0.0f;
// This is set from native code via JNI.
@Nullable
private static String observatoryUri;
// TODO(mattcarroll): add javadocs
public static native void nativeInit(
@NonNull Context context,
@NonNull String[] args,
@Nullable String bundlePath,
@NonNull String appStoragePath,
@NonNull String engineCachesPath
);
// TODO(mattcarroll): add javadocs
public static native void nativeRecordStartTimestamp(long initTimeMillis);
// TODO(mattcarroll): add javadocs
@UiThread
public static native boolean nativeGetIsSoftwareRenderingEnabled();
@Nullable
// TODO(mattcarroll): add javadocs
public static String getObservatoryUri() {
return observatoryUri;
}
public static void setRefreshRateFPS(float refreshRateFPS) {
FlutterJNI.refreshRateFPS = refreshRateFPS;
}
// TODO(mattcarroll): add javadocs
public static void setAsyncWaitForVsyncDelegate(@Nullable AsyncWaitForVsyncDelegate delegate) {
asyncWaitForVsyncDelegate = delegate;
}
// TODO(mattcarroll): add javadocs
// Called by native.
private static void asyncWaitForVsync(final long cookie) {
if (asyncWaitForVsyncDelegate != null) {
asyncWaitForVsyncDelegate.asyncWaitForVsync(cookie);
} else {
throw new IllegalStateException("An AsyncWaitForVsyncDelegate must be registered with FlutterJNI before asyncWaitForVsync() is invoked.");
}
}
// TODO(mattcarroll): add javadocs
public static native void nativeOnVsync(long frameTimeNanos, long frameTargetTimeNanos, long cookie);
// TODO(mattcarroll): add javadocs
@NonNull
public static native FlutterCallbackInformation nativeLookupCallbackInformation(long handle);
@Nullable
private Long nativePlatformViewId;
@Nullable
......@@ -772,4 +819,8 @@ public class FlutterJNI {
*/
void updateSemantics(@NonNull ByteBuffer buffer, @NonNull String[] strings);
}
public interface AsyncWaitForVsyncDelegate {
void asyncWaitForVsync(final long cookie);
}
}
......@@ -4,6 +4,10 @@
package io.flutter.view;
import android.support.annotation.NonNull;
import io.flutter.embedding.engine.FlutterJNI;
/**
* A class representing information for a callback registered using
* `PluginUtilities` from `dart:ui`.
......@@ -19,8 +23,9 @@ public final class FlutterCallbackInformation {
* `PluginUtilities.getCallbackHandle` in `dart:ui`.
* @return an instance of FlutterCallbackInformation for the provided handle.
*/
@NonNull
public static FlutterCallbackInformation lookupCallbackInformation(long handle) {
return nativeLookupCallbackInformation(handle);
return FlutterJNI.nativeLookupCallbackInformation(handle);
}
private FlutterCallbackInformation(String callbackName,
......@@ -29,6 +34,4 @@ public final class FlutterCallbackInformation {
this.callbackClassName = callbackClassName;
this.callbackLibraryPath = callbackLibraryPath;
}
private static native FlutterCallbackInformation nativeLookupCallbackInformation(long handle);
}
......@@ -15,7 +15,10 @@ import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.WindowManager;
import io.flutter.BuildConfig;
import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.util.PathUtils;
import java.io.File;
......@@ -118,13 +121,17 @@ public class FlutterMain {
System.loadLibrary("flutter");
VsyncWaiter
.getInstance((WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
.init();
// We record the initialization time using SystemClock because at the start of the
// initialization we have not yet loaded the native library to call into dart_tools_api.h.
// To get Timeline timestamp of the start of initialization we simply subtract the delta
// from the Timeline timestamp at the current moment (the assumption is that the overhead
// of the JNI call is negligible).
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
nativeRecordStartTimestamp(initTimeMillis);
FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
}
/**
......@@ -172,7 +179,7 @@ public class FlutterMain {
String appBundlePath = findAppBundlePath(applicationContext);
String appStoragePath = PathUtils.getFilesDir(applicationContext);
String engineCachesPath = PathUtils.getCacheDirectory(applicationContext);
nativeInit(applicationContext, shellArgs.toArray(new String[0]),
FlutterJNI.nativeInit(applicationContext, shellArgs.toArray(new String[0]),
appBundlePath, appStoragePath, engineCachesPath);
sInitialized = true;
......@@ -218,9 +225,6 @@ public class FlutterMain {
}).start();
}
private static native void nativeInit(Context context, String[] args, String bundlePath, String appStoragePath, String engineCachesPath);
private static native void nativeRecordStartTimestamp(long initTimeMillis);
@NonNull
private static ApplicationInfo getApplicationInfo(@NonNull Context applicationContext) {
try {
......
......@@ -652,11 +652,6 @@ public class FlutterView extends SurfaceView implements BinaryMessenger, Texture
mMetrics.physicalHeight, mMetrics.physicalPaddingTop, mMetrics.physicalPaddingRight,
mMetrics.physicalPaddingBottom, mMetrics.physicalPaddingLeft, mMetrics.physicalViewInsetTop,
mMetrics.physicalViewInsetRight, mMetrics.physicalViewInsetBottom, mMetrics.physicalViewInsetLeft);
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
float fps = wm.getDefaultDisplay().getRefreshRate();
VsyncWaiter.refreshPeriodNanos = (long) (1000000000.0 / fps);
VsyncWaiter.refreshRateFPS = fps;
}
// Called by native to update the semantics/accessibility tree.
......
......@@ -4,24 +4,51 @@
package io.flutter.view;
import android.support.annotation.NonNull;
import android.view.Choreographer;
import android.view.WindowManager;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterJNI;
// TODO(mattcarroll): add javadoc.
public class VsyncWaiter {
// This estimate will be updated by FlutterView when it is attached to a Display.
public static long refreshPeriodNanos = 1000000000 / 60;
// This should also be updated by FlutterView when it is attached to a Display.
// The initial value of 0.0 indicates unknown refresh rate.
public static float refreshRateFPS = 0.0f;
public static void asyncWaitForVsync(final long cookie) {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
}
});
private static VsyncWaiter instance;
@NonNull
public static VsyncWaiter getInstance(@NonNull WindowManager windowManager) {
if (instance == null) {
instance = new VsyncWaiter(windowManager);
}
return instance;
}
@NonNull
private final WindowManager windowManager;
private final FlutterJNI.AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate = new FlutterJNI.AsyncWaitForVsyncDelegate() {
@Override
public void asyncWaitForVsync(long cookie) {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
float fps = windowManager.getDefaultDisplay().getRefreshRate();
long refreshPeriodNanos = (long) (1000000000.0 / fps);
FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
}
});
}
};
private VsyncWaiter(@NonNull WindowManager windowManager) {
this.windowManager = windowManager;
}
private static native void nativeOnVsync(long frameTimeNanos, long frameTargetTimeNanos, long cookie);
public void init() {
FlutterJNI.setAsyncWaitForVsyncDelegate(asyncWaitForVsyncDelegate);
// TODO(mattcarroll): look into moving FPS reporting to a plugin
float fps = windowManager.getDefaultDisplay().getRefreshRate();
FlutterJNI.setRefreshRateFPS(fps);
}
}
......@@ -637,6 +637,13 @@ bool RegisterApi(JNIEnv* env) {
.signature = "(JJ)V",
.fnPtr = reinterpret_cast<void*>(&UnregisterTexture),
},
// Methods for Dart callback functionality.
{
.name = "nativeLookupCallbackInformation",
.signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
.fnPtr = reinterpret_cast<void*>(&LookupCallbackInformation),
},
};
if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods,
......@@ -735,21 +742,6 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
return false;
}
static const JNINativeMethod callback_info_methods[] = {
{
.name = "nativeLookupCallbackInformation",
.signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
.fnPtr = reinterpret_cast<void*>(&LookupCallbackInformation),
},
};
if (env->RegisterNatives(g_flutter_callback_info_class->obj(),
callback_info_methods,
fml::size(callback_info_methods)) != 0) {
FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterCallbackInfo";
return false;
}
g_attach_to_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "attachToGLContext", "(I)V");
......
......@@ -87,7 +87,7 @@ bool VsyncWaiterAndroid::Register(JNIEnv* env) {
.fnPtr = reinterpret_cast<void*>(&OnNativeVsync),
}};
jclass clazz = env->FindClass("io/flutter/view/VsyncWaiter");
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
if (clazz == nullptr) {
return false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册