Implement sharesheet ranking in PeopleService. Ranking is only based on
recency of past sharing for the moment. Bug: 149822311 Test: atest com.android.server.people.data.DataManagerTest Test: atest com.android.server.people.data.ShareTargetPredictorTest Change-Id: I90d1b3f488b34fede7d577dc04832b976f4a1bbb
This commit is contained in:
@@ -51,7 +51,6 @@ import android.provider.Telephony.MmsSms;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.SparseArray;
|
||||
@@ -275,40 +274,35 @@ public class DataManager {
|
||||
mContext.getPackageName(), intentFilter, callingUserId);
|
||||
}
|
||||
|
||||
/** Reports the {@link AppTargetEvent} from App Prediction Manager. */
|
||||
public void reportAppTargetEvent(@NonNull AppTargetEvent event,
|
||||
/** Reports the sharing related {@link AppTargetEvent} from App Prediction Manager. */
|
||||
public void reportShareTargetEvent(@NonNull AppTargetEvent event,
|
||||
@Nullable IntentFilter intentFilter) {
|
||||
AppTarget appTarget = event.getTarget();
|
||||
ShortcutInfo shortcutInfo = appTarget != null ? appTarget.getShortcutInfo() : null;
|
||||
if (shortcutInfo == null || event.getAction() != AppTargetEvent.ACTION_LAUNCH) {
|
||||
return;
|
||||
}
|
||||
PackageData packageData = getPackage(appTarget.getPackageName(),
|
||||
appTarget.getUser().getIdentifier());
|
||||
if (packageData == null) {
|
||||
if (appTarget == null || event.getAction() != AppTargetEvent.ACTION_LAUNCH) {
|
||||
return;
|
||||
}
|
||||
UserData userData = getUnlockedUserData(appTarget.getUser().getIdentifier());
|
||||
PackageData packageData = userData.getOrCreatePackageData(appTarget.getPackageName());
|
||||
String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
|
||||
@Event.EventType int eventType = mimeTypeToShareEventType(mimeType);
|
||||
EventHistoryImpl eventHistory;
|
||||
if (ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE.equals(event.getLaunchLocation())) {
|
||||
String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
|
||||
String shortcutId = shortcutInfo.getId();
|
||||
if (packageData.getConversationStore().getConversation(shortcutId) == null
|
||||
|| TextUtils.isEmpty(mimeType)) {
|
||||
// Direct share event
|
||||
if (appTarget.getShortcutInfo() == null) {
|
||||
return;
|
||||
}
|
||||
EventHistoryImpl eventHistory = packageData.getEventStore().getOrCreateEventHistory(
|
||||
EventStore.CATEGORY_SHORTCUT_BASED, shortcutInfo.getId());
|
||||
@Event.EventType int eventType;
|
||||
if (mimeType.startsWith("text/")) {
|
||||
eventType = Event.TYPE_SHARE_TEXT;
|
||||
} else if (mimeType.startsWith("image/")) {
|
||||
eventType = Event.TYPE_SHARE_IMAGE;
|
||||
} else if (mimeType.startsWith("video/")) {
|
||||
eventType = Event.TYPE_SHARE_VIDEO;
|
||||
} else {
|
||||
eventType = Event.TYPE_SHARE_OTHER;
|
||||
String shortcutId = appTarget.getShortcutInfo().getId();
|
||||
if (packageData.getConversationStore().getConversation(shortcutId) == null) {
|
||||
addOrUpdateConversationInfo(appTarget.getShortcutInfo());
|
||||
}
|
||||
eventHistory.addEvent(new Event(System.currentTimeMillis(), eventType));
|
||||
eventHistory = packageData.getEventStore().getOrCreateEventHistory(
|
||||
EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
|
||||
} else {
|
||||
// App share event
|
||||
eventHistory = packageData.getEventStore().getOrCreateEventHistory(
|
||||
EventStore.CATEGORY_CLASS_BASED, appTarget.getClassName());
|
||||
}
|
||||
eventHistory.addEvent(new Event(System.currentTimeMillis(), eventType));
|
||||
}
|
||||
|
||||
/** Prunes the data for the specified user. */
|
||||
@@ -335,6 +329,17 @@ public class DataManager {
|
||||
});
|
||||
}
|
||||
|
||||
private int mimeTypeToShareEventType(String mimeType) {
|
||||
if (mimeType.startsWith("text/")) {
|
||||
return Event.TYPE_SHARE_TEXT;
|
||||
} else if (mimeType.startsWith("image/")) {
|
||||
return Event.TYPE_SHARE_IMAGE;
|
||||
} else if (mimeType.startsWith("video/")) {
|
||||
return Event.TYPE_SHARE_VIDEO;
|
||||
}
|
||||
return Event.TYPE_SHARE_OTHER;
|
||||
}
|
||||
|
||||
private void pruneUninstalledPackageData(@NonNull UserData userData) {
|
||||
Set<String> installApps = new ArraySet<>();
|
||||
mPackageManagerInternal.forEachInstalledPackage(
|
||||
@@ -410,12 +415,13 @@ public class DataManager {
|
||||
EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
|
||||
}
|
||||
|
||||
private boolean isPersonShortcut(@NonNull ShortcutInfo shortcutInfo) {
|
||||
return shortcutInfo.getPersons() != null && shortcutInfo.getPersons().length != 0;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@WorkerThread
|
||||
void onShortcutAddedOrUpdated(@NonNull ShortcutInfo shortcutInfo) {
|
||||
if (shortcutInfo.getPersons() == null || shortcutInfo.getPersons().length == 0) {
|
||||
return;
|
||||
}
|
||||
void addOrUpdateConversationInfo(@NonNull ShortcutInfo shortcutInfo) {
|
||||
UserData userData = getUnlockedUserData(shortcutInfo.getUserId());
|
||||
if (userData == null) {
|
||||
return;
|
||||
@@ -431,24 +437,24 @@ public class DataManager {
|
||||
builder.setShortcutId(shortcutInfo.getId());
|
||||
builder.setLocusId(shortcutInfo.getLocusId());
|
||||
builder.setShortcutFlags(shortcutInfo.getFlags());
|
||||
builder.setContactUri(null);
|
||||
builder.setContactPhoneNumber(null);
|
||||
builder.setContactStarred(false);
|
||||
|
||||
Person person = shortcutInfo.getPersons()[0];
|
||||
builder.setPersonImportant(person.isImportant());
|
||||
builder.setPersonBot(person.isBot());
|
||||
String contactUri = person.getUri();
|
||||
if (contactUri != null) {
|
||||
ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
|
||||
if (helper.query(contactUri)) {
|
||||
builder.setContactUri(helper.getContactUri());
|
||||
builder.setContactStarred(helper.isStarred());
|
||||
builder.setContactPhoneNumber(helper.getPhoneNumber());
|
||||
if (shortcutInfo.getPersons() != null && shortcutInfo.getPersons().length != 0) {
|
||||
Person person = shortcutInfo.getPersons()[0];
|
||||
builder.setPersonImportant(person.isImportant());
|
||||
builder.setPersonBot(person.isBot());
|
||||
String contactUri = person.getUri();
|
||||
if (contactUri != null) {
|
||||
ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
|
||||
if (helper.query(contactUri)) {
|
||||
builder.setContactUri(helper.getContactUri());
|
||||
builder.setContactStarred(helper.isStarred());
|
||||
builder.setContactPhoneNumber(helper.getPhoneNumber());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
builder.setContactUri(null);
|
||||
builder.setContactPhoneNumber(null);
|
||||
builder.setContactStarred(false);
|
||||
}
|
||||
|
||||
conversationStore.addOrUpdate(builder.build());
|
||||
}
|
||||
|
||||
@@ -626,7 +632,9 @@ public class DataManager {
|
||||
List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
|
||||
/*shortcutIds=*/ null);
|
||||
for (ShortcutInfo shortcut : shortcuts) {
|
||||
onShortcutAddedOrUpdated(shortcut);
|
||||
if (isPersonShortcut(shortcut)) {
|
||||
addOrUpdateConversationInfo(shortcut);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ public class AppTargetPredictor {
|
||||
*/
|
||||
@MainThread
|
||||
public void onAppTargetEvent(AppTargetEvent event) {
|
||||
mCallbackExecutor.execute(() -> reportAppTargetEvent(event));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,6 +105,11 @@ public class AppTargetPredictor {
|
||||
return mUpdatePredictionsMethod;
|
||||
}
|
||||
|
||||
/** To be overridden by the subclass to report app target event. */
|
||||
@WorkerThread
|
||||
void reportAppTargetEvent(AppTargetEvent event) {
|
||||
}
|
||||
|
||||
/** To be overridden by the subclass to predict the targets. */
|
||||
@WorkerThread
|
||||
void predictTargets() {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server.people.prediction;
|
||||
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
@@ -28,15 +27,18 @@ import android.app.prediction.AppTargetId;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager.ShareShortcutInfo;
|
||||
import android.util.Range;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.ChooserActivity;
|
||||
import com.android.server.people.data.ConversationInfo;
|
||||
import com.android.server.people.data.DataManager;
|
||||
import com.android.server.people.data.Event;
|
||||
import com.android.server.people.data.EventHistory;
|
||||
import com.android.server.people.data.PackageData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -52,89 +54,139 @@ class ShareTargetPredictor extends AppTargetPredictor {
|
||||
ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
@Override
|
||||
public void onAppTargetEvent(AppTargetEvent event) {
|
||||
getDataManager().reportAppTargetEvent(event, mIntentFilter);
|
||||
}
|
||||
|
||||
/** Reports chosen history of direct/app share targets. */
|
||||
@WorkerThread
|
||||
@Override
|
||||
protected void predictTargets() {
|
||||
List<ShareTarget> shareTargets = getShareTargets();
|
||||
// TODO: Rank the share targets with the data in ShareTarget.mConversationData.
|
||||
List<AppTarget> appTargets = new ArrayList<>();
|
||||
for (ShareTarget shareTarget : shareTargets) {
|
||||
|
||||
ShortcutInfo shortcutInfo = shareTarget.getShareShortcutInfo().getShortcutInfo();
|
||||
AppTargetId appTargetId = new AppTargetId(shortcutInfo.getId());
|
||||
String shareTargetClassName =
|
||||
shareTarget.getShareShortcutInfo().getTargetComponent().getClassName();
|
||||
AppTarget appTarget = new AppTarget.Builder(appTargetId, shortcutInfo)
|
||||
.setClassName(shareTargetClassName)
|
||||
.build();
|
||||
appTargets.add(appTarget);
|
||||
if (appTargets.size() >= getPredictionContext().getPredictedTargetCount()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
updatePredictions(appTargets);
|
||||
void reportAppTargetEvent(AppTargetEvent event) {
|
||||
getDataManager().reportShareTargetEvent(event, mIntentFilter);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
List<ShareTarget> getShareTargets() {
|
||||
/** Provides prediction on direct share targets */
|
||||
@WorkerThread
|
||||
@Override
|
||||
void predictTargets() {
|
||||
List<ShareTarget> shareTargets = getDirectShareTargets();
|
||||
rankTargets(shareTargets);
|
||||
List<AppTarget> res = new ArrayList<>();
|
||||
for (int i = 0; i < Math.min(getPredictionContext().getPredictedTargetCount(),
|
||||
shareTargets.size()); i++) {
|
||||
res.add(shareTargets.get(i).getAppTarget());
|
||||
}
|
||||
updatePredictions(res);
|
||||
}
|
||||
|
||||
/** Provides prediction on app share targets */
|
||||
@WorkerThread
|
||||
@Override
|
||||
void sortTargets(List<AppTarget> targets, Consumer<List<AppTarget>> callback) {
|
||||
List<ShareTarget> shareTargets = getAppShareTargets(targets);
|
||||
rankTargets(shareTargets);
|
||||
List<AppTarget> appTargetList = new ArrayList<>();
|
||||
shareTargets.forEach(t -> appTargetList.add(t.getAppTarget()));
|
||||
callback.accept(appTargetList);
|
||||
}
|
||||
|
||||
private void rankTargets(List<ShareTarget> shareTargets) {
|
||||
// Rank targets based on recency of sharing history only for the moment.
|
||||
// TODO: Take more factors into ranking, e.g. frequency, mime type, foreground app.
|
||||
Collections.sort(shareTargets, (t1, t2) -> {
|
||||
if (t1.getEventHistory() == null) {
|
||||
return 1;
|
||||
}
|
||||
if (t2.getEventHistory() == null) {
|
||||
return -1;
|
||||
}
|
||||
Range<Long> timeSlot1 = t1.getEventHistory().getEventIndex(
|
||||
Event.SHARE_EVENT_TYPES).getMostRecentActiveTimeSlot();
|
||||
Range<Long> timeSlot2 = t2.getEventHistory().getEventIndex(
|
||||
Event.SHARE_EVENT_TYPES).getMostRecentActiveTimeSlot();
|
||||
if (timeSlot1 == null) {
|
||||
return 1;
|
||||
} else if (timeSlot2 == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return -Long.compare(timeSlot1.getUpper(), timeSlot2.getUpper());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<ShareTarget> getDirectShareTargets() {
|
||||
List<ShareTarget> shareTargets = new ArrayList<>();
|
||||
List<ShareShortcutInfo> shareShortcuts =
|
||||
getDataManager().getShareShortcuts(mIntentFilter, mCallingUserId);
|
||||
|
||||
for (ShareShortcutInfo shareShortcut : shareShortcuts) {
|
||||
ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
|
||||
AppTarget appTarget = new AppTarget.Builder(
|
||||
new AppTargetId(shortcutInfo.getId()),
|
||||
shortcutInfo)
|
||||
.setClassName(shareShortcut.getTargetComponent().getClassName())
|
||||
.build();
|
||||
String packageName = shortcutInfo.getPackage();
|
||||
int userId = shortcutInfo.getUserId();
|
||||
PackageData packageData = getDataManager().getPackage(packageName, userId);
|
||||
|
||||
ConversationData conversationData = null;
|
||||
ConversationInfo conversationInfo = null;
|
||||
EventHistory eventHistory = null;
|
||||
if (packageData != null) {
|
||||
String shortcutId = shortcutInfo.getId();
|
||||
ConversationInfo conversationInfo =
|
||||
packageData.getConversationInfo(shortcutId);
|
||||
|
||||
conversationInfo = packageData.getConversationInfo(shortcutId);
|
||||
if (conversationInfo != null) {
|
||||
EventHistory eventHistory = packageData.getEventHistory(shortcutId);
|
||||
conversationData = new ConversationData(
|
||||
packageName, userId, conversationInfo, eventHistory);
|
||||
eventHistory = packageData.getEventHistory(shortcutId);
|
||||
}
|
||||
}
|
||||
shareTargets.add(new ShareTarget(shareShortcut, conversationData));
|
||||
shareTargets.add(new ShareTarget(appTarget, eventHistory, conversationInfo));
|
||||
}
|
||||
|
||||
return shareTargets;
|
||||
}
|
||||
|
||||
private List<ShareTarget> getAppShareTargets(List<AppTarget> targets) {
|
||||
List<ShareTarget> shareTargets = new ArrayList<>();
|
||||
for (AppTarget target : targets) {
|
||||
PackageData packageData = getDataManager().getPackage(target.getPackageName(),
|
||||
target.getUser().getIdentifier());
|
||||
shareTargets.add(new ShareTarget(target,
|
||||
packageData == null ? null
|
||||
: packageData.getClassLevelEventHistory(target.getClassName()), null));
|
||||
}
|
||||
return shareTargets;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class ShareTarget {
|
||||
|
||||
@NonNull
|
||||
private final ShareShortcutInfo mShareShortcutInfo;
|
||||
private final AppTarget mAppTarget;
|
||||
@Nullable
|
||||
private final ConversationData mConversationData;
|
||||
private final EventHistory mEventHistory;
|
||||
@Nullable
|
||||
private final ConversationInfo mConversationInfo;
|
||||
|
||||
private ShareTarget(@NonNull ShareShortcutInfo shareShortcutInfo,
|
||||
@Nullable ConversationData conversationData) {
|
||||
mShareShortcutInfo = shareShortcutInfo;
|
||||
mConversationData = conversationData;
|
||||
private ShareTarget(@NonNull AppTarget appTarget,
|
||||
@Nullable EventHistory eventHistory,
|
||||
@Nullable ConversationInfo conversationInfo) {
|
||||
mAppTarget = appTarget;
|
||||
mEventHistory = eventHistory;
|
||||
mConversationInfo = conversationInfo;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@VisibleForTesting
|
||||
ShareShortcutInfo getShareShortcutInfo() {
|
||||
return mShareShortcutInfo;
|
||||
AppTarget getAppTarget() {
|
||||
return mAppTarget;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
ConversationData getConversationData() {
|
||||
return mConversationData;
|
||||
EventHistory getEventHistory() {
|
||||
return mEventHistory;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
ConversationInfo getConversationInfo() {
|
||||
return mConversationInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ public final class DataManagerTest {
|
||||
private static final int USER_ID_PRIMARY_MANAGED = 10;
|
||||
private static final int USER_ID_SECONDARY = 11;
|
||||
private static final String TEST_PKG_NAME = "pkg";
|
||||
private static final String TEST_CLASS_NAME = "class";
|
||||
private static final String TEST_SHORTCUT_ID = "sc";
|
||||
private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
|
||||
private static final String PHONE_NUMBER = "+1234567890";
|
||||
@@ -206,13 +207,13 @@ public final class DataManagerTest {
|
||||
mDataManager.onUserUnlocked(USER_ID_PRIMARY_MANAGED);
|
||||
mDataManager.onUserUnlocked(USER_ID_SECONDARY);
|
||||
|
||||
mDataManager.onShortcutAddedOrUpdated(
|
||||
mDataManager.addOrUpdateConversationInfo(
|
||||
buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1",
|
||||
buildPerson(true, false)));
|
||||
mDataManager.onShortcutAddedOrUpdated(
|
||||
mDataManager.addOrUpdateConversationInfo(
|
||||
buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2",
|
||||
buildPerson(false, true)));
|
||||
mDataManager.onShortcutAddedOrUpdated(
|
||||
mDataManager.addOrUpdateConversationInfo(
|
||||
buildShortcutInfo("pkg_3", USER_ID_SECONDARY, "sc_3", buildPerson()));
|
||||
|
||||
List<ConversationInfo> conversations = getConversationsInPrimary();
|
||||
@@ -236,9 +237,9 @@ public final class DataManagerTest {
|
||||
@Test
|
||||
public void testAccessConversationForUnlockedUsersOnly() {
|
||||
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
|
||||
mDataManager.onShortcutAddedOrUpdated(
|
||||
mDataManager.addOrUpdateConversationInfo(
|
||||
buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson()));
|
||||
mDataManager.onShortcutAddedOrUpdated(
|
||||
mDataManager.addOrUpdateConversationInfo(
|
||||
buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", buildPerson()));
|
||||
|
||||
List<ConversationInfo> conversations = getConversationsInPrimary();
|
||||
@@ -261,11 +262,12 @@ public final class DataManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportAppTargetEvent() throws IntentFilter.MalformedMimeTypeException {
|
||||
public void testReportAppTargetEvent_directSharing()
|
||||
throws IntentFilter.MalformedMimeTypeException {
|
||||
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
|
||||
.build();
|
||||
@@ -274,7 +276,55 @@ public final class DataManagerTest {
|
||||
.setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
|
||||
.build();
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
|
||||
mDataManager.reportAppTargetEvent(appTargetEvent, intentFilter);
|
||||
mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
|
||||
|
||||
List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
|
||||
Event.SHARE_EVENT_TYPES);
|
||||
assertEquals(1, activeShareTimeSlots.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportAppTargetEvent_directSharing_createConversation()
|
||||
throws IntentFilter.MalformedMimeTypeException {
|
||||
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
null);
|
||||
AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
|
||||
.build();
|
||||
AppTargetEvent appTargetEvent =
|
||||
new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
|
||||
.setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
|
||||
.build();
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
|
||||
|
||||
mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
|
||||
|
||||
List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
|
||||
Event.SHARE_EVENT_TYPES);
|
||||
assertEquals(1, activeShareTimeSlots.size());
|
||||
ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
|
||||
.getConversationStore()
|
||||
.getConversation(TEST_SHORTCUT_ID);
|
||||
assertNotNull(conversationInfo);
|
||||
assertEquals(conversationInfo.getShortcutId(), TEST_SHORTCUT_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportAppTargetEvent_appSharing()
|
||||
throws IntentFilter.MalformedMimeTypeException {
|
||||
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
|
||||
AppTarget appTarget = new AppTarget.Builder(
|
||||
new AppTargetId(TEST_SHORTCUT_ID),
|
||||
TEST_PKG_NAME,
|
||||
UserHandle.of(USER_ID_PRIMARY))
|
||||
.setClassName(TEST_CLASS_NAME)
|
||||
.build();
|
||||
AppTargetEvent appTargetEvent =
|
||||
new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
|
||||
.build();
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
|
||||
|
||||
mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
|
||||
|
||||
List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
|
||||
Event.SHARE_EVENT_TYPES);
|
||||
@@ -288,7 +338,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
final String newPhoneNumber = "+1000000000";
|
||||
mInjector.mContactsQueryHelper.mIsStarred = true;
|
||||
@@ -312,7 +362,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
NotificationListenerService listenerService =
|
||||
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
|
||||
@@ -330,7 +380,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
NotificationListenerService listenerService =
|
||||
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
|
||||
@@ -350,7 +400,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
NotificationListenerService listenerService =
|
||||
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
|
||||
@@ -375,7 +425,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
NotificationListenerService listenerService =
|
||||
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
|
||||
@@ -401,7 +451,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
NotificationListenerService listenerService =
|
||||
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
|
||||
@@ -430,7 +480,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
ContentObserver contentObserver = mDataManager.getCallLogContentObserverForTesting();
|
||||
contentObserver.onChange(false);
|
||||
@@ -453,7 +503,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME);
|
||||
|
||||
ContentObserver contentObserver = mDataManager.getMmsSmsContentObserverForTesting();
|
||||
@@ -476,7 +526,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));
|
||||
|
||||
PackageMonitor packageMonitor = mDataManager.getPackageMonitorForTesting(USER_ID_PRIMARY);
|
||||
@@ -493,7 +543,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));
|
||||
|
||||
doAnswer(ans -> null).when(mPackageManagerInternal)
|
||||
@@ -508,7 +558,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
|
||||
long currentTimestamp = System.currentTimeMillis();
|
||||
mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
|
||||
@@ -529,7 +579,7 @@ public final class DataManagerTest {
|
||||
|
||||
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
|
||||
buildPerson());
|
||||
mDataManager.onShortcutAddedOrUpdated(shortcut);
|
||||
mDataManager.addOrUpdateConversationInfo(shortcut);
|
||||
mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME);
|
||||
|
||||
long currentTimestamp = System.currentTimeMillis();
|
||||
|
||||
@@ -16,16 +16,19 @@
|
||||
|
||||
package com.android.server.people.prediction;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.anySet;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.app.prediction.AppTargetId;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -33,22 +36,26 @@ import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager.ShareShortcutInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Range;
|
||||
|
||||
import com.android.server.people.data.ConversationInfo;
|
||||
import com.android.server.people.data.DataManager;
|
||||
import com.android.server.people.data.EventHistory;
|
||||
import com.android.server.people.data.EventIndex;
|
||||
import com.android.server.people.data.PackageData;
|
||||
import com.android.server.people.prediction.ShareTargetPredictor.ShareTarget;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public final class ShareTargetPredictorTest {
|
||||
@@ -57,17 +64,32 @@ public final class ShareTargetPredictorTest {
|
||||
private static final int NUM_PREDICTED_TARGETS = 5;
|
||||
private static final int USER_ID = 0;
|
||||
private static final String PACKAGE_1 = "pkg1";
|
||||
private static final String CLASS_1 = "cls1";
|
||||
private static final String PACKAGE_2 = "pkg2";
|
||||
private static final String PACKAGE_3 = "pkg3";
|
||||
private static final String CLASS_1 = "cls1";
|
||||
private static final String CLASS_2 = "cls2";
|
||||
|
||||
@Mock private Context mContext;
|
||||
@Mock private DataManager mDataManager;
|
||||
@Mock private Consumer<List<AppTarget>> mUpdatePredictionsMethod;
|
||||
@Mock private PackageData mPackageData1;
|
||||
@Mock private PackageData mPackageData2;
|
||||
@Mock private EventHistory mEventHistory1;
|
||||
@Mock private EventHistory mEventHistory2;
|
||||
@Mock private EventHistory mEventHistory3;
|
||||
@Mock private EventHistory mEventHistory4;
|
||||
@Mock private EventHistory mEventHistory5;
|
||||
@Mock private EventHistory mEventHistory6;
|
||||
|
||||
@Mock private EventIndex mEventIndex1;
|
||||
@Mock private EventIndex mEventIndex2;
|
||||
@Mock private EventIndex mEventIndex3;
|
||||
@Mock private EventIndex mEventIndex4;
|
||||
@Mock private EventIndex mEventIndex5;
|
||||
@Mock private EventIndex mEventIndex6;
|
||||
@Captor private ArgumentCaptor<List<AppTarget>> mAppTargetCaptor;
|
||||
|
||||
private List<ShareShortcutInfo> mShareShortcuts = new ArrayList<>();
|
||||
|
||||
private ShareTargetPredictor mPredictor;
|
||||
|
||||
@Before
|
||||
@@ -84,11 +106,11 @@ public final class ShareTargetPredictorTest {
|
||||
.setExtras(new Bundle())
|
||||
.build();
|
||||
mPredictor = new ShareTargetPredictor(
|
||||
predictionContext, targets -> { }, mDataManager, USER_ID);
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetShareTargets() {
|
||||
public void testPredictTargets() {
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc1"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc2"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc3"));
|
||||
@@ -99,24 +121,148 @@ public final class ShareTargetPredictorTest {
|
||||
when(mPackageData2.getConversationInfo("sc3")).thenReturn(mock(ConversationInfo.class));
|
||||
// "sc4" does not have a ConversationInfo.
|
||||
|
||||
when(mPackageData1.getEventHistory(anyString())).thenReturn(mock(EventHistory.class));
|
||||
when(mPackageData2.getEventHistory(anyString())).thenReturn(mock(EventHistory.class));
|
||||
when(mPackageData1.getEventHistory("sc1")).thenReturn(mEventHistory1);
|
||||
when(mPackageData1.getEventHistory("sc2")).thenReturn(mEventHistory2);
|
||||
when(mPackageData2.getEventHistory("sc3")).thenReturn(mEventHistory3);
|
||||
when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
|
||||
when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
|
||||
when(mEventHistory3.getEventIndex(anySet())).thenReturn(mEventIndex3);
|
||||
when(mEventIndex1.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(1L, 2L));
|
||||
when(mEventIndex2.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(2L, 3L));
|
||||
when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(3L, 4L));
|
||||
|
||||
List<ShareTarget> shareTargets = mPredictor.getShareTargets();
|
||||
mPredictor.predictTargets();
|
||||
|
||||
assertEquals(4, shareTargets.size());
|
||||
verify(mUpdatePredictionsMethod).accept(mAppTargetCaptor.capture());
|
||||
List<AppTarget> res = mAppTargetCaptor.getValue();
|
||||
assertEquals(4, res.size());
|
||||
|
||||
assertEquals("sc1", shareTargets.get(0).getShareShortcutInfo().getShortcutInfo().getId());
|
||||
assertNotNull(shareTargets.get(0).getConversationData());
|
||||
assertEquals("sc3", res.get(0).getId().getId());
|
||||
assertEquals(CLASS_2, res.get(0).getClassName());
|
||||
assertEquals(PACKAGE_2, res.get(0).getPackageName());
|
||||
|
||||
assertEquals("sc2", shareTargets.get(1).getShareShortcutInfo().getShortcutInfo().getId());
|
||||
assertNotNull(shareTargets.get(1).getConversationData());
|
||||
assertEquals("sc2", res.get(1).getId().getId());
|
||||
assertEquals(CLASS_1, res.get(1).getClassName());
|
||||
assertEquals(PACKAGE_1, res.get(1).getPackageName());
|
||||
|
||||
assertEquals("sc3", shareTargets.get(2).getShareShortcutInfo().getShortcutInfo().getId());
|
||||
assertNotNull(shareTargets.get(2).getConversationData());
|
||||
assertEquals("sc1", res.get(2).getId().getId());
|
||||
assertEquals(CLASS_1, res.get(2).getClassName());
|
||||
assertEquals(PACKAGE_1, res.get(2).getPackageName());
|
||||
|
||||
assertEquals("sc4", shareTargets.get(3).getShareShortcutInfo().getShortcutInfo().getId());
|
||||
assertNull(shareTargets.get(3).getConversationData());
|
||||
assertEquals("sc4", res.get(3).getId().getId());
|
||||
assertEquals(CLASS_2, res.get(3).getClassName());
|
||||
assertEquals(PACKAGE_2, res.get(3).getPackageName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPredictTargets_reachTargetsLimit() {
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc1"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc2"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc3"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc4"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc5"));
|
||||
mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc6"));
|
||||
|
||||
when(mPackageData1.getConversationInfo("sc1")).thenReturn(mock(ConversationInfo.class));
|
||||
when(mPackageData1.getConversationInfo("sc2")).thenReturn(mock(ConversationInfo.class));
|
||||
when(mPackageData2.getConversationInfo("sc3")).thenReturn(mock(ConversationInfo.class));
|
||||
when(mPackageData2.getConversationInfo("sc4")).thenReturn(mock(ConversationInfo.class));
|
||||
when(mPackageData1.getConversationInfo("sc5")).thenReturn(mock(ConversationInfo.class));
|
||||
when(mPackageData2.getConversationInfo("sc6")).thenReturn(mock(ConversationInfo.class));
|
||||
|
||||
when(mPackageData1.getEventHistory("sc1")).thenReturn(mEventHistory1);
|
||||
when(mPackageData1.getEventHistory("sc2")).thenReturn(mEventHistory2);
|
||||
when(mPackageData2.getEventHistory("sc3")).thenReturn(mEventHistory3);
|
||||
when(mPackageData2.getEventHistory("sc4")).thenReturn(mEventHistory4);
|
||||
when(mPackageData1.getEventHistory("sc5")).thenReturn(mEventHistory5);
|
||||
when(mPackageData2.getEventHistory("sc6")).thenReturn(mEventHistory6);
|
||||
|
||||
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(mEventHistory6.getEventIndex(anySet())).thenReturn(mEventIndex6);
|
||||
when(mEventIndex1.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(1L, 2L));
|
||||
when(mEventIndex2.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(2L, 3L));
|
||||
when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(3L, 4L));
|
||||
when(mEventIndex4.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(4L, 5L));
|
||||
when(mEventIndex5.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(5L, 6L));
|
||||
when(mEventIndex6.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(6L, 7L));
|
||||
|
||||
mPredictor.predictTargets();
|
||||
|
||||
verify(mUpdatePredictionsMethod).accept(mAppTargetCaptor.capture());
|
||||
List<AppTarget> res = mAppTargetCaptor.getValue();
|
||||
assertEquals(5, res.size());
|
||||
|
||||
assertEquals("sc6", res.get(0).getId().getId());
|
||||
assertEquals(CLASS_2, res.get(0).getClassName());
|
||||
assertEquals(PACKAGE_2, res.get(0).getPackageName());
|
||||
|
||||
assertEquals("sc5", res.get(1).getId().getId());
|
||||
assertEquals(CLASS_1, res.get(1).getClassName());
|
||||
assertEquals(PACKAGE_1, res.get(1).getPackageName());
|
||||
|
||||
assertEquals("sc4", res.get(2).getId().getId());
|
||||
assertEquals(CLASS_2, res.get(2).getClassName());
|
||||
assertEquals(PACKAGE_2, res.get(2).getPackageName());
|
||||
|
||||
assertEquals("sc3", res.get(3).getId().getId());
|
||||
assertEquals(CLASS_2, res.get(3).getClassName());
|
||||
assertEquals(PACKAGE_2, res.get(3).getPackageName());
|
||||
|
||||
assertEquals("sc2", res.get(4).getId().getId());
|
||||
assertEquals(CLASS_1, res.get(4).getClassName());
|
||||
assertEquals(PACKAGE_1, res.get(4).getPackageName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSortTargets() {
|
||||
AppTarget appTarget1 = new AppTarget.Builder(
|
||||
new AppTargetId("cls1#pkg1"), PACKAGE_1, UserHandle.of(USER_ID))
|
||||
.setClassName(CLASS_1)
|
||||
.build();
|
||||
AppTarget appTarget2 = new AppTarget.Builder(
|
||||
new AppTargetId("cls2#pkg1"), PACKAGE_1, UserHandle.of(USER_ID))
|
||||
.setClassName(CLASS_2)
|
||||
.build();
|
||||
AppTarget appTarget3 = new AppTarget.Builder(
|
||||
new AppTargetId("cls1#pkg2"), PACKAGE_2, UserHandle.of(USER_ID))
|
||||
.setClassName(CLASS_1)
|
||||
.build();
|
||||
AppTarget appTarget4 = new AppTarget.Builder(
|
||||
new AppTargetId("cls2#pkg2"), PACKAGE_2, UserHandle.of(USER_ID))
|
||||
.setClassName(CLASS_2)
|
||||
.build();
|
||||
AppTarget appTarget5 = new AppTarget.Builder(
|
||||
new AppTargetId("cls1#pkg3"), PACKAGE_3, UserHandle.of(USER_ID))
|
||||
.setClassName(CLASS_1)
|
||||
.build();
|
||||
|
||||
when(mPackageData1.getClassLevelEventHistory(CLASS_1)).thenReturn(mEventHistory1);
|
||||
when(mPackageData1.getClassLevelEventHistory(CLASS_2)).thenReturn(mEventHistory2);
|
||||
when(mPackageData2.getClassLevelEventHistory(CLASS_1)).thenReturn(mEventHistory3);
|
||||
when(mPackageData2.getClassLevelEventHistory(CLASS_2)).thenReturn(mEventHistory4);
|
||||
// PackageData of PACKAGE_3 is empty.
|
||||
when(mDataManager.getPackage(PACKAGE_3, USER_ID)).thenReturn(null);
|
||||
|
||||
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(mEventIndex1.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(1L, 2L));
|
||||
when(mEventIndex2.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(2L, 3L));
|
||||
when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(3L, 4L));
|
||||
when(mEventIndex4.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(4L, 5L));
|
||||
|
||||
mPredictor.sortTargets(
|
||||
List.of(appTarget1, appTarget2, appTarget3, appTarget4, appTarget5),
|
||||
mUpdatePredictionsMethod);
|
||||
|
||||
verify(mUpdatePredictionsMethod).accept(mAppTargetCaptor.capture());
|
||||
assertThat(mAppTargetCaptor.getValue()).containsExactly(
|
||||
appTarget4, appTarget3, appTarget2, appTarget1, appTarget5);
|
||||
}
|
||||
|
||||
private ShareShortcutInfo buildShareShortcut(
|
||||
|
||||
Reference in New Issue
Block a user