Merge "Add sharesheet logging for empty direct share row and app share prediction timeout." into sc-dev

This commit is contained in:
Song Hu
2021-06-02 19:03:16 +00:00
committed by Android (Google) Code Review
9 changed files with 107 additions and 15 deletions

View File

@@ -64,6 +64,7 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC
private static final int WATCHDOG_TIMEOUT_MILLIS = 500; private static final int WATCHDOG_TIMEOUT_MILLIS = 500;
private final Comparator<ResolveInfo> mAzComparator; private final Comparator<ResolveInfo> mAzComparator;
private ChooserActivityLogger mChooserActivityLogger;
protected final Handler mHandler = new Handler(Looper.getMainLooper()) { protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
@@ -85,6 +86,9 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC
} }
mHandler.removeMessages(RANKER_SERVICE_RESULT); mHandler.removeMessages(RANKER_SERVICE_RESULT);
afterCompute(); afterCompute();
if (mChooserActivityLogger != null) {
mChooserActivityLogger.logSharesheetAppShareRankingTimeout();
}
break; break;
default: default:
@@ -131,6 +135,14 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC
mAfterCompute = afterCompute; mAfterCompute = afterCompute;
} }
void setChooserActivityLogger(ChooserActivityLogger chooserActivityLogger) {
mChooserActivityLogger = chooserActivityLogger;
}
ChooserActivityLogger getChooserActivityLogger() {
return mChooserActivityLogger;
}
protected final void afterCompute() { protected final void afterCompute() {
final AfterCompute afterCompute = mAfterCompute; final AfterCompute afterCompute = mAfterCompute;
if (afterCompute != null) { if (afterCompute != null) {

View File

@@ -61,17 +61,19 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
private ResolverRankerServiceResolverComparator mResolverRankerService; private ResolverRankerServiceResolverComparator mResolverRankerService;
AppPredictionServiceResolverComparator( AppPredictionServiceResolverComparator(
Context context, Context context,
Intent intent, Intent intent,
String referrerPackage, String referrerPackage,
AppPredictor appPredictor, AppPredictor appPredictor,
UserHandle user) { UserHandle user,
ChooserActivityLogger chooserActivityLogger) {
super(context, intent); super(context, intent);
mContext = context; mContext = context;
mIntent = intent; mIntent = intent;
mAppPredictor = appPredictor; mAppPredictor = appPredictor;
mUser = user; mUser = user;
mReferrerPackage = referrerPackage; mReferrerPackage = referrerPackage;
setChooserActivityLogger(chooserActivityLogger);
} }
@Override @Override
@@ -116,8 +118,9 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
// APS for chooser is disabled. Fallback to resolver. // APS for chooser is disabled. Fallback to resolver.
mResolverRankerService = mResolverRankerService =
new ResolverRankerServiceResolverComparator( new ResolverRankerServiceResolverComparator(
mContext, mIntent, mReferrerPackage, mContext, mIntent, mReferrerPackage,
() -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT)); () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT),
getChooserActivityLogger());
mResolverRankerService.compute(targets); mResolverRankerService.compute(targets);
} else { } else {
Log.i(TAG, "AppPredictionService response received"); Log.i(TAG, "AppPredictionService response received");

View File

@@ -2591,7 +2591,8 @@ public class ChooserActivity extends ResolverActivity implements
boolean filterLastUsed, ResolverListController resolverListController) { boolean filterLastUsed, ResolverListController resolverListController) {
return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
filterLastUsed, resolverListController, this, filterLastUsed, resolverListController, this,
this, context.getPackageManager()); this, context.getPackageManager(),
getChooserActivityLogger());
} }
@VisibleForTesting @VisibleForTesting
@@ -2600,11 +2601,11 @@ public class ChooserActivity extends ResolverActivity implements
AbstractResolverComparator resolverComparator; AbstractResolverComparator resolverComparator;
if (appPredictor != null) { if (appPredictor != null) {
resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(), resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
getReferrerPackageName(), appPredictor, userHandle); getReferrerPackageName(), appPredictor, userHandle, getChooserActivityLogger());
} else { } else {
resolverComparator = resolverComparator =
new ResolverRankerServiceResolverComparator(this, getTargetIntent(), new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
getReferrerPackageName(), null); getReferrerPackageName(), null, getChooserActivityLogger());
} }
return new ChooserListController( return new ChooserListController(

View File

@@ -74,6 +74,20 @@ public interface ChooserActivityLogger {
SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); 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 * Logs a UiEventReported event for a given share activity
* @param event * @param event
@@ -168,7 +182,11 @@ public interface ChooserActivityLogger {
@UiEvent(doc = "Sharesheet direct targets is fully populated.") @UiEvent(doc = "Sharesheet direct targets is fully populated.")
SHARESHEET_DIRECT_LOAD_COMPLETE(323), SHARESHEET_DIRECT_LOAD_COMPLETE(323),
@UiEvent(doc = "Sharesheet direct targets timed out.") @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; private final int mId;
SharesheetStandardEvent(int id) { SharesheetStandardEvent(int id) {

View File

@@ -79,6 +79,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
private final ChooserListCommunicator mChooserListCommunicator; private final ChooserListCommunicator mChooserListCommunicator;
private final SelectableTargetInfo.SelectableTargetInfoCommunicator private final SelectableTargetInfo.SelectableTargetInfoCommunicator
mSelectableTargetInfoCommunicator; mSelectableTargetInfoCommunicator;
private final ChooserActivityLogger mChooserActivityLogger;
private int mNumShortcutResults = 0; private int mNumShortcutResults = 0;
private Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>(); private Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();
@@ -104,7 +105,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
boolean filterLastUsed, ResolverListController resolverListController, boolean filterLastUsed, ResolverListController resolverListController,
ChooserListCommunicator chooserListCommunicator, ChooserListCommunicator chooserListCommunicator,
SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator, SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
PackageManager packageManager) { PackageManager packageManager,
ChooserActivityLogger chooserActivityLogger) {
// Don't send the initial intents through the shared ResolverActivity path, // Don't send the initial intents through the shared ResolverActivity path,
// we want to separate them into a different section. // we want to separate them into a different section.
super(context, payloadIntents, null, rList, filterLastUsed, super(context, payloadIntents, null, rList, filterLastUsed,
@@ -115,6 +117,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
mChooserListCommunicator = chooserListCommunicator; mChooserListCommunicator = chooserListCommunicator;
createPlaceHolders(); createPlaceHolders();
mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator; mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator;
mChooserActivityLogger = chooserActivityLogger;
if (initialIntents != null) { if (initialIntents != null) {
for (int i = 0; i < initialIntents.length; i++) { for (int i = 0; i < initialIntents.length; i++) {
@@ -590,6 +593,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
mServiceTargets.removeIf(o -> o instanceof ChooserActivity.PlaceHolderTargetInfo); mServiceTargets.removeIf(o -> o instanceof ChooserActivity.PlaceHolderTargetInfo);
if (mServiceTargets.isEmpty()) { if (mServiceTargets.isEmpty()) {
mServiceTargets.add(new ChooserActivity.EmptyTargetInfo()); mServiceTargets.add(new ChooserActivity.EmptyTargetInfo());
mChooserActivityLogger.logSharesheetEmptyDirectShareRow();
} }
notifyDataSetChanged(); notifyDataSetChanged();
} }

View File

@@ -70,7 +70,7 @@ public class ResolverListController {
UserHandle userHandle) { UserHandle userHandle) {
this(context, pm, targetIntent, referrerPackage, launchedFromUid, userHandle, this(context, pm, targetIntent, referrerPackage, launchedFromUid, userHandle,
new ResolverRankerServiceResolverComparator( new ResolverRankerServiceResolverComparator(
context, targetIntent, referrerPackage, null)); context, targetIntent, referrerPackage, null, null));
} }
public ResolverListController( public ResolverListController(

View File

@@ -85,7 +85,8 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
private CountDownLatch mConnectSignal; private CountDownLatch mConnectSignal;
public ResolverRankerServiceResolverComparator(Context context, Intent intent, public ResolverRankerServiceResolverComparator(Context context, Intent intent,
String referrerPackage, AfterCompute afterCompute) { String referrerPackage, AfterCompute afterCompute,
ChooserActivityLogger chooserActivityLogger) {
super(context, intent); super(context, intent);
mCollator = Collator.getInstance(context.getResources().getConfiguration().locale); mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
mReferrerPackage = referrerPackage; mReferrerPackage = referrerPackage;
@@ -97,6 +98,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
mAction = intent.getAction(); mAction = intent.getAction();
mRankerServiceName = new ComponentName(mContext, this.getClass()); mRankerServiceName = new ComponentName(mContext, this.getClass());
setCallBack(afterCompute); setCallBack(afterCompute);
setChooserActivityLogger(chooserActivityLogger);
} }
@Override @Override

View File

@@ -1856,6 +1856,57 @@ public class ChooserActivityTest {
.SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId())); .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<ResolvedComponentInfo> 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 @Test
public void testCopyTextToClipboardLogging() throws Exception { public void testCopyTextToClipboardLogging() throws Exception {
Intent sendIntent = createSendTextIntent(); Intent sendIntent = createSendTextIntent();

View File

@@ -68,7 +68,8 @@ public class ChooserWrapperActivity extends ChooserActivity {
: sOverrides.packageManager; : sOverrides.packageManager;
return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
filterLastUsed, resolverListController, filterLastUsed, resolverListController,
this, this, packageManager); this, this, packageManager,
getChooserActivityLogger());
} }
ChooserListAdapter getAdapter() { ChooserListAdapter getAdapter() {