Promote frequently sharing apps as per monthly stats fetched from UsageStatsManager, in case PeopleService does not store enough sharing events when users just swicth to Sharesheet ranking in PeopleService.
Bug: 156320324 Test: atest com.android.server.people.prediction.ShareTargetPredictorTest Test: atest com.android.server.people.prediction.SharesheetModelScorerTest Test: atest com.android.server.people.data.UsageStatsQueryHelperTest Change-Id: Iae7a3a8195ae4901cd1d9d673fe0cf8a27845488
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.server.people.data;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/** The data containing package usage info. */
|
||||
public class AppUsageStatsData {
|
||||
|
||||
private int mLaunchCount;
|
||||
|
||||
private int mChosenCount;
|
||||
|
||||
@VisibleForTesting
|
||||
public AppUsageStatsData(int chosenCount, int launchCount) {
|
||||
this.mChosenCount = chosenCount;
|
||||
this.mLaunchCount = launchCount;
|
||||
}
|
||||
|
||||
public AppUsageStatsData() {
|
||||
}
|
||||
|
||||
public int getLaunchCount() {
|
||||
return mLaunchCount;
|
||||
}
|
||||
|
||||
void incrementLaunchCountBy(int launchCount) {
|
||||
this.mLaunchCount += launchCount;
|
||||
}
|
||||
|
||||
public int getChosenCount() {
|
||||
return mChosenCount;
|
||||
}
|
||||
|
||||
void incrementChosenCountBy(int chosenCount) {
|
||||
this.mChosenCount += chosenCount;
|
||||
}
|
||||
}
|
||||
@@ -257,13 +257,16 @@ public class DataManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries launch counts of apps within {@code packageNameFilter} between {@code startTime}
|
||||
* and {@code endTime}.
|
||||
* Queries usage stats of apps within {@code packageNameFilter} between {@code startTime} and
|
||||
* {@code endTime}.
|
||||
*
|
||||
* @return a map which keys are package names and values are {@link AppUsageStatsData}.
|
||||
*/
|
||||
@NonNull
|
||||
public Map<String, Integer> queryAppLaunchCount(@UserIdInt int callingUserId, long startTime,
|
||||
public Map<String, AppUsageStatsData> queryAppUsageStats(
|
||||
@UserIdInt int callingUserId, long startTime,
|
||||
long endTime, Set<String> packageNameFilter) {
|
||||
return UsageStatsQueryHelper.queryAppLaunchCount(callingUserId, startTime, endTime,
|
||||
return UsageStatsQueryHelper.queryAppUsageStats(callingUserId, startTime, endTime,
|
||||
packageNameFilter);
|
||||
}
|
||||
|
||||
|
||||
@@ -137,27 +137,48 @@ class UsageStatsQueryHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries {@link UsageStatsManagerInternal} for launch count of apps within {@code
|
||||
* packageNameFilter} between {@code startTime} and {@code endTime}.obfuscateInstantApps
|
||||
* Queries {@link UsageStatsManagerInternal} for usage stats of apps within {@code
|
||||
* packageNameFilter} between {@code startTime} and {@code endTime}.
|
||||
*
|
||||
* @return a map which keys are package names and values are app launch counts.
|
||||
* @return a map which keys are package names and values are {@link AppUsageStatsData}.
|
||||
*/
|
||||
static Map<String, Integer> queryAppLaunchCount(@UserIdInt int userId, long startTime,
|
||||
static Map<String, AppUsageStatsData> queryAppUsageStats(@UserIdInt int userId, long startTime,
|
||||
long endTime, Set<String> packageNameFilter) {
|
||||
List<UsageStats> stats = getUsageStatsManagerInternal().queryUsageStatsForUser(userId,
|
||||
UsageStatsManager.INTERVAL_BEST, startTime, endTime,
|
||||
/* obfuscateInstantApps= */ false);
|
||||
Map<String, Integer> aggregatedStats = new ArrayMap<>();
|
||||
Map<String, AppUsageStatsData> aggregatedStats = new ArrayMap<>();
|
||||
for (UsageStats stat : stats) {
|
||||
String packageName = stat.getPackageName();
|
||||
if (packageNameFilter.contains(packageName)) {
|
||||
aggregatedStats.put(packageName,
|
||||
aggregatedStats.getOrDefault(packageName, 0) + stat.getAppLaunchCount());
|
||||
AppUsageStatsData packageStats = aggregatedStats.computeIfAbsent(packageName,
|
||||
(key) -> new AppUsageStatsData());
|
||||
packageStats.incrementChosenCountBy(sumChooserCounts(stat.mChooserCounts));
|
||||
packageStats.incrementLaunchCountBy(stat.getAppLaunchCount());
|
||||
}
|
||||
}
|
||||
return aggregatedStats;
|
||||
}
|
||||
|
||||
private static int sumChooserCounts(ArrayMap<String, ArrayMap<String, Integer>> chooserCounts) {
|
||||
int sum = 0;
|
||||
if (chooserCounts == null) {
|
||||
return sum;
|
||||
}
|
||||
int chooserCountsSize = chooserCounts.size();
|
||||
for (int i = 0; i < chooserCountsSize; i++) {
|
||||
ArrayMap<String, Integer> counts = chooserCounts.valueAt(i);
|
||||
if (counts == null) {
|
||||
continue;
|
||||
}
|
||||
final int annotationSize = counts.size();
|
||||
for (int j = 0; j < annotationSize; j++) {
|
||||
sum += counts.valueAt(j);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private void onInAppConversationEnded(@NonNull PackageData packageData,
|
||||
@NonNull UsageEvents.Event endEvent) {
|
||||
ComponentName activityName =
|
||||
|
||||
@@ -27,17 +27,18 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.ChooserActivity;
|
||||
import com.android.server.people.data.AppUsageStatsData;
|
||||
import com.android.server.people.data.DataManager;
|
||||
import com.android.server.people.data.Event;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
/** Ranking scorer for Sharesheet targets. */
|
||||
class SharesheetModelScorer {
|
||||
@@ -50,8 +51,8 @@ class SharesheetModelScorer {
|
||||
private static final float RECENCY_SCORE_SUBSEQUENT_DECAY = 0.02F;
|
||||
private static final long ONE_MONTH_WINDOW = TimeUnit.DAYS.toMillis(30);
|
||||
private static final long FOREGROUND_APP_PROMO_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10);
|
||||
private static final float USAGE_STATS_CHOOSER_SCORE_INITIAL_DECAY = 0.9F;
|
||||
private static final float FREQUENTLY_USED_APP_SCORE_INITIAL_DECAY = 0.3F;
|
||||
private static final float FREQUENTLY_USED_APP_SCORE_DECAY = 0.9F;
|
||||
@VisibleForTesting
|
||||
static final float FOREGROUND_APP_WEIGHT = 0F;
|
||||
@VisibleForTesting
|
||||
@@ -192,14 +193,16 @@ class SharesheetModelScorer {
|
||||
targetsList.add(index, shareTarget);
|
||||
}
|
||||
promoteForegroundApp(shareTargetMap, dataManager, callingUserId);
|
||||
promoteFrequentlyUsedApps(shareTargetMap, targetsLimit, dataManager, callingUserId);
|
||||
promoteMostChosenAndFrequentlyUsedApps(shareTargetMap, targetsLimit, dataManager,
|
||||
callingUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Promotes frequently used sharing apps, if recommended apps based on sharing history have not
|
||||
* reached the limit (e.g. user did not share any content in last couple weeks)
|
||||
* Promotes frequently chosen sharing apps and frequently used sharing apps as per
|
||||
* UsageStatsManager, if recommended apps based on sharing history have not reached the limit
|
||||
* (e.g. user did not share any content in last couple weeks)
|
||||
*/
|
||||
private static void promoteFrequentlyUsedApps(
|
||||
private static void promoteMostChosenAndFrequentlyUsedApps(
|
||||
Map<String, List<ShareTargetPredictor.ShareTarget>> shareTargetMap, int targetsLimit,
|
||||
@NonNull DataManager dataManager, @UserIdInt int callingUserId) {
|
||||
int validPredictionNum = 0;
|
||||
@@ -217,39 +220,50 @@ class SharesheetModelScorer {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
Map<String, Integer> appLaunchCountsMap = dataManager.queryAppLaunchCount(
|
||||
callingUserId, now - ONE_MONTH_WINDOW, now, shareTargetMap.keySet());
|
||||
List<Pair<String, Integer>> appLaunchCounts = new ArrayList<>();
|
||||
minValidScore *= FREQUENTLY_USED_APP_SCORE_INITIAL_DECAY;
|
||||
for (Map.Entry<String, Integer> entry : appLaunchCountsMap.entrySet()) {
|
||||
if (entry.getValue() > 0) {
|
||||
appLaunchCounts.add(new Pair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
Collections.sort(appLaunchCounts, (p1, p2) -> -Integer.compare(p1.second, p2.second));
|
||||
for (Pair<String, Integer> entry : appLaunchCounts) {
|
||||
if (!shareTargetMap.containsKey(entry.first)) {
|
||||
continue;
|
||||
}
|
||||
ShareTargetPredictor.ShareTarget target = shareTargetMap.get(entry.first).get(0);
|
||||
if (target.getScore() > 0f) {
|
||||
continue;
|
||||
}
|
||||
target.setScore(minValidScore);
|
||||
minValidScore *= FREQUENTLY_USED_APP_SCORE_DECAY;
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, String.format(
|
||||
"SharesheetModel: promoteFrequentUsedApps packageName: %s, className: %s,"
|
||||
+ " total:%.2f",
|
||||
target.getAppTarget().getPackageName(),
|
||||
target.getAppTarget().getClassName(),
|
||||
target.getScore()));
|
||||
}
|
||||
validPredictionNum++;
|
||||
if (validPredictionNum == targetsLimit) {
|
||||
return;
|
||||
Map<String, AppUsageStatsData> appStatsMap =
|
||||
dataManager.queryAppUsageStats(
|
||||
callingUserId, now - ONE_MONTH_WINDOW, now, shareTargetMap.keySet());
|
||||
// Promotes frequently chosen sharing apps as per UsageStatsManager.
|
||||
minValidScore = promoteApp(shareTargetMap, appStatsMap, AppUsageStatsData::getChosenCount,
|
||||
USAGE_STATS_CHOOSER_SCORE_INITIAL_DECAY * minValidScore, minValidScore);
|
||||
// Promotes frequently used sharing apps as per UsageStatsManager.
|
||||
promoteApp(shareTargetMap, appStatsMap, AppUsageStatsData::getLaunchCount,
|
||||
FREQUENTLY_USED_APP_SCORE_INITIAL_DECAY * minValidScore, minValidScore);
|
||||
}
|
||||
|
||||
private static float promoteApp(
|
||||
Map<String, List<ShareTargetPredictor.ShareTarget>> shareTargetMap,
|
||||
Map<String, AppUsageStatsData> appStatsMap,
|
||||
Function<AppUsageStatsData, Integer> countFunc, float baseScore, float minValidScore) {
|
||||
int maxCount = 0;
|
||||
for (AppUsageStatsData data : appStatsMap.values()) {
|
||||
maxCount = Math.max(maxCount, countFunc.apply(data));
|
||||
}
|
||||
if (maxCount > 0) {
|
||||
for (Map.Entry<String, AppUsageStatsData> entry : appStatsMap.entrySet()) {
|
||||
if (!shareTargetMap.containsKey(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
ShareTargetPredictor.ShareTarget target = shareTargetMap.get(entry.getKey()).get(0);
|
||||
if (target.getScore() > 0f) {
|
||||
continue;
|
||||
}
|
||||
float curScore = baseScore * countFunc.apply(entry.getValue()) / maxCount;
|
||||
target.setScore(curScore);
|
||||
if (curScore > 0) {
|
||||
minValidScore = Math.min(minValidScore, curScore);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, String.format(
|
||||
"SharesheetModel: promote as per AppUsageStats packageName: %s, "
|
||||
+ "className: %s, total:%.2f",
|
||||
target.getAppTarget().getPackageName(),
|
||||
target.getAppTarget().getClassName(),
|
||||
target.getScore()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return minValidScore;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.app.usage.UsageStats;
|
||||
import android.app.usage.UsageStatsManagerInternal;
|
||||
import android.content.Context;
|
||||
import android.content.LocusId;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
@@ -196,39 +197,42 @@ public final class UsageStatsQueryHelperTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryAppLaunchCount() {
|
||||
|
||||
UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2);
|
||||
UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3);
|
||||
UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1);
|
||||
public void testQueryAppUsageStats() {
|
||||
UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2, createDummyChooserCounts());
|
||||
UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3, null);
|
||||
UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1, createDummyChooserCounts());
|
||||
when(mUsageStatsManagerInternal.queryUsageStatsForUser(anyInt(), anyInt(), anyLong(),
|
||||
anyLong(), anyBoolean())).thenReturn(
|
||||
List.of(packageStats1, packageStats2, packageStats3));
|
||||
|
||||
Map<String, Integer> appLaunchCounts = mHelper.queryAppLaunchCount(USER_ID_PRIMARY, 90_000L,
|
||||
200_000L, Set.of(PKG_NAME_1, PKG_NAME_2));
|
||||
Map<String, AppUsageStatsData> appLaunchChooserCountCounts =
|
||||
mHelper.queryAppUsageStats(USER_ID_PRIMARY, 90_000L,
|
||||
200_000L, Set.of(PKG_NAME_1, PKG_NAME_2));
|
||||
|
||||
assertEquals(2, appLaunchCounts.size());
|
||||
assertEquals(5, (long) appLaunchCounts.get(PKG_NAME_1));
|
||||
assertEquals(1, (long) appLaunchCounts.get(PKG_NAME_2));
|
||||
assertEquals(2, appLaunchChooserCountCounts.size());
|
||||
assertEquals(4, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getChosenCount());
|
||||
assertEquals(5, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getLaunchCount());
|
||||
assertEquals(4, (long) appLaunchChooserCountCounts.get(PKG_NAME_2).getChosenCount());
|
||||
assertEquals(1, (long) appLaunchChooserCountCounts.get(PKG_NAME_2).getLaunchCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryAppLaunchCount_packageNameFiltered() {
|
||||
|
||||
UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2);
|
||||
UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3);
|
||||
UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1);
|
||||
public void testQueryAppUsageStats_packageNameFiltered() {
|
||||
UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2, createDummyChooserCounts());
|
||||
UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3, createDummyChooserCounts());
|
||||
UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1, null);
|
||||
when(mUsageStatsManagerInternal.queryUsageStatsForUser(anyInt(), anyInt(), anyLong(),
|
||||
anyLong(), anyBoolean())).thenReturn(
|
||||
List.of(packageStats1, packageStats2, packageStats3));
|
||||
|
||||
Map<String, Integer> appLaunchCounts = mHelper.queryAppLaunchCount(USER_ID_PRIMARY, 90_000L,
|
||||
200_000L,
|
||||
Set.of(PKG_NAME_1));
|
||||
Map<String, AppUsageStatsData> appLaunchChooserCountCounts =
|
||||
mHelper.queryAppUsageStats(USER_ID_PRIMARY, 90_000L,
|
||||
200_000L,
|
||||
Set.of(PKG_NAME_1));
|
||||
|
||||
assertEquals(1, appLaunchCounts.size());
|
||||
assertEquals(5, (long) appLaunchCounts.get(PKG_NAME_1));
|
||||
assertEquals(1, appLaunchChooserCountCounts.size());
|
||||
assertEquals(8, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getChosenCount());
|
||||
assertEquals(5, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getLaunchCount());
|
||||
}
|
||||
|
||||
private void addUsageEvents(UsageEvents.Event... events) {
|
||||
@@ -237,13 +241,27 @@ public final class UsageStatsQueryHelperTest {
|
||||
anyInt())).thenReturn(usageEvents);
|
||||
}
|
||||
|
||||
private static UsageStats createUsageStats(String packageName, int launchCount) {
|
||||
private static UsageStats createUsageStats(String packageName, int launchCount,
|
||||
ArrayMap<String, ArrayMap<String, Integer>> chooserCounts) {
|
||||
UsageStats packageStats = new UsageStats();
|
||||
packageStats.mPackageName = packageName;
|
||||
packageStats.mAppLaunchCount = launchCount;
|
||||
packageStats.mChooserCounts = chooserCounts;
|
||||
return packageStats;
|
||||
}
|
||||
|
||||
private static ArrayMap<String, ArrayMap<String, Integer>> createDummyChooserCounts() {
|
||||
ArrayMap<String, ArrayMap<String, Integer>> chooserCounts = new ArrayMap<>();
|
||||
ArrayMap<String, Integer> counts1 = new ArrayMap<>();
|
||||
counts1.put("text", 2);
|
||||
counts1.put("image", 1);
|
||||
chooserCounts.put("intent1", counts1);
|
||||
ArrayMap<String, Integer> counts2 = new ArrayMap<>();
|
||||
counts2.put("video", 1);
|
||||
chooserCounts.put("intent2", counts2);
|
||||
return chooserCounts;
|
||||
}
|
||||
|
||||
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
|
||||
LocalServices.removeServiceForTest(clazz);
|
||||
LocalServices.addService(clazz, mock);
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.app.usage.UsageEvents;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Range;
|
||||
|
||||
import com.android.server.people.data.AppUsageStatsData;
|
||||
import com.android.server.people.data.DataManager;
|
||||
import com.android.server.people.data.Event;
|
||||
import com.android.server.people.data.EventHistory;
|
||||
@@ -256,6 +257,39 @@ public final class SharesheetModelScorerTest {
|
||||
assertEquals(0f, mShareTarget6.getScore(), DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeScoreForAppShare_promoteFrequentlyChosenApps() {
|
||||
when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
|
||||
when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
|
||||
when(mEventHistory3.getEventIndex(anySet())).thenReturn(mEventIndex3);
|
||||
when(mEventHistory4.getEventIndex(anySet())).thenReturn(mEventIndex4);
|
||||
when(mEventHistory5.getEventIndex(anySet())).thenReturn(mEventIndex5);
|
||||
when(mEventHistory1.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex6);
|
||||
when(mEventHistory2.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex7);
|
||||
when(mEventHistory3.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex8);
|
||||
when(mEventHistory4.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex9);
|
||||
when(mEventHistory5.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex10);
|
||||
when(mDataManager.queryAppUsageStats(anyInt(), anyLong(), anyLong(), anySet()))
|
||||
.thenReturn(
|
||||
Map.of(PACKAGE_1, new AppUsageStatsData(1, 0),
|
||||
PACKAGE_2, new AppUsageStatsData(2, 0),
|
||||
PACKAGE_3, new AppUsageStatsData(3, 0)));
|
||||
|
||||
SharesheetModelScorer.computeScoreForAppShare(
|
||||
List.of(mShareTarget1, mShareTarget2, mShareTarget3, mShareTarget4, mShareTarget5,
|
||||
mShareTarget6),
|
||||
Event.TYPE_SHARE_TEXT, 20, NOW, mDataManager, USER_ID);
|
||||
|
||||
verify(mDataManager, times(1)).queryAppUsageStats(anyInt(), anyLong(), anyLong(),
|
||||
anySet());
|
||||
assertEquals(0.9f, mShareTarget5.getScore(), DELTA);
|
||||
assertEquals(0.6f, mShareTarget3.getScore(), DELTA);
|
||||
assertEquals(0.3f, mShareTarget1.getScore(), DELTA);
|
||||
assertEquals(0f, mShareTarget2.getScore(), DELTA);
|
||||
assertEquals(0f, mShareTarget4.getScore(), DELTA);
|
||||
assertEquals(0f, mShareTarget6.getScore(), DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeScoreForAppShare_promoteFrequentlyUsedApps() {
|
||||
when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
|
||||
@@ -268,22 +302,22 @@ public final class SharesheetModelScorerTest {
|
||||
when(mEventHistory3.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex8);
|
||||
when(mEventHistory4.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex9);
|
||||
when(mEventHistory5.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex10);
|
||||
when(mDataManager.queryAppLaunchCount(anyInt(), anyLong(), anyLong(), anySet()))
|
||||
when(mDataManager.queryAppUsageStats(anyInt(), anyLong(), anyLong(), anySet()))
|
||||
.thenReturn(
|
||||
Map.of(PACKAGE_1, 1,
|
||||
PACKAGE_2, 2,
|
||||
PACKAGE_3, 3));
|
||||
Map.of(PACKAGE_1, new AppUsageStatsData(0, 1),
|
||||
PACKAGE_2, new AppUsageStatsData(0, 2),
|
||||
PACKAGE_3, new AppUsageStatsData(1, 0)));
|
||||
|
||||
SharesheetModelScorer.computeScoreForAppShare(
|
||||
List.of(mShareTarget1, mShareTarget2, mShareTarget3, mShareTarget4, mShareTarget5,
|
||||
mShareTarget6),
|
||||
Event.TYPE_SHARE_TEXT, 20, NOW, mDataManager, USER_ID);
|
||||
|
||||
verify(mDataManager, times(1)).queryAppLaunchCount(anyInt(), anyLong(), anyLong(),
|
||||
verify(mDataManager, times(1)).queryAppUsageStats(anyInt(), anyLong(), anyLong(),
|
||||
anySet());
|
||||
assertEquals(0.3f, mShareTarget5.getScore(), DELTA);
|
||||
assertEquals(0.9f, mShareTarget5.getScore(), DELTA);
|
||||
assertEquals(0.27f, mShareTarget3.getScore(), DELTA);
|
||||
assertEquals(0.243f, mShareTarget1.getScore(), DELTA);
|
||||
assertEquals(0.135f, mShareTarget1.getScore(), DELTA);
|
||||
assertEquals(0f, mShareTarget2.getScore(), DELTA);
|
||||
assertEquals(0f, mShareTarget4.getScore(), DELTA);
|
||||
assertEquals(0f, mShareTarget6.getScore(), DELTA);
|
||||
@@ -306,18 +340,19 @@ public final class SharesheetModelScorerTest {
|
||||
when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(FIVE_DAYS_AGO);
|
||||
when(mEventIndex4.getMostRecentActiveTimeSlot()).thenReturn(EIGHT_DAYS_AGO);
|
||||
when(mEventIndex5.getMostRecentActiveTimeSlot()).thenReturn(null);
|
||||
when(mDataManager.queryAppLaunchCount(anyInt(), anyLong(), anyLong(), anySet()))
|
||||
when(mDataManager.queryAppUsageStats(anyInt(), anyLong(), anyLong(), anySet()))
|
||||
.thenReturn(
|
||||
Map.of(PACKAGE_1, 1,
|
||||
PACKAGE_2, 2,
|
||||
PACKAGE_3, 3));
|
||||
Map.of(PACKAGE_1, new AppUsageStatsData(0, 1),
|
||||
PACKAGE_2, new AppUsageStatsData(0, 2),
|
||||
PACKAGE_3, new AppUsageStatsData(1, 0)));
|
||||
|
||||
SharesheetModelScorer.computeScoreForAppShare(
|
||||
List.of(mShareTarget1, mShareTarget2, mShareTarget3, mShareTarget4, mShareTarget5,
|
||||
mShareTarget6),
|
||||
Event.TYPE_SHARE_TEXT, 4, NOW, mDataManager, USER_ID);
|
||||
|
||||
verify(mDataManager, never()).queryAppLaunchCount(anyInt(), anyLong(), anyLong(), anySet());
|
||||
verify(mDataManager, never()).queryAppUsageStats(anyInt(), anyLong(), anyLong(),
|
||||
anySet());
|
||||
assertEquals(0.4f, mShareTarget1.getScore(), DELTA);
|
||||
assertEquals(0.35f, mShareTarget2.getScore(), DELTA);
|
||||
assertEquals(0.33f, mShareTarget3.getScore(), DELTA);
|
||||
|
||||
Reference in New Issue
Block a user