• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 
17 package com.android.intentresolver.logging;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.AdditionalMatchers.gt;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.anyBoolean;
24 import static org.mockito.ArgumentMatchers.anyInt;
25 import static org.mockito.ArgumentMatchers.anyString;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.ArgumentMatchers.isNull;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.verifyNoMoreInteractions;
31 
32 import android.content.Intent;
33 import android.metrics.LogMaker;
34 
35 import com.android.intentresolver.contentpreview.ContentPreviewType;
36 import com.android.intentresolver.logging.EventLogImpl.SharesheetStandardEvent;
37 import com.android.intentresolver.logging.EventLogImpl.SharesheetStartedEvent;
38 import com.android.intentresolver.logging.EventLogImpl.SharesheetTargetSelectedEvent;
39 import com.android.internal.logging.InstanceId;
40 import com.android.internal.logging.InstanceIdSequence;
41 import com.android.internal.logging.MetricsLogger;
42 import com.android.internal.logging.UiEventLogger;
43 import com.android.internal.logging.UiEventLogger.UiEventEnum;
44 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
45 import com.android.internal.util.FrameworkStatsLog;
46 
47 import org.junit.After;
48 import org.junit.Before;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.Mock;
53 import org.mockito.junit.MockitoJUnitRunner;
54 
55 @RunWith(MockitoJUnitRunner.class)
56 public final class EventLogImplTest {
57     @Mock private UiEventLogger mUiEventLog;
58     @Mock private FrameworkStatsLogger mFrameworkLog;
59     @Mock private MetricsLogger mMetricsLogger;
60 
61     private EventLogImpl mChooserLogger;
62 
63     private final InstanceIdSequence mSequence = EventLogImpl.newIdSequence();
64 
65     @Before
setUp()66     public void setUp() {
67         mChooserLogger = new EventLogImpl(mUiEventLog, mFrameworkLog, mMetricsLogger,
68                 mSequence.newInstanceId());
69     }
70 
71     @After
tearDown()72     public void tearDown() {
73         verifyNoMoreInteractions(mUiEventLog);
74         verifyNoMoreInteractions(mFrameworkLog);
75         verifyNoMoreInteractions(mMetricsLogger);
76     }
77 
78     @Test
testLogChooserActivityShown_personalProfile()79     public void testLogChooserActivityShown_personalProfile() {
80         final boolean isWorkProfile = false;
81         final String mimeType = "application/TestType";
82         final long systemCost = 456;
83 
84         mChooserLogger.logChooserActivityShown(isWorkProfile, mimeType, systemCost);
85 
86         ArgumentCaptor<LogMaker> eventCaptor = ArgumentCaptor.forClass(LogMaker.class);
87         verify(mMetricsLogger).write(eventCaptor.capture());
88         LogMaker event = eventCaptor.getValue();
89 
90         assertThat(event.getCategory()).isEqualTo(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
91         assertThat(event.getSubtype()).isEqualTo(MetricsEvent.PARENT_PROFILE);
92         assertThat(event.getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE)).isEqualTo(mimeType);
93         assertThat(event.getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS))
94                 .isEqualTo(systemCost);
95     }
96 
97     @Test
testLogChooserActivityShown_workProfile()98     public void testLogChooserActivityShown_workProfile() {
99         final boolean isWorkProfile = true;
100         final String mimeType = "application/TestType";
101         final long systemCost = 456;
102 
103         mChooserLogger.logChooserActivityShown(isWorkProfile, mimeType, systemCost);
104 
105         ArgumentCaptor<LogMaker> eventCaptor = ArgumentCaptor.forClass(LogMaker.class);
106         verify(mMetricsLogger).write(eventCaptor.capture());
107         LogMaker event = eventCaptor.getValue();
108 
109         assertThat(event.getCategory()).isEqualTo(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
110         assertThat(event.getSubtype()).isEqualTo(MetricsEvent.MANAGED_PROFILE);
111         assertThat(event.getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE)).isEqualTo(mimeType);
112         assertThat(event.getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS))
113                 .isEqualTo(systemCost);
114     }
115 
116     @Test
testLogShareStarted()117     public void testLogShareStarted() {
118         final String packageName = "com.test.foo";
119         final String mimeType = "text/plain";
120         final int appProvidedDirectTargets = 123;
121         final int appProvidedAppTargets = 456;
122         final boolean workProfile = true;
123         final int previewType = ContentPreviewType.CONTENT_PREVIEW_FILE;
124         final String intentAction = Intent.ACTION_SENDTO;
125         final int numCustomActions = 3;
126         final boolean modifyShareProvided = true;
127 
128         mChooserLogger.logShareStarted(
129                 packageName,
130                 mimeType,
131                 appProvidedDirectTargets,
132                 appProvidedAppTargets,
133                 workProfile,
134                 previewType,
135                 intentAction,
136                 numCustomActions,
137                 modifyShareProvided);
138 
139         verify(mFrameworkLog).write(
140                 eq(FrameworkStatsLog.SHARESHEET_STARTED),
141                 eq(SharesheetStartedEvent.SHARE_STARTED.getId()),
142                 eq(packageName),
143                 /* instanceId=*/ gt(0),
144                 eq(mimeType),
145                 eq(appProvidedDirectTargets),
146                 eq(appProvidedAppTargets),
147                 eq(workProfile),
148                 eq(FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE),
149                 eq(FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO),
150                 /* custom actions provided */ eq(numCustomActions),
151                 /* reselection action provided */ eq(modifyShareProvided));
152     }
153 
154     @Test
testLogShareTargetSelected()155     public void testLogShareTargetSelected() {
156         final int targetType = EventLogImpl.SELECTION_TYPE_SERVICE;
157         final String packageName = "com.test.foo";
158         final int positionPicked = 123;
159         final int directTargetAlsoRanked = -1;
160         final int callerTargetCount = 0;
161         final boolean isPinned = true;
162         final boolean isSuccessfullySelected = true;
163         final long selectionCost = 456;
164 
165         mChooserLogger.logShareTargetSelected(
166                 targetType,
167                 packageName,
168                 positionPicked,
169                 directTargetAlsoRanked,
170                 callerTargetCount,
171                 /* directTargetHashed= */ null,
172                 isPinned,
173                 isSuccessfullySelected,
174                 selectionCost);
175 
176         verify(mFrameworkLog).write(
177                 eq(FrameworkStatsLog.RANKING_SELECTED),
178                 eq(SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId()),
179                 eq(packageName),
180                 /* instanceId=*/ gt(0),
181                 eq(positionPicked),
182                 eq(isPinned));
183 
184         ArgumentCaptor<LogMaker> eventCaptor = ArgumentCaptor.forClass(LogMaker.class);
185         verify(mMetricsLogger).write(eventCaptor.capture());
186         LogMaker event = eventCaptor.getValue();
187         assertThat(event.getCategory()).isEqualTo(
188                 MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET);
189         assertThat(event.getSubtype()).isEqualTo(positionPicked);
190     }
191 
192     @Test
testLogActionSelected()193     public void testLogActionSelected() {
194         mChooserLogger.logActionSelected(EventLogImpl.SELECTION_TYPE_COPY);
195 
196         verify(mFrameworkLog).write(
197                 eq(FrameworkStatsLog.RANKING_SELECTED),
198                 eq(SharesheetTargetSelectedEvent.SHARESHEET_COPY_TARGET_SELECTED.getId()),
199                 eq(""),
200                 /* instanceId=*/ gt(0),
201                 eq(-1),
202                 eq(false));
203 
204         ArgumentCaptor<LogMaker> eventCaptor = ArgumentCaptor.forClass(LogMaker.class);
205         verify(mMetricsLogger).write(eventCaptor.capture());
206         LogMaker event = eventCaptor.getValue();
207         assertThat(event.getCategory()).isEqualTo(
208                 MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET);
209         assertThat(event.getSubtype()).isEqualTo(1);
210     }
211 
212     @Test
testLogCustomActionSelected()213     public void testLogCustomActionSelected() {
214         final int position = 4;
215         mChooserLogger.logCustomActionSelected(position);
216 
217         verify(mFrameworkLog).write(
218                 eq(FrameworkStatsLog.RANKING_SELECTED),
219                 eq(SharesheetTargetSelectedEvent.SHARESHEET_CUSTOM_ACTION_SELECTED.getId()),
220                 any(), anyInt(), eq(position), eq(false));
221     }
222 
223     @Test
testLogDirectShareTargetReceived()224     public void testLogDirectShareTargetReceived() {
225         final int category = MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER;
226         final int latency = 123;
227 
228         mChooserLogger.logDirectShareTargetReceived(category, latency);
229 
230         ArgumentCaptor<LogMaker> eventCaptor = ArgumentCaptor.forClass(LogMaker.class);
231         verify(mMetricsLogger).write(eventCaptor.capture());
232         LogMaker event = eventCaptor.getValue();
233         assertThat(event.getCategory()).isEqualTo(category);
234         assertThat(event.getSubtype()).isEqualTo(latency);
235     }
236 
237     @Test
testLogActionShareWithPreview()238     public void testLogActionShareWithPreview() {
239         final int previewType = ContentPreviewType.CONTENT_PREVIEW_TEXT;
240 
241         mChooserLogger.logActionShareWithPreview(previewType);
242 
243         ArgumentCaptor<LogMaker> eventCaptor = ArgumentCaptor.forClass(LogMaker.class);
244         verify(mMetricsLogger).write(eventCaptor.capture());
245         LogMaker event = eventCaptor.getValue();
246         assertThat(event.getCategory()).isEqualTo(MetricsEvent.ACTION_SHARE_WITH_PREVIEW);
247         assertThat(event.getSubtype()).isEqualTo(previewType);
248     }
249 
250     @Test
testLogSharesheetTriggered()251     public void testLogSharesheetTriggered() {
252         mChooserLogger.logSharesheetTriggered();
253         verify(mUiEventLog).logWithInstanceId(
254                 eq(SharesheetStandardEvent.SHARESHEET_TRIGGERED), eq(0), isNull(), any());
255     }
256 
257     @Test
testLogSharesheetAppLoadComplete()258     public void testLogSharesheetAppLoadComplete() {
259         mChooserLogger.logSharesheetAppLoadComplete();
260         verify(mUiEventLog).logWithInstanceId(
261                 eq(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE), eq(0), isNull(), any());
262     }
263 
264     @Test
testLogSharesheetDirectLoadComplete()265     public void testLogSharesheetDirectLoadComplete() {
266         mChooserLogger.logSharesheetDirectLoadComplete();
267         verify(mUiEventLog).logWithInstanceId(
268                 eq(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE),
269                 eq(0),
270                 isNull(),
271                 any());
272     }
273 
274     @Test
testLogSharesheetDirectLoadTimeout()275     public void testLogSharesheetDirectLoadTimeout() {
276         mChooserLogger.logSharesheetDirectLoadTimeout();
277         verify(mUiEventLog).logWithInstanceId(
278                 eq(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT), eq(0), isNull(), any());
279     }
280 
281     @Test
testLogSharesheetProfileChanged()282     public void testLogSharesheetProfileChanged() {
283         mChooserLogger.logSharesheetProfileChanged();
284         verify(mUiEventLog).logWithInstanceId(
285                 eq(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED), eq(0), isNull(), any());
286     }
287 
288     @Test
testLogSharesheetExpansionChanged_collapsed()289     public void testLogSharesheetExpansionChanged_collapsed() {
290         mChooserLogger.logSharesheetExpansionChanged(/* isCollapsed=*/ true);
291         verify(mUiEventLog).logWithInstanceId(
292                 eq(SharesheetStandardEvent.SHARESHEET_COLLAPSED), eq(0), isNull(), any());
293     }
294 
295     @Test
testLogSharesheetExpansionChanged_expanded()296     public void testLogSharesheetExpansionChanged_expanded() {
297         mChooserLogger.logSharesheetExpansionChanged(/* isCollapsed=*/ false);
298         verify(mUiEventLog).logWithInstanceId(
299                 eq(SharesheetStandardEvent.SHARESHEET_EXPANDED), eq(0), isNull(), any());
300     }
301 
302     @Test
testLogSharesheetAppShareRankingTimeout()303     public void testLogSharesheetAppShareRankingTimeout() {
304         mChooserLogger.logSharesheetAppShareRankingTimeout();
305         verify(mUiEventLog).logWithInstanceId(
306                 eq(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT),
307                 eq(0),
308                 isNull(),
309                 any());
310     }
311 
312     @Test
testLogSharesheetEmptyDirectShareRow()313     public void testLogSharesheetEmptyDirectShareRow() {
314         mChooserLogger.logSharesheetEmptyDirectShareRow();
315         verify(mUiEventLog).logWithInstanceId(
316                 eq(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW),
317                 eq(0),
318                 isNull(),
319                 any());
320     }
321 
322     @Test
testDifferentLoggerInstancesUseDifferentInstanceIds()323     public void testDifferentLoggerInstancesUseDifferentInstanceIds() {
324         ArgumentCaptor<Integer> idIntCaptor = ArgumentCaptor.forClass(Integer.class);
325         EventLogImpl chooserLogger2 =
326                 new EventLogImpl(mUiEventLog, mFrameworkLog, mMetricsLogger,
327                         mSequence.newInstanceId());
328 
329         final int targetType = EventLogImpl.SELECTION_TYPE_COPY;
330         final String packageName = "com.test.foo";
331         final int positionPicked = 123;
332         final int directTargetAlsoRanked = -1;
333         final int callerTargetCount = 0;
334         final boolean isPinned = true;
335         final boolean isSuccessfullySelected = true;
336         final long selectionCost = 456;
337 
338         mChooserLogger.logShareTargetSelected(
339                 targetType,
340                 packageName,
341                 positionPicked,
342                 directTargetAlsoRanked,
343                 callerTargetCount,
344                 /* directTargetHashed= */ null,
345                 isPinned,
346                 isSuccessfullySelected,
347                 selectionCost);
348 
349         chooserLogger2.logShareTargetSelected(
350                 targetType,
351                 packageName,
352                 positionPicked,
353                 directTargetAlsoRanked,
354                 callerTargetCount,
355                 /* directTargetHashed= */ null,
356                 isPinned,
357                 isSuccessfullySelected,
358                 selectionCost);
359 
360         verify(mFrameworkLog, times(2)).write(
361                 anyInt(), anyInt(), anyString(), idIntCaptor.capture(), anyInt(), anyBoolean());
362 
363         int id1 = idIntCaptor.getAllValues().get(0);
364         int id2 = idIntCaptor.getAllValues().get(1);
365 
366         assertThat(id1).isGreaterThan(0);
367         assertThat(id2).isGreaterThan(0);
368         assertThat(id1).isNotEqualTo(id2);
369     }
370 
371     @Test
testUiAndFrameworkEventsUseSameInstanceIdForSameLoggerInstance()372     public void testUiAndFrameworkEventsUseSameInstanceIdForSameLoggerInstance() {
373         ArgumentCaptor<Integer> idIntCaptor = ArgumentCaptor.forClass(Integer.class);
374         ArgumentCaptor<InstanceId> idObjectCaptor = ArgumentCaptor.forClass(InstanceId.class);
375 
376         final int targetType = EventLogImpl.SELECTION_TYPE_COPY;
377         final String packageName = "com.test.foo";
378         final int positionPicked = 123;
379         final int directTargetAlsoRanked = -1;
380         final int callerTargetCount = 0;
381         final boolean isPinned = true;
382         final boolean isSuccessfullySelected = true;
383         final long selectionCost = 456;
384 
385         mChooserLogger.logShareTargetSelected(
386                 targetType,
387                 packageName,
388                 positionPicked,
389                 directTargetAlsoRanked,
390                 callerTargetCount,
391                 /* directTargetHashed= */ null,
392                 isPinned,
393                 isSuccessfullySelected,
394                 selectionCost);
395 
396         verify(mFrameworkLog).write(
397                 anyInt(), anyInt(), anyString(), idIntCaptor.capture(), anyInt(), anyBoolean());
398 
399         mChooserLogger.logSharesheetTriggered();
400         verify(mUiEventLog).logWithInstanceId(
401                 any(UiEventEnum.class), anyInt(), any(), idObjectCaptor.capture());
402 
403         assertThat(idIntCaptor.getValue()).isGreaterThan(0);
404         assertThat(idObjectCaptor.getValue().getId()).isEqualTo(idIntCaptor.getValue());
405     }
406 
407     @Test
testTargetSelectionCategories()408     public void testTargetSelectionCategories() {
409         assertThat(EventLogImpl.getTargetSelectionCategory(
410                 EventLogImpl.SELECTION_TYPE_SERVICE))
411                         .isEqualTo(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET);
412         assertThat(EventLogImpl.getTargetSelectionCategory(
413                 EventLogImpl.SELECTION_TYPE_APP))
414                         .isEqualTo(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET);
415         assertThat(EventLogImpl.getTargetSelectionCategory(
416                 EventLogImpl.SELECTION_TYPE_STANDARD))
417                         .isEqualTo(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET);
418         assertThat(EventLogImpl.getTargetSelectionCategory(
419                 EventLogImpl.SELECTION_TYPE_COPY)).isEqualTo(0);
420         assertThat(EventLogImpl.getTargetSelectionCategory(
421                 EventLogImpl.SELECTION_TYPE_NEARBY)).isEqualTo(0);
422         assertThat(EventLogImpl.getTargetSelectionCategory(
423                 EventLogImpl.SELECTION_TYPE_EDIT)).isEqualTo(0);
424     }
425 }
426