diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 6c4faa4dec065..7878611266926 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -99,7 +99,7 @@ public class ChooserActivity extends ResolverActivity { private Intent mReferrerFillInIntent; private long mChooserShownTime; - private boolean mIsSuccessfullySelected; + protected boolean mIsSuccessfullySelected; private ChooserListAdapter mChooserListAdapter; private ChooserRowAdapter mChooserRowAdapter; @@ -418,7 +418,7 @@ public class ChooserActivity extends ResolverActivity { } } } - updateChooserCounts(target, mContentType); + updateChooserCounts(target); return super.onTargetSelected(target, alwaysCheck); } @@ -575,7 +575,7 @@ public class ChooserActivity extends ResolverActivity { // Do nothing. We'll send the voice stuff ourselves. } - void updateChooserCounts(TargetInfo info, String annotation) { + void updateChooserCounts(TargetInfo info) { if (info != null) { UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); @@ -586,14 +586,17 @@ public class ChooserActivity extends ResolverActivity { return; } final ResolveInfo ri = info.getResolveInfo(); - if (ri != null && ri.activityInfo != null) { + Intent targetIntent = getTargetIntent(); + if (ri != null && ri.activityInfo != null && targetIntent != null) { usageStatsManager.reportChooserSelection(ri.activityInfo.packageName, getUserId(), - annotation, null, info.getResolvedIntent().getAction()); + targetIntent.getType(), null, targetIntent.getAction()); if (mAdapter != null) { mAdapter.updateModel(info.getResolvedComponentName()); } if (DEBUG) { - Log.d(TAG, "ResolveInfo Package is" + ri.activityInfo.packageName); + Log.d(TAG, "ResolveInfo Package is " + ri.activityInfo.packageName); + Log.d(TAG, "Annotation to be updated is " + targetIntent.getType()); + Log.d(TAG, "Action to be updated is " + targetIntent.getAction()); } } else if(DEBUG) { Log.d(TAG, "Can not log Chooser Counts of null ResovleInfo"); @@ -615,7 +618,7 @@ public class ChooserActivity extends ResolverActivity { } else { TargetInfo clonedTarget = selectedTarget.cloneFilledIn(matchingIntent, 0); if (super.onTargetSelected(clonedTarget, false)) { - updateChooserCounts(clonedTarget, mContentType); + updateChooserCounts(clonedTarget); finish(); return; } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 282d3e9284acc..095063099395c 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -110,7 +110,6 @@ public class ResolverActivity extends Activity { private int mDefaultTitleResId; protected ResolverDrawerLayout mResolverDrawerLayout; - protected String mContentType; protected PackageManager mPm; protected int mLaunchedFromUid; diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 504541d9522ba..cba485a606cc8 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -85,6 +85,8 @@ + + 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 8a7b881e4ae87..4ac5e13560e7e 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -25,14 +25,18 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; +import android.app.usage.UsageStats; +import android.app.usage.UsageStatsManager; import android.content.Intent; import android.content.pm.ResolveInfo; +import android.os.UserHandle; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; @@ -45,6 +49,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; /** * Chooser activity instrumentation tests @@ -114,6 +120,56 @@ public class ChooserActivityTest { assertThat(chosen[0], is(toChoose)); } + @Test + public void updateChooserCountsAfterUserSelection() throws InterruptedException { + Intent sendIntent = createSendImageIntent(); + List resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + + final ChooserWrapperActivity activity = mActivityRule + .launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + UsageStatsManager usm = activity.getUsageStatsManager(); + verify(sOverrides.resolverListController, times(1)) + .sort(Mockito.any(List.class)); + assertThat(activity.getIsSelected(), is(false)); + sOverrides.onSafelyStartCallback = targetInfo -> { + return true; + }; + String action = sendIntent.getAction(); + String annotation = sendIntent.getType(); + ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0); + String packageName = toChoose.activityInfo.packageName; + long toChooseCount = getCount(usm, packageName, action, annotation); + onView(withText(toChoose.activityInfo.name)) + .perform(click()); + waitForIdle(); + verify(sOverrides.resolverListController, times(1)) + .updateModel(toChoose.activityInfo.getComponentName()); + assertThat(activity.getIsSelected(), is(true)); + long updatedCount = getCount(usm, packageName, action, annotation); + assertThat(updatedCount, is(toChooseCount + 1l)); + } + + @Test + public void reportChooserSelection() throws InterruptedException { + Intent sendIntent = createSendImageIntent(); + final ChooserWrapperActivity activity = mActivityRule + .launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + UsageStatsManager usm = activity.getUsageStatsManager(); + String packageName = "test_package"; + String action = "test_action"; + String annotation = "test_annotation"; + long beforeReport = getCount(usm, packageName, action, annotation); + usm.reportChooserSelection(packageName, activity.getUserId(), annotation, null, action); + long afterReport = getCount(usm, packageName, action, annotation); + assertThat(afterReport, is(beforeReport + 1l)); + } + @Test public void noResultsFromPackageManager() { when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), @@ -175,4 +231,19 @@ public class ChooserActivityTest { private void waitForIdle() { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } + + private Integer getCount( + UsageStatsManager usm, String packageName, String action, String annotation) { + if (usm == null) { + return 0; + } + Map stats = + usm.queryAndAggregateUsageStats(Long.MIN_VALUE, Long.MAX_VALUE); + UsageStats packageStats = stats.get(packageName); + if (packageStats == null || packageStats.mChooserCounts == null + || packageStats.mChooserCounts.get(action) == null) { + return 0; + } + return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0); + } } \ No newline at end of file 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 66fb45148a6e7..41016e12bbf94 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -16,6 +16,8 @@ package com.android.internal.app; +import android.app.usage.UsageStatsManager; +import android.content.Context; import android.content.pm.PackageManager; import java.util.function.Function; @@ -28,11 +30,21 @@ import static org.mockito.Mockito.mock; */ public class ChooserWrapperActivity extends ChooserActivity { static final OverrideData sOverrides = new OverrideData(); + private UsageStatsManager mUsm; ResolveListAdapter getAdapter() { return mAdapter; } + boolean getIsSelected() { return mIsSuccessfullySelected; } + + UsageStatsManager getUsageStatsManager() { + if (mUsm == null) { + mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); + } + return mUsm; + } + @Override public boolean isVoiceInteraction() { if (sOverrides.isVoiceInteraction != null) {