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.data
18 
19 import android.content.Context
20 import com.android.launcher3.LauncherSettings
21 import com.android.launcher3.R
22 import com.android.launcher3.icons.IconCache
23 import com.android.launcher3.logger.LauncherAtom
24 import com.android.launcher3.views.ActivityContext
25 
26 /** A type of app collection that launches multiple apps into split screen. */
27 class AppPairInfo() : CollectionInfo() {
28     private var contents: ArrayList<WorkspaceItemInfo> = ArrayList()
29 
30     init {
31         itemType = LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR
32     }
33 
34     /** Convenience constructor, calls primary constructor and init block */
35     constructor(app1: WorkspaceItemInfo, app2: WorkspaceItemInfo) : this() {
36         add(app1)
37         add(app2)
38     }
39 
40     /** Creates a new AppPairInfo that is a copy of the provided one. */
41     constructor(appPairInfo: AppPairInfo) : this() {
42         contents = appPairInfo.contents.clone() as ArrayList<WorkspaceItemInfo>
43         copyFrom(appPairInfo)
44     }
45 
46     /** Adds an element to the contents ArrayList. */
47     override fun add(item: ItemInfo) {
48         if (item !is WorkspaceItemInfo) {
49             throw RuntimeException("tried to add an illegal type into an app pair")
50         }
51 
52         contents.add(item)
53     }
54 
55     /** Returns the app pair's member apps as an ArrayList of [ItemInfo]. */
56     override fun getContents(): ArrayList<ItemInfo> =
57         ArrayList(contents.stream().map { it as ItemInfo }.toList())
58 
59     /** Returns the app pair's member apps as an ArrayList of [WorkspaceItemInfo]. */
60     override fun getAppContents(): ArrayList<WorkspaceItemInfo> = contents
61 
62     /** Returns the first app in the pair. */
63     fun getFirstApp() = contents[0]
64 
65     /** Returns the second app in the pair. */
66     fun getSecondApp() = contents[1]
67 
68     /** Returns if either of the app pair members is currently disabled. */
69     override fun isDisabled() = anyMatch { it.isDisabled }
70 
71     /** Checks if member apps are launchable at the current screen size. */
72     fun isLaunchable(context: Context): Pair<Boolean, Boolean> {
73         val isTablet =
74             (ActivityContext.lookupContext(context) as ActivityContext).getDeviceProfile().isTablet
75         return Pair(
76             isTablet || !getFirstApp().isNonResizeable(),
77             isTablet || !getSecondApp().isNonResizeable()
78         )
79     }
80 
81     /** Fetches high-res icons for member apps if needed. */
82     fun fetchHiResIconsIfNeeded(iconCache: IconCache) {
83         getAppContents().stream().filter(ItemInfoWithIcon::usingLowResIcon).forEach { member ->
84             iconCache.getTitleAndIcon(member, false)
85         }
86     }
87 
88     /**
89      * App pairs will report itself as "disabled" (for accessibility) if either of the following is
90      * true:
91      * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is paused
92      *    or can't be launched for some other reason).
93      * 2) One of the member apps can't be launched due to screen size requirements.
94      */
95     fun shouldReportDisabled(context: Context): Boolean {
96         return isDisabled || !isLaunchable(context).first || !isLaunchable(context).second
97     }
98 
99     /** Generates a default title for the app pair and sets it. */
100     fun generateTitle(context: Context): CharSequence? {
101         val app1: CharSequence? = getFirstApp().title
102         val app2: CharSequence? = getSecondApp().title
103         title = context.getString(R.string.app_pair_default_title, app1, app2)
104         return title
105     }
106 
107     /** Generates an ItemInfo for logging. */
108     override fun buildProto(cInfo: CollectionInfo?): LauncherAtom.ItemInfo {
109         val appPairIcon = LauncherAtom.FolderIcon.newBuilder().setCardinality(contents.size)
110         appPairIcon.setLabelInfo(title.toString())
111         return getDefaultItemInfoBuilder()
112             .setFolderIcon(appPairIcon)
113             .setRank(rank)
114             .setContainerInfo(getContainerInfo())
115             .build()
116     }
117 }
118