• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Build;
27 import android.os.Process;
28 import android.os.UserHandle;
29 import android.os.UserManager;
30 
31 import androidx.annotation.NonNull;
32 import androidx.annotation.Nullable;
33 import androidx.annotation.VisibleForTesting;
34 
35 import com.android.launcher3.LauncherSettings;
36 import com.android.launcher3.Utilities;
37 import com.android.launcher3.pm.PackageInstallInfo;
38 import com.android.launcher3.util.PackageManagerHelper;
39 
40 import java.util.Comparator;
41 
42 /**
43  * Represents an app in AllAppsView.
44  */
45 public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
46 
47     public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0];
48     public static final Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> {
49         int uc = a.user.hashCode() - b.user.hashCode();
50         return uc != 0 ? uc : a.componentName.compareTo(b.componentName);
51     };
52 
53     /**
54      * The intent used to start the application.
55      */
56     public Intent intent;
57 
58     @NonNull
59     public ComponentName componentName;
60 
61     // Section name used for indexing.
62     public String sectionName = "";
63 
64     /**
65      * The uid of the application.
66      * The kernel user-ID that has been assigned to this application. Currently this is not a unique
67      * ID (multiple applications can have the same uid).
68      */
69     public int uid = -1;
70 
AppInfo()71     public AppInfo() {
72         itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
73     }
74 
75     @Override
76     @Nullable
getIntent()77     public Intent getIntent() {
78         return intent;
79     }
80 
81     /**
82      * Must not hold the Context.
83      */
AppInfo(Context context, LauncherActivityInfo info, UserHandle user)84     public AppInfo(Context context, LauncherActivityInfo info, UserHandle user) {
85         this(info, user, context.getSystemService(UserManager.class).isQuietModeEnabled(user));
86     }
87 
AppInfo(LauncherActivityInfo info, UserHandle user, boolean quietModeEnabled)88     public AppInfo(LauncherActivityInfo info, UserHandle user, boolean quietModeEnabled) {
89         this.componentName = info.getComponentName();
90         this.container = CONTAINER_ALL_APPS;
91         this.user = user;
92         intent = makeLaunchIntent(info);
93 
94         if (quietModeEnabled) {
95             runtimeStatusFlags |= FLAG_DISABLED_QUIET_USER;
96         }
97         uid = info.getApplicationInfo().uid;
98         updateRuntimeFlagsForActivityTarget(this, info);
99     }
100 
AppInfo(AppInfo info)101     public AppInfo(AppInfo info) {
102         super(info);
103         componentName = info.componentName;
104         title = Utilities.trim(info.title);
105         intent = new Intent(info.intent);
106         uid = info.uid;
107     }
108 
109     @VisibleForTesting
AppInfo(ComponentName componentName, CharSequence title, UserHandle user, Intent intent)110     public AppInfo(ComponentName componentName, CharSequence title,
111             UserHandle user, Intent intent) {
112         this.componentName = componentName;
113         this.title = title;
114         this.user = user;
115         this.intent = intent;
116     }
117 
AppInfo(@onNull PackageInstallInfo installInfo)118     public AppInfo(@NonNull PackageInstallInfo installInfo) {
119         componentName = installInfo.componentName;
120         intent = new Intent(Intent.ACTION_MAIN)
121             .addCategory(Intent.CATEGORY_LAUNCHER)
122             .setComponent(componentName)
123             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
124                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
125         setProgressLevel(installInfo);
126         user = installInfo.user;
127     }
128 
129     @Override
dumpProperties()130     protected String dumpProperties() {
131         return super.dumpProperties() + " componentName=" + componentName;
132     }
133 
134     @Override
makeWorkspaceItem(Context context)135     public WorkspaceItemInfo makeWorkspaceItem(Context context) {
136         WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(this);
137 
138         if ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
139             // We need to update the component name when the apk is installed
140             workspaceItemInfo.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
141             // Since the user is manually placing it on homescreen, it should not be auto-removed
142             // later
143             workspaceItemInfo.status |= WorkspaceItemInfo.FLAG_RESTORE_STARTED;
144             workspaceItemInfo.status |= FLAG_INSTALL_SESSION_ACTIVE;
145         }
146         if ((runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) {
147             workspaceItemInfo.runtimeStatusFlags |= FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
148         }
149 
150         return workspaceItemInfo;
151     }
152 
makeLaunchIntent(LauncherActivityInfo info)153     public static Intent makeLaunchIntent(LauncherActivityInfo info) {
154         return makeLaunchIntent(info.getComponentName());
155     }
156 
makeLaunchIntent(ComponentName cn)157     public static Intent makeLaunchIntent(ComponentName cn) {
158         return new Intent(Intent.ACTION_MAIN)
159                 .addCategory(Intent.CATEGORY_LAUNCHER)
160                 .setComponent(cn)
161                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
162                         | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
163     }
164 
165     @NonNull
166     @Override
getTargetComponent()167     public ComponentName getTargetComponent() {
168         return componentName;
169     }
170 
updateRuntimeFlagsForActivityTarget( ItemInfoWithIcon info, LauncherActivityInfo lai)171     public static void updateRuntimeFlagsForActivityTarget(
172             ItemInfoWithIcon info, LauncherActivityInfo lai) {
173         ApplicationInfo appInfo = lai.getApplicationInfo();
174         if (PackageManagerHelper.isAppSuspended(appInfo)) {
175             info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
176         }
177         info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
178                 ? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
179 
180         if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O
181                 && Process.myUserHandle().equals(lai.getUser())) {
182             // The icon for a non-primary user is badged, hence it's not exactly an adaptive icon.
183             info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
184         }
185 
186         // Sets the progress level, installation and incremental download flags.
187         info.setProgressLevel(
188                 PackageManagerHelper.getLoadingProgress(lai),
189                 PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
190     }
191 
192     @Override
clone()193     public AppInfo clone() {
194         return new AppInfo(this);
195     }
196 }
197