• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.model;
17 
18 import android.app.PendingIntent;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.PackageInstaller.SessionInfo;
22 import android.util.Log;
23 
24 import com.android.launcher3.FolderInfo;
25 import com.android.launcher3.ItemInfo;
26 import com.android.launcher3.LauncherAppWidgetInfo;
27 import com.android.launcher3.LauncherSettings;
28 import com.android.launcher3.util.MultiHashMap;
29 
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 
37 /**
38  * Helper class to send broadcasts to package installers that have:
39  * - Items on the first screen
40  * - Items with an active install session
41  *
42  * The packages are broken down by: folder items, workspace items, hotseat items, and widgets.
43  *
44  * Package installers only receive data for items that they are installing.
45  */
46 public class FirstScreenBroadcast {
47 
48     private static final String TAG = "FirstScreenBroadcast";
49     private static final boolean DEBUG = false;
50 
51     private static final String ACTION_FIRST_SCREEN_ACTIVE_INSTALLS
52             = "com.android.launcher3.action.FIRST_SCREEN_ACTIVE_INSTALLS";
53 
54     private static final String FOLDER_ITEM_EXTRA = "folderItem";
55     private static final String WORKSPACE_ITEM_EXTRA = "workspaceItem";
56     private static final String HOTSEAT_ITEM_EXTRA = "hotseatItem";
57     private static final String WIDGET_ITEM_EXTRA = "widgetItem";
58 
59     private static final String VERIFICATION_TOKEN_EXTRA = "verificationToken";
60 
61     private final MultiHashMap<String, String> mPackagesForInstaller;
62 
FirstScreenBroadcast(HashMap<String, SessionInfo> sessionInfoForPackage)63     public FirstScreenBroadcast(HashMap<String, SessionInfo> sessionInfoForPackage) {
64         mPackagesForInstaller = getPackagesForInstaller(sessionInfoForPackage);
65     }
66 
67     /**
68      * @return Map where the key is the package name of the installer, and the value is a list
69      *         of packages with active sessions for that installer.
70      */
getPackagesForInstaller( HashMap<String, SessionInfo> sessionInfoForPackage)71     private MultiHashMap<String, String> getPackagesForInstaller(
72             HashMap<String, SessionInfo> sessionInfoForPackage) {
73         MultiHashMap<String, String> packagesForInstaller = new MultiHashMap<>();
74         for (Map.Entry<String, SessionInfo> entry : sessionInfoForPackage.entrySet()) {
75             packagesForInstaller.addToList(entry.getValue().getInstallerPackageName(),
76                     entry.getKey());
77         }
78         return packagesForInstaller;
79     }
80 
81     /**
82      * Sends a broadcast to all package installers that have items with active sessions on the users
83      * first screen.
84      */
sendBroadcasts(Context context, List<ItemInfo> firstScreenItems)85     public void sendBroadcasts(Context context, List<ItemInfo> firstScreenItems) {
86         for (Map.Entry<String, ArrayList<String>> entry : mPackagesForInstaller.entrySet()) {
87             sendBroadcastToInstaller(context, entry.getKey(), entry.getValue(), firstScreenItems);
88         }
89     }
90 
91     /**
92      * @param installerPackageName Package name of the package installer.
93      * @param packages List of packages with active sessions for this package installer.
94      * @param firstScreenItems List of items on the first screen.
95      */
sendBroadcastToInstaller(Context context, String installerPackageName, List<String> packages, List<ItemInfo> firstScreenItems)96     private void sendBroadcastToInstaller(Context context, String installerPackageName,
97             List<String> packages, List<ItemInfo> firstScreenItems) {
98         Set<String> folderItems = new HashSet<>();
99         Set<String> workspaceItems = new HashSet<>();
100         Set<String> hotseatItems = new HashSet<>();
101         Set<String> widgetItems = new HashSet<>();
102 
103         for (ItemInfo info : firstScreenItems) {
104             if (info instanceof FolderInfo) {
105                 FolderInfo folderInfo = (FolderInfo) info;
106                 String folderItemInfoPackage;
107                 for (ItemInfo folderItemInfo : folderInfo.contents) {
108                     folderItemInfoPackage = getPackageName(folderItemInfo);
109                     if (folderItemInfoPackage != null
110                             && packages.contains(folderItemInfoPackage)) {
111                         folderItems.add(folderItemInfoPackage);
112                     }
113                 }
114             }
115 
116             String packageName = getPackageName(info);
117             if (packageName == null || !packages.contains(packageName)) {
118                 continue;
119             }
120             if (info instanceof LauncherAppWidgetInfo) {
121                 widgetItems.add(packageName);
122             } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
123                 hotseatItems.add(packageName);
124             } else if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
125                 workspaceItems.add(packageName);
126             }
127         }
128 
129         if (DEBUG) {
130             printList(installerPackageName, "Folder item", folderItems);
131             printList(installerPackageName, "Workspace item", workspaceItems);
132             printList(installerPackageName, "Hotseat item", hotseatItems);
133             printList(installerPackageName, "Widget item", widgetItems);
134         }
135 
136         context.sendBroadcast(new Intent(ACTION_FIRST_SCREEN_ACTIVE_INSTALLS)
137                 .setPackage(installerPackageName)
138                 .putStringArrayListExtra(FOLDER_ITEM_EXTRA, new ArrayList<>(folderItems))
139                 .putStringArrayListExtra(WORKSPACE_ITEM_EXTRA, new ArrayList<>(workspaceItems))
140                 .putStringArrayListExtra(HOTSEAT_ITEM_EXTRA, new ArrayList<>(hotseatItems))
141                 .putStringArrayListExtra(WIDGET_ITEM_EXTRA, new ArrayList<>(widgetItems))
142                 .putExtra(VERIFICATION_TOKEN_EXTRA, PendingIntent.getActivity(context, 0,
143                         new Intent(), PendingIntent.FLAG_ONE_SHOT)));
144     }
145 
getPackageName(ItemInfo info)146     private static String getPackageName(ItemInfo info) {
147         String packageName = null;
148         if (info instanceof LauncherAppWidgetInfo) {
149             LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
150             if (widgetInfo.providerName != null) {
151                 packageName = widgetInfo.providerName.getPackageName();
152             }
153         } else if (info.getTargetComponent() != null){
154             packageName = info.getTargetComponent().getPackageName();
155         }
156         return packageName;
157     }
158 
printList(String packageInstaller, String label, Set<String> packages)159     private static void printList(String packageInstaller, String label, Set<String> packages) {
160         for (String pkg : packages) {
161             Log.d(TAG, packageInstaller + ":" + label + ":" + pkg);
162         }
163     }
164 }
165