From 58534f4139ebdec4ef9fed16688fda0b9798477d Mon Sep 17 00:00:00 2001 From: Mark Renouf Date: Fri, 28 Jul 2023 10:42:00 -0400 Subject: Renames ChooserActivityLogger => logging/EventLog Change-Id: Ia742b6f425c1f1df84b58f7e4fe81eebb8c20117 --- .../intentresolver/ChooserActionFactory.java | 17 +- .../android/intentresolver/ChooserActivity.java | 49 +- .../intentresolver/ChooserActivityLogger.java | 538 -------------------- .../android/intentresolver/ChooserListAdapter.java | 9 +- .../android/intentresolver/logging/EventLog.java | 539 +++++++++++++++++++++ .../model/AbstractResolverComparator.java | 16 +- .../AppPredictionServiceResolverComparator.java | 8 +- .../ResolverRankerServiceResolverComparator.java | 10 +- 8 files changed, 595 insertions(+), 591 deletions(-) delete mode 100644 java/src/com/android/intentresolver/ChooserActivityLogger.java create mode 100644 java/src/com/android/intentresolver/logging/EventLog.java (limited to 'java/src') diff --git a/java/src/com/android/intentresolver/ChooserActionFactory.java b/java/src/com/android/intentresolver/ChooserActionFactory.java index 06c7e8d7..a54e8c62 100644 --- a/java/src/com/android/intentresolver/ChooserActionFactory.java +++ b/java/src/com/android/intentresolver/ChooserActionFactory.java @@ -37,6 +37,7 @@ import android.view.View; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.TargetInfo; import com.android.intentresolver.contentpreview.ChooserContentPreviewUi; +import com.android.intentresolver.logging.EventLog; import com.android.intentresolver.widget.ActionRow; import com.android.internal.annotations.VisibleForTesting; @@ -97,7 +98,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio private final @Nullable ChooserAction mModifyShareAction; private final Consumer mExcludeSharedTextAction; private final Consumer mFinishCallback; - private final ChooserActivityLogger mLogger; + private final EventLog mLogger; /** * @param context @@ -116,7 +117,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio Context context, ChooserRequestParameters chooserRequest, ChooserIntegratedDeviceComponents integratedDeviceComponents, - ChooserActivityLogger logger, + EventLog logger, Consumer onUpdateSharedTextIsExcluded, Callable firstVisibleImageQuery, ActionActivityStarter activityStarter, @@ -152,7 +153,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio List customActions, @Nullable ChooserAction modifyShareAction, Consumer onUpdateSharedTextIsExcluded, - ChooserActivityLogger logger, + EventLog logger, Consumer finishCallback) { mContext = context; mCopyButtonRunnable = copyButtonRunnable; @@ -208,7 +209,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio mModifyShareAction, mFinishCallback, () -> { - mLogger.logActionSelected(ChooserActivityLogger.SELECTION_TYPE_MODIFY_SHARE); + mLogger.logActionSelected(EventLog.SELECTION_TYPE_MODIFY_SHARE); }); } @@ -232,7 +233,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio Intent targetIntent, String referrerPackageName, Consumer finishCallback, - ChooserActivityLogger logger) { + EventLog logger) { final ClipData clipData; try { clipData = extractTextToCopy(targetIntent); @@ -248,7 +249,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio Context.CLIPBOARD_SERVICE); clipboardManager.setPrimaryClipAsPackage(clipData, referrerPackageName); - logger.logActionSelected(ChooserActivityLogger.SELECTION_TYPE_COPY); + logger.logActionSelected(EventLog.SELECTION_TYPE_COPY); finishCallback.accept(Activity.RESULT_OK); }; } @@ -327,10 +328,10 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio TargetInfo editSharingTarget, Callable firstVisibleImageQuery, ActionActivityStarter activityStarter, - ChooserActivityLogger logger) { + EventLog logger) { return () -> { // Log share completion via edit. - logger.logActionSelected(ChooserActivityLogger.SELECTION_TYPE_EDIT); + logger.logActionSelected(EventLog.SELECTION_TYPE_EDIT); View firstImageView = null; try { diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 7ebcf9f9..b041475b 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -92,6 +92,7 @@ import com.android.intentresolver.flags.FeatureFlagRepositoryFactory; 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.measurements.Tracer; import com.android.intentresolver.model.AbstractResolverComparator; import com.android.intentresolver.model.AppPredictionServiceResolverComparator; @@ -193,7 +194,7 @@ public class ChooserActivity extends ResolverActivity implements private boolean mShouldDisplayLandscape; // statsd logger wrapper - protected ChooserActivityLogger mChooserActivityLogger; + protected EventLog mEventLog; private long mChooserShownTime; protected boolean mIsSuccessfullySelected; @@ -236,7 +237,7 @@ public class ChooserActivity extends ResolverActivity implements final long intentReceivedTime = System.currentTimeMillis(); mLatencyTracker.onActionStart(ACTION_LOAD_SHARE_SHEET); - getChooserActivityLogger().logSharesheetTriggered(); + getEventLog().logSharesheetTriggered(); mFeatureFlagRepository = createFeatureFlagRepository(); mIntegratedDeviceComponents = getIntegratedDeviceComponents(); @@ -314,7 +315,7 @@ public class ChooserActivity extends ResolverActivity implements mChooserShownTime = System.currentTimeMillis(); final long systemCost = mChooserShownTime - intentReceivedTime; - getChooserActivityLogger().logChooserActivityShown( + getEventLog().logChooserActivityShown( isWorkProfile(), mChooserRequest.getTargetType(), systemCost); if (mResolverDrawerLayout != null) { @@ -323,7 +324,7 @@ public class ChooserActivity extends ResolverActivity implements mResolverDrawerLayout.setOnCollapsedChangedListener( isCollapsed -> { mChooserMultiProfilePagerAdapter.setIsCollapsed(isCollapsed); - getChooserActivityLogger().logSharesheetExpansionChanged(isCollapsed); + getEventLog().logSharesheetExpansionChanged(isCollapsed); }); } @@ -331,7 +332,7 @@ public class ChooserActivity extends ResolverActivity implements Log.d(TAG, "System Time Cost is " + systemCost); } - getChooserActivityLogger().logShareStarted( + getEventLog().logShareStarted( getReferrerPackageName(), mChooserRequest.getTargetType(), mChooserRequest.getCallerChooserTargets().size(), @@ -550,7 +551,7 @@ public class ChooserActivity extends ResolverActivity implements if (shouldShowStickyContentPreview() || mChooserMultiProfilePagerAdapter .getCurrentRootAdapter().getSystemRowCount() != 0) { - getChooserActivityLogger().logActionShareWithPreview( + getEventLog().logActionShareWithPreview( mChooserContentPreviewUi.getPreferredContentPreview()); } return postRebuildListInternal(rebuildCompleted); @@ -910,8 +911,8 @@ public class ChooserActivity extends ResolverActivity implements if ((currentListAdapter.getCount() > 0) && (targetInfo != null)) { switch (currentListAdapter.getPositionTargetType(which)) { case ChooserListAdapter.TARGET_SERVICE: - getChooserActivityLogger().logShareTargetSelected( - ChooserActivityLogger.SELECTION_TYPE_SERVICE, + getEventLog().logShareTargetSelected( + EventLog.SELECTION_TYPE_SERVICE, targetInfo.getResolveInfo().activityInfo.processName, which, /* directTargetAlsoRanked= */ getRankedPosition(targetInfo), @@ -924,8 +925,8 @@ public class ChooserActivity extends ResolverActivity implements return; case ChooserListAdapter.TARGET_CALLER: case ChooserListAdapter.TARGET_STANDARD: - getChooserActivityLogger().logShareTargetSelected( - ChooserActivityLogger.SELECTION_TYPE_APP, + getEventLog().logShareTargetSelected( + EventLog.SELECTION_TYPE_APP, targetInfo.getResolveInfo().activityInfo.processName, (which - currentListAdapter.getSurfacedTargetInfo().size()), /* directTargetAlsoRanked= */ -1, @@ -941,8 +942,8 @@ public class ChooserActivity extends ResolverActivity implements // they are from the alphabetical pool. // TODO: why do we log a different selection type if the -1 value already // designates the same condition? - getChooserActivityLogger().logShareTargetSelected( - ChooserActivityLogger.SELECTION_TYPE_STANDARD, + getEventLog().logShareTargetSelected( + EventLog.SELECTION_TYPE_STANDARD, targetInfo.getResolveInfo().activityInfo.processName, /* value= */ -1, /* directTargetAlsoRanked= */ -1, @@ -994,7 +995,7 @@ public class ChooserActivity extends ResolverActivity implements if (profileRecord == null) { return; } - getChooserActivityLogger().logDirectShareTargetReceived( + getEventLog().logDirectShareTargetReceived( MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER, (int) (SystemClock.elapsedRealtime() - profileRecord.loadingStartTime)); } @@ -1128,11 +1129,11 @@ public class ChooserActivity extends ResolverActivity implements } } - protected ChooserActivityLogger getChooserActivityLogger() { - if (mChooserActivityLogger == null) { - mChooserActivityLogger = new ChooserActivityLogger(); + protected EventLog getEventLog() { + if (mEventLog == null) { + mEventLog = new EventLog(); } - return mChooserActivityLogger; + return mEventLog; } public class ChooserListController extends ResolverListController { @@ -1258,7 +1259,7 @@ public class ChooserActivity extends ResolverActivity implements targetIntent, this, context.getPackageManager(), - getChooserActivityLogger(), + getEventLog(), chooserRequest, maxTargetsPerRow, initialIntentsUserSpace, @@ -1282,7 +1283,7 @@ public class ChooserActivity extends ResolverActivity implements AbstractResolverComparator resolverComparator; if (appPredictor != null) { resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(), - getReferrerPackageName(), appPredictor, userHandle, getChooserActivityLogger(), + getReferrerPackageName(), appPredictor, userHandle, getEventLog(), getIntegratedDeviceComponents().getNearbySharingComponent()); } else { resolverComparator = @@ -1291,7 +1292,7 @@ public class ChooserActivity extends ResolverActivity implements getTargetIntent(), getReferrerPackageName(), null, - getChooserActivityLogger(), + getEventLog(), getResolverRankerServiceUserHandleList(userHandle), getIntegratedDeviceComponents().getNearbySharingComponent()); } @@ -1316,7 +1317,7 @@ public class ChooserActivity extends ResolverActivity implements this, mChooserRequest, mIntegratedDeviceComponents, - getChooserActivityLogger(), + getEventLog(), (isExcluded) -> mExcludeSharedText = isExcluded, this::getFirstVisibleImgPreviewView, new ChooserActionFactory.ActionActivityStarter() { @@ -1531,7 +1532,7 @@ public class ChooserActivity extends ResolverActivity implements Log.d(TAG, "app target loading time " + duration + " ms"); } addCallerChooserTargets(); - getChooserActivityLogger().logSharesheetAppLoadComplete(); + getEventLog().logSharesheetAppLoadComplete(); maybeQueryAdditionalPostProcessingTargets(chooserListAdapter); mLatencyTracker.onActionEnd(ACTION_LOAD_SHARE_SHEET); } @@ -1578,7 +1579,7 @@ public class ChooserActivity extends ResolverActivity implements } logDirectShareTargetReceived(userHandle); sendVoiceChoicesIfNeeded(); - getChooserActivityLogger().logSharesheetDirectLoadComplete(); + getEventLog().logSharesheetDirectLoadComplete(); } private void setupScrollListener() { @@ -1884,7 +1885,7 @@ public class ChooserActivity extends ResolverActivity implements @Override protected void maybeLogProfileChange() { - getChooserActivityLogger().logSharesheetProfileChanged(); + getEventLog().logSharesheetProfileChanged(); } private static class ProfileRecord { diff --git a/java/src/com/android/intentresolver/ChooserActivityLogger.java b/java/src/com/android/intentresolver/ChooserActivityLogger.java deleted file mode 100644 index 1f606f26..00000000 --- a/java/src/com/android/intentresolver/ChooserActivityLogger.java +++ /dev/null @@ -1,538 +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 android.annotation.Nullable; -import android.content.Intent; -import android.metrics.LogMaker; -import android.net.Uri; -import android.provider.MediaStore; -import android.util.HashedStringCache; -import android.util.Log; - -import com.android.intentresolver.contentpreview.ContentPreviewType; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.logging.InstanceId; -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; - -/** - * Helper for writing Sharesheet atoms to statsd log. - * @hide - */ -public class ChooserActivityLogger { - private static final String TAG = "ChooserActivity"; - private static final boolean DEBUG = true; - - public static final int SELECTION_TYPE_SERVICE = 1; - public static final int SELECTION_TYPE_APP = 2; - public static final int SELECTION_TYPE_STANDARD = 3; - public static final int SELECTION_TYPE_COPY = 4; - public static final int SELECTION_TYPE_NEARBY = 5; - public static final int SELECTION_TYPE_EDIT = 6; - public static final int SELECTION_TYPE_MODIFY_SHARE = 7; - public static final int SELECTION_TYPE_CUSTOM_ACTION = 8; - - /** - * 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, - int numCustomActions, - boolean modifyShareActionProvided); - - /** 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; - private final MetricsLogger mMetricsLogger; - - public ChooserActivityLogger() { - this(new UiEventLoggerImpl(), new DefaultFrameworkStatsLogger(), new MetricsLogger()); - } - - @VisibleForTesting - ChooserActivityLogger( - UiEventLogger uiEventLogger, - FrameworkStatsLogger frameworkLogger, - MetricsLogger metricsLogger) { - mUiEventLogger = uiEventLogger; - mFrameworkStatsLogger = frameworkLogger; - mMetricsLogger = metricsLogger; - } - - /** Records metrics for the start time of the {@link ChooserActivity}. */ - public void logChooserActivityShown( - boolean isWorkProfile, String targetMimeType, long systemCost) { - mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN) - .setSubtype( - isWorkProfile ? MetricsEvent.MANAGED_PROFILE : MetricsEvent.PARENT_PROFILE) - .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, targetMimeType) - .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost)); - } - - /** Logs a UiEventReported event for the system sharesheet completing initial start-up. */ - public void logShareStarted( - String packageName, - String mimeType, - int appProvidedDirect, - int appProvidedApp, - boolean isWorkprofile, - int previewType, - String intent, - int customActionCount, - boolean modifyShareActionProvided) { - 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), - /* num_provided_custom_actions = 10 */ customActionCount, - /* modify_share_action_provided = 11 */ modifyShareActionProvided); - } - - /** - * Log that a custom action has been tapped by the user. - * - * @param positionPicked index of the custom action within the list of custom actions. - */ - public void logCustomActionSelected(int positionPicked) { - mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, - /* event_id = 1 */ - SharesheetTargetSelectedEvent.SHARESHEET_CUSTOM_ACTION_SELECTED.getId(), - /* package_name = 2 */ null, - /* instance_id = 3 */ getInstanceId().getId(), - /* position_picked = 4 */ positionPicked, - /* is_pinned = 5 */ false); - } - - /** - * Logs a UiEventReported event for the system sharesheet when the user selects a target. - * TODO: document parameters and/or consider breaking up by targetType so we don't have to - * support an overly-generic signature. - */ - public void logShareTargetSelected( - int targetType, - String packageName, - int positionPicked, - int directTargetAlsoRanked, - int numCallerProvided, - @Nullable HashedStringCache.HashResult directTargetHashed, - boolean isPinned, - boolean successfullySelected, - long selectionCost) { - 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); - - int category = getTargetSelectionCategory(targetType); - if (category != 0) { - LogMaker targetLogMaker = new LogMaker(category).setSubtype(positionPicked); - if (directTargetHashed != null) { - targetLogMaker.addTaggedData( - MetricsEvent.FIELD_HASHED_TARGET_NAME, directTargetHashed.hashedString); - targetLogMaker.addTaggedData( - MetricsEvent.FIELD_HASHED_TARGET_SALT_GEN, - directTargetHashed.saltGeneration); - targetLogMaker.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION, - directTargetAlsoRanked); - } - targetLogMaker.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, numCallerProvided); - mMetricsLogger.write(targetLogMaker); - } - - if (successfullySelected) { - if (DEBUG) { - Log.d(TAG, "User Selection Time Cost is " + selectionCost); - Log.d(TAG, "position of selected app/service/caller is " + positionPicked); - } - MetricsLogger.histogram( - null, "user_selection_cost_for_smart_sharing", (int) selectionCost); - MetricsLogger.histogram(null, "app_position_for_smart_sharing", positionPicked); - } - } - - /** Log when direct share targets were received. */ - public void logDirectShareTargetReceived(int category, int latency) { - mMetricsLogger.write(new LogMaker(category).setSubtype(latency)); - } - - /** - * Log when we display a preview UI of the specified {@code previewType} as part of our - * Sharesheet session. - */ - public void logActionShareWithPreview(int previewType) { - mMetricsLogger.write( - new LogMaker(MetricsEvent.ACTION_SHARE_WITH_PREVIEW).setSubtype(previewType)); - } - - /** Log when the user selects an action button with the specified {@code targetType}. */ - public void logActionSelected(int targetType) { - if (targetType == SELECTION_TYPE_COPY) { - LogMaker targetLogMaker = new LogMaker( - MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET).setSubtype(1); - mMetricsLogger.write(targetLogMaker); - } - mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, - /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), - /* package_name = 2 */ "", - /* instance_id = 3 */ getInstanceId().getId(), - /* position_picked = 4 */ -1, - /* is_pinned = 5 */ false); - } - - /** Log a warning that we couldn't display the content preview from the supplied {@code uri}. */ - public void logContentPreviewWarning(Uri uri) { - // The ContentResolver already logs the exception. Log something more informative. - Log.w(TAG, "Could not load (" + uri.toString() + ") thumbnail/name for preview. If " - + "desired, consider using Intent#createChooser to launch the ChooserActivity, " - + "and set your Intent's clipData and flags in accordance with that method's " - + "documentation"); - - } - - /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */ - public void logSharesheetTriggered() { - log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId()); - } - - /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */ - public void logSharesheetAppLoadComplete() { - log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId()); - } - - /** - * Logs a UiEventReported event for the system sharesheet completing loading service targets. - */ - public void logSharesheetDirectLoadComplete() { - log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId()); - } - - /** - * Logs a UiEventReported event for the system sharesheet timing out loading service targets. - */ - public void logSharesheetDirectLoadTimeout() { - log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId()); - } - - /** - * Logs a UiEventReported event for the system sharesheet switching - * between work and main profile. - */ - public void logSharesheetProfileChanged() { - log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId()); - } - - /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */ - public void logSharesheetExpansionChanged(boolean isCollapsed) { - log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED : - SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); - } - - /** - * Logs a UiEventReported event for the system sharesheet app share ranking timing out. - */ - 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. - */ - public void logSharesheetEmptyDirectShareRow() { - log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId()); - } - - /** - * Logs a UiEventReported event for a given share activity - * @param event - * @param instanceId - */ - private void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) { - mUiEventLogger.logWithInstanceId( - event, - 0, - null, - instanceId); - } - - /** - * @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 { - @UiEvent(doc = "Basic system Sharesheet has started and is visible.") - SHARE_STARTED(228); - - private final int mId; - SharesheetStartedEvent(int id) { - mId = id; - } - @Override - public int getId() { - return mId; - } - } - - /** - * The UiEvent enums that this class can log. - */ - enum SharesheetTargetSelectedEvent implements UiEventLogger.UiEventEnum { - INVALID(0), - @UiEvent(doc = "User selected a service target.") - SHARESHEET_SERVICE_TARGET_SELECTED(232), - @UiEvent(doc = "User selected an app target.") - SHARESHEET_APP_TARGET_SELECTED(233), - @UiEvent(doc = "User selected a standard target.") - SHARESHEET_STANDARD_TARGET_SELECTED(234), - @UiEvent(doc = "User selected the copy target.") - SHARESHEET_COPY_TARGET_SELECTED(235), - @UiEvent(doc = "User selected the nearby target.") - SHARESHEET_NEARBY_TARGET_SELECTED(626), - @UiEvent(doc = "User selected the edit target.") - SHARESHEET_EDIT_TARGET_SELECTED(669), - @UiEvent(doc = "User selected the modify share target.") - SHARESHEET_MODIFY_SHARE_SELECTED(1316), - @UiEvent(doc = "User selected a custom action.") - SHARESHEET_CUSTOM_ACTION_SELECTED(1317); - - private final int mId; - SharesheetTargetSelectedEvent(int id) { - mId = id; - } - @Override public int getId() { - return mId; - } - - public static SharesheetTargetSelectedEvent fromTargetType(int targetType) { - switch(targetType) { - case SELECTION_TYPE_SERVICE: - return SHARESHEET_SERVICE_TARGET_SELECTED; - case SELECTION_TYPE_APP: - return SHARESHEET_APP_TARGET_SELECTED; - case SELECTION_TYPE_STANDARD: - return SHARESHEET_STANDARD_TARGET_SELECTED; - case SELECTION_TYPE_COPY: - return SHARESHEET_COPY_TARGET_SELECTED; - case SELECTION_TYPE_NEARBY: - return SHARESHEET_NEARBY_TARGET_SELECTED; - case SELECTION_TYPE_EDIT: - return SHARESHEET_EDIT_TARGET_SELECTED; - case SELECTION_TYPE_MODIFY_SHARE: - return SHARESHEET_MODIFY_SHARE_SELECTED; - case SELECTION_TYPE_CUSTOM_ACTION: - return SHARESHEET_CUSTOM_ACTION_SELECTED; - default: - return INVALID; - } - } - } - - /** - * The UiEvent enums that this class can log. - */ - enum SharesheetStandardEvent implements UiEventLogger.UiEventEnum { - INVALID(0), - @UiEvent(doc = "User clicked share.") - SHARESHEET_TRIGGERED(227), - @UiEvent(doc = "User changed from work to personal profile or vice versa.") - SHARESHEET_PROFILE_CHANGED(229), - @UiEvent(doc = "User expanded target list.") - SHARESHEET_EXPANDED(230), - @UiEvent(doc = "User collapsed target list.") - SHARESHEET_COLLAPSED(231), - @UiEvent(doc = "Sharesheet app targets is fully populated.") - SHARESHEET_APP_LOAD_COMPLETE(322), - @UiEvent(doc = "Sharesheet direct targets is fully populated.") - SHARESHEET_DIRECT_LOAD_COMPLETE(323), - @UiEvent(doc = "Sharesheet direct targets timed out.") - SHARESHEET_DIRECT_LOAD_TIMEOUT(324), - @UiEvent(doc = "Sharesheet app share ranking timed out.") - SHARESHEET_APP_SHARE_RANKING_TIMEOUT(831), - @UiEvent(doc = "Sharesheet empty direct share row.") - SHARESHEET_EMPTY_DIRECT_SHARE_ROW(828); - - private final int mId; - SharesheetStandardEvent(int id) { - mId = id; - } - @Override public int getId() { - return mId; - } - } - - /** - * Returns the enum used in sharesheet started atom to indicate what preview type was used. - */ - private static int typeFromPreviewInt(int previewType) { - switch(previewType) { - case ContentPreviewType.CONTENT_PREVIEW_IMAGE: - return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_IMAGE; - case ContentPreviewType.CONTENT_PREVIEW_FILE: - return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE; - case ContentPreviewType.CONTENT_PREVIEW_TEXT: - default: - return FrameworkStatsLog - .SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_TYPE_UNKNOWN; - } - } - - /** - * Returns the enum used in sharesheet started atom to indicate what intent triggers the - * ChooserActivity. - */ - private static int typeFromIntentString(String intent) { - if (intent == null) { - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; - } - switch (intent) { - case Intent.ACTION_VIEW: - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_VIEW; - case Intent.ACTION_EDIT: - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_EDIT; - case Intent.ACTION_SEND: - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND; - case Intent.ACTION_SENDTO: - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO; - case Intent.ACTION_SEND_MULTIPLE: - return FrameworkStatsLog - .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND_MULTIPLE; - case MediaStore.ACTION_IMAGE_CAPTURE: - return FrameworkStatsLog - .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_IMAGE_CAPTURE; - case Intent.ACTION_MAIN: - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_MAIN; - default: - return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; - } - } - - @VisibleForTesting - static int getTargetSelectionCategory(int targetType) { - switch (targetType) { - case SELECTION_TYPE_SERVICE: - return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET; - case SELECTION_TYPE_APP: - return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET; - case SELECTION_TYPE_STANDARD: - return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET; - default: - 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/ChooserListAdapter.java b/java/src/com/android/intentresolver/ChooserListAdapter.java index de947bd1..e6d6dbf4 100644 --- a/java/src/com/android/intentresolver/ChooserListAdapter.java +++ b/java/src/com/android/intentresolver/ChooserListAdapter.java @@ -49,6 +49,7 @@ import com.android.intentresolver.chooser.NotSelectableTargetInfo; import com.android.intentresolver.chooser.SelectableTargetInfo; import com.android.intentresolver.chooser.TargetInfo; import com.android.intentresolver.icons.TargetDataLoader; +import com.android.intentresolver.logging.EventLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; @@ -80,7 +81,7 @@ public class ChooserListAdapter extends ResolverListAdapter { private final ChooserRequestParameters mChooserRequest; private final int mMaxRankedTargets; - private final ChooserActivityLogger mChooserActivityLogger; + private final EventLog mEventLog; private final Set mRequestedIcons = new HashSet<>(); @@ -139,7 +140,7 @@ public class ChooserListAdapter extends ResolverListAdapter { Intent targetIntent, ResolverListCommunicator resolverListCommunicator, PackageManager packageManager, - ChooserActivityLogger chooserActivityLogger, + EventLog eventLog, ChooserRequestParameters chooserRequest, int maxRankedTargets, UserHandle initialIntentsUserSpace, @@ -165,7 +166,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mPlaceHolderTargetInfo = NotSelectableTargetInfo.newPlaceHolderTargetInfo(context); mTargetDataLoader = targetDataLoader; createPlaceHolders(); - mChooserActivityLogger = chooserActivityLogger; + mEventLog = eventLog; mShortcutSelectionLogic = new ShortcutSelectionLogic( context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp), DeviceConfig.getBoolean( @@ -633,7 +634,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mServiceTargets.removeIf(o -> o.isPlaceHolderTargetInfo()); if (mServiceTargets.isEmpty()) { mServiceTargets.add(NotSelectableTargetInfo.newEmptyTargetInfo()); - mChooserActivityLogger.logSharesheetEmptyDirectShareRow(); + mEventLog.logSharesheetEmptyDirectShareRow(); } notifyDataSetChanged(); } diff --git a/java/src/com/android/intentresolver/logging/EventLog.java b/java/src/com/android/intentresolver/logging/EventLog.java new file mode 100644 index 00000000..b30e825b --- /dev/null +++ b/java/src/com/android/intentresolver/logging/EventLog.java @@ -0,0 +1,539 @@ +/* + * 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.annotation.Nullable; +import android.content.Intent; +import android.metrics.LogMaker; +import android.net.Uri; +import android.provider.MediaStore; +import android.util.HashedStringCache; +import android.util.Log; + +import com.android.intentresolver.ChooserActivity; +import com.android.intentresolver.contentpreview.ContentPreviewType; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.InstanceId; +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; + +/** + * Helper for writing Sharesheet atoms to statsd log. + * @hide + */ +public class EventLog { + private static final String TAG = "ChooserActivity"; + private static final boolean DEBUG = true; + + public static final int SELECTION_TYPE_SERVICE = 1; + public static final int SELECTION_TYPE_APP = 2; + public static final int SELECTION_TYPE_STANDARD = 3; + public static final int SELECTION_TYPE_COPY = 4; + public static final int SELECTION_TYPE_NEARBY = 5; + public static final int SELECTION_TYPE_EDIT = 6; + public static final int SELECTION_TYPE_MODIFY_SHARE = 7; + public static final int SELECTION_TYPE_CUSTOM_ACTION = 8; + + /** + * 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, + int numCustomActions, + boolean modifyShareActionProvided); + + /** 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; + private final MetricsLogger mMetricsLogger; + + public EventLog() { + this(new UiEventLoggerImpl(), new DefaultFrameworkStatsLogger(), new MetricsLogger()); + } + + @VisibleForTesting + EventLog( + UiEventLogger uiEventLogger, + FrameworkStatsLogger frameworkLogger, + MetricsLogger metricsLogger) { + mUiEventLogger = uiEventLogger; + mFrameworkStatsLogger = frameworkLogger; + mMetricsLogger = metricsLogger; + } + + /** Records metrics for the start time of the {@link ChooserActivity}. */ + public void logChooserActivityShown( + boolean isWorkProfile, String targetMimeType, long systemCost) { + mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN) + .setSubtype( + isWorkProfile ? MetricsEvent.MANAGED_PROFILE : MetricsEvent.PARENT_PROFILE) + .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, targetMimeType) + .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost)); + } + + /** Logs a UiEventReported event for the system sharesheet completing initial start-up. */ + public void logShareStarted( + String packageName, + String mimeType, + int appProvidedDirect, + int appProvidedApp, + boolean isWorkprofile, + int previewType, + String intent, + int customActionCount, + boolean modifyShareActionProvided) { + 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), + /* num_provided_custom_actions = 10 */ customActionCount, + /* modify_share_action_provided = 11 */ modifyShareActionProvided); + } + + /** + * Log that a custom action has been tapped by the user. + * + * @param positionPicked index of the custom action within the list of custom actions. + */ + public void logCustomActionSelected(int positionPicked) { + mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, + /* event_id = 1 */ + SharesheetTargetSelectedEvent.SHARESHEET_CUSTOM_ACTION_SELECTED.getId(), + /* package_name = 2 */ null, + /* instance_id = 3 */ getInstanceId().getId(), + /* position_picked = 4 */ positionPicked, + /* is_pinned = 5 */ false); + } + + /** + * Logs a UiEventReported event for the system sharesheet when the user selects a target. + * TODO: document parameters and/or consider breaking up by targetType so we don't have to + * support an overly-generic signature. + */ + public void logShareTargetSelected( + int targetType, + String packageName, + int positionPicked, + int directTargetAlsoRanked, + int numCallerProvided, + @Nullable HashedStringCache.HashResult directTargetHashed, + boolean isPinned, + boolean successfullySelected, + long selectionCost) { + 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); + + int category = getTargetSelectionCategory(targetType); + if (category != 0) { + LogMaker targetLogMaker = new LogMaker(category).setSubtype(positionPicked); + if (directTargetHashed != null) { + targetLogMaker.addTaggedData( + MetricsEvent.FIELD_HASHED_TARGET_NAME, directTargetHashed.hashedString); + targetLogMaker.addTaggedData( + MetricsEvent.FIELD_HASHED_TARGET_SALT_GEN, + directTargetHashed.saltGeneration); + targetLogMaker.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION, + directTargetAlsoRanked); + } + targetLogMaker.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, numCallerProvided); + mMetricsLogger.write(targetLogMaker); + } + + if (successfullySelected) { + if (DEBUG) { + Log.d(TAG, "User Selection Time Cost is " + selectionCost); + Log.d(TAG, "position of selected app/service/caller is " + positionPicked); + } + MetricsLogger.histogram( + null, "user_selection_cost_for_smart_sharing", (int) selectionCost); + MetricsLogger.histogram(null, "app_position_for_smart_sharing", positionPicked); + } + } + + /** Log when direct share targets were received. */ + public void logDirectShareTargetReceived(int category, int latency) { + mMetricsLogger.write(new LogMaker(category).setSubtype(latency)); + } + + /** + * Log when we display a preview UI of the specified {@code previewType} as part of our + * Sharesheet session. + */ + public void logActionShareWithPreview(int previewType) { + mMetricsLogger.write( + new LogMaker(MetricsEvent.ACTION_SHARE_WITH_PREVIEW).setSubtype(previewType)); + } + + /** Log when the user selects an action button with the specified {@code targetType}. */ + public void logActionSelected(int targetType) { + if (targetType == SELECTION_TYPE_COPY) { + LogMaker targetLogMaker = new LogMaker( + MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET).setSubtype(1); + mMetricsLogger.write(targetLogMaker); + } + mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, + /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), + /* package_name = 2 */ "", + /* instance_id = 3 */ getInstanceId().getId(), + /* position_picked = 4 */ -1, + /* is_pinned = 5 */ false); + } + + /** Log a warning that we couldn't display the content preview from the supplied {@code uri}. */ + public void logContentPreviewWarning(Uri uri) { + // The ContentResolver already logs the exception. Log something more informative. + Log.w(TAG, "Could not load (" + uri.toString() + ") thumbnail/name for preview. If " + + "desired, consider using Intent#createChooser to launch the ChooserActivity, " + + "and set your Intent's clipData and flags in accordance with that method's " + + "documentation"); + + } + + /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */ + public void logSharesheetTriggered() { + log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId()); + } + + /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */ + public void logSharesheetAppLoadComplete() { + log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId()); + } + + /** + * Logs a UiEventReported event for the system sharesheet completing loading service targets. + */ + public void logSharesheetDirectLoadComplete() { + log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId()); + } + + /** + * Logs a UiEventReported event for the system sharesheet timing out loading service targets. + */ + public void logSharesheetDirectLoadTimeout() { + log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId()); + } + + /** + * Logs a UiEventReported event for the system sharesheet switching + * between work and main profile. + */ + public void logSharesheetProfileChanged() { + log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId()); + } + + /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */ + public void logSharesheetExpansionChanged(boolean isCollapsed) { + log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED : + SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); + } + + /** + * Logs a UiEventReported event for the system sharesheet app share ranking timing out. + */ + 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. + */ + public void logSharesheetEmptyDirectShareRow() { + log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId()); + } + + /** + * Logs a UiEventReported event for a given share activity + * @param event + * @param instanceId + */ + private void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) { + mUiEventLogger.logWithInstanceId( + event, + 0, + null, + instanceId); + } + + /** + * @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 { + @UiEvent(doc = "Basic system Sharesheet has started and is visible.") + SHARE_STARTED(228); + + private final int mId; + SharesheetStartedEvent(int id) { + mId = id; + } + @Override + public int getId() { + return mId; + } + } + + /** + * The UiEvent enums that this class can log. + */ + enum SharesheetTargetSelectedEvent implements UiEventLogger.UiEventEnum { + INVALID(0), + @UiEvent(doc = "User selected a service target.") + SHARESHEET_SERVICE_TARGET_SELECTED(232), + @UiEvent(doc = "User selected an app target.") + SHARESHEET_APP_TARGET_SELECTED(233), + @UiEvent(doc = "User selected a standard target.") + SHARESHEET_STANDARD_TARGET_SELECTED(234), + @UiEvent(doc = "User selected the copy target.") + SHARESHEET_COPY_TARGET_SELECTED(235), + @UiEvent(doc = "User selected the nearby target.") + SHARESHEET_NEARBY_TARGET_SELECTED(626), + @UiEvent(doc = "User selected the edit target.") + SHARESHEET_EDIT_TARGET_SELECTED(669), + @UiEvent(doc = "User selected the modify share target.") + SHARESHEET_MODIFY_SHARE_SELECTED(1316), + @UiEvent(doc = "User selected a custom action.") + SHARESHEET_CUSTOM_ACTION_SELECTED(1317); + + private final int mId; + SharesheetTargetSelectedEvent(int id) { + mId = id; + } + @Override public int getId() { + return mId; + } + + public static SharesheetTargetSelectedEvent fromTargetType(int targetType) { + switch(targetType) { + case SELECTION_TYPE_SERVICE: + return SHARESHEET_SERVICE_TARGET_SELECTED; + case SELECTION_TYPE_APP: + return SHARESHEET_APP_TARGET_SELECTED; + case SELECTION_TYPE_STANDARD: + return SHARESHEET_STANDARD_TARGET_SELECTED; + case SELECTION_TYPE_COPY: + return SHARESHEET_COPY_TARGET_SELECTED; + case SELECTION_TYPE_NEARBY: + return SHARESHEET_NEARBY_TARGET_SELECTED; + case SELECTION_TYPE_EDIT: + return SHARESHEET_EDIT_TARGET_SELECTED; + case SELECTION_TYPE_MODIFY_SHARE: + return SHARESHEET_MODIFY_SHARE_SELECTED; + case SELECTION_TYPE_CUSTOM_ACTION: + return SHARESHEET_CUSTOM_ACTION_SELECTED; + default: + return INVALID; + } + } + } + + /** + * The UiEvent enums that this class can log. + */ + enum SharesheetStandardEvent implements UiEventLogger.UiEventEnum { + INVALID(0), + @UiEvent(doc = "User clicked share.") + SHARESHEET_TRIGGERED(227), + @UiEvent(doc = "User changed from work to personal profile or vice versa.") + SHARESHEET_PROFILE_CHANGED(229), + @UiEvent(doc = "User expanded target list.") + SHARESHEET_EXPANDED(230), + @UiEvent(doc = "User collapsed target list.") + SHARESHEET_COLLAPSED(231), + @UiEvent(doc = "Sharesheet app targets is fully populated.") + SHARESHEET_APP_LOAD_COMPLETE(322), + @UiEvent(doc = "Sharesheet direct targets is fully populated.") + SHARESHEET_DIRECT_LOAD_COMPLETE(323), + @UiEvent(doc = "Sharesheet direct targets timed out.") + SHARESHEET_DIRECT_LOAD_TIMEOUT(324), + @UiEvent(doc = "Sharesheet app share ranking timed out.") + SHARESHEET_APP_SHARE_RANKING_TIMEOUT(831), + @UiEvent(doc = "Sharesheet empty direct share row.") + SHARESHEET_EMPTY_DIRECT_SHARE_ROW(828); + + private final int mId; + SharesheetStandardEvent(int id) { + mId = id; + } + @Override public int getId() { + return mId; + } + } + + /** + * Returns the enum used in sharesheet started atom to indicate what preview type was used. + */ + private static int typeFromPreviewInt(int previewType) { + switch(previewType) { + case ContentPreviewType.CONTENT_PREVIEW_IMAGE: + return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_IMAGE; + case ContentPreviewType.CONTENT_PREVIEW_FILE: + return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE; + case ContentPreviewType.CONTENT_PREVIEW_TEXT: + default: + return FrameworkStatsLog + .SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_TYPE_UNKNOWN; + } + } + + /** + * Returns the enum used in sharesheet started atom to indicate what intent triggers the + * ChooserActivity. + */ + private static int typeFromIntentString(String intent) { + if (intent == null) { + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; + } + switch (intent) { + case Intent.ACTION_VIEW: + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_VIEW; + case Intent.ACTION_EDIT: + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_EDIT; + case Intent.ACTION_SEND: + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND; + case Intent.ACTION_SENDTO: + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO; + case Intent.ACTION_SEND_MULTIPLE: + return FrameworkStatsLog + .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND_MULTIPLE; + case MediaStore.ACTION_IMAGE_CAPTURE: + return FrameworkStatsLog + .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_IMAGE_CAPTURE; + case Intent.ACTION_MAIN: + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_MAIN; + default: + return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; + } + } + + @VisibleForTesting + static int getTargetSelectionCategory(int targetType) { + switch (targetType) { + case SELECTION_TYPE_SERVICE: + return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET; + case SELECTION_TYPE_APP: + return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET; + case SELECTION_TYPE_STANDARD: + return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET; + default: + 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/model/AbstractResolverComparator.java b/java/src/com/android/intentresolver/model/AbstractResolverComparator.java index bc54e01e..ff2d6a0f 100644 --- a/java/src/com/android/intentresolver/model/AbstractResolverComparator.java +++ b/java/src/com/android/intentresolver/model/AbstractResolverComparator.java @@ -30,7 +30,7 @@ import android.os.Message; import android.os.UserHandle; import android.util.Log; -import com.android.intentresolver.ChooserActivityLogger; +import com.android.intentresolver.logging.EventLog; import com.android.intentresolver.ResolvedComponentInfo; import com.android.intentresolver.ResolverActivity; import com.android.intentresolver.chooser.TargetInfo; @@ -72,7 +72,7 @@ public abstract class AbstractResolverComparator implements Comparator mAzComparator; - private ChooserActivityLogger mChooserActivityLogger; + private EventLog mEventLog; protected final Handler mHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(Message msg) { @@ -94,8 +94,8 @@ public abstract class AbstractResolverComparator implements Comparator mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT), - getChooserActivityLogger(), + getEventLog(), mUser, mPromoteToFirst); mComparatorModel = buildUpdatedModel(); diff --git a/java/src/com/android/intentresolver/model/ResolverRankerServiceResolverComparator.java b/java/src/com/android/intentresolver/model/ResolverRankerServiceResolverComparator.java index ebaffc36..7d473660 100644 --- a/java/src/com/android/intentresolver/model/ResolverRankerServiceResolverComparator.java +++ b/java/src/com/android/intentresolver/model/ResolverRankerServiceResolverComparator.java @@ -39,7 +39,7 @@ import android.service.resolver.ResolverRankerService; import android.service.resolver.ResolverTarget; import android.util.Log; -import com.android.intentresolver.ChooserActivityLogger; +import com.android.intentresolver.logging.EventLog; import com.android.intentresolver.ResolvedComponentInfo; import com.android.intentresolver.chooser.TargetInfo; import com.android.internal.logging.MetricsLogger; @@ -102,9 +102,9 @@ public class ResolverRankerServiceResolverComparator extends AbstractResolverCom */ public ResolverRankerServiceResolverComparator(Context launchedFromContext, Intent intent, String referrerPackage, Runnable afterCompute, - ChooserActivityLogger chooserActivityLogger, UserHandle targetUserSpace, + EventLog eventLog, UserHandle targetUserSpace, ComponentName promoteToFirst) { - this(launchedFromContext, intent, referrerPackage, afterCompute, chooserActivityLogger, + this(launchedFromContext, intent, referrerPackage, afterCompute, eventLog, Lists.newArrayList(targetUserSpace), promoteToFirst); } @@ -118,7 +118,7 @@ public class ResolverRankerServiceResolverComparator extends AbstractResolverCom */ public ResolverRankerServiceResolverComparator(Context launchedFromContext, Intent intent, String referrerPackage, Runnable afterCompute, - ChooserActivityLogger chooserActivityLogger, List targetUserSpaceList, + EventLog eventLog, List targetUserSpaceList, @Nullable ComponentName promoteToFirst) { super(launchedFromContext, intent, targetUserSpaceList, promoteToFirst); mCollator = Collator.getInstance( @@ -139,7 +139,7 @@ public class ResolverRankerServiceResolverComparator extends AbstractResolverCom mAction = intent.getAction(); mRankerServiceName = new ComponentName(mContext, this.getClass()); setCallBack(afterCompute); - setChooserActivityLogger(chooserActivityLogger); + setEventLog(eventLog); mComparatorModel = buildUpdatedModel(); } -- cgit v1.2.3-59-g8ed1b