1 /* 2 * Copyright (C) 2020 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 package com.android.launcher3.model; 17 18 import static com.android.launcher3.EncryptionType.ENCRYPTED; 19 import static com.android.launcher3.LauncherPrefs.nonRestorableItem; 20 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; 21 import static com.android.launcher3.icons.cache.CacheLookupFlag.DEFAULT_LOOKUP_FLAG; 22 import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER; 23 24 import android.app.prediction.AppTarget; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.pm.LauncherActivityInfo; 28 import android.content.pm.LauncherApps; 29 import android.content.pm.ShortcutInfo; 30 import android.os.UserHandle; 31 32 import androidx.annotation.NonNull; 33 34 import com.android.launcher3.ConstantItem; 35 import com.android.launcher3.LauncherModel.ModelUpdateTask; 36 import com.android.launcher3.LauncherPrefs; 37 import com.android.launcher3.icons.IconCache; 38 import com.android.launcher3.model.BgDataModel.FixedContainerItems; 39 import com.android.launcher3.model.QuickstepModelDelegate.PredictorState; 40 import com.android.launcher3.model.data.AppInfo; 41 import com.android.launcher3.model.data.ItemInfo; 42 import com.android.launcher3.model.data.WorkspaceItemInfo; 43 44 import java.util.ArrayList; 45 import java.util.List; 46 import java.util.Set; 47 import java.util.stream.Collectors; 48 49 /** 50 * Task to update model as a result of predicted apps update 51 */ 52 public class PredictionUpdateTask implements ModelUpdateTask { 53 54 public static final ConstantItem<Boolean> LAST_PREDICTION_ENABLED = 55 nonRestorableItem("last_prediction_enabled_state", true, ENCRYPTED); 56 57 private final List<AppTarget> mTargets; 58 private final PredictorState mPredictorState; 59 PredictionUpdateTask(PredictorState predictorState, List<AppTarget> targets)60 PredictionUpdateTask(PredictorState predictorState, List<AppTarget> targets) { 61 mPredictorState = predictorState; 62 mTargets = targets; 63 } 64 65 @Override execute(@onNull ModelTaskController taskController, @NonNull BgDataModel dataModel, @NonNull AllAppsList apps)66 public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel, 67 @NonNull AllAppsList apps) { 68 IconCache iconCache = taskController.getIconCache(); 69 Context context = taskController.getContext(); 70 71 // TODO: remove this 72 LauncherPrefs.get(context).put(LAST_PREDICTION_ENABLED, !mTargets.isEmpty()); 73 74 Set<UserHandle> usersForChangedShortcuts = 75 dataModel.extraItems.get(mPredictorState.containerId).items.stream() 76 .filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT) 77 .map(info -> info.user) 78 .collect(Collectors.toSet()); 79 80 List<ItemInfo> items = new ArrayList<>(mTargets.size()); 81 for (AppTarget target : mTargets) { 82 WorkspaceItemInfo itemInfo; 83 ShortcutInfo si = target.getShortcutInfo(); 84 if (si != null) { 85 usersForChangedShortcuts.add(si.getUserHandle()); 86 itemInfo = new WorkspaceItemInfo(si, context); 87 iconCache.getShortcutIcon(itemInfo, si); 88 } else { 89 String className = target.getClassName(); 90 if (COMPONENT_CLASS_MARKER.equals(className)) { 91 // TODO: Implement this 92 continue; 93 } 94 ComponentName cn = new ComponentName(target.getPackageName(), className); 95 UserHandle user = target.getUser(); 96 itemInfo = apps.data.stream() 97 .filter(info -> user.equals(info.user) && cn.equals(info.componentName)) 98 .map(ai -> { 99 iconCache.getTitleAndIcon(ai, mPredictorState.lookupFlag); 100 return ai.makeWorkspaceItem(context); 101 }) 102 .findAny() 103 .orElseGet(() -> { 104 LauncherActivityInfo lai = context.getSystemService(LauncherApps.class) 105 .resolveActivity(AppInfo.makeLaunchIntent(cn), user); 106 if (lai == null) { 107 return null; 108 } 109 AppInfo ai = new AppInfo(context, lai, user); 110 iconCache.getTitleAndIcon(ai, lai, DEFAULT_LOOKUP_FLAG); 111 return ai.makeWorkspaceItem(context); 112 }); 113 114 if (itemInfo == null) { 115 continue; 116 } 117 } 118 119 itemInfo.container = mPredictorState.containerId; 120 items.add(itemInfo); 121 } 122 123 FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId, items); 124 dataModel.extraItems.put(fci.containerId, fci); 125 taskController.bindExtraContainerItems(fci); 126 usersForChangedShortcuts.forEach(u -> dataModel.updateShortcutPinnedState(context, u)); 127 128 // Save to disk 129 mPredictorState.storage.write(context, fci.items); 130 } 131 } 132