author | Jim Chen <nchen@mozilla.com> |
Thu, 04 Aug 2016 09:16:04 -0400 | |
changeset 308199 | 9a90e9fe5bf1c99dc1f049b259155c5f89e5e26d |
parent 308198 | 32966f97f82e60c65372de3a2ee7bb11d3c1cb10 |
child 308200 | d404ad0723c0585341d3f2400b6e0f672bc1b441 |
push id | 31092 |
push user | cbook@mozilla.com |
push date | Fri, 05 Aug 2016 10:16:59 +0000 |
treeherder | autoland@b97dd7dd3cb9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | snorp |
bugs | 1288838 |
milestone | 51.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/java/org/mozilla/gecko/Telemetry.java +++ b/mobile/android/base/java/org/mozilla/gecko/Telemetry.java @@ -1,16 +1,17 @@ /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko; import org.mozilla.gecko.annotation.RobocopTarget; +import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.TelemetryContract.Event; import org.mozilla.gecko.TelemetryContract.Method; import org.mozilla.gecko.TelemetryContract.Reason; import org.mozilla.gecko.TelemetryContract.Session; import android.os.SystemClock; import android.util.Log; @@ -23,35 +24,54 @@ import android.util.Log; * avoid timing a user activity when their phone is in their pocket! * * The majority of methods in this class are defined in terms of real time. */ @RobocopTarget public class Telemetry { private static final String LOGTAG = "Telemetry"; + @WrapForJNI(stubName="AddHistogram") + private static native void nativeAddHistogram(String name, int value); + @WrapForJNI(stubName="AddKeyedHistogram") + private static native void nativeAddKeyedHistogram(String name, String key, int value); + @WrapForJNI(stubName="StartUISession") + private static native void nativeStartUiSession(String name, long timestamp); + @WrapForJNI(stubName="StopUISession") + private static native void nativeStopUiSession(String name, String reason, long timestamp); + @WrapForJNI(stubName="AddUIEvent") + private static native void nativeAddUiEvent(String action, String method, + long timestamp, String extras); + public static long uptime() { return SystemClock.uptimeMillis(); } public static long realtime() { return SystemClock.elapsedRealtime(); } // Define new histograms in: // toolkit/components/telemetry/Histograms.json public static void addToHistogram(String name, int value) { - GeckoEvent event = GeckoEvent.createTelemetryHistogramAddEvent(name, value); - GeckoAppShell.sendEventToGecko(event); + if (GeckoThread.isRunning()) { + nativeAddHistogram(name, value); + } else { + GeckoThread.queueNativeCall(Telemetry.class, "nativeAddHistogram", + String.class, name, value); + } } - public static void addToKeyedHistogram(String histogram, String keyName, int value) { - GeckoEvent event = GeckoEvent.createTelemetryKeyedHistogramAddEvent(histogram, - keyName, value); - GeckoAppShell.sendEventToGecko(event); + public static void addToKeyedHistogram(String name, String key, int value) { + if (GeckoThread.isRunning()) { + nativeAddKeyedHistogram(name, key, value); + } else { + GeckoThread.queueNativeCall(Telemetry.class, "nativeAddKeyedHistogram", + String.class, name, String.class, key, value); + } } public abstract static class Timer { private final long mStartTime; private final String mName; private volatile boolean mHasFinished; private volatile long mElapsed = -1; @@ -116,33 +136,40 @@ public class Telemetry { return Telemetry.uptime(); } } public static void startUISession(final Session session, final String sessionNameSuffix) { final String sessionName = getSessionName(session, sessionNameSuffix); Log.d(LOGTAG, "StartUISession: " + sessionName); - final GeckoEvent geckoEvent = - GeckoEvent.createTelemetryUISessionStartEvent(sessionName, realtime()); - GeckoAppShell.sendEventToGecko(geckoEvent); + if (GeckoThread.isRunning()) { + nativeStartUiSession(sessionName, realtime()); + } else { + GeckoThread.queueNativeCall(Telemetry.class, "nativeStartUiSession", + String.class, sessionName, realtime()); + } } public static void startUISession(final Session session) { startUISession(session, null); } public static void stopUISession(final Session session, final String sessionNameSuffix, final Reason reason) { final String sessionName = getSessionName(session, sessionNameSuffix); Log.d(LOGTAG, "StopUISession: " + sessionName + ", reason=" + reason); - final GeckoEvent geckoEvent = GeckoEvent.createTelemetryUISessionStopEvent( - sessionName, reason.toString(), realtime()); - GeckoAppShell.sendEventToGecko(geckoEvent); + if (GeckoThread.isRunning()) { + nativeStopUiSession(sessionName, reason.toString(), realtime()); + } else { + GeckoThread.queueNativeCall(Telemetry.class, "nativeStopUiSession", + String.class, sessionName, + String.class, reason.toString(), realtime()); + } } public static void stopUISession(final Session session, final Reason reason) { stopUISession(session, null, reason); } public static void stopUISession(final Session session, final String sessionNameSuffix) { stopUISession(session, sessionNameSuffix, Reason.NONE); @@ -169,19 +196,23 @@ public class Telemetry { throw new IllegalArgumentException("Expected non-null method - use Method.NONE?"); } if (!AppConstants.RELEASE_BUILD) { final String logString = "SendUIEvent: event = " + eventName + " method = " + method + " timestamp = " + timestamp + " extras = " + extras; Log.d(LOGTAG, logString); } - final GeckoEvent geckoEvent = GeckoEvent.createTelemetryUIEvent( - eventName, method.toString(), timestamp, extras); - GeckoAppShell.sendEventToGecko(geckoEvent); + if (GeckoThread.isRunning()) { + nativeAddUiEvent(eventName, method.toString(), timestamp, extras); + } else { + GeckoThread.queueNativeCall(Telemetry.class, "nativeAddUiEvent", + String.class, eventName, String.class, method.toString(), + timestamp, String.class, extras); + } } public static void sendUIEvent(final Event event, final Method method, final long timestamp, final String extras) { sendUIEvent(event.toString(), method, timestamp, extras); } public static void sendUIEvent(final Event event, final Method method, final long timestamp) {
--- a/mobile/android/tests/browser/robocop/testUITelemetry.js +++ b/mobile/android/tests/browser/robocop/testUITelemetry.js @@ -12,18 +12,17 @@ Cu.import("resource://gre/modules/Servic const EVENT_TEST1 = "_test_event_1.1"; const EVENT_TEST2 = "_test_event_2.1"; const EVENT_TEST3 = "_test_event_3.1"; const EVENT_TEST4 = "_test_event_4.1"; const METHOD_TEST1 = "_test_method_1"; const METHOD_TEST2 = "_test_method_2"; -// Method.NONE is converted to an empty string after a few JSON stringifications -const METHOD_NONE = ""; +const METHOD_NONE = null; const REASON_TEST1 = "_test_reason_1"; const REASON_TEST2 = "_test_reason_2"; const SESSION_STARTED_TWICE = "_test_session_started_twice.1"; const SESSION_STOPPED_TWICE = "_test_session_stopped_twice.1"; function do_check_array_eq(a1, a2) {
new file mode 100644 --- /dev/null +++ b/widget/android/Telemetry.h @@ -0,0 +1,101 @@ +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_widget_Telemetry_h__ +#define mozilla_widget_Telemetry_h__ + +#include "GeneratedJNINatives.h" +#include "nsAppShell.h" +#include "nsIAndroidBridge.h" + +#include "mozilla/Telemetry.h" + +namespace mozilla { +namespace widget { + +class Telemetry final + : public java::Telemetry::Natives<Telemetry> + , public UsesGeckoThreadProxy +{ + Telemetry() = delete; + + static already_AddRefed<nsIUITelemetryObserver> + GetObserver() + { + nsAppShell* const appShell = nsAppShell::Get(); + if (!appShell) { + return nullptr; + } + + nsCOMPtr<nsIAndroidBrowserApp> browserApp = appShell->GetBrowserApp(); + nsCOMPtr<nsIUITelemetryObserver> obs; + + if (!browserApp || NS_FAILED(browserApp->GetUITelemetryObserver( + getter_AddRefs(obs))) || !obs) { + return nullptr; + } + + return obs.forget(); + } + +public: + static void + AddHistogram(jni::String::Param aName, int32_t aValue) + { + MOZ_ASSERT(aName); + mozilla::Telemetry::Accumulate(aName->ToCString().get(), aValue); + } + + static void + AddKeyedHistogram(jni::String::Param aName, jni::String::Param aKey, + int32_t aValue) + { + MOZ_ASSERT(aName && aKey); + mozilla::Telemetry::Accumulate(aName->ToCString().get(), + aKey->ToCString(), aValue); + } + + static void + StartUISession(jni::String::Param aName, int64_t aTimestamp) + { + MOZ_ASSERT(aName); + nsCOMPtr<nsIUITelemetryObserver> obs = GetObserver(); + if (obs) { + obs->StartSession(aName->ToString().get(), aTimestamp); + } + } + + static void + StopUISession(jni::String::Param aName, jni::String::Param aReason, + int64_t aTimestamp) + { + MOZ_ASSERT(aName); + nsCOMPtr<nsIUITelemetryObserver> obs = GetObserver(); + if (obs) { + obs->StopSession(aName->ToString().get(), + aReason ? aReason->ToString().get() : nullptr, + aTimestamp); + } + } + + static void + AddUIEvent(jni::String::Param aAction, jni::String::Param aMethod, + int64_t aTimestamp, jni::String::Param aExtras) + { + MOZ_ASSERT(aAction); + nsCOMPtr<nsIUITelemetryObserver> obs = GetObserver(); + if (obs) { + obs->AddEvent(aAction->ToString().get(), + aMethod ? aMethod->ToString().get() : nullptr, + aTimestamp, + aExtras ? aExtras->ToString().get() : nullptr); + } + } +}; + +} // namespace widget +} // namespace mozilla + +#endif // mozilla_widget_Telemetry_h__
--- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -57,16 +57,17 @@ #ifdef MOZ_LOGGING #include "mozilla/Logging.h" #endif #include "ANRReporter.h" #include "GeckoNetworkManager.h" #include "GeckoScreenOrientation.h" #include "PrefsHelper.h" +#include "Telemetry.h" #include "ThumbnailHelper.h" #ifdef DEBUG_ANDROID_EVENTS #define EVLOG(args...) ALOG(args) #else #define EVLOG(args...) do { } while (0) #endif @@ -347,16 +348,17 @@ nsAppShell::nsAppShell() // Initialize JNI and Set the corresponding state in GeckoThread. AndroidBridge::ConstructBridge(); GeckoAppShellSupport::Init(); GeckoThreadSupport::Init(); mozilla::ANRReporter::Init(); mozilla::GeckoNetworkManager::Init(); mozilla::GeckoScreenOrientation::Init(); mozilla::PrefsHelper::Init(); + mozilla::widget::Telemetry::Init(); mozilla::ThumbnailHelper::Init(); nsWindow::InitNatives(); java::GeckoThread::SetState(java::GeckoThread::State::JNI_READY()); } sPowerManagerService = do_GetService(POWERMANAGERSERVICE_CONTRACTID);
--- a/widget/android/nsIAndroidBridge.idl +++ b/widget/android/nsIAndroidBridge.idl @@ -10,23 +10,23 @@ interface mozIDOMWindowProxy; interface nsIBrowserTab : nsISupports { readonly attribute mozIDOMWindowProxy window; readonly attribute float scale; }; [scriptable, uuid(08426a73-e70b-4680-9282-630932e2b2bb)] interface nsIUITelemetryObserver : nsISupports { void startSession(in wstring name, - in unsigned long timestamp); + in long long timestamp); void stopSession(in wstring name, in wstring reason, - in unsigned long timestamp); + in long long timestamp); void addEvent(in wstring action, in wstring method, - in unsigned long timestamp, + in long long timestamp, in wstring extras); }; [scriptable, uuid(0370450f-2e9c-4d16-b333-8ca6ce31a5ff)] interface nsIAndroidBrowserApp : nsISupports { readonly attribute nsIBrowserTab selectedTab; nsIBrowserTab getBrowserTab(in int32_t tabId); nsIUITelemetryObserver getUITelemetryObserver();