diff options
| author | 2023-09-14 20:57:57 +0000 | |
|---|---|---|
| committer | 2023-09-14 20:57:57 +0000 | |
| commit | 63cd47c3db33a2901aed2e14f6de8be9997014d9 (patch) | |
| tree | 5a5933ad762d3161b49fdb943c67958c4fe28146 /java | |
| parent | 0aff6449c2f52ffb76108be40869d612a5daffc3 (diff) | |
| parent | ae322c4ddbcb552979fba17a22b931081020014e (diff) | |
Merge "Injects EventLog, provides FakeEventLog within tests" into main
Diffstat (limited to 'java')
14 files changed, 559 insertions, 220 deletions
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index c27d3bac..acfd3572 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -85,7 +85,6 @@ import com.android.intentresolver.grid.ChooserGridAdapter; import com.android.intentresolver.icons.DefaultTargetDataLoader; import com.android.intentresolver.icons.TargetDataLoader; import com.android.intentresolver.logging.EventLog; -import com.android.intentresolver.logging.EventLogImpl; import com.android.intentresolver.measurements.Tracer; import com.android.intentresolver.model.AbstractResolverComparator; import com.android.intentresolver.model.AppPredictionServiceResolverComparator; @@ -172,6 +171,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements public @interface ShareTargetType {} @Inject public FeatureFlags mFeatureFlags; + @Inject public EventLog mEventLog; private ChooserIntegratedDeviceComponents mIntegratedDeviceComponents; @@ -189,9 +189,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements private ChooserContentPreviewUi mChooserContentPreviewUi; private boolean mShouldDisplayLandscape; - // statsd logger wrapper - protected EventLog mEventLog; - private long mChooserShownTime; protected boolean mIsSuccessfullySelected; @@ -237,8 +234,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements final long intentReceivedTime = System.currentTimeMillis(); mLatencyTracker.onActionStart(ACTION_LOAD_SHARE_SHEET); - getEventLog().logSharesheetTriggered(); - try { mChooserRequest = new ChooserRequestParameters( getIntent(), @@ -276,6 +271,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements new DefaultTargetDataLoader(this, getLifecycle(), false), /* safeForwardingMode= */ true); + getEventLog().logSharesheetTriggered(); + mIntegratedDeviceComponents = getIntegratedDeviceComponents(); mRefinementManager = new ViewModelProvider(this).get(ChooserRefinementManager.class); @@ -1107,9 +1104,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements } protected EventLog getEventLog() { - if (mEventLog == null) { - mEventLog = new EventLogImpl(); - } return mEventLog; } @@ -1573,6 +1567,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements getResources().getDimensionPixelSize(R.dimen.chooser_header_scroll_elevation); mChooserMultiProfilePagerAdapter.getActiveAdapterView().addOnScrollListener( new RecyclerView.OnScrollListener() { + @Override public void onScrollStateChanged(RecyclerView view, int scrollState) { if (scrollState == RecyclerView.SCROLL_STATE_IDLE) { if (mScrollStatus == SCROLL_STATUS_SCROLLING_VERTICAL) { @@ -1587,6 +1582,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements } } + @Override public void onScrolled(RecyclerView view, int dx, int dy) { if (view.getChildCount() > 0) { View child = view.getLayoutManager().findViewByPosition(0); diff --git a/java/src/com/android/intentresolver/inject/SingletonModule.kt b/java/src/com/android/intentresolver/inject/SingletonModule.kt new file mode 100644 index 00000000..fbda8be6 --- /dev/null +++ b/java/src/com/android/intentresolver/inject/SingletonModule.kt @@ -0,0 +1,15 @@ +package com.android.intentresolver.inject + +import com.android.intentresolver.logging.EventLogImpl +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +class SingletonModule { + + @Provides @Singleton fun instanceIdSequence() = EventLogImpl.newIdSequence() +} diff --git a/java/src/com/android/intentresolver/logging/EventLogImpl.java b/java/src/com/android/intentresolver/logging/EventLogImpl.java index 33e617b1..26c79d00 100644 --- a/java/src/com/android/intentresolver/logging/EventLogImpl.java +++ b/java/src/com/android/intentresolver/logging/EventLogImpl.java @@ -32,10 +32,13 @@ import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; -import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.FrameworkStatsLog; +import javax.inject.Inject; + +import dagger.hilt.android.scopes.ActivityScoped; + /** * Helper for writing Sharesheet atoms to statsd log. */ @@ -45,29 +48,26 @@ public class EventLogImpl implements EventLog { 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 InstanceId mInstanceId; private final UiEventLogger mUiEventLogger; private final FrameworkStatsLogger mFrameworkStatsLogger; private final MetricsLogger mMetricsLogger; - public EventLogImpl() { - this(new UiEventLoggerImpl(), new DefaultFrameworkStatsLogger(), new MetricsLogger()); + public static InstanceIdSequence newIdSequence() { + return new InstanceIdSequence(SHARESHEET_INSTANCE_ID_MAX); } - @VisibleForTesting - EventLogImpl( - UiEventLogger uiEventLogger, - FrameworkStatsLogger frameworkLogger, - MetricsLogger metricsLogger) { + @Inject + public EventLogImpl(UiEventLogger uiEventLogger, FrameworkStatsLogger frameworkLogger, + MetricsLogger metricsLogger, InstanceId instanceId) { mUiEventLogger = uiEventLogger; mFrameworkStatsLogger = frameworkLogger; mMetricsLogger = metricsLogger; + mInstanceId = instanceId; } + /** Records metrics for the start time of the {@link ChooserActivity}. */ @Override public void logChooserActivityShown( @@ -94,7 +94,7 @@ public class EventLogImpl implements EventLog { mFrameworkStatsLogger.write(FrameworkStatsLog.SHARESHEET_STARTED, /* event_id = 1 */ SharesheetStartedEvent.SHARE_STARTED.getId(), /* package_name = 2 */ packageName, - /* instance_id = 3 */ getInstanceId().getId(), + /* instance_id = 3 */ mInstanceId.getId(), /* mime_type = 4 */ mimeType, /* num_app_provided_direct_targets = 5 */ appProvidedDirect, /* num_app_provided_app_targets = 6 */ appProvidedApp, @@ -116,7 +116,7 @@ public class EventLogImpl implements EventLog { /* event_id = 1 */ SharesheetTargetSelectedEvent.SHARESHEET_CUSTOM_ACTION_SELECTED.getId(), /* package_name = 2 */ null, - /* instance_id = 3 */ getInstanceId().getId(), + /* instance_id = 3 */ mInstanceId.getId(), /* position_picked = 4 */ positionPicked, /* is_pinned = 5 */ false); } @@ -140,7 +140,7 @@ public class EventLogImpl implements EventLog { mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), /* package_name = 2 */ packageName, - /* instance_id = 3 */ getInstanceId().getId(), + /* instance_id = 3 */ mInstanceId.getId(), /* position_picked = 4 */ positionPicked, /* is_pinned = 5 */ isPinned); @@ -198,7 +198,7 @@ public class EventLogImpl implements EventLog { mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), /* package_name = 2 */ "", - /* instance_id = 3 */ getInstanceId().getId(), + /* instance_id = 3 */ mInstanceId.getId(), /* position_picked = 4 */ -1, /* is_pinned = 5 */ false); } @@ -217,13 +217,13 @@ public class EventLogImpl implements EventLog { /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */ @Override public void logSharesheetTriggered() { - log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, mInstanceId); } /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */ @Override public void logSharesheetAppLoadComplete() { - log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, mInstanceId); } /** @@ -231,7 +231,7 @@ public class EventLogImpl implements EventLog { */ @Override public void logSharesheetDirectLoadComplete() { - log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, mInstanceId); } /** @@ -239,7 +239,7 @@ public class EventLogImpl implements EventLog { */ @Override public void logSharesheetDirectLoadTimeout() { - log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, mInstanceId); } /** @@ -248,14 +248,14 @@ public class EventLogImpl implements EventLog { */ @Override public void logSharesheetProfileChanged() { - log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, mInstanceId); } /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */ @Override public void logSharesheetExpansionChanged(boolean isCollapsed) { log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED : - SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); + SharesheetStandardEvent.SHARESHEET_EXPANDED, mInstanceId); } /** @@ -263,7 +263,7 @@ public class EventLogImpl implements EventLog { */ @Override public void logSharesheetAppShareRankingTimeout() { - log(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT, mInstanceId); } /** @@ -271,7 +271,7 @@ public class EventLogImpl implements EventLog { */ @Override public void logSharesheetEmptyDirectShareRow() { - log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId()); + log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, mInstanceId); } /** @@ -288,19 +288,6 @@ public class EventLogImpl implements EventLog { } /** - * @return A unique {@link InstanceId} to join across events recorded by this logger instance. - */ - 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. */ enum SharesheetStartedEvent implements UiEventLogger.UiEventEnum { @@ -463,52 +450,4 @@ public class EventLogImpl implements EventLog { return 0; } } - - 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, - int numCustomActions, - boolean modifyShareActionProvided) { - 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, - /* num_provided_custom_actions = 10 */ numCustomActions, - /* modify_share_action_provided = 11 */ modifyShareActionProvided); - } - - @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/logging/EventLogModule.kt b/java/src/com/android/intentresolver/logging/EventLogModule.kt new file mode 100644 index 00000000..eba8ecc8 --- /dev/null +++ b/java/src/com/android/intentresolver/logging/EventLogModule.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 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.logging + +import com.android.internal.logging.InstanceId +import com.android.internal.logging.InstanceIdSequence +import com.android.internal.logging.MetricsLogger +import com.android.internal.logging.UiEventLogger +import com.android.internal.logging.UiEventLoggerImpl +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ActivityComponent +import dagger.hilt.android.scopes.ActivityScoped + +@Module +@InstallIn(ActivityComponent::class) +interface EventLogModule { + + @Binds @ActivityScoped fun eventLog(value: EventLogImpl): EventLog + + companion object { + @Provides + fun instanceId(sequence: InstanceIdSequence): InstanceId = sequence.newInstanceId() + + @Provides fun uiEventLogger(): UiEventLogger = UiEventLoggerImpl() + + @Provides fun frameworkLogger(): FrameworkStatsLogger = object : FrameworkStatsLogger {} + + @Provides fun metricsLogger(): MetricsLogger = MetricsLogger() + } +} diff --git a/java/src/com/android/intentresolver/logging/FrameworkStatsLogger.kt b/java/src/com/android/intentresolver/logging/FrameworkStatsLogger.kt index e0682b9e..6508d305 100644 --- a/java/src/com/android/intentresolver/logging/FrameworkStatsLogger.kt +++ b/java/src/com/android/intentresolver/logging/FrameworkStatsLogger.kt @@ -21,7 +21,8 @@ import com.android.internal.util.FrameworkStatsLog internal annotation class ForUiEvent(vararg val uiEventId: Int) /** Isolates the specific method signatures to use for each of the logged UiEvents. */ -internal interface FrameworkStatsLogger { +interface FrameworkStatsLogger { + @ForUiEvent(FrameworkStatsLog.SHARESHEET_STARTED) fun write( frameworkEventId: Int, @@ -35,8 +36,23 @@ internal interface FrameworkStatsLogger { previewType: Int, intentType: Int, numCustomActions: Int, - modifyShareActionProvided: Boolean - ) + modifyShareActionProvided: Boolean, + ) { + 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, /* num_provided_custom_actions = 10 */ + numCustomActions, /* modify_share_action_provided = 11 */ + modifyShareActionProvided + ) + } @ForUiEvent(FrameworkStatsLog.RANKING_SELECTED) fun write( @@ -45,6 +61,15 @@ internal interface FrameworkStatsLogger { packageName: String?, instanceId: Int, positionPicked: Int, - isPinned: Boolean - ) + isPinned: Boolean, + ) { + 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/tests/src/com/android/intentresolver/ChooserActionFactoryTest.kt b/java/tests/src/com/android/intentresolver/ChooserActionFactoryTest.kt index e2b987c2..2d1ac4e4 100644 --- a/java/tests/src/com/android/intentresolver/ChooserActionFactoryTest.kt +++ b/java/tests/src/com/android/intentresolver/ChooserActionFactoryTest.kt @@ -28,13 +28,12 @@ import android.graphics.drawable.Icon import android.service.chooser.ChooserAction import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry -import com.android.intentresolver.logging.EventLogImpl +import com.android.intentresolver.logging.EventLog import com.google.common.collect.ImmutableList import com.google.common.truth.Truth.assertThat import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import java.util.function.Consumer -import com.android.intentresolver.logging.EventLog import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java index b5c14ff1..d77aa099 100644 --- a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java +++ b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java @@ -29,7 +29,6 @@ import android.os.UserHandle; import com.android.intentresolver.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; import com.android.intentresolver.chooser.TargetInfo; import com.android.intentresolver.contentpreview.ImageLoader; -import com.android.intentresolver.logging.EventLogImpl; import com.android.intentresolver.shortcuts.ShortcutLoader; import java.util.function.Consumer; @@ -64,7 +63,6 @@ public class ChooserActivityOverrideData { public Cursor resolverCursor; public boolean resolverForceException; public ImageLoader imageLoader; - public EventLogImpl mEventLog; public int alternateProfileSetting; public Resources resources; public UserHandle workProfileUserHandle; @@ -86,7 +84,6 @@ public class ChooserActivityOverrideData { resolverForceException = false; resolverListController = mock(ChooserActivity.ChooserListController.class); workResolverListController = mock(ChooserActivity.ChooserListController.class); - mEventLog = mock(EventLogImpl.class); alternateProfileSetting = 0; resources = null; workProfileUserHandle = null; diff --git a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java index d488e02b..27b7037f 100644 --- a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java +++ b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java @@ -39,7 +39,6 @@ import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.TargetInfo; import com.android.intentresolver.grid.ChooserGridAdapter; import com.android.intentresolver.icons.TargetDataLoader; -import com.android.intentresolver.logging.EventLogImpl; import com.android.intentresolver.shortcuts.ShortcutLoader; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -204,11 +203,6 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW } @Override - public EventLogImpl getEventLog() { - return sOverrides.mEventLog; - } - - @Override public Cursor queryResolver(ContentResolver resolver, Uri uri) { if (sOverrides.resolverCursor != null) { return sOverrides.resolverCursor; diff --git a/java/tests/src/com/android/intentresolver/IChooserWrapper.java b/java/tests/src/com/android/intentresolver/IChooserWrapper.java index 54e4da9e..d439b037 100644 --- a/java/tests/src/com/android/intentresolver/IChooserWrapper.java +++ b/java/tests/src/com/android/intentresolver/IChooserWrapper.java @@ -23,7 +23,6 @@ import android.content.pm.ResolveInfo; import android.os.UserHandle; import com.android.intentresolver.chooser.DisplayResolveInfo; -import com.android.intentresolver.logging.EventLogImpl; import java.util.concurrent.Executor; @@ -42,6 +41,5 @@ public interface IChooserWrapper { CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, @Nullable TargetPresentationGetter resolveInfoPresentationGetter); UserHandle getCurrentUserHandle(); - EventLogImpl getEventLog(); Executor getMainExecutor(); } diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index 0b3cb20a..9f16ced5 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -36,6 +36,7 @@ import static com.android.intentresolver.ChooserListAdapter.CALLER_TARGET_SCORE_ import static com.android.intentresolver.ChooserListAdapter.SHORTCUT_TARGET_SCORE_BOOST; import static com.android.intentresolver.MatcherUtils.first; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static junit.framework.Assert.assertNull; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.is; @@ -44,9 +45,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -93,7 +92,6 @@ import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; import android.text.style.UnderlineSpan; -import android.util.HashedStringCache; import android.util.Pair; import android.util.SparseArray; import android.view.View; @@ -113,11 +111,14 @@ import androidx.test.rule.ActivityTestRule; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.contentpreview.ImageLoader; import com.android.intentresolver.logging.EventLog; -import com.android.intentresolver.logging.EventLogImpl; +import com.android.intentresolver.logging.FakeEventLog; import com.android.intentresolver.shortcuts.ShortcutLoader; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import dagger.hilt.android.testing.HiltAndroidRule; +import dagger.hilt.android.testing.HiltAndroidTest; + import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.Matchers; @@ -146,9 +147,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; -import dagger.hilt.android.testing.HiltAndroidRule; -import dagger.hilt.android.testing.HiltAndroidTest; - /** * Instrumentation tests for ChooserActivity. * <p> @@ -159,6 +157,10 @@ import dagger.hilt.android.testing.HiltAndroidTest; @HiltAndroidTest public class UnbundledChooserActivityTest { + private static FakeEventLog getEventLog(ChooserWrapperActivity activity) { + return (FakeEventLog) activity.mEventLog; + } + private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry .getInstrumentation().getTargetContext().getUser(); private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm; @@ -179,6 +181,20 @@ public class UnbundledChooserActivityTest { }); } + private static final String TEST_MIME_TYPE = "application/TestType"; + + private static final int CONTENT_PREVIEW_IMAGE = 1; + private static final int CONTENT_PREVIEW_FILE = 2; + private static final int CONTENT_PREVIEW_TEXT = 3; + + + @Rule(order = 0) + public HiltAndroidRule mHiltAndroidRule = new HiltAndroidRule(this); + + @Rule(order = 1) + public ActivityTestRule<ChooserWrapperActivity> mActivityRule = + new ActivityTestRule<>(ChooserWrapperActivity.class, false, false); + @Before public void setUp() { // TODO: use the other form of `adoptShellPermissionIdentity()` where we explicitly list the @@ -189,21 +205,9 @@ public class UnbundledChooserActivityTest { .adoptShellPermissionIdentity(); cleanOverrideData(); + mHiltAndroidRule.inject(); } - @Rule(order = 0) - public HiltAndroidRule mHiltAndroidRule = new HiltAndroidRule(this); - - @Rule(order = 1) - public ActivityTestRule<ChooserWrapperActivity> mActivityRule = - new ActivityTestRule<>(ChooserWrapperActivity.class, false, false); - - private static final String TEST_MIME_TYPE = "application/TestType"; - - private static final int CONTENT_PREVIEW_IMAGE = 1; - private static final int CONTENT_PREVIEW_FILE = 2; - private static final int CONTENT_PREVIEW_TEXT = 3; - private final Function<PackageManager, PackageManager> mPackageManagerOverride; public UnbundledChooserActivityTest( @@ -845,15 +849,16 @@ public class UnbundledChooserActivityTest { setupResolverControllers(resolvedComponentInfos); - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.copy)).check(matches(isDisplayed())); onView(withId(R.id.copy)).perform(click()); - - EventLog logger = activity.getEventLog(); - verify(logger, times(1)).logActionSelected(eq(EventLogImpl.SELECTION_TYPE_COPY)); + FakeEventLog eventLog = getEventLog(activity); + assertThat(eventLog.getActionSelected()) + .isEqualTo(new FakeEventLog.ActionSelected( + /* targetType = */ EventLog.SELECTION_TYPE_COPY)); } @Test @@ -864,8 +869,7 @@ public class UnbundledChooserActivityTest { setupResolverControllers(resolvedComponentInfos); - final IChooserWrapper activity = (IChooserWrapper) - mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(com.android.internal.R.id.chooser_nearby_button)) @@ -888,8 +892,7 @@ public class UnbundledChooserActivityTest { setupResolverControllers(resolvedComponentInfos); - final IChooserWrapper activity = (IChooserWrapper) - mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(com.android.internal.R.id.chooser_edit_button)).check(matches(isDisplayed())); @@ -1200,12 +1203,15 @@ public class UnbundledChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test")); - EventLog logger = activity.getEventLog(); waitForIdle(); - verify(logger).logChooserActivityShown(eq(false), eq(TEST_MIME_TYPE), anyLong()); + FakeEventLog eventLog = getEventLog(activity); + FakeEventLog.ChooserActivityShown event = eventLog.getChooserActivityShown(); + assertThat(event).isNotNull(); + assertThat(event.isWorkProfile()).isFalse(); + assertThat(event.getTargetMimeType()).isEqualTo(TEST_MIME_TYPE); } @Test @@ -1215,25 +1221,31 @@ public class UnbundledChooserActivityTest { ChooserActivityOverrideData.getInstance().alternateProfileSetting = MetricsEvent.MANAGED_PROFILE; - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test")); - EventLog logger = activity.getEventLog(); waitForIdle(); - verify(logger).logChooserActivityShown(eq(true), eq(TEST_MIME_TYPE), anyLong()); + FakeEventLog eventLog = getEventLog(activity); + FakeEventLog.ChooserActivityShown event = eventLog.getChooserActivityShown(); + assertThat(event).isNotNull(); + assertThat(event.isWorkProfile()).isTrue(); + assertThat(event.getTargetMimeType()).isEqualTo(TEST_MIME_TYPE); } @Test public void testEmptyPreviewLogging() { Intent sendIntent = createSendTextIntentWithPreview(null, null); - final IChooserWrapper activity = (IChooserWrapper) - mActivityRule.launchActivity( - Intent.createChooser(sendIntent, "empty preview logger test")); - EventLog logger = activity.getEventLog(); + ChooserWrapperActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, + "empty preview logger test")); waitForIdle(); - verify(logger).logChooserActivityShown(eq(false), eq(null), anyLong()); + FakeEventLog eventLog = getEventLog(activity); + FakeEventLog.ChooserActivityShown event = eventLog.getChooserActivityShown(); + assertThat(event).isNotNull(); + assertThat(event.isWorkProfile()).isFalse(); + assertThat(event.getTargetMimeType()).isNull(); } @Test @@ -1244,13 +1256,14 @@ public class UnbundledChooserActivityTest { setupResolverControllers(resolvedComponentInfos); - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - // Second invocation is from onCreate - EventLog logger = activity.getEventLog(); - Mockito.verify(logger, times(1)).logActionShareWithPreview(eq(CONTENT_PREVIEW_TEXT)); + FakeEventLog eventLog = getEventLog(activity); + assertThat(eventLog.getActionShareWithPreview()) + .isEqualTo(new FakeEventLog.ActionShareWithPreview( + /* previewType = */ CONTENT_PREVIEW_TEXT)); } @Test @@ -1268,11 +1281,14 @@ public class UnbundledChooserActivityTest { setupResolverControllers(resolvedComponentInfos); - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - EventLog logger = activity.getEventLog(); - Mockito.verify(logger, times(1)).logActionShareWithPreview(eq(CONTENT_PREVIEW_IMAGE)); + + FakeEventLog eventLog = getEventLog(activity); + assertThat(eventLog.getActionShareWithPreview()) + .isEqualTo(new FakeEventLog.ActionShareWithPreview( + /* previewType = */ CONTENT_PREVIEW_IMAGE)); } @Test @@ -1421,7 +1437,7 @@ public class UnbundledChooserActivityTest { createShortcutLoaderFactory(); // Start activity - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); @@ -1471,22 +1487,15 @@ public class UnbundledChooserActivityTest { .perform(click()); waitForIdle(); - ArgumentCaptor<HashedStringCache.HashResult> hashCaptor = - ArgumentCaptor.forClass(HashedStringCache.HashResult.class); - verify(activity.getEventLog(), times(1)).logShareTargetSelected( - eq(EventLogImpl.SELECTION_TYPE_SERVICE), - /* packageName= */ any(), - /* positionPicked= */ anyInt(), - /* directTargetAlsoRanked= */ eq(-1), - /* numCallerProvided= */ anyInt(), - /* directTargetHashed= */ hashCaptor.capture(), - /* isPinned= */ anyBoolean(), - /* successfullySelected= */ anyBoolean(), - /* selectionCost= */ anyLong()); - String hashedName = hashCaptor.getValue().hashedString; - assertThat( - "Hash is not predictable but must be obfuscated", - hashedName, is(not(name))); + FakeEventLog eventLog = getEventLog(activity); + assertThat(eventLog.getShareTargetSelected()).hasSize(1); + FakeEventLog.ShareTargetSelected call = eventLog.getShareTargetSelected().get(0); + assertThat(call.getTargetType()).isEqualTo(EventLog.SELECTION_TYPE_SERVICE); + assertThat(call.getDirectTargetAlsoRanked()).isEqualTo(-1); + var hashResult = call.getDirectTargetHashed(); + var hash = hashResult == null ? "" : hashResult.hashedString; + assertWithMessage("Hash is not predictable but must be obfuscated") + .that(hash).isNotEqualTo(name); } // This test is too long and too slow and should not be taken as an example for future tests. @@ -1502,7 +1511,7 @@ public class UnbundledChooserActivityTest { createShortcutLoaderFactory(); // Start activity - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); @@ -1554,16 +1563,12 @@ public class UnbundledChooserActivityTest { .perform(click()); waitForIdle(); - verify(activity.getEventLog(), times(1)).logShareTargetSelected( - eq(EventLogImpl.SELECTION_TYPE_SERVICE), - /* packageName= */ any(), - /* positionPicked= */ anyInt(), - /* directTargetAlsoRanked= */ eq(0), - /* numCallerProvided= */ anyInt(), - /* directTargetHashed= */ any(), - /* isPinned= */ anyBoolean(), - /* successfullySelected= */ anyBoolean(), - /* selectionCost= */ anyLong()); + FakeEventLog eventLog = getEventLog(activity); + assertThat(eventLog.getShareTargetSelected()).hasSize(1); + FakeEventLog.ShareTargetSelected call = eventLog.getShareTargetSelected().get(0); + + assertThat(call.getTargetType()).isEqualTo(EventLog.SELECTION_TYPE_SERVICE); + assertThat(call.getDirectTargetAlsoRanked()).isEqualTo(0); } @Test @@ -1935,14 +1940,14 @@ public class UnbundledChooserActivityTest { ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0, PERSONAL_USER_HANDLE); // Start activity - final IChooserWrapper wrapper = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); // Insert the direct share target Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>(); directShareToShortcutInfos.put(serviceTargets.get(0), null); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> wrapper.getAdapter().addServiceResults( - wrapper.createTestDisplayResolveInfo(sendIntent, + () -> activity.getAdapter().addServiceResults( + activity.createTestDisplayResolveInfo(sendIntent, ri, "testLabel", "testInfo", @@ -1957,11 +1962,11 @@ public class UnbundledChooserActivityTest { assertThat( String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)", appTargetsExpected + 16, appTargetsExpected), - wrapper.getAdapter().getCount(), is(appTargetsExpected + 16)); + activity.getAdapter().getCount(), is(appTargetsExpected + 16)); assertThat("Chooser should have exactly one selectable direct target", - wrapper.getAdapter().getSelectableServiceTargetCount(), is(1)); + activity.getAdapter().getSelectableServiceTargetCount(), is(1)); assertThat("The resolver info must match the resolver info used to create the target", - wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri)); + activity.getAdapter().getItem(0).getResolveInfo(), is(ri)); // Click on the direct target String name = serviceTargets.get(0).getTitle().toString(); @@ -1969,18 +1974,16 @@ public class UnbundledChooserActivityTest { .perform(click()); waitForIdle(); - EventLog logger = wrapper.getEventLog(); - verify(logger, times(1)).logShareTargetSelected( - eq(EventLogImpl.SELECTION_TYPE_SERVICE), - /* packageName= */ any(), - /* positionPicked= */ anyInt(), - // The packages sholdn't match for app target and direct target: - /* directTargetAlsoRanked= */ eq(-1), - /* numCallerProvided= */ anyInt(), - /* directTargetHashed= */ any(), - /* isPinned= */ anyBoolean(), - /* successfullySelected= */ anyBoolean(), - /* selectionCost= */ anyLong()); + FakeEventLog eventLog = getEventLog(activity); + var invocations = eventLog.getShareTargetSelected(); + assertWithMessage("Only one ShareTargetSelected event logged") + .that(invocations).hasSize(1); + FakeEventLog.ShareTargetSelected call = invocations.get(0); + assertWithMessage("targetType should be SELECTION_TYPE_SERVICE") + .that(call.getTargetType()).isEqualTo(EventLog.SELECTION_TYPE_SERVICE); + assertWithMessage( + "The packages shouldn't match for app target and direct target") + .that(call.getDirectTargetAlsoRanked()).isEqualTo(-1); } @Test @@ -2253,7 +2256,7 @@ public class UnbundledChooserActivityTest { }; // Start activity - final IChooserWrapper activity = (IChooserWrapper) + ChooserWrapperActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); @@ -2301,18 +2304,10 @@ public class UnbundledChooserActivityTest { .perform(click()); waitForIdle(); - EventLog logger = activity.getEventLog(); - ArgumentCaptor<Integer> typeCaptor = ArgumentCaptor.forClass(Integer.class); - verify(logger, times(1)).logShareTargetSelected( - eq(EventLogImpl.SELECTION_TYPE_SERVICE), - /* packageName= */ any(), - /* positionPicked= */ anyInt(), - /* directTargetAlsoRanked= */ anyInt(), - /* numCallerProvided= */ anyInt(), - /* directTargetHashed= */ any(), - /* isPinned= */ anyBoolean(), - /* successfullySelected= */ anyBoolean(), - /* selectionCost= */ anyLong()); + FakeEventLog eventLog = getEventLog(activity); + assertThat(eventLog.getShareTargetSelected()).hasSize(1); + FakeEventLog.ShareTargetSelected call = eventLog.getShareTargetSelected().get(0); + assertThat(call.getTargetType()).isEqualTo(EventLog.SELECTION_TYPE_SERVICE); } @Test diff --git a/java/tests/src/com/android/intentresolver/logging/EventLogImplTest.java b/java/tests/src/com/android/intentresolver/logging/EventLogImplTest.java index 19177798..d75ea99b 100644 --- a/java/tests/src/com/android/intentresolver/logging/EventLogImplTest.java +++ b/java/tests/src/com/android/intentresolver/logging/EventLogImplTest.java @@ -37,6 +37,7 @@ import com.android.intentresolver.logging.EventLogImpl.SharesheetStartedEvent; import com.android.intentresolver.logging.EventLogImpl.SharesheetTargetSelectedEvent; import com.android.intentresolver.contentpreview.ContentPreviewType; import com.android.internal.logging.InstanceId; +import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger.UiEventEnum; @@ -59,10 +60,12 @@ public final class EventLogImplTest { private EventLogImpl mChooserLogger; + private final InstanceIdSequence mSequence = EventLogImpl.newIdSequence(); + @Before public void setUp() { - //Mockito.reset(mUiEventLog, mFrameworkLog, mMetricsLogger); - mChooserLogger = new EventLogImpl(mUiEventLog, mFrameworkLog, mMetricsLogger); + mChooserLogger = new EventLogImpl(mUiEventLog, mFrameworkLog, mMetricsLogger, + mSequence.newInstanceId()); } @After @@ -320,7 +323,8 @@ public final class EventLogImplTest { public void testDifferentLoggerInstancesUseDifferentInstanceIds() { ArgumentCaptor<Integer> idIntCaptor = ArgumentCaptor.forClass(Integer.class); EventLogImpl chooserLogger2 = - new EventLogImpl(mUiEventLog, mFrameworkLog, mMetricsLogger); + new EventLogImpl(mUiEventLog, mFrameworkLog, mMetricsLogger, + mSequence.newInstanceId()); final int targetType = EventLogImpl.SELECTION_TYPE_COPY; final String packageName = "com.test.foo"; diff --git a/java/tests/src/com/android/intentresolver/logging/FakeEventLog.kt b/java/tests/src/com/android/intentresolver/logging/FakeEventLog.kt new file mode 100644 index 00000000..9ed47db6 --- /dev/null +++ b/java/tests/src/com/android/intentresolver/logging/FakeEventLog.kt @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2023 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.logging + +import android.net.Uri +import android.util.HashedStringCache +import android.util.Log +import com.android.internal.logging.InstanceId +import javax.inject.Inject + +private const val TAG = "EventLog" +private const val LOG = true + +/** A fake EventLog. */ +class FakeEventLog @Inject constructor(private val instanceId: InstanceId) : EventLog { + + var chooserActivityShown: ChooserActivityShown? = null + var actionSelected: ActionSelected? = null + var customActionSelected: CustomActionSelected? = null + var actionShareWithPreview: ActionShareWithPreview? = null + val shareTargetSelected: MutableList<ShareTargetSelected> = mutableListOf() + + private fun log(message: () -> Any?) { + if (LOG) { + Log.d(TAG, "[%04x] ".format(instanceId.id) + message()) + } + } + + override fun logChooserActivityShown( + isWorkProfile: Boolean, + targetMimeType: String?, + systemCost: Long + ) { + chooserActivityShown = ChooserActivityShown(isWorkProfile, targetMimeType, systemCost) + log { chooserActivityShown } + } + + override fun logShareStarted( + packageName: String?, + mimeType: String?, + appProvidedDirect: Int, + appProvidedApp: Int, + isWorkprofile: Boolean, + previewType: Int, + intent: String?, + customActionCount: Int, + modifyShareActionProvided: Boolean + ) { + log { + ShareStarted( + packageName, + mimeType, + appProvidedDirect, + appProvidedApp, + isWorkprofile, + previewType, + intent, + customActionCount, + modifyShareActionProvided + ) + } + } + + override fun logCustomActionSelected(positionPicked: Int) { + customActionSelected = CustomActionSelected(positionPicked) + log { "logCustomActionSelected(positionPicked=$positionPicked)" } + } + + override fun logShareTargetSelected( + targetType: Int, + packageName: String?, + positionPicked: Int, + directTargetAlsoRanked: Int, + numCallerProvided: Int, + directTargetHashed: HashedStringCache.HashResult?, + isPinned: Boolean, + successfullySelected: Boolean, + selectionCost: Long + ) { + shareTargetSelected.add( + ShareTargetSelected( + targetType, + packageName, + positionPicked, + directTargetAlsoRanked, + numCallerProvided, + directTargetHashed, + isPinned, + successfullySelected, + selectionCost + ) + ) + log { shareTargetSelected.last() } + shareTargetSelected.limitSize(10) + } + + private fun MutableList<*>.limitSize(n: Int) { + while (size > n) { + removeFirst() + } + } + + override fun logDirectShareTargetReceived(category: Int, latency: Int) { + log { "logDirectShareTargetReceived(category=$category, latency=$latency)" } + } + + override fun logActionShareWithPreview(previewType: Int) { + actionShareWithPreview = ActionShareWithPreview(previewType) + log { actionShareWithPreview } + } + + override fun logActionSelected(targetType: Int) { + actionSelected = ActionSelected(targetType) + log { actionSelected } + } + + override fun logContentPreviewWarning(uri: Uri?) { + log { "logContentPreviewWarning(uri=$uri)" } + } + + override fun logSharesheetTriggered() { + log { "logSharesheetTriggered()" } + } + + override fun logSharesheetAppLoadComplete() { + log { "logSharesheetAppLoadComplete()" } + } + + override fun logSharesheetDirectLoadComplete() { + log { "logSharesheetAppLoadComplete()" } + } + + override fun logSharesheetDirectLoadTimeout() { + log { "logSharesheetDirectLoadTimeout()" } + } + + override fun logSharesheetProfileChanged() { + log { "logSharesheetProfileChanged()" } + } + + override fun logSharesheetExpansionChanged(isCollapsed: Boolean) { + log { "logSharesheetExpansionChanged(isCollapsed=$isCollapsed)" } + } + + override fun logSharesheetAppShareRankingTimeout() { + log { "logSharesheetAppShareRankingTimeout()" } + } + + override fun logSharesheetEmptyDirectShareRow() { + log { "logSharesheetEmptyDirectShareRow()" } + } + + data class ActionSelected(val targetType: Int) + data class CustomActionSelected(val positionPicked: Int) + data class ActionShareWithPreview(val previewType: Int) + data class ChooserActivityShown( + val isWorkProfile: Boolean, + val targetMimeType: String?, + val systemCost: Long + ) + data class ShareStarted( + val packageName: String?, + val mimeType: String?, + val appProvidedDirect: Int, + val appProvidedApp: Int, + val isWorkprofile: Boolean, + val previewType: Int, + val intent: String?, + val customActionCount: Int, + val modifyShareActionProvided: Boolean + ) + data class ShareTargetSelected( + val targetType: Int, + val packageName: String?, + val positionPicked: Int, + val directTargetAlsoRanked: Int, + val numCallerProvided: Int, + val directTargetHashed: HashedStringCache.HashResult?, + val pinned: Boolean, + val successfullySelected: Boolean, + val selectionCost: Long + ) +} diff --git a/java/tests/src/com/android/intentresolver/logging/FakeFrameworkStatsLogger.kt b/java/tests/src/com/android/intentresolver/logging/FakeFrameworkStatsLogger.kt new file mode 100644 index 00000000..dcf8d23f --- /dev/null +++ b/java/tests/src/com/android/intentresolver/logging/FakeFrameworkStatsLogger.kt @@ -0,0 +1,95 @@ +package com.android.intentresolver.logging +/* + * Copyright (C) 2023 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. + */ + +import com.android.internal.util.FrameworkStatsLog + +internal data class ShareSheetStarted( + val frameworkEventId: Int = FrameworkStatsLog.SHARESHEET_STARTED, + val appEventId: Int, + val packageName: String?, + val instanceId: Int, + val mimeType: String?, + val numAppProvidedDirectTargets: Int, + val numAppProvidedAppTargets: Int, + val isWorkProfile: Boolean, + val previewType: Int, + val intentType: Int, + val numCustomActions: Int, + val modifyShareActionProvided: Boolean +) + +internal data class RankingSelected( + val frameworkEventId: Int = FrameworkStatsLog.RANKING_SELECTED, + val appEventId: Int, + val packageName: String?, + val instanceId: Int, + val positionPicked: Int, + val isPinned: Boolean +) + +internal class FakeFrameworkStatsLogger : FrameworkStatsLogger { + var shareSheetStarted: ShareSheetStarted? = null + var rankingSelected: RankingSelected? = null + override fun write( + frameworkEventId: Int, + appEventId: Int, + packageName: String?, + instanceId: Int, + mimeType: String?, + numAppProvidedDirectTargets: Int, + numAppProvidedAppTargets: Int, + isWorkProfile: Boolean, + previewType: Int, + intentType: Int, + numCustomActions: Int, + modifyShareActionProvided: Boolean + ) { + shareSheetStarted = + ShareSheetStarted( + frameworkEventId, + appEventId, + packageName, + instanceId, + mimeType, + numAppProvidedDirectTargets, + numAppProvidedAppTargets, + isWorkProfile, + previewType, + intentType, + numCustomActions, + modifyShareActionProvided + ) + } + override fun write( + frameworkEventId: Int, + appEventId: Int, + packageName: String?, + instanceId: Int, + positionPicked: Int, + isPinned: Boolean + ) { + rankingSelected = + RankingSelected( + frameworkEventId, + appEventId, + packageName, + instanceId, + positionPicked, + isPinned + ) + } +} diff --git a/java/tests/src/com/android/intentresolver/logging/TestEventLogModule.kt b/java/tests/src/com/android/intentresolver/logging/TestEventLogModule.kt new file mode 100644 index 00000000..cd808af4 --- /dev/null +++ b/java/tests/src/com/android/intentresolver/logging/TestEventLogModule.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 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.logging + +import com.android.internal.logging.InstanceId +import com.android.internal.logging.InstanceIdSequence +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.android.components.ActivityComponent +import dagger.hilt.android.scopes.ActivityScoped +import dagger.hilt.testing.TestInstallIn + +/** Binds a [FakeEventLog] as [EventLog] in tests. */ +@Module +@TestInstallIn(components = [ActivityComponent::class], replaces = [EventLogModule::class]) +interface TestEventLogModule { + + @Binds @ActivityScoped fun fakeEventLog(impl: FakeEventLog): EventLog + + companion object { + @Provides + fun instanceId(sequence: InstanceIdSequence): InstanceId = sequence.newInstanceId() + } +} |