1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.people.prediction;
18 
19 import android.annotation.MainThread;
20 import android.annotation.NonNull;
21 import android.annotation.UserIdInt;
22 import android.annotation.WorkerThread;
23 import android.app.prediction.AppPredictionContext;
24 import android.app.prediction.AppTarget;
25 import android.app.prediction.AppTargetEvent;
26 import android.app.prediction.AppTargetId;
27 import android.content.Context;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.server.people.data.DataManager;
31 
32 import java.util.List;
33 import java.util.concurrent.ExecutorService;
34 import java.util.concurrent.Executors;
35 import java.util.function.Consumer;
36 
37 /**
38  * Predictor that predicts the {@link AppTarget} the user is most likely to open.
39  */
40 public class AppTargetPredictor {
41 
42     private static final String UI_SURFACE_SHARE = "share";
43 
44     /** Creates a {@link AppTargetPredictor} instance based on the prediction context. */
create(@onNull AppPredictionContext predictionContext, @NonNull Consumer<List<AppTarget>> updatePredictionsMethod, @NonNull DataManager dataManager, @UserIdInt int callingUserId, Context context)45     public static AppTargetPredictor create(@NonNull AppPredictionContext predictionContext,
46             @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
47             @NonNull DataManager dataManager, @UserIdInt int callingUserId, Context context) {
48         if (UI_SURFACE_SHARE.equals(predictionContext.getUiSurface())) {
49             return new ShareTargetPredictor(predictionContext, updatePredictionsMethod, dataManager,
50                     callingUserId, context);
51         }
52         return new AppTargetPredictor(
53                 predictionContext, updatePredictionsMethod, dataManager, callingUserId);
54     }
55 
56     private final AppPredictionContext mPredictionContext;
57     private final Consumer<List<AppTarget>> mUpdatePredictionsMethod;
58     private final DataManager mDataManager;
59     final int mCallingUserId;
60     private final ExecutorService mCallbackExecutor;
61 
AppTargetPredictor(@onNull AppPredictionContext predictionContext, @NonNull Consumer<List<AppTarget>> updatePredictionsMethod, @NonNull DataManager dataManager, @UserIdInt int callingUserId)62     AppTargetPredictor(@NonNull AppPredictionContext predictionContext,
63             @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
64             @NonNull DataManager dataManager, @UserIdInt int callingUserId) {
65         mPredictionContext = predictionContext;
66         mUpdatePredictionsMethod = updatePredictionsMethod;
67         mDataManager = dataManager;
68         mCallingUserId = callingUserId;
69         mCallbackExecutor = Executors.newSingleThreadExecutor();
70     }
71 
72     /**
73      * Called by the client app to indicate a target launch.
74      */
75     @MainThread
onAppTargetEvent(AppTargetEvent event)76     public void onAppTargetEvent(AppTargetEvent event) {
77         mCallbackExecutor.execute(() -> reportAppTargetEvent(event));
78     }
79 
80     /**
81      * Called by the client app to indicate a particular location has been shown to the user.
82      */
83     @MainThread
onLaunchLocationShown(String launchLocation, List<AppTargetId> targetIds)84     public void onLaunchLocationShown(String launchLocation, List<AppTargetId> targetIds) {
85     }
86 
87     /**
88      * Called by the client app to request sorting of the provided targets based on the prediction
89      * ranking.
90      */
91     @MainThread
onSortAppTargets(List<AppTarget> targets, Consumer<List<AppTarget>> callback)92     public void onSortAppTargets(List<AppTarget> targets, Consumer<List<AppTarget>> callback) {
93         mCallbackExecutor.execute(() -> sortTargets(targets, callback));
94     }
95 
96     /**
97      * Called by the client app to request target predictions.
98      */
99     @MainThread
onRequestPredictionUpdate()100     public void onRequestPredictionUpdate() {
101         mCallbackExecutor.execute(this::predictTargets);
102     }
103 
104     @VisibleForTesting
getUpdatePredictionsMethod()105     public Consumer<List<AppTarget>> getUpdatePredictionsMethod() {
106         return mUpdatePredictionsMethod;
107     }
108 
109     /** To be overridden by the subclass to report app target event. */
110     @WorkerThread
reportAppTargetEvent(AppTargetEvent event)111     void reportAppTargetEvent(AppTargetEvent event) {
112     }
113 
114     /** To be overridden by the subclass to predict the targets. */
115     @WorkerThread
predictTargets()116     void predictTargets() {
117     }
118 
119     /**
120      * To be overridden by the subclass to sort the provided targets based on the prediction
121      * ranking.
122      */
123     @WorkerThread
sortTargets(List<AppTarget> targets, Consumer<List<AppTarget>> callback)124     void sortTargets(List<AppTarget> targets, Consumer<List<AppTarget>> callback) {
125         callback.accept(targets);
126     }
127 
128     /** To be overridden by the subclass to recycle resources. */
129     @WorkerThread
destroy()130     void destroy() {
131     }
132 
getPredictionContext()133     AppPredictionContext getPredictionContext() {
134         return mPredictionContext;
135     }
136 
getDataManager()137     DataManager getDataManager() {
138         return mDataManager;
139     }
140 
updatePredictions(List<AppTarget> targets)141     void updatePredictions(List<AppTarget> targets) {
142         mUpdatePredictionsMethod.accept(targets);
143     }
144 }
145