1 /*
<lambda>null2  * Copyright (C) 2024 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.launcher3.model
18 
19 import com.android.launcher3.LauncherAppState
20 import com.android.launcher3.LauncherModel
21 import com.android.launcher3.LauncherModel.CallbackTask
22 import com.android.launcher3.celllayout.CellPosMapper
23 import com.android.launcher3.model.BgDataModel.FixedContainerItems
24 import com.android.launcher3.model.data.ItemInfo
25 import com.android.launcher3.model.data.WorkspaceItemInfo
26 import com.android.launcher3.util.PackageUserKey
27 import java.util.Objects
28 import java.util.concurrent.Executor
29 import java.util.function.Predicate
30 
31 /** Class with utility methods and properties for running a LauncherModel Task */
32 class ModelTaskController(
33     val app: LauncherAppState,
34     val dataModel: BgDataModel,
35     val allAppsList: AllAppsList,
36     private val model: LauncherModel,
37     private val uiExecutor: Executor
38 ) {
39 
40     /** Schedules a {@param task} to be executed on the current callbacks. */
41     fun scheduleCallbackTask(task: CallbackTask) {
42         for (cb in model.callbacks) {
43             uiExecutor.execute { task.execute(cb) }
44         }
45     }
46 
47     /**
48      * Updates from model task, do not deal with icon position in hotseat. Also no need to verify
49      * changes as the ModelTasks always push the changes to callbacks
50      */
51     fun getModelWriter() = model.getWriter(false /* verifyChanges */, CellPosMapper.DEFAULT, null)
52 
53     fun bindUpdatedWorkspaceItems(allUpdates: List<WorkspaceItemInfo>) {
54         // Bind workspace items
55         val workspaceUpdates =
56             allUpdates.stream().filter { info -> info.id != ItemInfo.NO_ID }.toList()
57         if (workspaceUpdates.isNotEmpty()) {
58             scheduleCallbackTask { it.bindWorkspaceItemsChanged(workspaceUpdates) }
59         }
60 
61         // Bind extra items if any
62         allUpdates
63             .stream()
64             .mapToInt { info: WorkspaceItemInfo -> info.container }
65             .distinct()
66             .mapToObj { dataModel.extraItems.get(it) }
67             .filter { Objects.nonNull(it) }
68             .forEach { bindExtraContainerItems(it) }
69     }
70 
71     fun bindExtraContainerItems(item: FixedContainerItems) {
72         scheduleCallbackTask { it.bindExtraContainerItems(item) }
73     }
74 
75     fun bindDeepShortcuts(dataModel: BgDataModel) {
76         val shortcutMapCopy = HashMap(dataModel.deepShortcutMap)
77         scheduleCallbackTask { it.bindDeepShortcutMap(shortcutMapCopy) }
78     }
79 
80     fun bindUpdatedWidgets(dataModel: BgDataModel) {
81         val widgets = dataModel.widgetsModel.getWidgetsListForPicker(app.context)
82         scheduleCallbackTask { it.bindAllWidgets(widgets) }
83     }
84 
85     fun deleteAndBindComponentsRemoved(matcher: Predicate<ItemInfo?>, reason: String?) {
86         getModelWriter().deleteItemsFromDatabase(matcher, reason)
87 
88         // Call the components-removed callback
89         scheduleCallbackTask { it.bindWorkspaceComponentsRemoved(matcher) }
90     }
91 
92     fun bindApplicationsIfNeeded() {
93         if (allAppsList.getAndResetChangeFlag()) {
94             val apps = allAppsList.copyData()
95             val flags = allAppsList.flags
96             val packageUserKeyToUidMap =
97                 apps.associateBy(
98                     keySelector = { PackageUserKey(it.componentName!!.packageName, it.user) },
99                     valueTransform = { it.uid }
100                 )
101             scheduleCallbackTask { it.bindAllApplications(apps, flags, packageUserKeyToUidMap) }
102         }
103     }
104 }
105