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