1 /* 2 * Copyright (C) 2008 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 static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; 20 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.LauncherActivityInfo; 26 import android.os.UserHandle; 27 import android.os.UserManager; 28 29 import androidx.annotation.NonNull; 30 import androidx.annotation.Nullable; 31 import androidx.annotation.VisibleForTesting; 32 33 import com.android.launcher3.Flags; 34 import com.android.launcher3.LauncherSettings; 35 import com.android.launcher3.Utilities; 36 import com.android.launcher3.pm.PackageInstallInfo; 37 import com.android.launcher3.pm.UserCache; 38 import com.android.launcher3.util.ApiWrapper; 39 import com.android.launcher3.util.PackageManagerHelper; 40 import com.android.launcher3.util.UserIconInfo; 41 42 import java.util.Comparator; 43 44 /** 45 * Represents an app in AllAppsView. 46 */ 47 @SuppressWarnings("NewApi") 48 public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory { 49 50 public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0]; 51 public static final Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> { 52 int uc = a.user.hashCode() - b.user.hashCode(); 53 return uc != 0 ? uc : a.componentName.compareTo(b.componentName); 54 }; 55 56 public static final Comparator<AppInfo> PACKAGE_KEY_COMPARATOR = Comparator.comparingInt( 57 (AppInfo a) -> a.user.hashCode()).thenComparing(ItemInfo::getTargetPackage); 58 59 /** 60 * The intent used to start the application. 61 */ 62 public Intent intent; 63 64 // componentName for the Private Space Install App button can be null 65 @Nullable 66 public ComponentName componentName; 67 68 // Section name used for indexing. 69 public String sectionName = ""; 70 71 /** 72 * The uid of the application. 73 * The kernel user-ID that has been assigned to this application. Currently this is not a unique 74 * ID (multiple applications can have the same uid). 75 */ 76 public int uid = -1; 77 AppInfo()78 public AppInfo() { 79 itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; 80 } 81 82 @Override 83 @Nullable getIntent()84 public Intent getIntent() { 85 return intent; 86 } 87 88 /** 89 * Must not hold the Context. 90 */ AppInfo(Context context, LauncherActivityInfo info, UserHandle user)91 public AppInfo(Context context, LauncherActivityInfo info, UserHandle user) { 92 this(info, UserCache.INSTANCE.get(context).getUserInfo(user), 93 ApiWrapper.INSTANCE.get(context), PackageManagerHelper.INSTANCE.get(context), 94 context.getSystemService(UserManager.class).isQuietModeEnabled(user)); 95 } 96 AppInfo(LauncherActivityInfo info, UserIconInfo userIconInfo, ApiWrapper apiWrapper, PackageManagerHelper pmHelper, boolean quietModeEnabled)97 public AppInfo(LauncherActivityInfo info, UserIconInfo userIconInfo, 98 ApiWrapper apiWrapper, PackageManagerHelper pmHelper, boolean quietModeEnabled) { 99 this.componentName = info.getComponentName(); 100 this.container = CONTAINER_ALL_APPS; 101 this.user = userIconInfo.user; 102 intent = makeLaunchIntent(info); 103 104 if (quietModeEnabled) { 105 runtimeStatusFlags |= FLAG_DISABLED_QUIET_USER; 106 } 107 uid = info.getApplicationInfo().uid; 108 updateRuntimeFlagsForActivityTarget(this, info, userIconInfo, apiWrapper, pmHelper); 109 } 110 AppInfo(AppInfo info)111 public AppInfo(AppInfo info) { 112 super(info); 113 componentName = info.componentName; 114 title = Utilities.trim(info.title); 115 intent = new Intent(info.intent); 116 uid = info.uid; 117 } 118 119 @VisibleForTesting AppInfo(ComponentName componentName, CharSequence title, UserHandle user, Intent intent)120 public AppInfo(ComponentName componentName, CharSequence title, 121 UserHandle user, Intent intent) { 122 this.componentName = componentName; 123 this.title = title; 124 this.user = user; 125 this.intent = intent; 126 } 127 AppInfo(@onNull PackageInstallInfo installInfo)128 public AppInfo(@NonNull PackageInstallInfo installInfo) { 129 componentName = installInfo.componentName; 130 intent = new Intent(Intent.ACTION_MAIN) 131 .addCategory(Intent.CATEGORY_LAUNCHER) 132 .setComponent(componentName) 133 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 134 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 135 setProgressLevel(installInfo); 136 user = installInfo.user; 137 } 138 139 @Override dumpProperties()140 protected String dumpProperties() { 141 return super.dumpProperties() + " componentName=" + componentName; 142 } 143 144 @Override makeWorkspaceItem(Context context)145 public WorkspaceItemInfo makeWorkspaceItem(Context context) { 146 WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(this); 147 148 if ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) { 149 // We need to update the component name when the apk is installed 150 workspaceItemInfo.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON; 151 // Since the user is manually placing it on homescreen, it should not be auto-removed 152 // later 153 workspaceItemInfo.status |= WorkspaceItemInfo.FLAG_RESTORE_STARTED; 154 workspaceItemInfo.status |= FLAG_INSTALL_SESSION_ACTIVE; 155 } 156 if ((runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) { 157 workspaceItemInfo.runtimeStatusFlags |= FLAG_INCREMENTAL_DOWNLOAD_ACTIVE; 158 } 159 160 return workspaceItemInfo; 161 } 162 makeLaunchIntent(LauncherActivityInfo info)163 public static Intent makeLaunchIntent(LauncherActivityInfo info) { 164 return makeLaunchIntent(info.getComponentName()); 165 } 166 makeLaunchIntent(ComponentName cn)167 public static Intent makeLaunchIntent(ComponentName cn) { 168 return new Intent(Intent.ACTION_MAIN) 169 .addCategory(Intent.CATEGORY_LAUNCHER) 170 .setComponent(cn) 171 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 172 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 173 } 174 175 @NonNull 176 @Override getTargetComponent()177 public ComponentName getTargetComponent() { 178 return componentName; 179 } 180 181 /** 182 * Updates the runtime status flags for the given info based on the state of the specified 183 * activity. 184 */ updateRuntimeFlagsForActivityTarget( ItemInfoWithIcon info, LauncherActivityInfo lai, UserIconInfo userIconInfo, ApiWrapper apiWrapper, PackageManagerHelper pmHelper)185 public static boolean updateRuntimeFlagsForActivityTarget( 186 ItemInfoWithIcon info, LauncherActivityInfo lai, UserIconInfo userIconInfo, 187 ApiWrapper apiWrapper, PackageManagerHelper pmHelper) { 188 final int oldProgressLevel = info.getProgressLevel(); 189 final int oldRuntimeStatusFlags = info.runtimeStatusFlags; 190 ApplicationInfo appInfo = lai.getApplicationInfo(); 191 if (PackageManagerHelper.isAppSuspended(appInfo)) { 192 info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED; 193 } else { 194 info.runtimeStatusFlags &= ~FLAG_DISABLED_SUSPENDED; 195 } 196 if (Flags.enableSupportForArchiving()) { 197 if (lai.getActivityInfo().isArchived) { 198 info.runtimeStatusFlags |= FLAG_ARCHIVED; 199 } else { 200 info.runtimeStatusFlags &= ~FLAG_ARCHIVED; 201 } 202 } 203 info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 204 ? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES; 205 206 if (Flags.privateSpaceRestrictAccessibilityDrag()) { 207 if (userIconInfo.isPrivate()) { 208 info.runtimeStatusFlags |= FLAG_NOT_PINNABLE; 209 } else { 210 info.runtimeStatusFlags &= ~FLAG_NOT_PINNABLE; 211 } 212 } 213 214 // Sets the progress level, installation and incremental download flags. 215 info.setProgressLevel( 216 PackageManagerHelper.getLoadingProgress(lai), 217 PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING); 218 info.setNonResizeable(apiWrapper.isNonResizeableActivity(lai)); 219 info.setSupportsMultiInstance( 220 pmHelper.supportsMultiInstance(lai.getComponentName())); 221 return (oldProgressLevel != info.getProgressLevel()) 222 || (oldRuntimeStatusFlags != info.runtimeStatusFlags); 223 } 224 225 @Override clone()226 public AppInfo clone() { 227 return new AppInfo(this); 228 } 229 } 230