Merge "Adding tracing for suspending via Wellbeing" into ub-launcher3-qt-qpr1-dev
diff --git a/robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
index e9324f9..42a4f5c 100644
--- a/robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
@@ -29,7 +29,8 @@
private PackageInstallStateChangedTask newTask(String pkg, int progress) {
int state = PackageInstallerCompat.STATUS_INSTALLING;
- PackageInstallInfo installInfo = new PackageInstallInfo(pkg, state, progress);
+ PackageInstallInfo installInfo = new PackageInstallInfo(pkg, state, progress,
+ android.os.Process.myUserHandle());
return new PackageInstallStateChangedTask(installInfo);
}
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index 733f295..8b49c06 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -89,7 +89,7 @@
public void addPromiseApp(Context context,
PackageInstallerCompat.PackageInstallInfo installInfo) {
ApplicationInfo applicationInfo = LauncherAppsCompat.getInstance(context)
- .getApplicationInfo(installInfo.packageName, 0, Process.myUserHandle());
+ .getApplicationInfo(installInfo.packageName, 0, installInfo.user);
// only if not yet installed
if (applicationInfo == null) {
PromiseAppInfo info = new PromiseAppInfo(installInfo);
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index e9b932a..670cd28 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -19,6 +19,7 @@
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -29,7 +30,6 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
@@ -141,7 +141,8 @@
String pkg = getIntentPackage(info.launchIntent);
if (!TextUtils.isEmpty(pkg)
- && !launcherApps.isPackageEnabledForProfile(pkg, info.user)) {
+ && !launcherApps.isPackageEnabledForProfile(pkg, info.user)
+ && !info.isActivity) {
if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
+ info.launchIntent);
continue;
@@ -250,7 +251,8 @@
}
public static WorkspaceItemInfo fromActivityInfo(LauncherActivityInfo info, Context context) {
- return (WorkspaceItemInfo) (new PendingInstallShortcutInfo(info, context).getItemInfo().first);
+ return (WorkspaceItemInfo)
+ new PendingInstallShortcutInfo(info, context).getItemInfo().first;
}
public static void queueShortcut(ShortcutInfo info, Context context) {
@@ -261,8 +263,9 @@
queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, widgetId, context), context);
}
- public static void queueActivityInfo(LauncherActivityInfo activity, Context context) {
- queuePendingShortcutInfo(new PendingInstallShortcutInfo(activity, context), context);
+ public static void queueApplication(Intent data, UserHandle user, Context context) {
+ queuePendingShortcutInfo(new PendingInstallShortcutInfo(data, context, user),
+ context);
}
public static HashSet<ShortcutKey> getPendingShortcuts(Context context) {
@@ -326,7 +329,7 @@
private static class PendingInstallShortcutInfo {
- final LauncherActivityInfo activityInfo;
+ final boolean isActivity;
final ShortcutInfo shortcutInfo;
final AppWidgetProviderInfo providerInfo;
@@ -340,7 +343,7 @@
* Initializes a PendingInstallShortcutInfo received from a different app.
*/
public PendingInstallShortcutInfo(Intent data, UserHandle user, Context context) {
- activityInfo = null;
+ isActivity = false;
shortcutInfo = null;
providerInfo = null;
@@ -350,14 +353,13 @@
launchIntent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
-
}
/**
* Initializes a PendingInstallShortcutInfo to represent a launcher target.
*/
public PendingInstallShortcutInfo(LauncherActivityInfo info, Context context) {
- activityInfo = info;
+ isActivity = true;
shortcutInfo = null;
providerInfo = null;
@@ -372,8 +374,24 @@
/**
* Initializes a PendingInstallShortcutInfo to represent a launcher target.
*/
+ public PendingInstallShortcutInfo(Intent data, Context context, UserHandle user) {
+ isActivity = true;
+ shortcutInfo = null;
+ providerInfo = null;
+
+ this.data = data;
+ this.user = user;
+ mContext = context;
+
+ launchIntent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+ label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+ }
+
+ /**
+ * Initializes a PendingInstallShortcutInfo to represent a launcher target.
+ */
public PendingInstallShortcutInfo(ShortcutInfo info, Context context) {
- activityInfo = null;
+ isActivity = false;
shortcutInfo = info;
providerInfo = null;
@@ -390,7 +408,7 @@
*/
public PendingInstallShortcutInfo(
AppWidgetProviderInfo info, int widgetId, Context context) {
- activityInfo = null;
+ isActivity = false;
shortcutInfo = null;
providerInfo = info;
@@ -405,17 +423,7 @@
public String encodeToString() {
try {
- if (activityInfo != null) {
- // If it a launcher target, we only need component name, and user to
- // recreate this.
- return new JSONStringer()
- .object()
- .key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
- .key(APP_SHORTCUT_TYPE_KEY).value(true)
- .key(USER_HANDLE_KEY).value(UserManagerCompat.getInstance(mContext)
- .getSerialNumberForUser(user))
- .endObject().toString();
- } else if (shortcutInfo != null) {
+ if (shortcutInfo != null) {
// If it a launcher target, we only need component name, and user to
// recreate this.
return new JSONStringer()
@@ -457,7 +465,8 @@
JSONStringer json = new JSONStringer()
.object()
.key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
- .key(NAME_KEY).value(name);
+ .key(NAME_KEY).value(name)
+ .key(APP_SHORTCUT_TYPE_KEY).value(isActivity);
if (icon != null) {
byte[] iconByteArray = GraphicsUtils.flattenBitmap(icon);
json = json.key(ICON_KEY).value(
@@ -477,29 +486,18 @@
}
public Pair<ItemInfo, Object> getItemInfo() {
- if (activityInfo != null) {
- AppInfo appInfo = new AppInfo(mContext, activityInfo, user);
- final LauncherAppState app = LauncherAppState.getInstance(mContext);
- // Set default values until proper values is loaded.
- appInfo.title = "";
- appInfo.applyFrom(app.getIconCache().getDefaultIcon(user));
- final WorkspaceItemInfo si = appInfo.makeWorkspaceItem();
- if (Looper.myLooper() == LauncherModel.getWorkerLooper()) {
- app.getIconCache().getTitleAndIcon(si, activityInfo, false /* useLowResIcon */);
- } else {
- app.getModel().updateAndBindWorkspaceItem(() -> {
- app.getIconCache().getTitleAndIcon(
- si, activityInfo, false /* useLowResIcon */);
- return si;
- });
- }
- return Pair.create((ItemInfo) si, (Object) activityInfo);
+ if (isActivity) {
+ WorkspaceItemInfo si = createWorkspaceItemInfo(data,
+ LauncherAppState.getInstance(mContext));
+ si.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+ si.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
+ return Pair.create(si, null);
} else if (shortcutInfo != null) {
- WorkspaceItemInfo si = new WorkspaceItemInfo(shortcutInfo, mContext);
+ WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, mContext);
LauncherIcons li = LauncherIcons.obtain(mContext);
- si.applyFrom(li.createShortcutIcon(shortcutInfo));
+ itemInfo.applyFrom(li.createShortcutIcon(shortcutInfo));
li.recycle();
- return Pair.create((ItemInfo) si, (Object) shortcutInfo);
+ return Pair.create(itemInfo, shortcutInfo);
} else if (providerInfo != null) {
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
.fromProviderInfo(mContext, providerInfo);
@@ -511,15 +509,16 @@
widgetInfo.minSpanY = info.minSpanY;
widgetInfo.spanX = Math.min(info.spanX, idp.numColumns);
widgetInfo.spanY = Math.min(info.spanY, idp.numRows);
- return Pair.create((ItemInfo) widgetInfo, (Object) providerInfo);
+ return Pair.create(widgetInfo, providerInfo);
} else {
- WorkspaceItemInfo si = createWorkspaceItemInfo(data, LauncherAppState.getInstance(mContext));
- return Pair.create((ItemInfo) si, null);
+ WorkspaceItemInfo itemInfo =
+ createWorkspaceItemInfo(data, LauncherAppState.getInstance(mContext));
+ return Pair.create(itemInfo, null);
}
}
public boolean isLauncherActivity() {
- return activityInfo != null;
+ return isActivity;
}
}
@@ -534,7 +533,9 @@
if (decoder.optBoolean(APP_SHORTCUT_TYPE_KEY)) {
LauncherActivityInfo info = LauncherAppsCompat.getInstance(context)
.resolveActivity(decoder.launcherIntent, decoder.user);
- return info == null ? null : new PendingInstallShortcutInfo(info, context);
+ if (info != null) {
+ return new PendingInstallShortcutInfo(info, context);
+ }
} else if (decoder.optBoolean(DEEPSHORTCUT_TYPE_KEY)) {
DeepShortcutManager sm = DeepShortcutManager.getInstance(context);
List<ShortcutInfo> si = sm.queryForFullDetails(
@@ -578,7 +579,11 @@
data.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
}
- return new PendingInstallShortcutInfo(data, decoder.user, context);
+ if (decoder.optBoolean(APP_SHORTCUT_TYPE_KEY)) {
+ return new PendingInstallShortcutInfo(data, context, decoder.user);
+ } else {
+ return new PendingInstallShortcutInfo(data, decoder.user, context);
+ }
} catch (JSONException | URISyntaxException e) {
Log.d(TAG, "Exception reading shortcut to add: " + e);
}
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index b0da6b9..b4078ee 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -18,28 +18,33 @@
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
+import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
-import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
import java.util.List;
+import static com.android.launcher3.compat.PackageInstallerCompat.getUserHandle;
+
/**
* BroadcastReceiver to handle session commit intent.
*/
@@ -66,15 +71,29 @@
SessionInfo info = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
+ PackageInstallerCompat packageInstallerCompat = PackageInstallerCompat.getInstance(context);
- if (TextUtils.isEmpty(info.getAppPackageName()) ||
- info.getInstallReason() != PackageManager.INSTALL_REASON_USER) {
+ if (TextUtils.isEmpty(info.getAppPackageName())
+ || info.getInstallReason() != PackageManager.INSTALL_REASON_USER
+ || packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
+ packageInstallerCompat.removePromiseIconId(info.getSessionId());
return;
}
queueAppIconAddition(context, info.getAppPackageName(), user);
}
+ public static void queuePromiseAppIconAddition(Context context, SessionInfo sessionInfo) {
+ String packageName = sessionInfo.getAppPackageName();
+ List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(context)
+ .getActivityList(packageName, getUserHandle(sessionInfo));
+ if (activities == null || activities.isEmpty()) {
+ // Ensure application isn't already installed.
+ queueAppIconAddition(context, packageName, sessionInfo.getAppLabel(),
+ sessionInfo.getAppIcon(), getUserHandle(sessionInfo));
+ }
+ }
+
public static void queueAppIconAddition(Context context, String packageName, UserHandle user) {
List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(context)
.getActivityList(packageName, user);
@@ -82,7 +101,18 @@
// no activity found
return;
}
- InstallShortcutReceiver.queueActivityInfo(activities.get(0), context);
+ queueAppIconAddition(context, packageName, activities.get(0).getLabel(), null, user);
+ }
+
+ private static void queueAppIconAddition(Context context, String packageName,
+ CharSequence label, Bitmap icon, UserHandle user) {
+ Intent data = new Intent();
+ data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent().setComponent(
+ new ComponentName(packageName, "")).setPackage(packageName));
+ data.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
+ data.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
+
+ InstallShortcutReceiver.queueApplication(data, user, context);
}
public static boolean isEnabled(Context context) {
diff --git a/src/com/android/launcher3/WorkspaceItemInfo.java b/src/com/android/launcher3/WorkspaceItemInfo.java
index b72866c..050a8be 100644
--- a/src/com/android/launcher3/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/WorkspaceItemInfo.java
@@ -50,24 +50,26 @@
* The icon was added as an auto-install app, and is not ready to be used. This flag can't
* be present along with {@link #FLAG_RESTORED_ICON}, and is set during default layout
* parsing.
+ *
+ * OR this icon was added due to it being an active install session created by the user.
*/
- public static final int FLAG_AUTOINSTALL_ICON = 2; //0B10;
+ public static final int FLAG_AUTOINSTALL_ICON = 1 << 1;
/**
* The icon is being installed. If {@link #FLAG_RESTORED_ICON} or {@link #FLAG_AUTOINSTALL_ICON}
* is set, then the icon is either being installed or is in a broken state.
*/
- public static final int FLAG_INSTALL_SESSION_ACTIVE = 4; // 0B100;
+ public static final int FLAG_INSTALL_SESSION_ACTIVE = 1 << 2;
/**
* Indicates that the widget restore has started.
*/
- public static final int FLAG_RESTORE_STARTED = 8; //0B1000;
+ public static final int FLAG_RESTORE_STARTED = 1 << 3;
/**
* Web UI supported.
*/
- public static final int FLAG_SUPPORTS_WEB_UI = 16; //0B10000;
+ public static final int FLAG_SUPPORTS_WEB_UI = 1 << 4;
/**
* The intent used to start the application.
@@ -210,7 +212,7 @@
public ComponentName getTargetComponent() {
ComponentName cn = super.getTargetComponent();
if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT
- || hasStatusFlag(FLAG_SUPPORTS_WEB_UI))) {
+ || hasStatusFlag(FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON))) {
// Legacy shortcuts and promise icons with web UI may not have a componentName but just
// a packageName. In that case create a dummy componentName instead of adding additional
// check everywhere.
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java
index 4f4d641..11cb1f8 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompat.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java
@@ -19,15 +19,23 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInstaller;
+import android.os.Process;
import android.os.UserHandle;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import androidx.annotation.NonNull;
+import com.android.launcher3.Utilities;
+
public abstract class PackageInstallerCompat {
+ // Set<String> of session ids of promise icons that have been added to the home screen
+ // as FLAG_PROMISE_NEW_INSTALLS.
+ protected static final String PROMISE_ICON_IDS = "promise_icon_ids";
+
public static final int STATUS_INSTALLED = 0;
public static final int STATUS_INSTALLING = 1;
public static final int STATUS_FAILED = 2;
@@ -44,6 +52,10 @@
}
}
+ public static UserHandle getUserHandle(PackageInstaller.SessionInfo info) {
+ return Utilities.ATLEAST_Q ? info.getUser() : Process.myUserHandle();
+ }
+
/**
* @return a map of active installs to their progress
*/
@@ -61,30 +73,44 @@
public final String packageName;
public final int state;
public final int progress;
+ public final UserHandle user;
private PackageInstallInfo(@NonNull PackageInstaller.SessionInfo info) {
this.state = STATUS_INSTALLING;
this.packageName = info.getAppPackageName();
this.componentName = new ComponentName(packageName, "");
this.progress = (int) (info.getProgress() * 100f);
+ this.user = getUserHandle(info);
}
- public PackageInstallInfo(String packageName, int state, int progress) {
+ public PackageInstallInfo(String packageName, int state, int progress, UserHandle user) {
this.state = state;
this.packageName = packageName;
this.componentName = new ComponentName(packageName, "");
this.progress = progress;
+ this.user = user;
}
public static PackageInstallInfo fromInstallingState(PackageInstaller.SessionInfo info) {
return new PackageInstallInfo(info);
}
- public static PackageInstallInfo fromState(int state, String packageName) {
- return new PackageInstallInfo(packageName, state, 0 /* progress */);
+ public static PackageInstallInfo fromState(int state, String packageName, UserHandle user) {
+ return new PackageInstallInfo(packageName, state, 0 /* progress */, user);
}
}
public abstract List<PackageInstaller.SessionInfo> getAllVerifiedSessions();
+
+ /**
+ * Returns true if a promise icon was already added to the home screen for {@param sessionId}.
+ * Applicable only for icons with flag FLAG_PROMISE_NEW_INSTALLS.
+ */
+ public abstract boolean promiseIconAddedForId(int sessionId);
+
+ /**
+ * Applicable only for icons with flag FLAG_PROMISE_NEW_INSTALLS.
+ */
+ public abstract void removePromiseIconId(int sessionId);
}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index 8a5eabc..e1f17cf 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -21,17 +21,21 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionCallback;
import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageManager;
import android.os.Handler;
-import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.SparseArray;
+import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -39,11 +43,13 @@
import java.util.Iterator;
import java.util.List;
+import static com.android.launcher3.Utilities.getPrefs;
+
public class PackageInstallerCompatVL extends PackageInstallerCompat {
private static final boolean DEBUG = false;
- @Thunk final SparseArray<String> mActiveSessions = new SparseArray<>();
+ @Thunk final SparseArray<PackageUserKey> mActiveSessions = new SparseArray<>();
@Thunk final PackageInstaller mInstaller;
private final IconCache mCache;
@@ -51,6 +57,7 @@
private final Context mAppContext;
private final HashMap<String,Boolean> mSessionVerifiedMap = new HashMap<>();
private final LauncherAppsCompat mLauncherApps;
+ private final IntSet mPromiseIconIds;
PackageInstallerCompatVL(Context context) {
mAppContext = context.getApplicationContext();
@@ -59,17 +66,38 @@
mWorker = new Handler(LauncherModel.getWorkerLooper());
mInstaller.registerSessionCallback(mCallback, mWorker);
mLauncherApps = LauncherAppsCompat.getInstance(context);
+ mPromiseIconIds = IntSet.wrap(IntArray.wrap(Utilities.getIntArrayFromString(
+ getPrefs(context).getString(PROMISE_ICON_IDS, ""))));
+
+ cleanUpPromiseIconIds();
+ }
+
+ private void cleanUpPromiseIconIds() {
+ IntArray existingIds = new IntArray();
+ for (SessionInfo info : updateAndGetActiveSessionCache().values()) {
+ existingIds.add(info.getSessionId());
+ }
+ IntArray idsToRemove = new IntArray();
+
+ for (int i = mPromiseIconIds.size() - 1; i >= 0; --i) {
+ if (!existingIds.contains(mPromiseIconIds.getArray().get(i))) {
+ idsToRemove.add(mPromiseIconIds.getArray().get(i));
+ }
+ }
+ for (int i = idsToRemove.size() - 1; i >= 0; --i) {
+ mPromiseIconIds.getArray().removeValue(idsToRemove.get(i));
+ }
}
@Override
public HashMap<String, SessionInfo> updateAndGetActiveSessionCache() {
HashMap<String, SessionInfo> activePackages = new HashMap<>();
- UserHandle primaryUser = Process.myUserHandle();
for (SessionInfo info : getAllVerifiedSessions()) {
- addSessionInfoToCache(info, Utilities.ATLEAST_Q ? info.getUser() : primaryUser);
+ addSessionInfoToCache(info, getUserHandle(info));
if (info.getAppPackageName() != null) {
activePackages.put(info.getAppPackageName(), info);
- mActiveSessions.put(info.getSessionId(), info.getAppPackageName());
+ mActiveSessions.put(info.getSessionId(),
+ new PackageUserKey(info.getAppPackageName(), getUserHandle(info)));
}
}
return activePackages;
@@ -78,7 +106,7 @@
public SessionInfo getActiveSessionInfo(UserHandle user, String pkg) {
for (SessionInfo info : getAllVerifiedSessions()) {
boolean match = pkg.equals(info.getAppPackageName());
- if (Utilities.ATLEAST_Q && !user.equals(info.getUser())) {
+ if (Utilities.ATLEAST_Q && !user.equals(getUserHandle(info))) {
match = false;
}
if (match) {
@@ -120,19 +148,38 @@
PackageInstallInfo.fromInstallingState(sessionInfo));
}
}
+
+ if (Utilities.ATLEAST_OREO && FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
+ && SessionCommitReceiver.isEnabled(mAppContext)
+ && sessionInfo != null
+ && sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER) {
+ SessionCommitReceiver.queuePromiseAppIconAddition(mAppContext, sessionInfo);
+ if (!mPromiseIconIds.contains(sessionInfo.getSessionId())) {
+ mPromiseIconIds.add(sessionInfo.getSessionId());
+ updatePromiseIconPrefs();
+ }
+ }
}
@Override
public void onFinished(int sessionId, boolean success) {
// For a finished session, we can't get the session info. So use the
// packageName from our local cache.
- String packageName = mActiveSessions.get(sessionId);
+ PackageUserKey key = mActiveSessions.get(sessionId);
mActiveSessions.remove(sessionId);
- if (packageName != null) {
- sendUpdate(PackageInstallInfo.fromState(
- success ? STATUS_INSTALLED : STATUS_FAILED,
- packageName));
+ if (key != null && key.mPackageName != null) {
+ String packageName = key.mPackageName;
+ sendUpdate(PackageInstallInfo.fromState(success ? STATUS_INSTALLED : STATUS_FAILED,
+ packageName, key.mUser));
+
+ if (!success && FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()) {
+ LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+ if (appState != null) {
+ LauncherModel model = appState.getModel();
+ model.onPackageRemoved(packageName, key.mUser);
+ }
+ }
}
}
@@ -155,8 +202,9 @@
private SessionInfo pushSessionDisplayToLauncher(int sessionId) {
SessionInfo session = verify(mInstaller.getSessionInfo(sessionId));
if (session != null && session.getAppPackageName() != null) {
- mActiveSessions.put(sessionId, session.getAppPackageName());
- addSessionInfoToCache(session, Process.myUserHandle());
+ mActiveSessions.put(session.getSessionId(),
+ new PackageUserKey(session.getAppPackageName(), getUserHandle(session)));
+ addSessionInfoToCache(session, getUserHandle(session));
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
if (app != null) {
app.getModel().updateSessionDisplayInfo(session.getAppPackageName());
@@ -178,7 +226,7 @@
if (!mSessionVerifiedMap.containsKey(pkg)) {
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mAppContext);
boolean hasSystemFlag = launcherApps.getApplicationInfo(pkg,
- ApplicationInfo.FLAG_SYSTEM, Process.myUserHandle()) != null;
+ ApplicationInfo.FLAG_SYSTEM, getUserHandle(sessionInfo)) != null;
mSessionVerifiedMap.put(pkg, DEBUG || hasSystemFlag);
}
}
@@ -198,4 +246,23 @@
}
return list;
}
+
+ @Override
+ public boolean promiseIconAddedForId(int sessionId) {
+ return mPromiseIconIds.contains(sessionId);
+ }
+
+ @Override
+ public void removePromiseIconId(int sessionId) {
+ if (mPromiseIconIds.contains(sessionId)) {
+ mPromiseIconIds.getArray().removeValue(sessionId);
+ updatePromiseIconPrefs();
+ }
+ }
+
+ private void updatePromiseIconPrefs() {
+ getPrefs(mAppContext).edit()
+ .putString(PROMISE_ICON_IDS, mPromiseIconIds.getArray().toConcatString())
+ .apply();
+ }
}
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 23edcd2..ea6261a 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -60,6 +60,11 @@
// When enabled the promise icon is visible in all apps while installation an app.
public static final boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false;
+ // When enabled a promise icon is added to the home screen when install session is active.
+ public static final TogglableFlag PROMISE_APPS_NEW_INSTALLS =
+ new TogglableFlag("PROMISE_APPS_NEW_INSTALLS", true,
+ "Adds a promise icon to the home screen for new install sessions.");
+
// Enable moving the QSB on the 0th screen of the workspace
public static final boolean QSB_ON_FIRST_SCREEN = true;
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index ed0d470..7d4f2f7 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -16,6 +16,8 @@
package com.android.launcher3.model;
import android.content.Intent;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.PackageInstaller.SessionInfo;
import android.os.UserHandle;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -32,6 +34,8 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
@@ -85,6 +89,10 @@
}
}
+ PackageInstallerCompat packageInstaller =
+ PackageInstallerCompat.getInstance(app.getContext());
+ LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(app.getContext());
+
for (ItemInfo item : filteredItems) {
// Find appropriate space for the item.
int[] coords = findSpaceForItem(app, dataModel, workspaceScreens,
@@ -101,6 +109,36 @@
throw new RuntimeException("Unexpected info type");
}
+ if (item instanceof WorkspaceItemInfo && ((WorkspaceItemInfo) item).isPromise()) {
+ WorkspaceItemInfo workspaceInfo = (WorkspaceItemInfo) item;
+ String packageName = item.getTargetComponent() != null
+ ? item.getTargetComponent().getPackageName() : null;
+ if (packageName == null) {
+ continue;
+ }
+ SessionInfo sessionInfo = packageInstaller.getActiveSessionInfo(item.user,
+ packageName);
+ if (sessionInfo == null) {
+ List<LauncherActivityInfo> activities = launcherApps
+ .getActivityList(packageName, item.user);
+ if (activities != null && !activities.isEmpty()) {
+ // App was installed while launcher was in the background.
+ itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user)
+ .makeWorkspaceItem();
+ WorkspaceItemInfo wii = (WorkspaceItemInfo) itemInfo;
+ wii.title = "";
+ wii.applyFrom(app.getIconCache().getDefaultIcon(item.user));
+ app.getIconCache().getTitleAndIcon(wii,
+ ((WorkspaceItemInfo) itemInfo).usingLowResIcon());
+ } else {
+ // Session was cancelled, do not add.
+ continue;
+ }
+ } else {
+ workspaceInfo.setInstallProgress((int) sessionInfo.getProgress());
+ }
+ }
+
// Add the shortcut to the db
getModelWriter().addItemToDatabase(itemInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId,
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 1a03b77..1c39d1f 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -227,7 +227,7 @@
if (!TextUtils.isEmpty(title)) {
info.title = Utilities.trim(title);
}
- } else if (hasRestoreFlag(WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON)) {
+ } else if (hasRestoreFlag(WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON)) {
if (TextUtils.isEmpty(info.title)) {
info.title = getTitle();
}
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 5f6d128..9fcab38 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -18,7 +18,6 @@
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.os.Process;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
@@ -56,7 +55,7 @@
ApplicationInfo ai = app.getContext()
.getPackageManager().getApplicationInfo(mInstallInfo.packageName, 0);
if (InstantAppResolver.newInstance(app.getContext()).isInstantApp(ai)) {
- app.getModel().onPackageAdded(ai.packageName, Process.myUserHandle());
+ app.getModel().onPackageAdded(ai.packageName, mInstallInfo.user);
}
} catch (PackageManager.NameNotFoundException e) {
// Ignore
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 3f3275a..4428c8e 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -56,6 +56,8 @@
import java.util.HashSet;
import java.util.List;
+import static com.android.launcher3.WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
+
/**
* Handles updates due to changes in package manager (app installed/updated/removed)
* or when a user availability changes.
@@ -104,7 +106,7 @@
if (DEBUG) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
iconCache.updateIconsForPkg(packages[i], mUser);
if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
- appsList.removePackage(packages[i], Process.myUserHandle());
+ appsList.removePackage(packages[i], mUser);
}
appsList.addPackage(context, packages[i], mUser);
@@ -232,8 +234,7 @@
isTargetValid = LauncherAppsCompat.getInstance(context)
.isActivityEnabledForProfile(cn, mUser);
}
- if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON)
- && !isTargetValid) {
+ if (si.hasStatusFlag(FLAG_AUTOINSTALL_ICON)) {
if (updateWorkspaceItemIntent(context, si, packageName)) {
infoUpdated = true;
} else if (si.hasPromiseIconUi()) {