• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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