Merge "Send directed broadcast to package installers that have active sessions." into ub-launcher3-master
This commit is contained in:
committed by
Android (Google) Code Review
commit
03ebe0cd00
@@ -45,7 +45,7 @@ public abstract class PackageInstallerCompat {
|
||||
/**
|
||||
* @return a map of active installs to their progress
|
||||
*/
|
||||
public abstract HashMap<String, Integer> updateAndGetActiveSessionCache();
|
||||
public abstract HashMap<String, PackageInstaller.SessionInfo> updateAndGetActiveSessionCache();
|
||||
|
||||
public abstract void onStop();
|
||||
|
||||
|
||||
@@ -59,13 +59,13 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, Integer> updateAndGetActiveSessionCache() {
|
||||
HashMap<String, Integer> activePackages = new HashMap<>();
|
||||
public HashMap<String, SessionInfo> updateAndGetActiveSessionCache() {
|
||||
HashMap<String, SessionInfo> activePackages = new HashMap<>();
|
||||
UserHandle user = Process.myUserHandle();
|
||||
for (SessionInfo info : getAllVerifiedSessions()) {
|
||||
addSessionInfoToCache(info, user);
|
||||
if (info.getAppPackageName() != null) {
|
||||
activePackages.put(info.getAppPackageName(), (int) (info.getProgress() * 100));
|
||||
activePackages.put(info.getAppPackageName(), info);
|
||||
mActiveSessions.put(info.getSessionId(), info.getAppPackageName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInstaller.SessionInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.util.MultiHashMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helper class to send broadcasts to package installers that have:
|
||||
* - Items on the first screen
|
||||
* - Items with an active install session
|
||||
*
|
||||
* The packages are broken down by: folder items, workspace items, hotseat items, and widgets.
|
||||
*
|
||||
* Package installers only receive data for items that they are installing.
|
||||
*/
|
||||
public class FirstScreenBroadcast {
|
||||
|
||||
private static final String TAG = "FirstScreenBroadcast";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String ACTION_FIRST_SCREEN_ACTIVE_INSTALLS
|
||||
= "com.android.launcher3.action.FIRST_SCREEN_ACTIVE_INSTALLS";
|
||||
|
||||
private static final String FOLDER_ITEM_EXTRA = "folderItem";
|
||||
private static final String WORKSPACE_ITEM_EXTRA = "workspaceItem";
|
||||
private static final String HOTSEAT_ITEM_EXTRA = "hotseatItem";
|
||||
private static final String WIDGET_ITEM_EXTRA = "widgetItem";
|
||||
|
||||
private static final String VERIFICATION_TOKEN_EXTRA = "verificationToken";
|
||||
|
||||
private final MultiHashMap<String, String> mPackagesForInstaller;
|
||||
|
||||
public FirstScreenBroadcast(HashMap<String, SessionInfo> sessionInfoForPackage) {
|
||||
mPackagesForInstaller = getPackagesForInstaller(sessionInfoForPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Map where the key is the package name of the installer, and the value is a list
|
||||
* of packages with active sessions for that installer.
|
||||
*/
|
||||
private MultiHashMap<String, String> getPackagesForInstaller(
|
||||
HashMap<String, SessionInfo> sessionInfoForPackage) {
|
||||
MultiHashMap<String, String> packagesForInstaller = new MultiHashMap<>();
|
||||
for (Map.Entry<String, SessionInfo> entry : sessionInfoForPackage.entrySet()) {
|
||||
packagesForInstaller.addToList(entry.getValue().getInstallerPackageName(),
|
||||
entry.getKey());
|
||||
}
|
||||
return packagesForInstaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a broadcast to all package installers that have items with active sessions on the users
|
||||
* first screen.
|
||||
*/
|
||||
public void sendBroadcasts(Context context, List<ItemInfo> firstScreenItems) {
|
||||
for (Map.Entry<String, ArrayList<String>> entry : mPackagesForInstaller.entrySet()) {
|
||||
sendBroadcastToInstaller(context, entry.getKey(), entry.getValue(), firstScreenItems);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param installerPackageName Package name of the package installer.
|
||||
* @param packages List of packages with active sessions for this package installer.
|
||||
* @param firstScreenItems List of items on the first screen.
|
||||
*/
|
||||
private void sendBroadcastToInstaller(Context context, String installerPackageName,
|
||||
List<String> packages, List<ItemInfo> firstScreenItems) {
|
||||
Set<String> folderItems = new HashSet<>();
|
||||
Set<String> workspaceItems = new HashSet<>();
|
||||
Set<String> hotseatItems = new HashSet<>();
|
||||
Set<String> widgetItems = new HashSet<>();
|
||||
|
||||
for (ItemInfo info : firstScreenItems) {
|
||||
if (info instanceof FolderInfo) {
|
||||
FolderInfo folderInfo = (FolderInfo) info;
|
||||
String folderItemInfoPackage;
|
||||
for (ItemInfo folderItemInfo : folderInfo.contents) {
|
||||
folderItemInfoPackage = getPackageName(folderItemInfo);
|
||||
if (folderItemInfoPackage != null
|
||||
&& packages.contains(folderItemInfoPackage)) {
|
||||
folderItems.add(folderItemInfoPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String packageName = getPackageName(info);
|
||||
if (packageName == null || !packages.contains(packageName)) {
|
||||
continue;
|
||||
}
|
||||
if (info instanceof LauncherAppWidgetInfo) {
|
||||
widgetItems.add(packageName);
|
||||
} else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
||||
hotseatItems.add(packageName);
|
||||
} else if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||
workspaceItems.add(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
printList(installerPackageName, "Folder item", folderItems);
|
||||
printList(installerPackageName, "Workspace item", workspaceItems);
|
||||
printList(installerPackageName, "Hotseat item", hotseatItems);
|
||||
printList(installerPackageName, "Widget item", widgetItems);
|
||||
}
|
||||
|
||||
context.sendBroadcast(new Intent(ACTION_FIRST_SCREEN_ACTIVE_INSTALLS)
|
||||
.setPackage(installerPackageName)
|
||||
.putExtra(FOLDER_ITEM_EXTRA, folderItems.toArray())
|
||||
.putExtra(WORKSPACE_ITEM_EXTRA, workspaceItems.toArray())
|
||||
.putExtra(HOTSEAT_ITEM_EXTRA, hotseatItems.toArray())
|
||||
.putExtra(WIDGET_ITEM_EXTRA, widgetItems.toArray())
|
||||
.putExtra(VERIFICATION_TOKEN_EXTRA, PendingIntent.getActivity(context, 0,
|
||||
new Intent(), PendingIntent.FLAG_ONE_SHOT)));
|
||||
}
|
||||
|
||||
private static String getPackageName(ItemInfo info) {
|
||||
String packageName = null;
|
||||
if (info instanceof LauncherAppWidgetInfo) {
|
||||
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
|
||||
if (widgetInfo.providerName != null) {
|
||||
packageName = widgetInfo.providerName.getPackageName();
|
||||
}
|
||||
} else if (info.getTargetComponent() != null){
|
||||
packageName = info.getTargetComponent().getPackageName();
|
||||
}
|
||||
return packageName;
|
||||
}
|
||||
|
||||
private static void printList(String packageInstaller, String label, Set<String> packages) {
|
||||
for (String pkg : packages) {
|
||||
Log.d(TAG, packageInstaller + ":" + label + ":" + pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,7 @@ public class LoaderResults {
|
||||
|
||||
/** Filters the set of items who are directly or indirectly (via another container) on the
|
||||
* specified screen. */
|
||||
private <T extends ItemInfo> void filterCurrentWorkspaceItems(long currentScreenId,
|
||||
public static <T extends ItemInfo> void filterCurrentWorkspaceItems(long currentScreenId,
|
||||
ArrayList<T> allWorkspaceItems,
|
||||
ArrayList<T> currentScreenItems,
|
||||
ArrayList<T> otherScreenItems) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
|
||||
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
|
||||
import static com.android.launcher3.model.LoaderResults.filterCurrentWorkspaceItems;
|
||||
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
@@ -29,6 +30,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageInstaller.SessionInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
@@ -92,6 +94,8 @@ public class LoaderTask implements Runnable {
|
||||
private final AllAppsList mBgAllAppsList;
|
||||
private final BgDataModel mBgDataModel;
|
||||
|
||||
private FirstScreenBroadcast mFirstScreenBroadcast;
|
||||
|
||||
private final LoaderResults mResults;
|
||||
|
||||
private final LauncherAppsCompat mLauncherApps;
|
||||
@@ -134,6 +138,22 @@ public class LoaderTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendFirstScreenActiveInstallsBroadcast() {
|
||||
ArrayList<ItemInfo> firstScreenItems = new ArrayList<>();
|
||||
|
||||
ArrayList<ItemInfo> allItems = new ArrayList<>();
|
||||
synchronized (mBgDataModel) {
|
||||
allItems.addAll(mBgDataModel.workspaceItems);
|
||||
allItems.addAll(mBgDataModel.appWidgets);
|
||||
}
|
||||
long firstScreen = mBgDataModel.workspaceScreens.isEmpty()
|
||||
? -1 // In this case, we can still look at the items in the hotseat.
|
||||
: mBgDataModel.workspaceScreens.get(0);
|
||||
filterCurrentWorkspaceItems(firstScreen, allItems, firstScreenItems,
|
||||
new ArrayList<>() /* otherScreenItems are ignored */);
|
||||
mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
synchronized (this) {
|
||||
// Skip fast if we are already stopped.
|
||||
@@ -151,6 +171,10 @@ public class LoaderTask implements Runnable {
|
||||
TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace");
|
||||
mResults.bindWorkspace();
|
||||
|
||||
// Notify the installer packages of packages with active installs on the first screen.
|
||||
TraceHelper.partitionSection(TAG, "step 1.3: send first screen broadcast");
|
||||
sendFirstScreenActiveInstallsBroadcast();
|
||||
|
||||
// Take a break
|
||||
TraceHelper.partitionSection(TAG, "step 1 completed, wait for idle");
|
||||
waitForIdle();
|
||||
@@ -242,8 +266,9 @@ public class LoaderTask implements Runnable {
|
||||
synchronized (mBgDataModel) {
|
||||
mBgDataModel.clear();
|
||||
|
||||
final HashMap<String, Integer> installingPkgs =
|
||||
final HashMap<String, SessionInfo> installingPkgs =
|
||||
mPackageInstaller.updateAndGetActiveSessionCache();
|
||||
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
|
||||
mBgDataModel.workspaceScreens.addAll(LauncherModel.loadWorkspaceScreensDb(context));
|
||||
|
||||
Map<ShortcutKey, ShortcutInfoCompat> shortcutKeyToPinnedShortcuts = new HashMap<>();
|
||||
@@ -511,11 +536,11 @@ public class LoaderTask implements Runnable {
|
||||
}
|
||||
|
||||
if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {
|
||||
Integer progress = installingPkgs.get(targetPkg);
|
||||
if (progress != null) {
|
||||
info.setInstallProgress(progress);
|
||||
} else {
|
||||
SessionInfo si = installingPkgs.get(targetPkg);
|
||||
if (si == null) {
|
||||
info.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
|
||||
} else {
|
||||
info.setInstallProgress((int) (si.getProgress() * 100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,7 +630,11 @@ public class LoaderTask implements Runnable {
|
||||
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
|
||||
component);
|
||||
appWidgetInfo.restoreStatus = c.restoreFlag;
|
||||
Integer installProgress = installingPkgs.get(component.getPackageName());
|
||||
SessionInfo si =
|
||||
installingPkgs.get(component.getPackageName());
|
||||
Integer installProgress = si == null
|
||||
? null
|
||||
: (int) (si.getProgress() * 100);
|
||||
|
||||
if (c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED)) {
|
||||
// Restore has started once.
|
||||
|
||||
Reference in New Issue
Block a user