From 198ff2693ebe41d8a664586bd9387f548a51b016 Mon Sep 17 00:00:00 2001 From: Joshua Trask Date: Fri, 21 Oct 2022 14:25:51 -0400 Subject: Simplify ChooserActivityLogger. This interface only had one implementation outside of tests, and the test implementation was also unnecessarily complex. This CL consolidates the "real" implementation into the base interface, with injectable shims for the logging backend we'll use in tests. After this CL, integration tests that want to verify logging sequences can use a mock `ChooserActivityLogger` instead of a `FakeChooserActivityLogger`, and then make assertions about the (simpler) application-level events in that API. A new `ChooserActivityLoggerTest` covers the translation of these events into the appropriate representation for their `UiEventLogger` or `FrameworkStatsLog` backend, so integration tests no longer need to worry about that underlying detail. In the past, the only integration tests that exercised logging had been disabled in `ChooserActivityTest` due to flakes with indeterminate logging sequences to be addressed in b/211669337. Instead of attempting to patch the new (mock `ChooserActivityLogger`) style into test code that's already broken and disabled, I just deleted the relevant sections of those tests for now. Test: atest IntentResolverUnitTests Bug: 202167050, 211669337 Change-Id: Iaab551625284335469069bab8ee9a2d52fd955e6 --- .../android/intentresolver/ChooserActivity.java | 4 +- .../intentresolver/ChooserActivityLogger.java | 168 ++++++++++-- .../intentresolver/ChooserActivityLoggerImpl.java | 84 ------ .../intentresolver/ChooserActivityLoggerFake.java | 134 ---------- .../intentresolver/ChooserActivityLoggerTest.java | 239 +++++++++++++++++ .../ChooserActivityOverrideData.java | 2 +- .../UnbundledChooserActivityTest.java | 291 --------------------- 7 files changed, 390 insertions(+), 532 deletions(-) delete mode 100644 java/src/com/android/intentresolver/ChooserActivityLoggerImpl.java delete mode 100644 java/tests/src/com/android/intentresolver/ChooserActivityLoggerFake.java create mode 100644 java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java (limited to 'java') diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 26c7fbc9..31254de8 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -2275,7 +2275,7 @@ public class ChooserActivity extends ResolverActivity implements protected ChooserActivityLogger getChooserActivityLogger() { if (mChooserActivityLogger == null) { - mChooserActivityLogger = new ChooserActivityLoggerImpl(); + mChooserActivityLogger = new ChooserActivityLogger(); } return mChooserActivityLogger; } @@ -4008,7 +4008,7 @@ public class ChooserActivity extends ResolverActivity implements @Override protected void maybeLogProfileChange() { - getChooserActivityLogger().logShareheetProfileChanged(); + getChooserActivityLogger().logSharesheetProfileChanged(); } private boolean shouldNearbyShareBeFirstInRankedRow() { diff --git a/java/src/com/android/intentresolver/ChooserActivityLogger.java b/java/src/com/android/intentresolver/ChooserActivityLogger.java index 1daae01a..6d760b1a 100644 --- a/java/src/com/android/intentresolver/ChooserActivityLogger.java +++ b/java/src/com/android/intentresolver/ChooserActivityLogger.java @@ -19,45 +19,116 @@ package com.android.intentresolver; import android.content.Intent; import android.provider.MediaStore; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.InstanceId; +import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; +import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.util.FrameworkStatsLog; /** - * Interface for writing Sharesheet atoms to statsd log. + * Helper for writing Sharesheet atoms to statsd log. * @hide */ -public interface ChooserActivityLogger { +public class ChooserActivityLogger { + /** + * This shim is provided only for testing. In production, clients will only ever use a + * {@link DefaultFrameworkStatsLogger}. + */ + @VisibleForTesting + interface FrameworkStatsLogger { + /** Overload to use for logging {@code FrameworkStatsLog.SHARESHEET_STARTED}. */ + void write( + int frameworkEventId, + int appEventId, + String packageName, + int instanceId, + String mimeType, + int numAppProvidedDirectTargets, + int numAppProvidedAppTargets, + boolean isWorkProfile, + int previewType, + int intentType); + + /** Overload to use for logging {@code FrameworkStatsLog.RANKING_SELECTED}. */ + void write( + int frameworkEventId, + int appEventId, + String packageName, + int instanceId, + int positionPicked, + boolean isPinned); + } + + private static final int SHARESHEET_INSTANCE_ID_MAX = (1 << 13); + + // A small per-notification ID, used for statsd logging. + // TODO: consider precomputing and storing as final. + private static InstanceIdSequence sInstanceIdSequence; + private InstanceId mInstanceId; + + private final UiEventLogger mUiEventLogger; + private final FrameworkStatsLogger mFrameworkStatsLogger; + + public ChooserActivityLogger() { + this(new UiEventLoggerImpl(), new DefaultFrameworkStatsLogger()); + } + + @VisibleForTesting + ChooserActivityLogger(UiEventLogger uiEventLogger, FrameworkStatsLogger frameworkLogger) { + mUiEventLogger = uiEventLogger; + mFrameworkStatsLogger = frameworkLogger; + } + /** Logs a UiEventReported event for the system sharesheet completing initial start-up. */ - void logShareStarted(int eventId, String packageName, String mimeType, int appProvidedDirect, - int appProvidedApp, boolean isWorkprofile, int previewType, String intent); + public void logShareStarted(int eventId, String packageName, String mimeType, + int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType, + String intent) { + mFrameworkStatsLogger.write(FrameworkStatsLog.SHARESHEET_STARTED, + /* event_id = 1 */ SharesheetStartedEvent.SHARE_STARTED.getId(), + /* package_name = 2 */ packageName, + /* instance_id = 3 */ getInstanceId().getId(), + /* mime_type = 4 */ mimeType, + /* num_app_provided_direct_targets = 5 */ appProvidedDirect, + /* num_app_provided_app_targets = 6 */ appProvidedApp, + /* is_workprofile = 7 */ isWorkprofile, + /* previewType = 8 */ typeFromPreviewInt(previewType), + /* intentType = 9 */ typeFromIntentString(intent)); + } /** Logs a UiEventReported event for the system sharesheet when the user selects a target. */ - void logShareTargetSelected(int targetType, String packageName, int positionPicked, - boolean isPinned); + public void logShareTargetSelected(int targetType, String packageName, int positionPicked, + boolean isPinned) { + mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, + /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), + /* package_name = 2 */ packageName, + /* instance_id = 3 */ getInstanceId().getId(), + /* position_picked = 4 */ positionPicked, + /* is_pinned = 5 */ isPinned); + } /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */ - default void logSharesheetTriggered() { + public void logSharesheetTriggered() { log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId()); } /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */ - default void logSharesheetAppLoadComplete() { + public void logSharesheetAppLoadComplete() { log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId()); } /** * Logs a UiEventReported event for the system sharesheet completing loading service targets. */ - default void logSharesheetDirectLoadComplete() { + public void logSharesheetDirectLoadComplete() { log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId()); } /** * Logs a UiEventReported event for the system sharesheet timing out loading service targets. */ - default void logSharesheetDirectLoadTimeout() { + public void logSharesheetDirectLoadTimeout() { log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId()); } @@ -65,12 +136,12 @@ public interface ChooserActivityLogger { * Logs a UiEventReported event for the system sharesheet switching * between work and main profile. */ - default void logShareheetProfileChanged() { + public void logSharesheetProfileChanged() { log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId()); } /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */ - default void logSharesheetExpansionChanged(boolean isCollapsed) { + public void logSharesheetExpansionChanged(boolean isCollapsed) { log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED : SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); } @@ -78,14 +149,14 @@ public interface ChooserActivityLogger { /** * Logs a UiEventReported event for the system sharesheet app share ranking timing out. */ - default void logSharesheetAppShareRankingTimeout() { + public void logSharesheetAppShareRankingTimeout() { log(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT, getInstanceId()); } /** * Logs a UiEventReported event for the system sharesheet when direct share row is empty. */ - default void logSharesheetEmptyDirectShareRow() { + public void logSharesheetEmptyDirectShareRow() { log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId()); } @@ -94,13 +165,26 @@ public interface ChooserActivityLogger { * @param event * @param instanceId */ - void log(UiEventLogger.UiEventEnum event, InstanceId instanceId); + private void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) { + mUiEventLogger.logWithInstanceId( + event, + 0, + null, + instanceId); + } /** - * - * @return + * @return A unique {@link InstanceId} to join across events recorded by this logger instance. */ - InstanceId getInstanceId(); + private InstanceId getInstanceId() { + if (mInstanceId == null) { + if (sInstanceIdSequence == null) { + sInstanceIdSequence = new InstanceIdSequence(SHARESHEET_INSTANCE_ID_MAX); + } + mInstanceId = sInstanceIdSequence.newInstanceId(); + } + return mInstanceId; + } /** * The UiEvent enums that this class can log. @@ -201,7 +285,7 @@ public interface ChooserActivityLogger { /** * Returns the enum used in sharesheet started atom to indicate what preview type was used. */ - default int typeFromPreviewInt(int previewType) { + private static int typeFromPreviewInt(int previewType) { switch(previewType) { case ChooserActivity.CONTENT_PREVIEW_IMAGE: return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_IMAGE; @@ -218,7 +302,7 @@ public interface ChooserActivityLogger { * Returns the enum used in sharesheet started atom to indicate what intent triggers the * ChooserActivity. */ - default int typeFromIntentString(String intent) { + private static int typeFromIntentString(String intent) { if (intent == null) { return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; } @@ -243,4 +327,48 @@ public interface ChooserActivityLogger { return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; } } + + private static class DefaultFrameworkStatsLogger implements FrameworkStatsLogger { + @Override + public void write( + int frameworkEventId, + int appEventId, + String packageName, + int instanceId, + String mimeType, + int numAppProvidedDirectTargets, + int numAppProvidedAppTargets, + boolean isWorkProfile, + int previewType, + int intentType) { + FrameworkStatsLog.write( + frameworkEventId, + /* event_id = 1 */ appEventId, + /* package_name = 2 */ packageName, + /* instance_id = 3 */ instanceId, + /* mime_type = 4 */ mimeType, + /* num_app_provided_direct_targets */ numAppProvidedDirectTargets, + /* num_app_provided_app_targets */ numAppProvidedAppTargets, + /* is_workprofile */ isWorkProfile, + /* previewType = 8 */ previewType, + /* intentType = 9 */ intentType); + } + + @Override + public void write( + int frameworkEventId, + int appEventId, + String packageName, + int instanceId, + int positionPicked, + boolean isPinned) { + FrameworkStatsLog.write( + frameworkEventId, + /* event_id = 1 */ appEventId, + /* package_name = 2 */ packageName, + /* instance_id = 3 */ instanceId, + /* position_picked = 4 */ positionPicked, + /* is_pinned = 5 */ isPinned); + } + } } diff --git a/java/src/com/android/intentresolver/ChooserActivityLoggerImpl.java b/java/src/com/android/intentresolver/ChooserActivityLoggerImpl.java deleted file mode 100644 index 08a345bc..00000000 --- a/java/src/com/android/intentresolver/ChooserActivityLoggerImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.intentresolver; - -import com.android.internal.logging.InstanceId; -import com.android.internal.logging.InstanceIdSequence; -import com.android.internal.logging.UiEventLogger; -import com.android.internal.logging.UiEventLoggerImpl; -import com.android.internal.util.FrameworkStatsLog; - -/** - * Standard implementation of ChooserActivityLogger interface. - * @hide - */ -public class ChooserActivityLoggerImpl implements ChooserActivityLogger { - private static final int SHARESHEET_INSTANCE_ID_MAX = (1 << 13); - - private UiEventLogger mUiEventLogger = new UiEventLoggerImpl(); - // A small per-notification ID, used for statsd logging. - private InstanceId mInstanceId; - private static InstanceIdSequence sInstanceIdSequence; - - @Override - public void logShareStarted(int eventId, String packageName, String mimeType, - int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType, - String intent) { - FrameworkStatsLog.write(FrameworkStatsLog.SHARESHEET_STARTED, - /* event_id = 1 */ SharesheetStartedEvent.SHARE_STARTED.getId(), - /* package_name = 2 */ packageName, - /* instance_id = 3 */ getInstanceId().getId(), - /* mime_type = 4 */ mimeType, - /* num_app_provided_direct_targets = 5 */ appProvidedDirect, - /* num_app_provided_app_targets = 6 */ appProvidedApp, - /* is_workprofile = 7 */ isWorkprofile, - /* previewType = 8 */ typeFromPreviewInt(previewType), - /* intentType = 9 */ typeFromIntentString(intent)); - } - - @Override - public void logShareTargetSelected(int targetType, String packageName, int positionPicked, - boolean isPinned) { - FrameworkStatsLog.write(FrameworkStatsLog.RANKING_SELECTED, - /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), - /* package_name = 2 */ packageName, - /* instance_id = 3 */ getInstanceId().getId(), - /* position_picked = 4 */ positionPicked, - /* is_pinned = 5 */ isPinned); - } - - @Override - public void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) { - mUiEventLogger.logWithInstanceId( - event, - 0, - null, - instanceId); - } - - @Override - public InstanceId getInstanceId() { - if (mInstanceId == null) { - if (sInstanceIdSequence == null) { - sInstanceIdSequence = new InstanceIdSequence(SHARESHEET_INSTANCE_ID_MAX); - } - mInstanceId = sInstanceIdSequence.newInstanceId(); - } - return mInstanceId; - } - -} diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityLoggerFake.java b/java/tests/src/com/android/intentresolver/ChooserActivityLoggerFake.java deleted file mode 100644 index e4146cc5..00000000 --- a/java/tests/src/com/android/intentresolver/ChooserActivityLoggerFake.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.intentresolver; - -import com.android.internal.logging.InstanceId; -import com.android.internal.logging.UiEventLogger; -import com.android.internal.util.FrameworkStatsLog; - -import java.util.ArrayList; -import java.util.List; - -public class ChooserActivityLoggerFake implements ChooserActivityLogger { - static class CallRecord { - // shared fields between all logs - public int atomId; - public String packageName; - public InstanceId instanceId; - - // generic log field - public UiEventLogger.UiEventEnum event; - - // share started fields - public String mimeType; - public int appProvidedDirect; - public int appProvidedApp; - public boolean isWorkprofile; - public int previewType; - public String intent; - - // share completed fields - public int targetType; - public int positionPicked; - public boolean isPinned; - - CallRecord(int atomId, UiEventLogger.UiEventEnum eventId, - String packageName, InstanceId instanceId) { - this.atomId = atomId; - this.packageName = packageName; - this.instanceId = instanceId; - this.event = eventId; - } - - CallRecord(int atomId, String packageName, InstanceId instanceId, String mimeType, - int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType, - String intent) { - this.atomId = atomId; - this.packageName = packageName; - this.instanceId = instanceId; - this.mimeType = mimeType; - this.appProvidedDirect = appProvidedDirect; - this.appProvidedApp = appProvidedApp; - this.isWorkprofile = isWorkprofile; - this.previewType = previewType; - this.intent = intent; - } - - CallRecord(int atomId, String packageName, InstanceId instanceId, int targetType, - int positionPicked, boolean isPinned) { - this.atomId = atomId; - this.packageName = packageName; - this.instanceId = instanceId; - this.targetType = targetType; - this.positionPicked = positionPicked; - this.isPinned = isPinned; - } - - } - private List mCalls = new ArrayList<>(); - - public int numCalls() { - return mCalls.size(); - } - - List getCalls() { - return mCalls; - } - - CallRecord get(int index) { - return mCalls.get(index); - } - - UiEventLogger.UiEventEnum event(int index) { - return mCalls.get(index).event; - } - - public void removeCallsForUiEventsOfType(int uiEventType) { - mCalls.removeIf( - call -> - (call.atomId == FrameworkStatsLog.UI_EVENT_REPORTED) - && (call.event.getId() == uiEventType)); - } - - @Override - public void logShareStarted(int eventId, String packageName, String mimeType, - int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType, - String intent) { - mCalls.add(new CallRecord(FrameworkStatsLog.SHARESHEET_STARTED, packageName, - getInstanceId(), mimeType, appProvidedDirect, appProvidedApp, isWorkprofile, - previewType, intent)); - } - - @Override - public void logShareTargetSelected(int targetType, String packageName, int positionPicked, - boolean isPinned) { - mCalls.add(new CallRecord(FrameworkStatsLog.RANKING_SELECTED, packageName, getInstanceId(), - SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), positionPicked, - isPinned)); - } - - @Override - public void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) { - mCalls.add(new CallRecord(FrameworkStatsLog.UI_EVENT_REPORTED, - event, "", instanceId)); - } - - @Override - public InstanceId getInstanceId() { - return InstanceId.fakeInstanceId(-1); - } -} diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java b/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java new file mode 100644 index 00000000..a93718fd --- /dev/null +++ b/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.AdditionalMatchers.gt; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.content.Intent; + +import com.android.intentresolver.ChooserActivityLogger.FrameworkStatsLogger; +import com.android.intentresolver.ChooserActivityLogger.SharesheetStandardEvent; +import com.android.intentresolver.ChooserActivityLogger.SharesheetStartedEvent; +import com.android.intentresolver.ChooserActivityLogger.SharesheetTargetSelectedEvent; +import com.android.internal.logging.InstanceId; +import com.android.internal.logging.UiEventLogger; +import com.android.internal.logging.UiEventLogger.UiEventEnum; +import com.android.internal.util.FrameworkStatsLog; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public final class ChooserActivityLoggerTest { + @Mock private UiEventLogger mUiEventLog; + @Mock private FrameworkStatsLogger mFrameworkLog; + + private ChooserActivityLogger mChooserLogger; + + @Before + public void setUp() { + mChooserLogger = new ChooserActivityLogger(mUiEventLog, mFrameworkLog); + } + + @After + public void tearDown() { + verifyNoMoreInteractions(mUiEventLog); + verifyNoMoreInteractions(mFrameworkLog); + } + + @Test + public void testLogShareStarted() { + final int eventId = -1; // Passed-in eventId is unused. TODO: remove from method signature. + final String packageName = "com.test.foo"; + final String mimeType = "text/plain"; + final int appProvidedDirectTargets = 123; + final int appProvidedAppTargets = 456; + final boolean workProfile = true; + final int previewType = ChooserActivity.CONTENT_PREVIEW_FILE; + final String intentAction = Intent.ACTION_SENDTO; + + mChooserLogger.logShareStarted( + eventId, + packageName, + mimeType, + appProvidedDirectTargets, + appProvidedAppTargets, + workProfile, + previewType, + intentAction); + + verify(mFrameworkLog).write( + eq(FrameworkStatsLog.SHARESHEET_STARTED), + eq(SharesheetStartedEvent.SHARE_STARTED.getId()), + eq(packageName), + /* instanceId=*/ gt(0), + eq(mimeType), + eq(appProvidedDirectTargets), + eq(appProvidedAppTargets), + eq(workProfile), + eq(FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE), + eq(FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO)); + } + + @Test + public void testLogShareTargetSelected() { + final int targetType = ChooserActivity.SELECTION_TYPE_COPY; + final String packageName = "com.test.foo"; + final int positionPicked = 123; + final boolean pinned = true; + + mChooserLogger.logShareTargetSelected(targetType, packageName, positionPicked, pinned); + + verify(mFrameworkLog).write( + eq(FrameworkStatsLog.RANKING_SELECTED), + eq(SharesheetTargetSelectedEvent.SHARESHEET_COPY_TARGET_SELECTED.getId()), + eq(packageName), + /* instanceId=*/ gt(0), + eq(positionPicked), + eq(pinned)); + } + + @Test + public void testLogSharesheetTriggered() { + mChooserLogger.logSharesheetTriggered(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_TRIGGERED), eq(0), isNull(), any()); + } + + @Test + public void testLogSharesheetAppLoadComplete() { + mChooserLogger.logSharesheetAppLoadComplete(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE), eq(0), isNull(), any()); + } + + @Test + public void testLogSharesheetDirectLoadComplete() { + mChooserLogger.logSharesheetDirectLoadComplete(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE), + eq(0), + isNull(), + any()); + } + + @Test + public void testLogSharesheetDirectLoadTimeout() { + mChooserLogger.logSharesheetDirectLoadTimeout(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT), eq(0), isNull(), any()); + } + + @Test + public void testLogSharesheetProfileChanged() { + mChooserLogger.logSharesheetProfileChanged(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED), eq(0), isNull(), any()); + } + + @Test + public void testLogSharesheetExpansionChanged_collapsed() { + mChooserLogger.logSharesheetExpansionChanged(/* isCollapsed=*/ true); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_COLLAPSED), eq(0), isNull(), any()); + } + + @Test + public void testLogSharesheetExpansionChanged_expanded() { + mChooserLogger.logSharesheetExpansionChanged(/* isCollapsed=*/ false); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_EXPANDED), eq(0), isNull(), any()); + } + + @Test + public void testLogSharesheetAppShareRankingTimeout() { + mChooserLogger.logSharesheetAppShareRankingTimeout(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT), + eq(0), + isNull(), + any()); + } + + @Test + public void testLogSharesheetEmptyDirectShareRow() { + mChooserLogger.logSharesheetEmptyDirectShareRow(); + verify(mUiEventLog).logWithInstanceId( + eq(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW), + eq(0), + isNull(), + any()); + } + + @Test + public void testDifferentLoggerInstancesUseDifferentInstanceIds() { + ArgumentCaptor idIntCaptor = ArgumentCaptor.forClass(Integer.class); + ChooserActivityLogger chooserLogger2 = + new ChooserActivityLogger(mUiEventLog, mFrameworkLog); + + final int targetType = ChooserActivity.SELECTION_TYPE_COPY; + final String packageName = "com.test.foo"; + final int positionPicked = 123; + final boolean pinned = true; + + mChooserLogger.logShareTargetSelected(targetType, packageName, positionPicked, pinned); + chooserLogger2.logShareTargetSelected(targetType, packageName, positionPicked, pinned); + + verify(mFrameworkLog, times(2)).write( + anyInt(), anyInt(), anyString(), idIntCaptor.capture(), anyInt(), anyBoolean()); + + int id1 = idIntCaptor.getAllValues().get(0); + int id2 = idIntCaptor.getAllValues().get(1); + + assertThat(id1).isGreaterThan(0); + assertThat(id2).isGreaterThan(0); + assertThat(id1).isNotEqualTo(id2); + } + + @Test + public void testUiAndFrameworkEventsUseSameInstanceIdForSameLoggerInstance() { + ArgumentCaptor idIntCaptor = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor idObjectCaptor = ArgumentCaptor.forClass(InstanceId.class); + + final int targetType = ChooserActivity.SELECTION_TYPE_COPY; + final String packageName = "com.test.foo"; + final int positionPicked = 123; + final boolean pinned = true; + + mChooserLogger.logShareTargetSelected(targetType, packageName, positionPicked, pinned); + verify(mFrameworkLog).write( + anyInt(), anyInt(), anyString(), idIntCaptor.capture(), anyInt(), anyBoolean()); + + mChooserLogger.logSharesheetTriggered(); + verify(mUiEventLog).logWithInstanceId( + any(UiEventEnum.class), anyInt(), any(), idObjectCaptor.capture()); + + assertThat(idIntCaptor.getValue()).isGreaterThan(0); + assertThat(idObjectCaptor.getValue().getId()).isEqualTo(idIntCaptor.getValue()); + } +} diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java index 080f1e41..d1ca2b09 100644 --- a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java +++ b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java @@ -81,7 +81,7 @@ public class ChooserActivityOverrideData { resolverListController = mock(ResolverListController.class); workResolverListController = mock(ResolverListController.class); metricsLogger = mock(MetricsLogger.class); - chooserActivityLogger = new ChooserActivityLoggerFake(); + chooserActivityLogger = mock(ChooserActivityLogger.class); alternateProfileSetting = 0; resources = null; workProfileUserHandle = null; diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index 5d600092..09ee8fc1 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -96,7 +96,6 @@ import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.util.FrameworkStatsLog; import org.hamcrest.Description; import org.hamcrest.Matcher; @@ -820,49 +819,7 @@ public class UnbundledChooserActivityTest { .check(matches(isDisplayed())); onView(withId(com.android.internal.R.id.chooser_nearby_button)).perform(click()); - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events. - logger.removeCallsForUiEventsOfType( - ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_DIRECT_LOAD_COMPLETE.getId()); - - // SHARESHEET_TRIGGERED: - assertThat(logger.event(0).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - - // SHARESHEET_STARTED: - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is("text/plain")); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(3)); - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(2).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // Next are just artifacts of test set-up: - assertThat(logger.event(3).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - assertThat(logger.event(4).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId())); - - // SHARESHEET_NEARBY_TARGET_SELECTED: - assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED)); - assertThat(logger.get(5).targetType, - is(ChooserActivityLogger - .SharesheetTargetSelectedEvent.SHARESHEET_NEARBY_TARGET_SELECTED.getId())); - - // No more events. - assertThat(logger.numCalls(), is(6)); } @@ -891,49 +848,7 @@ public class UnbundledChooserActivityTest { onView(withId(com.android.internal.R.id.chooser_edit_button)).check(matches(isDisplayed())); onView(withId(com.android.internal.R.id.chooser_edit_button)).perform(click()); - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events. - logger.removeCallsForUiEventsOfType( - ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_DIRECT_LOAD_COMPLETE.getId()); - - // SHARESHEET_TRIGGERED: - assertThat(logger.event(0).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - - // SHARESHEET_STARTED: - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is("image/png")); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(1)); - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(2).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // Next are just artifacts of test set-up: - assertThat(logger.event(3).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - assertThat(logger.event(4).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId())); - - // SHARESHEET_EDIT_TARGET_SELECTED: - assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED)); - assertThat(logger.get(5).targetType, - is(ChooserActivityLogger - .SharesheetTargetSelectedEvent.SHARESHEET_EDIT_TARGET_SELECTED.getId())); - - // No more events. - assertThat(logger.numCalls(), is(6)); } @@ -2033,49 +1948,7 @@ public class UnbundledChooserActivityTest { .perform(click()); waitForIdle(); - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events. - logger.removeCallsForUiEventsOfType( - ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_DIRECT_LOAD_COMPLETE.getId()); - - // SHARESHEET_TRIGGERED: - assertThat(logger.event(0).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - - // SHARESHEET_STARTED: - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is("text/plain")); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(3)); - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(2).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // Next are just artifacts of test set-up: - assertThat(logger.event(3).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - assertThat(logger.event(4).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId())); - - // SHARESHEET_APP_TARGET_SELECTED: - assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED)); - assertThat(logger.get(5).targetType, - is(ChooserActivityLogger - .SharesheetTargetSelectedEvent.SHARESHEET_APP_TARGET_SELECTED.getId())); - - // No more events. - assertThat(logger.numCalls(), is(6)); } @Test @Ignore @@ -2135,35 +2008,6 @@ public class UnbundledChooserActivityTest { onView(withText(name)) .perform(click()); waitForIdle(); - - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - assertThat(logger.numCalls(), is(6)); - // first one should be SHARESHEET_TRIGGERED uievent - assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED)); - assertThat(logger.get(0).event.getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - // second one should be SHARESHEET_STARTED event - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is("text/plain")); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(3)); - // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent - assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED)); - assertThat(logger.get(2).event.getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - // fourth and fifth are just artifacts of test set-up - // sixth one should be ranking atom with SHARESHEET_COPY_TARGET_SELECTED event - assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED)); - assertThat(logger.get(5).targetType, - is(ChooserActivityLogger - .SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId())); } @Test @Ignore @@ -2195,44 +2039,7 @@ public class UnbundledChooserActivityTest { assertThat("Chooser should have no direct targets", activity.getAdapter().getSelectableServiceTargetCount(), is(0)); - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events. - logger.removeCallsForUiEventsOfType( - ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_DIRECT_LOAD_COMPLETE.getId()); - - // SHARESHEET_TRIGGERED: - assertThat(logger.event(0).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - - // SHARESHEET_STARTED: - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is("text/plain")); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(3)); - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(2).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // SHARESHEET_EMPTY_DIRECT_SHARE_ROW: - assertThat(logger.event(3).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - - // Next is just an artifact of test set-up: - assertThat(logger.event(4).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId())); - - assertThat(logger.numCalls(), is(5)); } @Ignore // b/220067877 @@ -2259,49 +2066,7 @@ public class UnbundledChooserActivityTest { onView(withId(com.android.internal.R.id.chooser_copy_button)).check(matches(isDisplayed())); onView(withId(com.android.internal.R.id.chooser_copy_button)).perform(click()); - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events. - logger.removeCallsForUiEventsOfType( - ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_DIRECT_LOAD_COMPLETE.getId()); - - // SHARESHEET_TRIGGERED: - assertThat(logger.event(0).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - - // SHARESHEET_STARTED: - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is("text/plain")); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(3)); - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(2).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // Next are just artifacts of test set-up: - assertThat(logger.event(3).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - assertThat(logger.event(4).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId())); - - // SHARESHEET_COPY_TARGET_SELECTED: - assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED)); - assertThat(logger.get(5).targetType, - is(ChooserActivityLogger - .SharesheetTargetSelectedEvent.SHARESHEET_COPY_TARGET_SELECTED.getId())); - - // No more events. - assertThat(logger.numCalls(), is(6)); } @Test @Ignore("b/222124533") @@ -2324,63 +2089,7 @@ public class UnbundledChooserActivityTest { onView(withText(R.string.resolver_personal_tab)).perform(click()); waitForIdle(); - ChooserActivityLoggerFake logger = - (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); - // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events. - logger.removeCallsForUiEventsOfType( - ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_DIRECT_LOAD_COMPLETE.getId()); - - // SHARESHEET_TRIGGERED: - assertThat(logger.event(0).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); - - // SHARESHEET_STARTED: - assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); - assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); - assertThat(logger.get(1).mimeType, is(TEST_MIME_TYPE)); - assertThat(logger.get(1).packageName, is( - InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName())); - assertThat(logger.get(1).appProvidedApp, is(0)); - assertThat(logger.get(1).appProvidedDirect, is(0)); - assertThat(logger.get(1).isWorkprofile, is(false)); - assertThat(logger.get(1).previewType, is(3)); - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(2).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // Next is just an artifact of test set-up: - assertThat(logger.event(3).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - - // SHARESHEET_PROFILE_CHANGED: - assertThat(logger.event(4).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_PROFILE_CHANGED.getId())); - - // Repeat the loading steps in the new profile: - - // SHARESHEET_APP_LOAD_COMPLETE: - assertThat(logger.event(5).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); - - // Next is again an artifact of test set-up: - assertThat(logger.event(6).getId(), - is(ChooserActivityLogger - .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); - - // SHARESHEET_PROFILE_CHANGED: - assertThat(logger.event(7).getId(), - is(ChooserActivityLogger.SharesheetStandardEvent - .SHARESHEET_PROFILE_CHANGED.getId())); - - // No more events (this profile was already loaded). - assertThat(logger.numCalls(), is(8)); } @Test -- cgit v1.2.3-59-g8ed1b