Search in sources :

Example 1 with PINNED

use of com.android.launcher3.shortcuts.ShortcutRequest.PINNED in project android_packages_apps_Launcher3 by crdroidandroid.

the class LoaderTask method loadWorkspace.

protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
    final Context context = mApp.getContext();
    final ContentResolver contentResolver = context.getContentResolver();
    final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
    final boolean isSafeMode = pmHelper.isSafeMode();
    final boolean isSdCardReady = Utilities.isBootCompleted();
    final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
    boolean clearDb = false;
    try {
        ImportDataTask.performImportIfPossible(context);
    } catch (Exception e) {
        // Migration failed. Clear workspace.
        clearDb = true;
    }
    if (!clearDb && (MULTI_DB_GRID_MIRATION_ALGO.get() ? !GridSizeMigrationTaskV2.migrateGridIfNeeded(context) : !GridSizeMigrationTask.migrateGridIfNeeded(context))) {
        // Migration failed. Clear workspace.
        clearDb = true;
    }
    if (clearDb) {
        Log.d(TAG, "loadWorkspace: resetting launcher database");
        LauncherSettings.Settings.call(contentResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
    }
    Log.d(TAG, "loadWorkspace: loading default favorites");
    LauncherSettings.Settings.call(contentResolver, LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);
    synchronized (mBgDataModel) {
        mBgDataModel.clear();
        mPendingPackages.clear();
        final HashMap<PackageUserKey, SessionInfo> installingPkgs = mSessionHelper.getActiveSessions();
        installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);
        final PackageUserKey tempPackageKey = new PackageUserKey(null, null);
        mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
        Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();
        final LoaderCursor c = new LoaderCursor(contentResolver.query(contentUri, null, selection, null, null), contentUri, mApp, mUserManagerState);
        final Bundle extras = c.getExtras();
        mDbName = extras == null ? null : extras.getString(LauncherSettings.Settings.EXTRA_DB_NAME);
        try {
            final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);
            final int appWidgetProviderIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_PROVIDER);
            final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
            final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
            final int rankIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.RANK);
            final int optionsIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.OPTIONS);
            final int sourceContainerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_SOURCE);
            final LongSparseArray<Boolean> unlockedUsers = new LongSparseArray<>();
            mUserManagerState.init(mUserCache, mUserManager);
            for (UserHandle user : mUserCache.getUserProfiles()) {
                long serialNo = mUserCache.getSerialNumberForUser(user);
                boolean userUnlocked = mUserManager.isUserUnlocked(user);
                // We can only query for shortcuts when the user is unlocked.
                if (userUnlocked) {
                    QueryResult pinnedShortcuts = new ShortcutRequest(context, user).query(ShortcutRequest.PINNED);
                    if (pinnedShortcuts.wasSuccess()) {
                        for (ShortcutInfo shortcut : pinnedShortcuts) {
                            shortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut);
                        }
                    } else {
                        // Shortcut manager can fail due to some race condition when the
                        // lock state changes too frequently. For the purpose of the loading
                        // shortcuts, consider the user is still locked.
                        userUnlocked = false;
                    }
                }
                unlockedUsers.put(serialNo, userUnlocked);
            }
            WorkspaceItemInfo info;
            LauncherAppWidgetInfo appWidgetInfo;
            LauncherAppWidgetProviderInfo widgetProviderInfo;
            Intent intent;
            String targetPkg;
            while (!mStopped && c.moveToNext()) {
                try {
                    if (c.user == null) {
                        // User has been deleted, remove the item.
                        c.markDeleted("User has been deleted");
                        continue;
                    }
                    boolean allowMissingTarget = false;
                    switch(c.itemType) {
                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                        case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                            intent = c.parseIntent();
                            if (intent == null) {
                                c.markDeleted("Invalid or null intent");
                                continue;
                            }
                            int disabledState = mUserManagerState.isUserQuiet(c.serialNumber) ? WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER : 0;
                            ComponentName cn = intent.getComponent();
                            targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
                            if (TextUtils.isEmpty(targetPkg) && c.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
                                c.markDeleted("Only legacy shortcuts can have null package");
                                continue;
                            }
                            // If there is no target package, its an implicit intent
                            // (legacy shortcut) which is always valid
                            boolean validTarget = TextUtils.isEmpty(targetPkg) || mLauncherApps.isPackageEnabled(targetPkg, c.user);
                            // If it's a deep shortcut, we'll use pinned shortcuts to restore it
                            if (cn != null && validTarget && c.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
                                // If the component is already present
                                if (mLauncherApps.isActivityEnabled(cn, c.user)) {
                                    // no special handling necessary for this item
                                    c.markRestored();
                                } else {
                                    // Gracefully try to find a fallback activity.
                                    intent = pmHelper.getAppLaunchIntent(targetPkg, c.user);
                                    if (intent != null) {
                                        c.restoreFlag = 0;
                                        c.updater().put(LauncherSettings.Favorites.INTENT, intent.toUri(0)).commit();
                                        cn = intent.getComponent();
                                    } else {
                                        c.markDeleted("Unable to find a launch target");
                                        continue;
                                    }
                                }
                            }
                            if (!TextUtils.isEmpty(targetPkg) && !validTarget) {
                                if (c.restoreFlag != 0) {
                                    // Package is not yet available but might be
                                    // installed later.
                                    FileLog.d(TAG, "package not yet restored: " + targetPkg);
                                    tempPackageKey.update(targetPkg, c.user);
                                    if (c.hasRestoreFlag(WorkspaceItemInfo.FLAG_RESTORE_STARTED)) {
                                    // Restore has started once.
                                    } else if (installingPkgs.containsKey(tempPackageKey)) {
                                        // App restore has started. Update the flag
                                        c.restoreFlag |= WorkspaceItemInfo.FLAG_RESTORE_STARTED;
                                        c.updater().put(LauncherSettings.Favorites.RESTORED, c.restoreFlag).commit();
                                    } else {
                                        c.markDeleted("Unrestored app removed: " + targetPkg);
                                        continue;
                                    }
                                } else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) {
                                    // Package is present but not available.
                                    disabledState |= WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE;
                                    // Add the icon on the workspace anyway.
                                    allowMissingTarget = true;
                                } else if (!isSdCardReady) {
                                    // SdCard is not ready yet. Package might get available,
                                    // once it is ready.
                                    Log.d(TAG, "Missing pkg, will check later: " + targetPkg);
                                    mPendingPackages.add(new PackageUserKey(targetPkg, c.user));
                                    // Add the icon on the workspace anyway.
                                    allowMissingTarget = true;
                                } else {
                                    // Do not wait for external media load anymore.
                                    c.markDeleted("Invalid package removed: " + targetPkg);
                                    continue;
                                }
                            }
                            if ((c.restoreFlag & WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) != 0) {
                                validTarget = false;
                            }
                            if (validTarget) {
                                // The shortcut points to a valid target (either no target
                                // or something which is ready to be used)
                                c.markRestored();
                            }
                            boolean useLowResIcon = !c.isOnWorkspaceOrHotseat();
                            if (c.restoreFlag != 0) {
                                // Already verified above that user is same as default user
                                info = c.getRestoredItemInfo(intent);
                            } else if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                                info = c.getAppShortcutInfo(intent, allowMissingTarget, useLowResIcon);
                            } else if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
                                ShortcutKey key = ShortcutKey.fromIntent(intent, c.user);
                                if (unlockedUsers.get(c.serialNumber)) {
                                    ShortcutInfo pinnedShortcut = shortcutKeyToPinnedShortcuts.get(key);
                                    if (pinnedShortcut == null) {
                                        // The shortcut is no longer valid.
                                        c.markDeleted("Pinned shortcut not found");
                                        continue;
                                    }
                                    info = new WorkspaceItemInfo(pinnedShortcut, context);
                                    // If the pinned deep shortcut is no longer published,
                                    // use the last saved icon instead of the default.
                                    mIconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon);
                                    if (pmHelper.isAppSuspended(pinnedShortcut.getPackage(), info.user)) {
                                        info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
                                    }
                                    intent = info.getIntent();
                                    allDeepShortcuts.add(pinnedShortcut);
                                } else {
                                    // Create a shortcut info in disabled mode for now.
                                    info = c.loadSimpleWorkspaceItem();
                                    info.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
                                }
                            } else {
                                // item type == ITEM_TYPE_SHORTCUT
                                info = c.loadSimpleWorkspaceItem();
                                // Shortcuts are only available on the primary profile
                                if (!TextUtils.isEmpty(targetPkg) && pmHelper.isAppSuspended(targetPkg, c.user)) {
                                    disabledState |= FLAG_DISABLED_SUSPENDED;
                                }
                                // here
                                if (intent.getAction() != null && intent.getCategories() != null && intent.getAction().equals(Intent.ACTION_MAIN) && intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
                                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                                }
                            }
                            if (info != null) {
                                c.applyCommonProperties(info);
                                info.intent = intent;
                                info.rank = c.getInt(rankIndex);
                                info.spanX = 1;
                                info.spanY = 1;
                                info.runtimeStatusFlags |= disabledState;
                                if (isSafeMode && !isSystemApp(context, intent)) {
                                    info.runtimeStatusFlags |= FLAG_DISABLED_SAFEMODE;
                                }
                                LauncherActivityInfo activityInfo = c.getLauncherActivityInfo();
                                if (activityInfo != null) {
                                    info.setProgressLevel(PackageManagerHelper.getLoadingProgress(activityInfo), PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
                                }
                                if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {
                                    tempPackageKey.update(targetPkg, c.user);
                                    SessionInfo si = installingPkgs.get(tempPackageKey);
                                    if (si == null) {
                                        info.runtimeStatusFlags &= ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
                                    } else if (activityInfo == null) {
                                        int installProgress = (int) (si.getProgress() * 100);
                                        info.setProgressLevel(installProgress, PackageInstallInfo.STATUS_INSTALLING);
                                    }
                                }
                                c.checkAndAddItem(info, mBgDataModel);
                            } else {
                                throw new RuntimeException("Unexpected null WorkspaceItemInfo");
                            }
                            break;
                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                            FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id);
                            c.applyCommonProperties(folderInfo);
                            // Do not trim the folder label, as is was set by the user.
                            folderInfo.title = c.getString(c.titleIndex);
                            folderInfo.spanX = 1;
                            folderInfo.spanY = 1;
                            folderInfo.options = c.getInt(optionsIndex);
                            // no special handling required for restored folders
                            c.markRestored();
                            c.checkAndAddItem(folderInfo, mBgDataModel);
                            break;
                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                            if (WidgetsModel.GO_DISABLE_WIDGETS) {
                                c.markDeleted("Only legacy shortcuts can have null package");
                                continue;
                            }
                        // Follow through
                        case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
                            // Read all Launcher-specific widget details
                            boolean customWidget = c.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
                            int appWidgetId = c.getInt(appWidgetIdIndex);
                            String savedProvider = c.getString(appWidgetProviderIndex);
                            final ComponentName component;
                            boolean isSearchWidget = (c.getInt(optionsIndex) & LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET) != 0;
                            if (isSearchWidget) {
                                component = QsbContainerView.getSearchComponentName(context);
                                if (component == null) {
                                    c.markDeleted("Discarding SearchWidget without packagename ");
                                    continue;
                                }
                            } else {
                                component = ComponentName.unflattenFromString(savedProvider);
                            }
                            final boolean isIdValid = !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
                            final boolean wasProviderReady = !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);
                            ComponentKey providerKey = new ComponentKey(component, c.user);
                            if (!mWidgetProvidersMap.containsKey(providerKey)) {
                                mWidgetProvidersMap.put(providerKey, widgetHelper.findProvider(component, c.user));
                            }
                            final AppWidgetProviderInfo provider = mWidgetProvidersMap.get(providerKey);
                            final boolean isProviderReady = isValidProvider(provider);
                            if (!isSafeMode && !customWidget && wasProviderReady && !isProviderReady) {
                                c.markDeleted("Deleting widget that isn't installed anymore: " + provider);
                            } else {
                                if (isProviderReady) {
                                    appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, provider.provider);
                                    // The provider is available. So the widget is either
                                    // available or not available. We do not need to track
                                    // any future restore updates.
                                    int status = c.restoreFlag & ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED & ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
                                    if (!wasProviderReady) {
                                        // Id would be valid only if the widget restore broadcast was received.
                                        if (isIdValid) {
                                            status |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
                                        }
                                    }
                                    appWidgetInfo.restoreStatus = status;
                                } else {
                                    Log.v(TAG, "Widget restore pending id=" + c.id + " appWidgetId=" + appWidgetId + " status =" + c.restoreFlag);
                                    appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, component);
                                    appWidgetInfo.restoreStatus = c.restoreFlag;
                                    tempPackageKey.update(component.getPackageName(), c.user);
                                    SessionInfo si = installingPkgs.get(tempPackageKey);
                                    Integer installProgress = si == null ? null : (int) (si.getProgress() * 100);
                                    if (c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED)) {
                                    // Restore has started once.
                                    } else if (installProgress != null) {
                                        // App restore has started. Update the flag
                                        appWidgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
                                    } else if (!isSafeMode) {
                                        c.markDeleted("Unrestored widget removed: " + component);
                                        continue;
                                    }
                                    appWidgetInfo.installProgress = installProgress == null ? 0 : installProgress;
                                }
                                if (appWidgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) {
                                    appWidgetInfo.bindOptions = c.parseIntent();
                                }
                                c.applyCommonProperties(appWidgetInfo);
                                appWidgetInfo.spanX = c.getInt(spanXIndex);
                                appWidgetInfo.spanY = c.getInt(spanYIndex);
                                appWidgetInfo.options = c.getInt(optionsIndex);
                                appWidgetInfo.user = c.user;
                                appWidgetInfo.sourceContainer = c.getInt(sourceContainerIndex);
                                if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
                                    c.markDeleted("Widget has invalid size: " + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY);
                                    continue;
                                }
                                widgetProviderInfo = widgetHelper.getLauncherAppWidgetInfo(appWidgetId);
                                if (widgetProviderInfo != null && (appWidgetInfo.spanX < widgetProviderInfo.minSpanX || appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) {
                                    FileLog.d(TAG, "Widget " + widgetProviderInfo.getComponent() + " minSizes not meet: span=" + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY + " minSpan=" + widgetProviderInfo.minSpanX + "x" + widgetProviderInfo.minSpanY);
                                    logWidgetInfo(mApp.getInvariantDeviceProfile(), widgetProviderInfo);
                                }
                                if (!c.isOnWorkspaceOrHotseat()) {
                                    c.markDeleted("Widget found where container != " + "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
                                    continue;
                                }
                                if (!customWidget) {
                                    String providerName = appWidgetInfo.providerName.flattenToString();
                                    if (!providerName.equals(savedProvider) || (appWidgetInfo.restoreStatus != c.restoreFlag)) {
                                        c.updater().put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName).put(LauncherSettings.Favorites.RESTORED, appWidgetInfo.restoreStatus).commit();
                                    }
                                }
                                if (appWidgetInfo.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED) {
                                    appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(appWidgetInfo.providerName);
                                    appWidgetInfo.pendingItemInfo.user = appWidgetInfo.user;
                                    mIconCache.getTitleAndIconForApp(appWidgetInfo.pendingItemInfo, false);
                                }
                                c.checkAndAddItem(appWidgetInfo, mBgDataModel);
                            }
                            break;
                    }
                } catch (Exception e) {
                    Log.e(TAG, "Desktop items loading interrupted", e);
                }
            }
        } finally {
            IOUtils.closeSilently(c);
        }
        // Load delegate items
        mModelDelegate.loadItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
        // Break early if we've stopped loading
        if (mStopped) {
            mBgDataModel.clear();
            return;
        }
        // Remove dead items
        mItemsDeleted = c.commitDeleted();
        // Sort the folder items, update ranks, and make sure all preview items are high res.
        FolderGridOrganizer verifier = new FolderGridOrganizer(mApp.getInvariantDeviceProfile());
        for (FolderInfo folder : mBgDataModel.folders) {
            Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR);
            verifier.setFolderInfo(folder);
            int size = folder.contents.size();
            // for now. Database will be updated once user manually modifies folder.
            for (int rank = 0; rank < size; ++rank) {
                WorkspaceItemInfo info = folder.contents.get(rank);
                info.rank = rank;
                if (info.usingLowResIcon() && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && verifier.isItemInPreview(info.rank)) {
                    mIconCache.getTitleAndIcon(info, false);
                }
            }
        }
        c.commitRestoredItems();
    }
}
Also used : LongSparseArray(android.util.LongSparseArray) HashMap(java.util.HashMap) ComponentKey(com.android.launcher3.util.ComponentKey) SessionInfo(android.content.pm.PackageInstaller.SessionInfo) ShortcutKey(com.android.launcher3.shortcuts.ShortcutKey) ShortcutRequest(com.android.launcher3.shortcuts.ShortcutRequest) ContentResolver(android.content.ContentResolver) QueryResult(com.android.launcher3.shortcuts.ShortcutRequest.QueryResult) UserHandle(android.os.UserHandle) FolderGridOrganizer(com.android.launcher3.folder.FolderGridOrganizer) AppWidgetProviderInfo(android.appwidget.AppWidgetProviderInfo) LauncherAppWidgetProviderInfo(com.android.launcher3.widget.LauncherAppWidgetProviderInfo) WidgetManagerHelper(com.android.launcher3.widget.WidgetManagerHelper) PackageManagerHelper(com.android.launcher3.util.PackageManagerHelper) ComponentName(android.content.ComponentName) Context(android.content.Context) LauncherAppWidgetProviderInfo(com.android.launcher3.widget.LauncherAppWidgetProviderInfo) ComponentWithIconCachingLogic(com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic) LauncherActivityCachingLogic(com.android.launcher3.icons.LauncherActivityCachingLogic) ShortcutCachingLogic(com.android.launcher3.icons.ShortcutCachingLogic) ShortcutInfo(android.content.pm.ShortcutInfo) Bundle(android.os.Bundle) PackageUserKey(com.android.launcher3.util.PackageUserKey) LauncherAppWidgetInfo(com.android.launcher3.model.data.LauncherAppWidgetInfo) Intent(android.content.Intent) FolderInfo(com.android.launcher3.model.data.FolderInfo) CancellationException(java.util.concurrent.CancellationException) SuppressLint(android.annotation.SuppressLint) Point(android.graphics.Point) LauncherActivityInfo(android.content.pm.LauncherActivityInfo) WorkspaceItemInfo(com.android.launcher3.model.data.WorkspaceItemInfo)

Example 2 with PINNED

use of com.android.launcher3.shortcuts.ShortcutRequest.PINNED in project android_packages_apps_Launcher3 by crdroidandroid.

the class BgDataModel method updateShortcutPinnedState.

/**
 * Updates the deep shortucts state in system to match out internal model, pinning any missing
 * shortcuts and unpinning any extra shortcuts.
 */
public synchronized void updateShortcutPinnedState(Context context, UserHandle user) {
    if (GO_DISABLE_WIDGETS) {
        return;
    }
    // Collect all system shortcuts
    QueryResult result = new ShortcutRequest(context, user).query(PINNED | FLAG_GET_KEY_FIELDS_ONLY);
    if (!result.wasSuccess()) {
        return;
    }
    // Map of packageName to shortcutIds that are currently in the system
    Map<String, Set<String>> systemMap = result.stream().collect(groupingBy(ShortcutInfo::getPackage, mapping(ShortcutInfo::getId, Collectors.toSet())));
    // Collect all model shortcuts
    Stream.Builder<WorkspaceItemInfo> itemStream = Stream.builder();
    forAllWorkspaceItemInfos(user, itemStream::accept);
    // Map of packageName to shortcutIds that are currently in our model
    Map<String, Set<String>> modelMap = Stream.concat(// Model shortcuts
    itemStream.build().filter(wi -> wi.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT).map(ShortcutKey::fromItemInfo), // Pending shortcuts
    ItemInstallQueue.INSTANCE.get(context).getPendingShortcuts(user)).collect(groupingBy(ShortcutKey::getPackageName, mapping(ShortcutKey::getId, Collectors.toSet())));
    // Check for diff
    for (Map.Entry<String, Set<String>> entry : modelMap.entrySet()) {
        Set<String> modelShortcuts = entry.getValue();
        Set<String> systemShortcuts = systemMap.remove(entry.getKey());
        if (systemShortcuts == null) {
            systemShortcuts = Collections.emptySet();
        }
        // Do not use .equals as it can vary based on the type of set
        if (systemShortcuts.size() != modelShortcuts.size() || !systemShortcuts.containsAll(modelShortcuts)) {
            // Update system state for this package
            try {
                context.getSystemService(LauncherApps.class).pinShortcuts(entry.getKey(), new ArrayList<>(modelShortcuts), user);
            } catch (SecurityException | IllegalStateException e) {
                Log.w(TAG, "Failed to pin shortcut", e);
            }
        }
    }
    // If there are any extra pinned shortcuts, remove them
    systemMap.keySet().forEach(packageName -> {
        // Update system state
        try {
            context.getSystemService(LauncherApps.class).pinShortcuts(packageName, Collections.emptyList(), user);
        } catch (SecurityException | IllegalStateException e) {
            Log.w(TAG, "Failed to unpin shortcut", e);
        }
    });
}
Also used : Context(android.content.Context) Arrays(java.util.Arrays) AppInfo(com.android.launcher3.model.data.AppInfo) ViewOnDrawExecutor(com.android.launcher3.util.ViewOnDrawExecutor) ItemInfo(com.android.launcher3.model.data.ItemInfo) Collectors.groupingBy(java.util.stream.Collectors.groupingBy) HashMap(java.util.HashMap) LauncherSettings(com.android.launcher3.LauncherSettings) ShortcutKey(com.android.launcher3.shortcuts.ShortcutKey) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) WorkspaceItemInfo(com.android.launcher3.model.data.WorkspaceItemInfo) Collectors.mapping(java.util.stream.Collectors.mapping) UserHandle(android.os.UserHandle) Map(java.util.Map) FolderInfo(com.android.launcher3.model.data.FolderInfo) ArraySet(android.util.ArraySet) Log(android.util.Log) PrintWriter(java.io.PrintWriter) GO_DISABLE_WIDGETS(com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS) IntArray(com.android.launcher3.util.IntArray) PINNED(com.android.launcher3.shortcuts.ShortcutRequest.PINNED) FLAG_GET_KEY_FIELDS_ONLY(android.content.pm.LauncherApps.ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) Favorites(com.android.launcher3.LauncherSettings.Favorites) Iterator(java.util.Iterator) ShortcutInfo(android.content.pm.ShortcutInfo) LauncherAppWidgetInfo(com.android.launcher3.model.data.LauncherAppWidgetInfo) Set(java.util.Set) TextUtils(android.text.TextUtils) FeatureFlags(com.android.launcher3.config.FeatureFlags) UserCache(com.android.launcher3.pm.UserCache) Collectors(java.util.stream.Collectors) LauncherApps(android.content.pm.LauncherApps) Consumer(java.util.function.Consumer) IntSet(com.android.launcher3.util.IntSet) List(java.util.List) QueryResult(com.android.launcher3.shortcuts.ShortcutRequest.QueryResult) WidgetsListBaseEntry(com.android.launcher3.widget.model.WidgetsListBaseEntry) Stream(java.util.stream.Stream) ComponentKey(com.android.launcher3.util.ComponentKey) FileDescriptor(java.io.FileDescriptor) Workspace(com.android.launcher3.Workspace) ShortcutRequest(com.android.launcher3.shortcuts.ShortcutRequest) ItemInfoMatcher(com.android.launcher3.util.ItemInfoMatcher) IntSparseArrayMap(com.android.launcher3.util.IntSparseArrayMap) Collections(java.util.Collections) HashSet(java.util.HashSet) ArraySet(android.util.ArraySet) Set(java.util.Set) IntSet(com.android.launcher3.util.IntSet) ShortcutInfo(android.content.pm.ShortcutInfo) LauncherApps(android.content.pm.LauncherApps) ShortcutRequest(com.android.launcher3.shortcuts.ShortcutRequest) ShortcutKey(com.android.launcher3.shortcuts.ShortcutKey) QueryResult(com.android.launcher3.shortcuts.ShortcutRequest.QueryResult) Stream(java.util.stream.Stream) HashMap(java.util.HashMap) Map(java.util.Map) IntSparseArrayMap(com.android.launcher3.util.IntSparseArrayMap) WorkspaceItemInfo(com.android.launcher3.model.data.WorkspaceItemInfo)

Example 3 with PINNED

use of com.android.launcher3.shortcuts.ShortcutRequest.PINNED in project android_packages_apps_Launcher3 by crdroidandroid.

the class PackageInstallStateChangedTask method execute.

@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
    if (mInstallInfo.state == PackageInstallInfo.STATUS_INSTALLED) {
        try {
            // For instant apps we do not get package-add. Use setting events to update
            // any pinned icons.
            ApplicationInfo ai = app.getContext().getPackageManager().getApplicationInfo(mInstallInfo.packageName, 0);
            if (InstantAppResolver.newInstance(app.getContext()).isInstantApp(ai)) {
                app.getModel().onPackageAdded(ai.packageName, mInstallInfo.user);
            }
        } catch (PackageManager.NameNotFoundException e) {
        // Ignore
        }
        // Ignore install success events as they are handled by Package add events.
        return;
    }
    synchronized (apps) {
        List<AppInfo> updatedAppInfos = apps.updatePromiseInstallInfo(mInstallInfo);
        if (!updatedAppInfos.isEmpty()) {
            for (AppInfo appInfo : updatedAppInfos) {
                scheduleCallbackTask(c -> c.bindIncrementalDownloadProgressUpdated(appInfo));
            }
        }
        bindApplicationsIfNeeded();
    }
    synchronized (dataModel) {
        final HashSet<ItemInfo> updates = new HashSet<>();
        dataModel.forAllWorkspaceItemInfos(mInstallInfo.user, si -> {
            if (si.hasPromiseIconUi() && mInstallInfo.packageName.equals(si.getTargetPackage())) {
                si.setProgressLevel(mInstallInfo);
                updates.add(si);
            }
        });
        for (LauncherAppWidgetInfo widget : dataModel.appWidgets) {
            if (widget.providerName.getPackageName().equals(mInstallInfo.packageName)) {
                widget.installProgress = mInstallInfo.progress;
                updates.add(widget);
            }
        }
        if (!updates.isEmpty()) {
            scheduleCallbackTask(callbacks -> callbacks.bindRestoreItemsChange(updates));
        }
    }
}
Also used : PackageManager(android.content.pm.PackageManager) ItemInfo(com.android.launcher3.model.data.ItemInfo) ApplicationInfo(android.content.pm.ApplicationInfo) LauncherAppWidgetInfo(com.android.launcher3.model.data.LauncherAppWidgetInfo) AppInfo(com.android.launcher3.model.data.AppInfo) HashSet(java.util.HashSet)

Example 4 with PINNED

use of com.android.launcher3.shortcuts.ShortcutRequest.PINNED in project android_packages_apps_Launcher3 by crdroidandroid.

the class SearchAndRecommendationsScrollController method updateMarginAndPadding.

/**
 * Updates the margin and padding of {@link WidgetsFullSheet} to accumulate collapsible views.
 *
 * @return {@code true} if margins or/and padding of views in the search and recommendations
 * container have been updated.
 */
public boolean updateMarginAndPadding() {
    boolean hasMarginOrPaddingUpdated = false;
    mCollapsibleHeightForSearch = measureHeightWithVerticalMargins(mViewHolder.mHeaderTitle);
    mCollapsibleHeightForRecommendation = measureHeightWithVerticalMargins(mViewHolder.mHeaderTitle) + measureHeightWithVerticalMargins(mViewHolder.mCollapseHandle) + measureHeightWithVerticalMargins((View) mViewHolder.mSearchBarContainer) + measureHeightWithVerticalMargins(mViewHolder.mRecommendedWidgetsTable);
    int topContainerHeight = measureHeightWithVerticalMargins(mViewHolder.mContainer);
    int noWidgetsViewHeight = topContainerHeight - mBottomInset;
    if (mHasWorkProfile) {
        mCollapsibleHeightForTabs = measureHeightWithVerticalMargins(mViewHolder.mHeaderTitle) + measureHeightWithVerticalMargins(mViewHolder.mRecommendedWidgetsTable);
        // In a work profile setup, the full widget sheet contains the following views:
        // ------- (pinned)           -|
        // Widgets (collapsible)       -|---> LinearLayout for search & recommendations
        // Search bar (pinned)         -|
        // Widgets recommendation (collapsible)-|
        // Personal | Work (pinned)
        // View Pager
        // 
        // Views after the search & recommendations are not bound by RelativelyLayout param.
        // To position them on the expected location, padding & margin are added to these views
        // Tabs should have a padding of the height of the search & recommendations container.
        RelativeLayout.LayoutParams tabsLayoutParams = (RelativeLayout.LayoutParams) mPrimaryWorkTabsView.getLayoutParams();
        tabsLayoutParams.topMargin = topContainerHeight;
        mPrimaryWorkTabsView.setLayoutParams(tabsLayoutParams);
        // Instead of setting the top offset directly, we split the top offset into two values:
        // 1. topOffsetAfterAllViewsCollapsed: this is the top offset after all collapsible
        // views are no longer visible on the screen.
        // This value is set as the margin for the view pager.
        // 2. mMaxCollapsibleDistance
        // This value is set as the padding for the recycler views in order to work with
        // clipToPadding="false", which is an attribute for not showing top / bottom padding
        // when a recycler view has not reached the top or bottom of the list.
        // e.g. a list of 10 entries, only 3 entries are visible at a time.
        // case 1: recycler view is scrolled to the top. Top padding is visible/
        // (top padding)
        // item 1
        // item 2
        // item 3
        // 
        // case 2: recycler view is scrolled to the middle. No padding is visible.
        // item 4
        // item 5
        // item 6
        // 
        // case 3: recycler view is scrolled to the end. bottom padding is visible.
        // item 8
        // item 9
        // item 10
        // (bottom padding): not set in this case.
        // 
        // When the views are first inflated, the sum of topOffsetAfterAllViewsCollapsed and
        // mMaxCollapsibleDistance should equal to the top container height.
        int topOffsetAfterAllViewsCollapsed = topContainerHeight + mTabsHeight - mCollapsibleHeightForTabs;
        if (mPrimaryWorkTabsView.getVisibility() == View.VISIBLE) {
            noWidgetsViewHeight += mTabsHeight;
        }
        RelativeLayout.LayoutParams viewPagerLayoutParams = (RelativeLayout.LayoutParams) mPrimaryWorkViewPager.getLayoutParams();
        if (viewPagerLayoutParams.topMargin != topOffsetAfterAllViewsCollapsed) {
            viewPagerLayoutParams.topMargin = topOffsetAfterAllViewsCollapsed;
            mPrimaryWorkViewPager.setLayoutParams(viewPagerLayoutParams);
            hasMarginOrPaddingUpdated = true;
        }
        if (mPrimaryRecyclerView.getPaddingTop() != mCollapsibleHeightForTabs) {
            mPrimaryRecyclerView.setPadding(mPrimaryRecyclerView.getPaddingLeft(), mCollapsibleHeightForTabs, mPrimaryRecyclerView.getPaddingRight(), mPrimaryRecyclerView.getPaddingBottom());
            hasMarginOrPaddingUpdated = true;
        }
        if (mWorkRecyclerView.getPaddingTop() != mCollapsibleHeightForTabs) {
            mWorkRecyclerView.setPadding(mWorkRecyclerView.getPaddingLeft(), mCollapsibleHeightForTabs, mWorkRecyclerView.getPaddingRight(), mWorkRecyclerView.getPaddingBottom());
            hasMarginOrPaddingUpdated = true;
        }
    } else {
        if (mPrimaryRecyclerView.getPaddingTop() != topContainerHeight) {
            mPrimaryRecyclerView.setPadding(mPrimaryRecyclerView.getPaddingLeft(), topContainerHeight, mPrimaryRecyclerView.getPaddingRight(), mPrimaryRecyclerView.getPaddingBottom());
            hasMarginOrPaddingUpdated = true;
        }
    }
    if (mSearchRecyclerView.getPaddingTop() != topContainerHeight) {
        mSearchRecyclerView.setPadding(mSearchRecyclerView.getPaddingLeft(), topContainerHeight, mSearchRecyclerView.getPaddingRight(), mSearchRecyclerView.getPaddingBottom());
        hasMarginOrPaddingUpdated = true;
    }
    if (mNoWidgetsView.getPaddingTop() != noWidgetsViewHeight) {
        mNoWidgetsView.setPadding(mNoWidgetsView.getPaddingLeft(), noWidgetsViewHeight, mNoWidgetsView.getPaddingRight(), mNoWidgetsView.getPaddingBottom());
        hasMarginOrPaddingUpdated = true;
    }
    return hasMarginOrPaddingUpdated;
}
Also used : MarginLayoutParams(android.view.ViewGroup.MarginLayoutParams) RelativeLayout(android.widget.RelativeLayout) TextView(android.widget.TextView) PersonalWorkPagedView(com.android.launcher3.workprofile.PersonalWorkPagedView) View(android.view.View) Point(android.graphics.Point)

Example 5 with PINNED

use of com.android.launcher3.shortcuts.ShortcutRequest.PINNED in project android_packages_apps_Launcher3 by crdroidandroid.

the class RecentsView method addDismissedTaskAnimations.

private void addDismissedTaskAnimations(TaskView taskView, long duration, PendingAnimation anim) {
    // Use setFloat instead of setViewAlpha as we want to keep the view visible even when it's
    // alpha is set to 0 so that it can be recycled in the view pool properly
    anim.setFloat(taskView, VIEW_ALPHA, 0, clampToProgress(ACCEL, 0, 0.5f));
    SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
    ResourceProvider rp = DynamicResource.provider(mActivity);
    SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_START).setDampingRatio(rp.getFloat(R.dimen.dismiss_task_trans_y_damping_ratio)).setStiffness(rp.getFloat(R.dimen.dismiss_task_trans_y_stiffness));
    FloatProperty<TaskView> dismissingTaskViewTranslate = taskView.getSecondaryDissmissTranslationProperty();
    // TODO(b/186800707) translate entire grid size distance
    int translateDistance = mOrientationHandler.getSecondaryDimension(taskView);
    int positiveNegativeFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
    if (splitController.isSplitSelectActive()) {
        // Have the task translate towards whatever side was just pinned
        int dir = mOrientationHandler.getSplitTaskViewDismissDirection(splitController.getActiveSplitPositionOption(), mActivity.getDeviceProfile());
        switch(dir) {
            case PagedOrientationHandler.SPLIT_TRANSLATE_SECONDARY_NEGATIVE:
                dismissingTaskViewTranslate = taskView.getSecondaryDissmissTranslationProperty();
                positiveNegativeFactor = -1;
                break;
            case PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_POSITIVE:
                dismissingTaskViewTranslate = taskView.getPrimaryDismissTranslationProperty();
                positiveNegativeFactor = 1;
                break;
            case PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_NEGATIVE:
                dismissingTaskViewTranslate = taskView.getPrimaryDismissTranslationProperty();
                positiveNegativeFactor = -1;
                break;
            default:
                throw new IllegalStateException("Invalid split task translation: " + dir);
        }
    }
    // Double translation distance so dismissal drag is the full height, as we only animate
    // the drag for the first half of the progress.
    anim.add(ObjectAnimator.ofFloat(taskView, dismissingTaskViewTranslate, positiveNegativeFactor * translateDistance * 2).setDuration(duration), LINEAR, sp);
    if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
        anim.addOnFrameCallback(() -> {
            mLiveTileTaskViewSimulator.taskSecondaryTranslation.value = mOrientationHandler.getSecondaryValue(taskView.getTranslationX(), taskView.getTranslationY());
            redrawLiveTile();
        });
    }
}
Also used : SpringProperty(com.android.launcher3.anim.SpringProperty) ResourceProvider(com.android.systemui.plugins.ResourceProvider) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) TextPaint(android.text.TextPaint) Point(android.graphics.Point)

Aggregations

Point (android.graphics.Point)3 LauncherAppWidgetInfo (com.android.launcher3.model.data.LauncherAppWidgetInfo)3 Context (android.content.Context)2 ShortcutInfo (android.content.pm.ShortcutInfo)2 UserHandle (android.os.UserHandle)2 AppInfo (com.android.launcher3.model.data.AppInfo)2 FolderInfo (com.android.launcher3.model.data.FolderInfo)2 ItemInfo (com.android.launcher3.model.data.ItemInfo)2 WorkspaceItemInfo (com.android.launcher3.model.data.WorkspaceItemInfo)2 ShortcutKey (com.android.launcher3.shortcuts.ShortcutKey)2 ShortcutRequest (com.android.launcher3.shortcuts.ShortcutRequest)2 QueryResult (com.android.launcher3.shortcuts.ShortcutRequest.QueryResult)2 ComponentKey (com.android.launcher3.util.ComponentKey)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 SuppressLint (android.annotation.SuppressLint)1 AppWidgetProviderInfo (android.appwidget.AppWidgetProviderInfo)1 ComponentName (android.content.ComponentName)1 ContentResolver (android.content.ContentResolver)1 Intent (android.content.Intent)1