• 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 package com.android.launcher3.uioverrides
17 
18 import android.app.ActivityOptions
19 import android.app.PendingIntent
20 import android.app.role.RoleManager
21 import android.content.Context
22 import android.content.IIntentReceiver
23 import android.content.IIntentSender
24 import android.content.Intent
25 import android.content.pm.ActivityInfo
26 import android.content.pm.ApplicationInfo
27 import android.content.pm.LauncherActivityInfo
28 import android.content.pm.LauncherApps
29 import android.content.pm.ShortcutInfo
30 import android.os.Bundle
31 import android.os.Flags.allowPrivateProfile
32 import android.os.IBinder
33 import android.os.UserHandle
34 import android.os.UserManager
35 import android.util.ArrayMap
36 import android.widget.Toast
37 import android.window.RemoteTransition
38 import com.android.launcher3.Flags.enablePrivateSpace
39 import com.android.launcher3.Flags.enablePrivateSpaceInstallShortcut
40 import com.android.launcher3.Flags.privateSpaceAppInstallerButton
41 import com.android.launcher3.Flags.privateSpaceSysAppsSeparation
42 import com.android.launcher3.R
43 import com.android.launcher3.Utilities
44 import com.android.launcher3.dagger.ApplicationContext
45 import com.android.launcher3.dagger.LauncherAppSingleton
46 import com.android.launcher3.proxy.ProxyActivityStarter
47 import com.android.launcher3.util.ApiWrapper
48 import com.android.launcher3.util.Executors
49 import com.android.launcher3.util.StartActivityParams
50 import com.android.launcher3.util.UserIconInfo
51 import com.android.quickstep.util.FadeOutRemoteTransition
52 import javax.inject.Inject
53 
54 /** A wrapper for the hidden API calls */
55 @LauncherAppSingleton
56 open class SystemApiWrapper @Inject constructor(@ApplicationContext context: Context?) :
57     ApiWrapper(context) {
58 
59     override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY
60 
61     override fun getActivityOverrides(): Map<String, LauncherActivityInfo> =
62         mContext.getSystemService(LauncherApps::class.java)!!.activityOverrides
63 
64     override fun createFadeOutAnimOptions(): ActivityOptions =
65         ActivityOptions.makeBasic().apply {
66             remoteTransition = RemoteTransition(FadeOutRemoteTransition(), "FadeOut")
67         }
68 
69     override fun queryAllUsers(): Map<UserHandle, UserIconInfo> {
70         if (!allowPrivateProfile() || !enablePrivateSpace()) {
71             return super.queryAllUsers()
72         }
73         val users = ArrayMap<UserHandle, UserIconInfo>()
74         mContext.getSystemService(UserManager::class.java)!!.userProfiles?.forEach { user ->
75             mContext.getSystemService(LauncherApps::class.java)!!.getLauncherUserInfo(user)?.apply {
76                 users[user] =
77                     UserIconInfo(
78                         user,
79                         when (userType) {
80                             UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK
81                             UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED
82                             UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE
83                             else -> UserIconInfo.TYPE_MAIN
84                         },
85                         userSerialNumber.toLong(),
86                     )
87             }
88         }
89         return users
90     }
91 
92     override fun getPreInstalledSystemPackages(user: UserHandle): List<String> =
93         if (allowPrivateProfile() && enablePrivateSpace() && privateSpaceSysAppsSeparation())
94             mContext
95                 .getSystemService(LauncherApps::class.java)!!
96                 .getPreInstalledSystemPackages(user)
97         else ArrayList()
98 
99     override fun getAppMarketActivityIntent(packageName: String, user: UserHandle): Intent =
100         if (
101             allowPrivateProfile() &&
102                 enablePrivateSpace() &&
103                 (privateSpaceAppInstallerButton() || enablePrivateSpaceInstallShortcut())
104         )
105             ProxyActivityStarter.getLaunchIntent(
106                 mContext,
107                 StartActivityParams(null as PendingIntent?, 0).apply {
108                     intentSender =
109                         mContext
110                             .getSystemService(LauncherApps::class.java)!!
111                             .getAppMarketActivityIntent(packageName, user)
112                     options =
113                         ActivityOptions.makeBasic()
114                             .setPendingIntentBackgroundActivityStartMode(
115                                 ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
116                             )
117                             .toBundle()
118                     requireActivityResult = false
119                 },
120             )
121         else super.getAppMarketActivityIntent(packageName, user)
122 
123     /** Returns an intent which can be used to open Private Space Settings. */
124     override fun getPrivateSpaceSettingsIntent(): Intent? =
125         if (allowPrivateProfile() && enablePrivateSpace())
126             ProxyActivityStarter.getLaunchIntent(
127                 mContext,
128                 StartActivityParams(null as PendingIntent?, 0).apply {
129                     intentSender =
130                         mContext
131                             .getSystemService(LauncherApps::class.java)
132                             ?.privateSpaceSettingsIntent ?: return null
133                     options =
134                         ActivityOptions.makeBasic()
135                             .setPendingIntentBackgroundActivityStartMode(
136                                 ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
137                             )
138                             .toBundle()
139                     requireActivityResult = false
140                 },
141             )
142         else null
143 
144     override fun isNonResizeableActivity(lai: LauncherActivityInfo) =
145         lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE
146 
147     override fun supportsMultiInstance(lai: LauncherActivityInfo): Boolean {
148         return try {
149             super.supportsMultiInstance(lai) || lai.supportsMultiInstance()
150         } catch (e: Exception) {
151             false
152         }
153     }
154 
155     /**
156      * Starts an Activity which can be used to set this Launcher as the HOME app, via a consent
157      * screen. In case the consent screen cannot be shown, or the user does not set current Launcher
158      * as HOME app, a toast asking the user to do the latter is shown.
159      */
160     override fun assignDefaultHomeRole(context: Context) {
161         val roleManager = context.getSystemService(RoleManager::class.java)
162         if (
163             (roleManager!!.isRoleAvailable(RoleManager.ROLE_HOME) &&
164                 !roleManager.isRoleHeld(RoleManager.ROLE_HOME))
165         ) {
166             val roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
167             val pendingIntent =
168                 PendingIntent(
169                     object : IIntentSender.Stub() {
170                         override fun send(
171                             code: Int,
172                             intent: Intent,
173                             resolvedType: String?,
174                             allowlistToken: IBinder?,
175                             finishedReceiver: IIntentReceiver?,
176                             requiredPermission: String?,
177                             options: Bundle?,
178                         ) {
179                             if (code != -1) {
180                                 Executors.MAIN_EXECUTOR.execute {
181                                     Toast.makeText(
182                                             context,
183                                             context.getString(
184                                                 R.string.set_default_home_app,
185                                                 context.getString(R.string.derived_app_name),
186                                             ),
187                                             Toast.LENGTH_LONG,
188                                         )
189                                         .show()
190                                 }
191                             }
192                         }
193                     }
194                 )
195             val params = StartActivityParams(pendingIntent, 0)
196             params.intent = roleRequestIntent
197             context.startActivity(ProxyActivityStarter.getLaunchIntent(context, params))
198         }
199     }
200 
201     override fun getApplicationInfoHash(appInfo: ApplicationInfo): String =
202         (appInfo.sourceDir?.hashCode() ?: 0).toString() + " " + appInfo.longVersionCode
203 
204     override fun getRoundIconRes(appInfo: ApplicationInfo) = appInfo.roundIconRes
205 
206     override fun isFileDrawable(shortcutInfo: ShortcutInfo) =
207         shortcutInfo.hasIconFile() || shortcutInfo.hasIconUri()
208 }
209