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.VisibleForTesting;
32 
33 import com.android.launcher3.LauncherSettings;
34 import com.android.launcher3.Utilities;
35 import com.android.launcher3.util.ComponentKey;
36 import com.android.launcher3.util.PackageManagerHelper;
37 
38 import java.util.Comparator;
39 
40 /**
41  * Represents an app in AllAppsView.
42  */
43 public class AppInfo extends ItemInfoWithIcon {
44 
45     public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0];
46     public static final Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> {
47         int uc = a.user.hashCode() - b.user.hashCode();
48         return uc != 0 ? uc : a.componentName.compareTo(b.componentName);
49     };
50 
51     /**
52      * The intent used to start the application.
53      */
54     public Intent intent;
55 
56     public ComponentName componentName;
57 
58     // Section name used for indexing.
59     public String sectionName = "";
60 
AppInfo()61     public AppInfo() {
62         itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
63     }
64 
65     @Override
getIntent()66     public Intent getIntent() {
67         return intent;
68     }
69 
70     /**
71      * Must not hold the Context.
72      */
AppInfo(Context context, LauncherActivityInfo info, UserHandle user)73     public AppInfo(Context context, LauncherActivityInfo info, UserHandle user) {
74         this(info, user, context.getSystemService(UserManager.class).isQuietModeEnabled(user));
75     }
76 
AppInfo(LauncherActivityInfo info, UserHandle user, boolean quietModeEnabled)77     public AppInfo(LauncherActivityInfo info, UserHandle user, boolean quietModeEnabled) {
78         this.componentName = info.getComponentName();
79         this.container = CONTAINER_ALL_APPS;
80         this.user = user;
81         intent = makeLaunchIntent(info);
82 
83         if (quietModeEnabled) {
84             runtimeStatusFlags |= FLAG_DISABLED_QUIET_USER;
85         }
86         updateRuntimeFlagsForActivityTarget(this, info);
87     }
88 
AppInfo(AppInfo info)89     public AppInfo(AppInfo info) {
90         super(info);
91         componentName = info.componentName;
92         title = Utilities.trim(info.title);
93         intent = new Intent(info.intent);
94         user = info.user;
95         runtimeStatusFlags = info.runtimeStatusFlags;
96     }
97 
98     @VisibleForTesting
AppInfo(ComponentName componentName, CharSequence title, UserHandle user, Intent intent)99     public AppInfo(ComponentName componentName, CharSequence title,
100             UserHandle user, Intent intent) {
101         this.componentName = componentName;
102         this.title = title;
103         this.user = user;
104         this.intent = intent;
105     }
106 
107     @Override
dumpProperties()108     protected String dumpProperties() {
109         return super.dumpProperties() + " componentName=" + componentName;
110     }
111 
makeWorkspaceItem()112     public WorkspaceItemInfo makeWorkspaceItem() {
113         return new WorkspaceItemInfo(this);
114     }
115 
toComponentKey()116     public ComponentKey toComponentKey() {
117         return new ComponentKey(componentName, user);
118     }
119 
makeLaunchIntent(LauncherActivityInfo info)120     public static Intent makeLaunchIntent(LauncherActivityInfo info) {
121         return makeLaunchIntent(info.getComponentName());
122     }
123 
makeLaunchIntent(ComponentName cn)124     public static Intent makeLaunchIntent(ComponentName cn) {
125         return new Intent(Intent.ACTION_MAIN)
126                 .addCategory(Intent.CATEGORY_LAUNCHER)
127                 .setComponent(cn)
128                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
129                         | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
130     }
131 
updateRuntimeFlagsForActivityTarget( ItemInfoWithIcon info, LauncherActivityInfo lai)132     public static void updateRuntimeFlagsForActivityTarget(
133             ItemInfoWithIcon info, LauncherActivityInfo lai) {
134         ApplicationInfo appInfo = lai.getApplicationInfo();
135         if (PackageManagerHelper.isAppSuspended(appInfo)) {
136             info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
137         }
138         info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
139                 ? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
140 
141         if (Utilities.ATLEAST_OREO
142                 && appInfo.targetSdkVersion >= Build.VERSION_CODES.O
143                 && Process.myUserHandle().equals(lai.getUser())) {
144             // The icon for a non-primary user is badged, hence it's not exactly an adaptive icon.
145             info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
146         }
147     }
148 
149     @Override
clone()150     public AppInfo clone() {
151         return new AppInfo(this);
152     }
153 }
154