• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.settingslib.core.instrumentation;
17 
18 import android.app.Activity;
19 import android.app.settings.SettingsEnums;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.text.TextUtils;
24 import android.util.Pair;
25 
26 import androidx.annotation.NonNull;
27 import androidx.preference.Preference;
28 
29 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 
34 /**
35  * FeatureProvider for metrics.
36  */
37 public class MetricsFeatureProvider {
38     /**
39      * The metrics category constant for logging source when a setting fragment is opened.
40      */
41     public static final String EXTRA_SOURCE_METRICS_CATEGORY = ":settings:source_metrics";
42 
43     protected List<LogWriter> mLoggerWriters;
44 
MetricsFeatureProvider()45     public MetricsFeatureProvider() {
46         mLoggerWriters = new ArrayList<>();
47         installLogWriters();
48     }
49 
installLogWriters()50     protected void installLogWriters() {
51         mLoggerWriters.add(new EventLogWriter());
52     }
53 
54     /**
55      * Returns the attribution id for specified activity. If no attribution is set, returns {@link
56      * SettingsEnums#PAGE_UNKNOWN}.
57      *
58      * <p/> Attribution is a {@link SettingsEnums} page id that indicates where the specified
59      * activity is launched from.
60      */
getAttribution(Activity activity)61     public int getAttribution(Activity activity) {
62         if (activity == null) {
63             return SettingsEnums.PAGE_UNKNOWN;
64         }
65         final Intent intent = activity.getIntent();
66         if (intent == null) {
67             return SettingsEnums.PAGE_UNKNOWN;
68         }
69         return intent.getIntExtra(EXTRA_SOURCE_METRICS_CATEGORY,
70                 SettingsEnums.PAGE_UNKNOWN);
71     }
72 
73     /**
74      * Logs an event when target page is visible.
75      *
76      * @param source from this page id to target page
77      * @param category the target page id
78      * @param latency the latency of target page creation
79      */
visible(Context context, int source, int category, int latency)80     public void visible(Context context, int source, int category, int latency) {
81         for (LogWriter writer : mLoggerWriters) {
82             writer.visible(context, source, category, latency);
83         }
84     }
85 
86     /**
87      * Logs an event when target page is hidden.
88      *
89      * @param category the target page id
90      * @param visibleTime the time spending on target page since being visible
91      */
hidden(Context context, int category, int visibleTime)92     public void hidden(Context context, int category, int visibleTime) {
93         for (LogWriter writer : mLoggerWriters) {
94             writer.hidden(context, category, visibleTime);
95         }
96     }
97 
98     /**
99      * Logs a simple action without page id or attribution
100      */
action(Context context, int category, Pair<Integer, Object>... taggedData)101     public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
102         for (LogWriter writer : mLoggerWriters) {
103             writer.action(context, category, taggedData);
104         }
105     }
106 
107     /**
108      * Logs a generic Settings event.
109      */
action(Context context, int category, String pkg)110     public void action(Context context, int category, String pkg) {
111         for (LogWriter writer : mLoggerWriters) {
112             writer.action(context, category, pkg);
113         }
114     }
115 
116     /**
117      * Logs a generic Settings event.
118      */
action(int attribution, int action, int pageId, String key, int value)119     public void action(int attribution, int action, int pageId, String key, int value) {
120         for (LogWriter writer : mLoggerWriters) {
121             writer.action(attribution, action, pageId, key, value);
122         }
123     }
124 
action(Context context, int category, int value)125     public void action(Context context, int category, int value) {
126         for (LogWriter writer : mLoggerWriters) {
127             writer.action(context, category, value);
128         }
129     }
130 
action(Context context, int category, boolean value)131     public void action(Context context, int category, boolean value) {
132         for (LogWriter writer : mLoggerWriters) {
133             writer.action(context, category, value);
134         }
135     }
136 
getMetricsCategory(Object object)137     public int getMetricsCategory(Object object) {
138         if (object == null || !(object instanceof Instrumentable)) {
139             return MetricsEvent.VIEW_UNKNOWN;
140         }
141         return ((Instrumentable) object).getMetricsCategory();
142     }
143 
144     /**
145      * Logs an event when the preference is clicked.
146      *
147      * @return true if the preference is loggable, otherwise false
148      */
logClickedPreference(@onNull Preference preference, int sourceMetricsCategory)149     public boolean logClickedPreference(@NonNull Preference preference, int sourceMetricsCategory) {
150         if (preference == null) {
151             return false;
152         }
153         return logSettingsTileClick(preference.getKey(), sourceMetricsCategory)
154                 || logStartedIntent(preference.getIntent(), sourceMetricsCategory)
155                 || logSettingsTileClick(preference.getFragment(), sourceMetricsCategory);
156     }
157 
158     /**
159      * Logs an event when the intent is started.
160      *
161      * @return true if the intent is loggable, otherwise false
162      */
logStartedIntent(Intent intent, int sourceMetricsCategory)163     public boolean logStartedIntent(Intent intent, int sourceMetricsCategory) {
164         if (intent == null) {
165             return false;
166         }
167         final ComponentName cn = intent.getComponent();
168         return logSettingsTileClick(cn != null ? cn.flattenToString() : intent.getAction(),
169                 sourceMetricsCategory);
170     }
171 
172     /**
173      * Logs an event when the intent is started by Profile select dialog.
174      *
175      * @return true if the intent is loggable, otherwise false
176      */
logStartedIntentWithProfile(Intent intent, int sourceMetricsCategory, boolean isWorkProfile)177     public boolean logStartedIntentWithProfile(Intent intent, int sourceMetricsCategory,
178             boolean isWorkProfile) {
179         if (intent == null) {
180             return false;
181         }
182         final ComponentName cn = intent.getComponent();
183         final String key = cn != null ? cn.flattenToString() : intent.getAction();
184         return logSettingsTileClick(key + (isWorkProfile ? "/work" : "/personal"),
185                 sourceMetricsCategory);
186     }
187 
188     /**
189      * Logs an event when the setting key is clicked.
190      *
191      * @return true if the key is loggable, otherwise false
192      */
logSettingsTileClick(String logKey, int sourceMetricsCategory)193     public boolean logSettingsTileClick(String logKey, int sourceMetricsCategory) {
194         if (TextUtils.isEmpty(logKey)) {
195             // Not loggable
196             return false;
197         }
198         action(sourceMetricsCategory,
199                 MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
200                 SettingsEnums.PAGE_UNKNOWN,
201                 logKey,
202                 0);
203         return true;
204     }
205 }
206