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