diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt index 92b2446cc559..da83f7cd713d 100644 --- a/mobile/android/geckoview/api.txt +++ b/mobile/android/geckoview/api.txt @@ -329,6 +329,7 @@ package org.mozilla.geckoview { method public boolean getRemoteDebuggingEnabled(); method @Nullable public GeckoRuntime getRuntime(); method @Nullable public Rect getScreenSizeOverride(); + method @Nullable public RuntimeTelemetry.Delegate getTelemetryDelegate(); method public boolean getUseContentProcessHint(); method public boolean getUseMaxScreenDepth(); method public boolean getWebFontsEnabled(); @@ -376,6 +377,7 @@ package org.mozilla.geckoview { method @NonNull public GeckoRuntimeSettings.Builder preferredColorScheme(int); method @NonNull public GeckoRuntimeSettings.Builder remoteDebuggingEnabled(boolean); method @NonNull public GeckoRuntimeSettings.Builder screenSizeOverride(int, int); + method @NonNull public GeckoRuntimeSettings.Builder telemetryDelegate(@NonNull RuntimeTelemetry.Delegate); method @NonNull public GeckoRuntimeSettings.Builder useContentProcessHint(boolean); method @NonNull public GeckoRuntimeSettings.Builder useMaxScreenDepth(boolean); method @NonNull public GeckoRuntimeSettings.Builder webFontsEnabled(boolean); @@ -1073,6 +1075,16 @@ package org.mozilla.geckoview { method @AnyThread @NonNull public GeckoResult getSnapshots(boolean); } + public static interface RuntimeTelemetry.Delegate { + method @AnyThread default public void onTelemetryReceived(@NonNull RuntimeTelemetry.Metric); + } + + public static class RuntimeTelemetry.Metric { + ctor protected Metric(); + field @NonNull public final String name; + field @NonNull public final long[] values; + } + public class ScreenLength { method @NonNull @AnyThread public static ScreenLength bottom(); method @NonNull @AnyThread public static ScreenLength fromPixels(double); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java index e3fb978ffac4..a61895f384d7 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java @@ -375,6 +375,21 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { getSettings().mGlMsaaLevel.set(level); return this; } + + /** + * Add a {@link RuntimeTelemetry.Delegate} instance to this + * GeckoRuntime. This delegate can be used by the app to receive + * streaming telemetry data from GeckoView. + * + * @param delegate the delegate that will handle telemetry + * @return The builder instance. + */ + public @NonNull Builder telemetryDelegate( + final @NonNull RuntimeTelemetry.Delegate delegate) { + getSettings().mTelemetryProxy = new RuntimeTelemetry.Proxy(delegate); + getSettings().mTelemetryEnabled.set(true); + return this; + } } private GeckoRuntime mRuntime; @@ -411,6 +426,8 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { "apz.allow_double_tap_zooming", true); /* package */ final Pref mGlMsaaLevel = new Pref<>( "gl.msaa-level", 0); + /* package */ final Pref mTelemetryEnabled = new Pref<>( + "toolkit.telemetry.geckoview.streaming", false); /* package */ boolean mDebugPause; /* package */ boolean mUseMaxScreenDepth; @@ -420,6 +437,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { /* package */ int mScreenHeightOverride; /* package */ Class mCrashHandler; /* package */ String[] mRequestedLocales; + /* package */ RuntimeTelemetry.Proxy mTelemetryProxy; /** * Attach and commit the settings to the given runtime. @@ -471,6 +489,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { mCrashHandler = settings.mCrashHandler; mRequestedLocales = settings.mRequestedLocales; mConfigFilePath = settings.mConfigFilePath; + mTelemetryProxy = settings.mTelemetryProxy; } /* package */ void commit() { @@ -979,6 +998,10 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { return this; } + public @Nullable RuntimeTelemetry.Delegate getTelemetryDelegate() { + return mTelemetryProxy.getDelegate(); + } + @Override // Parcelable public void writeToParcel(final Parcel out, final int flags) { super.writeToParcel(out, flags); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java index 53f3510ae6ec..53625e4f2ca9 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java @@ -9,10 +9,16 @@ package org.mozilla.geckoview; import android.support.annotation.AnyThread; import android.support.annotation.NonNull; +import java.util.Arrays; + import org.json.JSONException; import org.json.JSONObject; + +import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.util.GeckoBundle; +import org.mozilla.gecko.mozglue.JNIObject; +import org.mozilla.gecko.GeckoThread; /** * The telemetry API gives access to telemetry data of the Gecko runtime. @@ -57,4 +63,98 @@ public final class RuntimeTelemetry { return result; } + + /** + * The runtime telemetry metric object. + */ + public static class Metric { + /** + * The runtime metric name. + */ + public final @NonNull String name; + + /** + * The metric values. + */ + public final @NonNull long[] values; + + /* package */ Metric(final String name, final long[] values) { + this.name = name; + this.values = values; + } + + @Override + public String toString() { + return "name: " + name + ", values: " + Arrays.toString(values); + } + + protected Metric() { + this.name = null; + this.values = null; + } + } + + /** + * The runtime telemetry delegate. + * Implement this if you want to receive runtime (Gecko) telemetry and + * attach it via {@link GeckoRuntimeSettings.Builder#telemetryDelegate}. + */ + public interface Delegate { + /** + * A runtime telemetry metric has been received. + * + * @param metric The runtime metric details. + */ + @AnyThread + default void onTelemetryReceived(final @NonNull Metric metric) {} + } + + // The proxy connects to telemetry core and forwards telemetry events + // to the attached delegate. + /* package */ final static class Proxy extends JNIObject { + private final Delegate mDelegate; + + public Proxy(final @NonNull Delegate delegate) { + mDelegate = delegate; + // We might want to remove implicit attaching in future. + attach(); + } + + // Attach to current runtime. + // We might have different mechanics of attaching to specific runtimes + // in future, for which case we should split the delegate assignment in + // the setup phase from the attaching. + public void attach() { + if (GeckoThread.isRunning()) { + registerDelegateProxy(this); + } else { + GeckoThread.queueNativeCall( + Proxy.class, "registerDelegateProxy", + Proxy.class, this); + } + } + + public @NonNull Delegate getDelegate() { + return mDelegate; + } + + @WrapForJNI(dispatchTo = "gecko") + private static native void registerDelegateProxy(Proxy proxy); + + @WrapForJNI(calledFrom = "gecko") + /* package */ void dispatchTelemetry( + final String name, final long[] values) { + if (mDelegate == null) { + // TODO throw? + return; + } + mDelegate.onTelemetryReceived(new Metric(name, values)); + } + + @Override // JNIObject + protected void disposeNative() { + // We don't hold native references. + throw new UnsupportedOperationException(); + } + } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md index 7914c9f873de..a47b57821069 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md @@ -29,6 +29,8 @@ exclude: true a link and then opening that in a new `GeckoSession`. - Added capture parameter to [`onFilePrompt`][70.9] and corresponding [`CAPTURE_TYPE_*`][70.7] constants. - Complete rewrite of [`PromptDelegate`][70.11]. +- Added [`RuntimeTelemetry.Delegate`][70.12] that receives streaming telemetry + data from GeckoView. [70.1]: {{javadoc_uri}}/GeckoSessionSettings.Builder.html#contextId-java.lang.String- [70.2]: {{javadoc_uri}}/StorageController.html#clearDataForSessionContext-java.lang.String- @@ -41,6 +43,7 @@ exclude: true [70.9]: {{javadoc_uri}}/GeckoSession.PromptDelegate.html#onFilePrompt-org.mozilla.geckoview.GeckoSession-java.lang.String-int-java.lang.String:A-int-org.mozilla.geckoview.GeckoSession.PromptDelegate.FileCallback- [70.10]: {{javadoc_uri}}/GeckoView.html#setSession-org.mozilla.geckoview.GeckoSession- [70.11]: {{javadoc_uri}}/GeckoSession.PromptDelegate.html +[70.12]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html ## v69 - Modified behavior of ['setAutomaticFontSizeAdjustment'][69.1] so that it no @@ -293,4 +296,4 @@ exclude: true [65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String- [65.25]: {{javadoc_uri}}/GeckoResult.html -[api-version]: 4550b507a55bdf91d21960209b66f893f4b5b317 +[api-version]: 00e5a05a0d16a0992b2044090e585031b80093c4