From 8b352b94c03aa08d1795b6277213f53c85c98969 Mon Sep 17 00:00:00 2001 From: Song Hu Date: Tue, 1 Jun 2021 08:46:45 -0700 Subject: [PATCH] Add sharesheet logging for empty direct share row and app share prediction timeout. Bug: 189833783 Test: atest ChooserActivityTest & manual verification Change-Id: Id24c6a2495b6a4f778b14028ee5ab975d88e9870 --- .../app/AbstractResolverComparator.java | 12 +++++ ...ppPredictionServiceResolverComparator.java | 17 ++++--- .../android/internal/app/ChooserActivity.java | 7 +-- .../internal/app/ChooserActivityLogger.java | 20 +++++++- .../internal/app/ChooserListAdapter.java | 6 ++- .../internal/app/ResolverListController.java | 2 +- ...solverRankerServiceResolverComparator.java | 4 +- .../internal/app/ChooserActivityTest.java | 51 +++++++++++++++++++ .../internal/app/ChooserWrapperActivity.java | 3 +- 9 files changed, 107 insertions(+), 15 deletions(-) diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java index ea3f1b1fc04cc..40ada0b2ffdcc 100644 --- a/core/java/com/android/internal/app/AbstractResolverComparator.java +++ b/core/java/com/android/internal/app/AbstractResolverComparator.java @@ -64,6 +64,7 @@ public abstract class AbstractResolverComparator implements Comparator mAzComparator; + private ChooserActivityLogger mChooserActivityLogger; protected final Handler mHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(Message msg) { @@ -85,6 +86,9 @@ public abstract class AbstractResolverComparator implements Comparator mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT)); + mContext, mIntent, mReferrerPackage, + () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT), + getChooserActivityLogger()); mResolverRankerService.compute(targets); } else { Log.i(TAG, "AppPredictionService response received"); diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 862c9001e3800..e6b5931d02c54 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -2590,7 +2590,8 @@ public class ChooserActivity extends ResolverActivity implements boolean filterLastUsed, ResolverListController resolverListController) { return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, filterLastUsed, resolverListController, this, - this, context.getPackageManager()); + this, context.getPackageManager(), + getChooserActivityLogger()); } @VisibleForTesting @@ -2599,11 +2600,11 @@ public class ChooserActivity extends ResolverActivity implements AbstractResolverComparator resolverComparator; if (appPredictor != null) { resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(), - getReferrerPackageName(), appPredictor, userHandle); + getReferrerPackageName(), appPredictor, userHandle, getChooserActivityLogger()); } else { resolverComparator = new ResolverRankerServiceResolverComparator(this, getTargetIntent(), - getReferrerPackageName(), null); + getReferrerPackageName(), null, getChooserActivityLogger()); } return new ChooserListController( diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java index 47d83346d038d..3217307864719 100644 --- a/core/java/com/android/internal/app/ChooserActivityLogger.java +++ b/core/java/com/android/internal/app/ChooserActivityLogger.java @@ -74,6 +74,20 @@ public interface ChooserActivityLogger { SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); } + /** + * Logs a UiEventReported event for the system sharesheet app share ranking timing out. + */ + default void logSharesheetAppShareRankingTimeout() { + log(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT, getInstanceId()); + } + + /** + * Logs a UiEventReported event for the system sharesheet when direct share row is empty. + */ + default void logSharesheetEmptyDirectShareRow() { + log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId()); + } + /** * Logs a UiEventReported event for a given share activity * @param event @@ -168,7 +182,11 @@ public interface ChooserActivityLogger { @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); + 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) { diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index cc2b12a99d79e..87737ca9c3af0 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -79,6 +79,7 @@ public class ChooserListAdapter extends ResolverListAdapter { private final ChooserListCommunicator mChooserListCommunicator; private final SelectableTargetInfo.SelectableTargetInfoCommunicator mSelectableTargetInfoCommunicator; + private final ChooserActivityLogger mChooserActivityLogger; private int mNumShortcutResults = 0; private Map mIconLoaders = new HashMap<>(); @@ -104,7 +105,8 @@ public class ChooserListAdapter extends ResolverListAdapter { boolean filterLastUsed, ResolverListController resolverListController, ChooserListCommunicator chooserListCommunicator, SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator, - PackageManager packageManager) { + PackageManager packageManager, + ChooserActivityLogger chooserActivityLogger) { // Don't send the initial intents through the shared ResolverActivity path, // we want to separate them into a different section. super(context, payloadIntents, null, rList, filterLastUsed, @@ -115,6 +117,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mChooserListCommunicator = chooserListCommunicator; createPlaceHolders(); mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator; + mChooserActivityLogger = chooserActivityLogger; if (initialIntents != null) { for (int i = 0; i < initialIntents.length; i++) { @@ -590,6 +593,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mServiceTargets.removeIf(o -> o instanceof ChooserActivity.PlaceHolderTargetInfo); if (mServiceTargets.isEmpty()) { mServiceTargets.add(new ChooserActivity.EmptyTargetInfo()); + mChooserActivityLogger.logSharesheetEmptyDirectShareRow(); } notifyDataSetChanged(); } diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 2b59907cf86b3..10ac1bc6ac3d6 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -70,7 +70,7 @@ public class ResolverListController { UserHandle userHandle) { this(context, pm, targetIntent, referrerPackage, launchedFromUid, userHandle, new ResolverRankerServiceResolverComparator( - context, targetIntent, referrerPackage, null)); + context, targetIntent, referrerPackage, null, null)); } public ResolverListController( diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java index 286945037ab71..cb946c0dcf99d 100644 --- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java @@ -85,7 +85,8 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator private CountDownLatch mConnectSignal; public ResolverRankerServiceResolverComparator(Context context, Intent intent, - String referrerPackage, AfterCompute afterCompute) { + String referrerPackage, AfterCompute afterCompute, + ChooserActivityLogger chooserActivityLogger) { super(context, intent); mCollator = Collator.getInstance(context.getResources().getConfiguration().locale); mReferrerPackage = referrerPackage; @@ -97,6 +98,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator mAction = intent.getAction(); mRankerServiceName = new ComponentName(mContext, this.getClass()); setCallBack(afterCompute); + setChooserActivityLogger(chooserActivityLogger); } @Override diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index 1633d2897fcbb..b86b882682570 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -1852,6 +1852,57 @@ public class ChooserActivityTest { .SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId())); } + @Test + public void testEmptyDirectRowLogging() throws InterruptedException { + Intent sendIntent = createSendTextIntent(); + // We need app targets for direct targets to get displayed + List resolvedComponentInfos = createResolvedComponentsForTest(2); + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + + // Start activity + final ChooserWrapperActivity activity = mActivityRule + .launchActivity(Intent.createChooser(sendIntent, null)); + + // Thread.sleep shouldn't be a thing in an integration test but it's + // necessary here because of the way the code is structured + Thread.sleep(3000); + + assertThat("Chooser should have 2 app targets", + activity.getAdapter().getCount(), is(2)); + assertThat("Chooser should have no direct targets", + activity.getAdapter().getSelectableServiceTargetCount(), is(0)); + + ChooserActivityLoggerFake logger = + (ChooserActivityLoggerFake) activity.getChooserActivityLogger(); + assertThat(logger.numCalls(), is(6)); + // first one should be SHARESHEET_TRIGGERED uievent + assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED)); + assertThat(logger.get(0).event.getId(), + is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId())); + // second one should be SHARESHEET_STARTED event + assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED)); + assertThat(logger.get(1).intent, is(Intent.ACTION_SEND)); + assertThat(logger.get(1).mimeType, is("text/plain")); + assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests")); + assertThat(logger.get(1).appProvidedApp, is(0)); + assertThat(logger.get(1).appProvidedDirect, is(0)); + assertThat(logger.get(1).isWorkprofile, is(false)); + assertThat(logger.get(1).previewType, is(3)); + // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent + assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED)); + assertThat(logger.get(2).event.getId(), + is(ChooserActivityLogger + .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId())); + // fourth and fifth are just artifacts of test set-up + // sixth one should be ranking atom with SHARESHEET_EMPTY_DIRECT_SHARE_ROW event + assertThat(logger.get(5).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED)); + assertThat(logger.get(5).event.getId(), + is(ChooserActivityLogger + .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId())); + } + @Test public void testCopyTextToClipboardLogging() throws Exception { Intent sendIntent = createSendTextIntent(); diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java index 16a2fbd6465e5..9fcab0923f2d8 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -68,7 +68,8 @@ public class ChooserWrapperActivity extends ChooserActivity { : sOverrides.packageManager; return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, filterLastUsed, resolverListController, - this, this, packageManager); + this, this, packageManager, + getChooserActivityLogger()); } ChooserListAdapter getAdapter() {