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