1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.metrics; 6 7 import org.chromium.base.ThreadUtils; 8 import org.chromium.base.VisibleForTesting; 9 import org.chromium.base.annotations.CalledByNative; 10 import org.chromium.base.annotations.JNINamespace; 11 12 /** 13 * Java API for recording UMA actions. 14 * 15 * WARNINGS: 16 * JNI calls are relatively costly - avoid using in performance-critical code. 17 * 18 * We use a script (extract_actions.py) to scan the source code and extract actions. A string 19 * literal (not a variable) must be passed to record(). 20 */ 21 @JNINamespace("base::android") 22 public class RecordUserAction { 23 private static Throwable sDisabledBy; 24 25 /** 26 * Tests may not have native initialized, so they may need to disable metrics. The value should 27 * be reset after the test done, to avoid carrying over state to unrelated tests. 28 */ 29 @VisibleForTesting setDisabledForTests(boolean disabled)30 public static void setDisabledForTests(boolean disabled) { 31 if (disabled && sDisabledBy != null) { 32 throw new IllegalStateException("UserActions are already disabled.", sDisabledBy); 33 } 34 sDisabledBy = disabled ? new Throwable() : null; 35 } 36 record(final String action)37 public static void record(final String action) { 38 if (sDisabledBy != null) return; 39 40 if (ThreadUtils.runningOnUiThread()) { 41 nativeRecordUserAction(action); 42 return; 43 } 44 45 ThreadUtils.runOnUiThread(new Runnable() { 46 @Override 47 public void run() { 48 nativeRecordUserAction(action); 49 } 50 }); 51 } 52 53 /** 54 * Interface to a class that receives a callback for each UserAction that is recorded. 55 */ 56 public interface UserActionCallback { 57 @CalledByNative("UserActionCallback") onActionRecorded(String action)58 void onActionRecorded(String action); 59 } 60 61 private static long sNativeActionCallback; 62 63 /** 64 * Register a callback that is executed for each recorded UserAction. 65 * Only one callback can be registered at a time. 66 * The callback has to be unregistered using removeActionCallbackForTesting(). 67 */ setActionCallbackForTesting(UserActionCallback callback)68 public static void setActionCallbackForTesting(UserActionCallback callback) { 69 assert sNativeActionCallback == 0; 70 sNativeActionCallback = nativeAddActionCallbackForTesting(callback); 71 } 72 73 /** 74 * Unregister the UserActionCallback. 75 */ removeActionCallbackForTesting()76 public static void removeActionCallbackForTesting() { 77 assert sNativeActionCallback != 0; 78 nativeRemoveActionCallbackForTesting(sNativeActionCallback); 79 sNativeActionCallback = 0; 80 } 81 nativeRecordUserAction(String action)82 private static native void nativeRecordUserAction(String action); nativeAddActionCallbackForTesting(UserActionCallback callback)83 private static native long nativeAddActionCallbackForTesting(UserActionCallback callback); nativeRemoveActionCallbackForTesting(long callbackId)84 private static native void nativeRemoveActionCallbackForTesting(long callbackId); 85 } 86