diff options
Diffstat (limited to 'src/com/android/launcher3/model')
17 files changed, 248 insertions, 96 deletions
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index 8f85bfbd3d..190eb78d2a 100644 --- a/src/com/android/launcher3/model/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -79,6 +79,8 @@ public class AllAppsList { * @see Callbacks#FLAG_HAS_SHORTCUT_PERMISSION * @see Callbacks#FLAG_QUIET_MODE_ENABLED * @see Callbacks#FLAG_QUIET_MODE_CHANGE_PERMISSION + * @see Callbacks#FLAG_WORK_PROFILE_QUIET_MODE_ENABLED + * @see Callbacks#FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED */ private int mFlags; diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java index dbb29b8864..9b2344d2ad 100644 --- a/src/com/android/launcher3/model/BaseLauncherBinder.java +++ b/src/com/android/launcher3/model/BaseLauncherBinder.java @@ -16,6 +16,7 @@ package com.android.launcher3.model; +import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL; import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; @@ -172,6 +173,11 @@ public abstract class BaseLauncherBinder { public abstract void bindWidgets(); /** + * bindWidgets is abstract because it is a no-op for the go launcher. + */ + public abstract void bindSmartspaceWidget(); + + /** * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right) */ protected void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile, @@ -288,6 +294,10 @@ public abstract class BaseLauncherBinder { executeCallbacksTask(c -> { c.clearPendingBinds(); c.startBinding(); + if (ENABLE_SMARTSPACE_REMOVAL.get()) { + c.setIsFirstPagePinnedItemEnabled( + mBgDataModel.isFirstPagePinnedItemEnabled); + } }, mUiExecutor); // Bind workspace screens @@ -305,6 +315,10 @@ public abstract class BaseLauncherBinder { Executor pendingExecutor = pendingTasks::add; bindWorkspaceItems(otherWorkspaceItems, pendingExecutor); bindAppWidgets(otherAppWidgets, pendingExecutor); + + StringCache cacheClone = mBgDataModel.stringCache.clone(); + executeCallbacksTask(c -> c.bindStringCache(cacheClone), pendingExecutor); + executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor); pendingExecutor.execute( () -> { @@ -319,9 +333,6 @@ public abstract class BaseLauncherBinder { c.onInitialBindComplete( currentScreenIds, pendingTasks, workspaceItemCount, isBindSync); }, mUiExecutor); - - StringCache cacheClone = mBgDataModel.stringCache.clone(); - executeCallbacksTask(c -> c.bindStringCache(cacheClone), pendingExecutor); } private void bindWorkspaceItems( diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java index 97f540e1db..529c30ae69 100644 --- a/src/com/android/launcher3/model/BaseModelUpdateTask.java +++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java @@ -101,8 +101,7 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask { public ModelWriter getModelWriter() { // Updates from model task, do not deal with icon position in hotseat. Also no need to // verify changes as the ModelTasks always push the changes to callbacks - return mModel.getWriter(false /* hasVerticalHotseat */, false /* verifyChanges */, - CellPosMapper.DEFAULT, null); + return mModel.getWriter(false /* verifyChanges */, CellPosMapper.DEFAULT, null); } public void bindUpdatedWorkspaceItems(@NonNull final List<WorkspaceItemInfo> allUpdates) { diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index 7bcd03863c..7f0f683091 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -17,6 +17,9 @@ package com.android.launcher3.model; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY; +import static com.android.launcher3.BuildConfig.QSB_ON_FIRST_SCREEN; +import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL; +import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget; import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS; import static com.android.launcher3.shortcuts.ShortcutRequest.PINNED; @@ -129,6 +132,8 @@ public class BgDataModel { * Load id for which the callbacks were successfully bound */ public int lastLoadId = -1; + public boolean isFirstPagePinnedItemEnabled = QSB_ON_FIRST_SCREEN + && !ENABLE_SMARTSPACE_REMOVAL.get(); /** * Clears all the data @@ -152,7 +157,9 @@ public class BgDataModel { screenSet.add(item.screenId); } } - if (FeatureFlags.QSB_ON_FIRST_SCREEN || screenSet.isEmpty()) { + if ((FeatureFlags.QSB_ON_FIRST_SCREEN + && !shouldShowFirstPageWidget()) + || screenSet.isEmpty()) { screenSet.add(Workspace.FIRST_SCREEN_ID); } return screenSet.getArray(); @@ -170,11 +177,15 @@ public class BgDataModel { writer.println(prefix + '\t' + appWidgets.get(i).toString()); } writer.println(prefix + " ---- folder items "); - for (int i = 0; i< folders.size(); i++) { + for (int i = 0; i < folders.size(); i++) { writer.println(prefix + '\t' + folders.valueAt(i).toString()); } + writer.println(prefix + " ---- extra items "); + for (int i = 0; i < extraItems.size(); i++) { + writer.println(prefix + '\t' + extraItems.valueAt(i).toString()); + } writer.println(prefix + " ---- items id map "); - for (int i = 0; i< itemsIdMap.size(); i++) { + for (int i = 0; i < itemsIdMap.size(); i++) { writer.println(prefix + '\t' + itemsIdMap.valueAt(i).toString()); } @@ -442,6 +453,20 @@ public class BgDataModel { this.containerId = containerId; this.items = Collections.unmodifiableList(items); } + + @Override + @NonNull + public final String toString() { + StringBuilder s = new StringBuilder(); + s.append("FixedContainerItems:"); + s.append(" id=").append(containerId); + s.append(" itemCount=").append(items.size()); + for (int i = 0; i < items.size(); i++) { + s.append(" item #").append(i).append(": ").append(items.get(i).toString()); + } + return s.toString(); + } + } @@ -452,6 +477,10 @@ public class BgDataModel { int FLAG_QUIET_MODE_ENABLED = 1 << 1; // If launcher can change quiet mode int FLAG_QUIET_MODE_CHANGE_PERMISSION = 1 << 2; + // If quiet mode is enabled for work profile user + int FLAG_WORK_PROFILE_QUIET_MODE_ENABLED = 1 << 3; + // If quiet mode is enabled for private profile user + int FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED = 1 << 4; /** * Returns an IntSet of page ids to bind first, synchronously if possible @@ -468,6 +497,7 @@ public class BgDataModel { default void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons) { } default void bindScreens(IntArray orderedScreenIds) { } + default void setIsFirstPagePinnedItemEnabled(boolean isFirstPagePinnedItemEnabled) { } default void finishBindingItems(IntSet pagesBoundFirst) { } default void preAddApps() { } default void bindAppsAdded(IntArray newScreens, @@ -487,6 +517,7 @@ public class BgDataModel { default void bindRestoreItemsChange(HashSet<ItemInfo> updates) { } default void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) { } default void bindAllWidgets(List<WidgetsListBaseEntry> widgets) { } + default void bindSmartspaceWidget() { } /** Called when workspace has been bound. */ default void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks, diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java index ecf5f67a97..13605101e7 100644 --- a/src/com/android/launcher3/model/DatabaseHelper.java +++ b/src/com/android/launcher3/model/DatabaseHelper.java @@ -16,6 +16,7 @@ package com.android.launcher3.model; import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb; +import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; import android.content.ContentValues; @@ -257,7 +258,8 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements Favorites.SCREEN, IntArray.wrap(-777, -778)), null); } case 30: { - if (FeatureFlags.QSB_ON_FIRST_SCREEN) { + if (FeatureFlags.QSB_ON_FIRST_SCREEN + && !shouldShowFirstPageWidget()) { // Clean up first row in screen 0 as it might contain junk data. Log.d(TAG, "Cleaning up first row"); db.delete(Favorites.TABLE_NAME, @@ -267,7 +269,6 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP, Favorites.CELLY, 0), null); } - return; } case 31: { LauncherDbUtils.migrateLegacyShortcuts(mContext, db); diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java index c233872cc5..efd5574519 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java +++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java @@ -18,6 +18,9 @@ package com.android.launcher3.model; import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; import static com.android.launcher3.LauncherSettings.Favorites.TMP_TABLE; +import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL; +import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget; +import static com.android.launcher3.model.LoaderTask.SMARTSPACE_ON_HOME_SCREEN; import static com.android.launcher3.provider.LauncherDbUtils.copyTable; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; @@ -37,6 +40,7 @@ import android.util.Log; import androidx.annotation.NonNull; import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; @@ -327,7 +331,11 @@ public class GridSizeMigrationUtil { @NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) { final GridOccupancy occupied = new GridOccupancy(trgX, trgY); final Point trg = new Point(trgX, trgY); - final Point next = new Point(0, screenId == 0 && FeatureFlags.QSB_ON_FIRST_SCREEN + final Point next = new Point(0, screenId == 0 + && (FeatureFlags.QSB_ON_FIRST_SCREEN + && (!ENABLE_SMARTSPACE_REMOVAL.get() || LauncherPrefs.getPrefs(destReader.mContext) + .getBoolean(SMARTSPACE_ON_HOME_SCREEN, true)) + && !shouldShowFirstPageWidget()) ? 1 /* smartspace */ : 0); List<DbEntry> existedEntries = destReader.mWorkspaceEntriesByScreenId.get(screenId); if (existedEntries != null) { @@ -465,6 +473,13 @@ public class GridSizeMigrationUtil { } break; } + case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR: { + int total = getFolderItemsCount(entry); + if (total != 2) { + throw new Exception("App pair contains fewer or more than 2 items"); + } + break; + } default: throw new Exception("Invalid item type"); } @@ -539,8 +554,8 @@ public class GridSizeMigrationUtil { verifyPackage(cn.getPackageName()); int widgetId = c.getInt(indexAppWidgetId); - LauncherAppWidgetProviderInfo pInfo = - widgetManagerHelper.getLauncherAppWidgetInfo(widgetId); + LauncherAppWidgetProviderInfo pInfo = widgetManagerHelper + .getLauncherAppWidgetInfo(widgetId, cn); Point spans = null; if (pInfo != null) { spans = pInfo.getMinSpans(); @@ -562,6 +577,13 @@ public class GridSizeMigrationUtil { } break; } + case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR: { + int total = getFolderItemsCount(entry); + if (total != 2) { + throw new Exception("App pair contains fewer or more than 2 items"); + } + break; + } default: throw new Exception("Invalid item type"); } @@ -679,6 +701,7 @@ public class GridSizeMigrationUtil { public String getEntryMigrationId() { switch (itemType) { case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: + case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR: return getFolderMigrationId(); case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: return mProvider; diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index 33332f01ed..4370043569 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -17,6 +17,7 @@ package com.android.launcher3.model; import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; +import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget; import android.content.ComponentName; import android.content.ContentValues; @@ -470,7 +471,7 @@ public class LoaderCursor extends CursorWrapper { // cause the item loading to get skipped ShortcutKey.fromItemInfo(info); } - if (checkItemPlacement(info)) { + if (checkItemPlacement(info, dataModel.isFirstPagePinnedItemEnabled)) { dataModel.addItem(mContext, info, false, logger); } else { markDeleted("Item position overlap"); @@ -480,7 +481,7 @@ public class LoaderCursor extends CursorWrapper { /** * check & update map of what's occupied; used to discard overlapping/invalid items */ - protected boolean checkItemPlacement(ItemInfo item) { + protected boolean checkItemPlacement(ItemInfo item, boolean isFirstPagePinnedItemEnabled) { int containerIndex = item.screenId; if (item.container == Favorites.CONTAINER_HOTSEAT) { final GridOccupancy hotseatOccupancy = @@ -528,7 +529,8 @@ public class LoaderCursor extends CursorWrapper { if (!mOccupied.containsKey(item.screenId)) { GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1); - if (item.screenId == Workspace.FIRST_SCREEN_ID && FeatureFlags.QSB_ON_FIRST_SCREEN) { + if (item.screenId == Workspace.FIRST_SCREEN_ID && (FeatureFlags.QSB_ON_FIRST_SCREEN + && !shouldShowFirstPageWidget() && isFirstPagePinnedItemEnabled)) { // Mark the first X columns (X is width of the search container) in the first row as // occupied (if the feature is enabled) in order to account for the search // container. diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 0e68db29e8..a98ec6484a 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -16,10 +16,17 @@ package com.android.launcher3.model; +import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN; +import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE; +import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR; import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; +import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL; +import static com.android.launcher3.config.FeatureFlags.SMARTSPACE_AS_A_WIDGET; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED; +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE; @@ -52,11 +59,14 @@ import android.util.LongSparseArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; +import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; @@ -95,6 +105,7 @@ import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.WidgetManagerHelper; +import com.android.launcher3.widget.custom.CustomWidgetManager; import java.util.ArrayList; import java.util.Collections; @@ -114,6 +125,7 @@ import java.util.concurrent.CancellationException; */ public class LoaderTask implements Runnable { private static final String TAG = "LoaderTask"; + public static final String SMARTSPACE_ON_HOME_SCREEN = "pref_smartspace_home_screen"; private static final boolean DEBUG = true; @@ -135,7 +147,7 @@ public class LoaderTask implements Runnable { private final InstallSessionHelper mSessionHelper; private final IconCache mIconCache; - private final UserManagerState mUserManagerState = new UserManagerState(); + private final UserManagerState mUserManagerState; protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>(); private Map<ShortcutKey, ShortcutInfo> mShortcutKeyToPinnedShortcuts; @@ -148,6 +160,13 @@ public class LoaderTask implements Runnable { public LoaderTask(@NonNull LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel bgModel, ModelDelegate modelDelegate, @NonNull LauncherBinder launcherBinder) { + this(app, bgAllAppsList, bgModel, modelDelegate, launcherBinder, new UserManagerState()); + } + + @VisibleForTesting + LoaderTask(@NonNull LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel bgModel, + ModelDelegate modelDelegate, @NonNull LauncherBinder launcherBinder, + UserManagerState userManagerState) { mApp = app; mBgAllAppsList = bgAllAppsList; mBgDataModel = bgModel; @@ -156,9 +175,10 @@ public class LoaderTask implements Runnable { mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class); mUserManager = mApp.getContext().getSystemService(UserManager.class); - mUserCache = UserCache.INSTANCE.get(mApp.getContext()); + mUserCache = UserCache.getInstance(mApp.getContext()); mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext()); mIconCache = mApp.getIconCache(); + mUserManagerState = userManagerState; } protected synchronized void waitForIdle() { @@ -295,6 +315,19 @@ public class LoaderTask implements Runnable { logASplit("bindWidgets"); verifyNotStopped(); + LauncherPrefs prefs = LauncherPrefs.get(mApp.getContext()); + if (SMARTSPACE_AS_A_WIDGET.get() && prefs.get(SHOULD_SHOW_SMARTSPACE)) { + mLauncherBinder.bindSmartspaceWidget(); + // Turn off pref. + prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(false)); + logASplit("bindSmartspaceWidget"); + verifyNotStopped(); + } else if (!SMARTSPACE_AS_A_WIDGET.get() && WIDGET_ON_FIRST_SCREEN + && !prefs.get(LauncherPrefs.SHOULD_SHOW_SMARTSPACE)) { + // Turn on pref. + prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(true)); + } + if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) { mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList); logASplit("otherDelegateItems"); @@ -350,6 +383,9 @@ public class LoaderTask implements Runnable { mModelDelegate.markActive(); logASplit("workspaceDelegateItems"); } + mBgDataModel.isFirstPagePinnedItemEnabled = FeatureFlags.QSB_ON_FIRST_SCREEN + && (!ENABLE_SMARTSPACE_REMOVAL.get() || LauncherPrefs.getPrefs( + mApp.getContext()).getBoolean(SMARTSPACE_ON_HOME_SCREEN, true)); } private void loadWorkspaceImpl( @@ -375,7 +411,7 @@ public class LoaderTask implements Runnable { mSessionHelper.getActiveSessions(); installingPkgs.forEach(mApp.getIconCache()::updateSessionCache); FileLog.d(TAG, "loadWorkspace: Packages with active install sessions: " - + installingPkgs.values()); + + installingPkgs.keySet().stream().map(info -> info.mPackageName).toList()); final PackageUserKey tempPackageKey = new PackageUserKey(null, null); mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs); @@ -404,10 +440,15 @@ public class LoaderTask implements Runnable { mShortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut); } + if (pinnedShortcuts.isEmpty()) { + FileLog.d(TAG, "No pinned shortcuts found for user " + user); + } } 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. + FileLog.d(TAG, "Shortcut request failed for user " + + user + ", user may still be locked."); userUnlocked = false; } } @@ -445,23 +486,27 @@ public class LoaderTask implements Runnable { mItemsDeleted = c.commitDeleted(); // Sort the folder items, update ranks, and make sure all preview items are high res. - FolderGridOrganizer verifier = - new FolderGridOrganizer(mApp.getInvariantDeviceProfile()); + List<FolderGridOrganizer> verifiers = + mApp.getInvariantDeviceProfile().supportedProfiles.stream().map( + FolderGridOrganizer::new).toList(); for (FolderInfo folder : mBgDataModel.folders) { Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR); - verifier.setFolderInfo(folder); + verifiers.forEach(verifier -> verifier.setFolderInfo(folder)); int size = folder.contents.size(); // Update ranks here to ensure there are no gaps caused by removed folder items. - // Ranks are the source of truth for folder items, so cellX and cellY can be ignored - // for now. Database will be updated once user manually modifies folder. + // Ranks are the source of truth for folder items, so cellX and cellY can be + // ignored 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; + // rank is used differently in app pairs, so don't reset + if (folder.itemType != ITEM_TYPE_APP_PAIR) { + info.rank = rank; + } - if (info.usingLowResIcon() - && info.itemType == Favorites.ITEM_TYPE_APPLICATION - && verifier.isItemInPreview(info.rank)) { + if (info.usingLowResIcon() && info.itemType == Favorites.ITEM_TYPE_APPLICATION + && verifiers.stream().anyMatch( + verifier -> verifier.isItemInPreview(info.rank))) { mIconCache.getTitleAndIcon(info, false); } } @@ -550,17 +595,17 @@ public class LoaderTask implements Runnable { // 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(Favorites.RESTORED, - c.restoreFlag).commit(); + FileLog.d(TAG, "restore started for installing app: " + targetPkg); + c.updater().put(Favorites.RESTORED, c.restoreFlag).commit(); } else { - c.markDeleted("Unrestored app removed: " + targetPkg); + c.markDeleted("removing app that is not restored and not " + + "installing. package: " + targetPkg); return; } } else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) { @@ -571,7 +616,7 @@ public class LoaderTask implements Runnable { } 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); + Log.d(TAG, "Missing package, will check later: " + targetPkg); mPendingPackages.add(new PackageUserKey(targetPkg, c.user)); // Add the icon on the workspace anyway. allowMissingTarget = true; @@ -607,7 +652,8 @@ public class LoaderTask implements Runnable { ShortcutInfo pinnedShortcut = mShortcutKeyToPinnedShortcuts.get(key); if (pinnedShortcut == null) { // The shortcut is no longer valid. - c.markDeleted("Pinned shortcut not found"); + c.markDeleted("Pinned shortcut not found for package: " + + key.getPackageName()); return; } info = new WorkspaceItemInfo(pinnedShortcut, mApp.getContext()); @@ -740,8 +786,13 @@ public class LoaderTask implements Runnable { ComponentKey providerKey = new ComponentKey(component, c.user); if (!mWidgetProvidersMap.containsKey(providerKey)) { - mWidgetProvidersMap.put(providerKey, - widgetHelper.findProvider(component, c.user)); + if (customWidget) { + mWidgetProvidersMap.put(providerKey, CustomWidgetManager.INSTANCE + .get(mApp.getContext()).getWidgetProvider(component)); + } else { + mWidgetProvidersMap.put(providerKey, + widgetHelper.findProvider(component, c.user)); + } } final AppWidgetProviderInfo provider = mWidgetProvidersMap.get(providerKey); @@ -772,7 +823,7 @@ public class LoaderTask implements Runnable { } else { Log.v(TAG, "Widget restore pending id=" + c.id + " appWidgetId=" + appWidgetId - + " status =" + c.restoreFlag); + + " status=" + c.restoreFlag); appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, component); appWidgetInfo.restoreStatus = c.restoreFlag; @@ -814,7 +865,8 @@ public class LoaderTask implements Runnable { return; } LauncherAppWidgetProviderInfo widgetProviderInfo = - widgetHelper.getLauncherAppWidgetInfo(appWidgetId); + widgetHelper.getLauncherAppWidgetInfo(appWidgetId, + appWidgetInfo.getTargetComponent()); if (widgetProviderInfo != null && (appWidgetInfo.spanX < widgetProviderInfo.minSpanX || appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) { @@ -940,6 +992,8 @@ public class LoaderTask implements Runnable { mBgAllAppsList.clear(); List<IconRequestInfo<AppInfo>> iconRequestInfos = new ArrayList<>(); + boolean isWorkProfileQuiet = false; + boolean isPrivateProfileQuiet = false; for (UserHandle user : profiles) { // Query for the set of apps final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user); @@ -949,6 +1003,14 @@ public class LoaderTask implements Runnable { return allActivityList; } boolean quietMode = mUserManagerState.isUserQuiet(user); + + if (Flags.enablePrivateSpace()) { + if (mUserCache.getUserInfo(user).isWork()) { + isWorkProfileQuiet = quietMode; + } else if (mUserCache.getUserInfo(user).isPrivate()) { + isPrivateProfileQuiet = quietMode; + } + } // Create the ApplicationInfos for (int i = 0; i < apps.size(); i++) { LauncherActivityInfo app = apps.get(i); @@ -990,8 +1052,13 @@ public class LoaderTask implements Runnable { Trace.endSection(); } - mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED, - mUserManagerState.isAnyProfileQuietModeEnabled()); + if (Flags.enablePrivateSpace()) { + mBgAllAppsList.setFlags(FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, isWorkProfileQuiet); + mBgAllAppsList.setFlags(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, isPrivateProfileQuiet); + } else { + mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED, + mUserManagerState.isAnyProfileQuietModeEnabled()); + } mBgAllAppsList.setFlags(FLAG_HAS_SHORTCUT_PERMISSION, hasShortcutsPermission(mApp.getContext())); mBgAllAppsList.setFlags(FLAG_QUIET_MODE_CHANGE_PERMISSION, diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java index e10e72d61b..d2b7161697 100644 --- a/src/com/android/launcher3/model/ModelDbController.java +++ b/src/com/android/launcher3/model/ModelDbController.java @@ -54,6 +54,7 @@ import com.android.launcher3.AutoInstallsLayout; import com.android.launcher3.AutoInstallsLayout.SourceResources; import com.android.launcher3.ConstantItem; import com.android.launcher3.DefaultLayoutParser; +import com.android.launcher3.EncryptionType; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherFiles; @@ -61,6 +62,7 @@ import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; +import com.android.launcher3.logging.FileLog; import com.android.launcher3.pm.UserCache; import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; @@ -261,7 +263,7 @@ public class ModelDbController { */ public void tryMigrateDB() { if (!migrateGridIfNeeded()) { - Log.d(TAG, "Migration failed: resetting launcher database"); + FileLog.d(TAG, "Migration failed: resetting launcher database"); createEmptyDB(); LauncherPrefs.get(mContext).putSync( getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()).to(true)); @@ -281,15 +283,17 @@ public class ModelDbController { createDbIfNotExists(); if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey())) { // If we have already create a new DB, ignore migration + Log.d(TAG, "migrateGridIfNeeded: new DB already created, skipping migration"); return false; } InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext); if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) { + Log.d(TAG, "migrateGridIfNeeded: no grid migration needed"); return true; } String targetDbName = new DeviceGridState(idp).getDbFile(); if (TextUtils.equals(targetDbName, mOpenHelper.getDatabaseName())) { - Log.e(TAG, "migrateGridIfNeeded - target db is same as current: " + targetDbName); + Log.e(TAG, "migrateGridIfNeeded: target db is same as current: " + targetDbName); return false; } DatabaseHelper oldHelper = mOpenHelper; @@ -298,6 +302,9 @@ public class ModelDbController { try { return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, idp, mOpenHelper, oldHelper.getWritableDatabase()); + } catch (Exception e) { + FileLog.e(TAG, "Failed to migrate grid", e); + return false; } finally { if (mOpenHelper != oldHelper) { oldHelper.close(); @@ -499,11 +506,11 @@ public class ModelDbController { private ConstantItem<Boolean> getEmptyDbCreatedKey(String dbName) { if (mContext instanceof SandboxContext) { return LauncherPrefs.nonRestorableItem(EMPTY_DATABASE_CREATED, - false /* default value */, false /* boot aware */); + false /* default value */, EncryptionType.ENCRYPTED); } String key = TextUtils.equals(dbName, LauncherFiles.LAUNCHER_DB) ? EMPTY_DATABASE_CREATED : EMPTY_DATABASE_CREATED + "@" + dbName; - return LauncherPrefs.backedUpItem(key, false /* default value */, false /* boot aware */); + return LauncherPrefs.backedUpItem(key, false /* default value */, EncryptionType.ENCRYPTED); } /** diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index 2358a9fc5f..55093a3afe 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -28,7 +28,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.CallbackTask; import com.android.launcher3.LauncherSettings.Favorites; @@ -74,7 +73,6 @@ public class ModelWriter { @Nullable private final Callbacks mOwner; - private final boolean mHasVerticalHotseat; private final boolean mVerifyChanges; // Keep track of delete operations that occur when an Undo option is present; we may not commit. @@ -83,12 +81,10 @@ public class ModelWriter { private final CellPosMapper mCellPosMapper; public ModelWriter(Context context, LauncherModel model, BgDataModel dataModel, - boolean hasVerticalHotseat, boolean verifyChanges, CellPosMapper cellPosMapper, - @Nullable Callbacks owner) { + boolean verifyChanges, CellPosMapper cellPosMapper, @Nullable Callbacks owner) { mContext = context; mModel = model; mBgDataModel = dataModel; - mHasVerticalHotseat = hasVerticalHotseat; mVerifyChanges = verifyChanges; mOwner = owner; mCellPosMapper = cellPosMapper; @@ -102,14 +98,8 @@ public class ModelWriter { item.container = container; item.cellX = modelPos.cellX; item.cellY = modelPos.cellY; - // We store hotseat items in canonical form which is this orientation invariant position - // in the hotseat - if (container == Favorites.CONTAINER_HOTSEAT) { - item.screenId = mHasVerticalHotseat - ? LauncherAppState.getIDP(mContext).numDatabaseHotseatIcons - cellY - 1 : cellX; - } else { - item.screenId = modelPos.screenId; - } + item.screenId = modelPos.screenId; + } /** diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index 2591550765..4f2d398b42 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -15,7 +15,9 @@ */ package com.android.launcher3.model; +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED; +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED; import static com.android.launcher3.model.data.WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON; import static com.android.launcher3.model.data.WorkspaceItemInfo.FLAG_RESTORED_ICON; @@ -31,7 +33,7 @@ import android.util.Log; import androidx.annotation.NonNull; -import com.android.launcher3.Launcher; +import com.android.launcher3.Flags; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; @@ -44,7 +46,6 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.PackageInstallInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutRequest; -import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; @@ -68,7 +69,8 @@ import java.util.stream.Collectors; */ public class PackageUpdatedTask extends BaseModelUpdateTask { - private static boolean DEBUG = false; + // TODO(b/290090023): Set to false after root causing is done. + private static final boolean DEBUG = true; private static final String TAG = "PackageUpdatedTask"; public static final int OP_NONE = 0; @@ -133,14 +135,6 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { iconCache.updateIconsForPkg(packages[i], mUser); activitiesLists.put( packages[i], appsList.updatePackage(context, packages[i], mUser)); - - // The update may have changed which shortcuts/widgets are available. - // Refresh the widgets for the package if we have an activity running. - Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity(); - if (launcher != null) { - launcher.refreshAndBindWidgetsForPackageUser( - new PackageUserKey(packages[i], mUser)); - } } } // Since package was just updated, the target must be available now. @@ -148,7 +142,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { break; case OP_REMOVE: { for (int i = 0; i < N; i++) { - FileLog.d(TAG, "Removing app icon" + packages[i]); + FileLog.d(TAG, "Removing app icon: " + packages[i]); iconCache.removeIconsForPkg(packages[i], mUser); } // Fall through @@ -169,14 +163,24 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { break; case OP_USER_AVAILABILITY_CHANGE: { UserManagerState ums = new UserManagerState(); - ums.init(UserCache.INSTANCE.get(context), - context.getSystemService(UserManager.class)); + UserManager userManager = context.getSystemService(UserManager.class); + ums.init(UserCache.INSTANCE.get(context), userManager); + boolean isUserQuiet = ums.isUserQuiet(mUser); flagOp = FlagOp.NO_OP.setFlag( - WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER, ums.isUserQuiet(mUser)); + WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER, isUserQuiet); appsList.updateDisabledFlags(matcher, flagOp); - // We are not synchronizing here, as int operations are atomic - appsList.setFlags(FLAG_QUIET_MODE_ENABLED, ums.isAnyProfileQuietModeEnabled()); + if (Flags.enablePrivateSpace()) { + UserCache userCache = UserCache.INSTANCE.get(context); + if (userCache.getUserInfo(mUser).isWork()) { + appsList.setFlags(FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, isUserQuiet); + } else if (userCache.getUserInfo(mUser).isPrivate()) { + appsList.setFlags(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, isUserQuiet); + } + } else { + // We are not synchronizing here, as int operations are atomic + appsList.setFlags(FLAG_QUIET_MODE_ENABLED, ums.isAnyProfileQuietModeEnabled()); + } break; } default: diff --git a/src/com/android/launcher3/model/UserManagerState.java b/src/com/android/launcher3/model/UserManagerState.java index 97a5905f0a..720f08e256 100644 --- a/src/com/android/launcher3/model/UserManagerState.java +++ b/src/com/android/launcher3/model/UserManagerState.java @@ -61,6 +61,9 @@ public class UserManagerState { /** * Returns true if any user profile has quiet mode enabled. + * <p> + * Do not use this for determining if a specific profile has quiet mode enabled, as their can + * be more than one profile in quiet mode. */ public boolean isAnyProfileQuietModeEnabled() { for (int i = mQuietUsersHashCodeMap.size() - 1; i >= 0; i--) { diff --git a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java index 1fc8a03a83..929f698236 100644 --- a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java +++ b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java @@ -16,6 +16,7 @@ package com.android.launcher3.model; import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID; +import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget; import android.util.LongSparseArray; @@ -66,7 +67,8 @@ public class WorkspaceItemSpaceFinder { int screenCount = workspaceScreens.size(); // First check the preferred screen. IntSet screensToExclude = new IntSet(); - if (FeatureFlags.QSB_ON_FIRST_SCREEN) { + if (FeatureFlags.QSB_ON_FIRST_SCREEN + && !shouldShowFirstPageWidget()) { screensToExclude.add(FIRST_SCREEN_ID); } diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java index 7e6cbef8d5..6c2f5890be 100644 --- a/src/com/android/launcher3/model/data/AppInfo.java +++ b/src/com/android/launcher3/model/data/AppInfo.java @@ -23,8 +23,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherActivityInfo; -import android.os.Build; -import android.os.Process; import android.os.UserHandle; import android.os.UserManager; @@ -177,12 +175,6 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory { info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES; - if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O - && Process.myUserHandle().equals(lai.getUser())) { - // The icon for a non-primary user is badged, hence it's not exactly an adaptive icon. - info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON; - } - // Sets the progress level, installation and incremental download flags. info.setProgressLevel( PackageManagerHelper.getLoadingProgress(lai), diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java index 9bf6d43b17..5b541d045b 100644 --- a/src/com/android/launcher3/model/data/FolderInfo.java +++ b/src/com/android/launcher3/model/data/FolderInfo.java @@ -46,7 +46,6 @@ import java.util.List; import java.util.OptionalInt; import java.util.stream.IntStream; - /** * Represents a folder containing shortcuts or apps. */ diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java index 9afa4593a9..86393a0012 100644 --- a/src/com/android/launcher3/model/data/ItemInfo.java +++ b/src/com/android/launcher3/model/data/ItemInfo.java @@ -60,9 +60,12 @@ import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer; import com.android.launcher3.logger.LauncherAtom.WallpapersContainer; import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers; import com.android.launcher3.model.ModelWriter; +import com.android.launcher3.pm.UserCache; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.SettingsCache; +import com.android.launcher3.util.UserIconInfo; +import com.android.systemui.shared.system.SysUiStatsLog; import java.util.Optional; @@ -414,7 +417,9 @@ public class ItemInfo { @NonNull protected LauncherAtom.ItemInfo.Builder getDefaultItemInfoBuilder() { LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder(); - itemBuilder.setIsWork(!Process.myUserHandle().equals(user)); + UserIconInfo info = getUserInfo(); + itemBuilder.setIsWork(info != null && info.isWork()); + itemBuilder.setUserType(getUserType(info)); SettingsCache settingsCache = SettingsCache.INSTANCE.getNoCreate(); boolean isKidsMode = settingsCache != null && settingsCache.getValue(NAV_BAR_KIDS_MODE, 0); itemBuilder.setIsKidsMode(isKidsMode); @@ -510,4 +515,29 @@ public class ItemInfo { @Nullable final ModelWriter modelWriter) { this.title = title; } + + private UserIconInfo getUserInfo() { + UserCache userCache = UserCache.INSTANCE.getNoCreate(); + if (userCache == null) { + return null; + } + + return userCache.getUserInfo(user); + } + + private int getUserType(UserIconInfo info) { + if (info == null) { + return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_UNKNOWN; + } else if (info.isMain()) { + return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_MAIN; + } else if (info.isPrivate()) { + return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_PRIVATE; + } else if (info.isWork()) { + return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_WORK; + } else if (info.isCloned()) { + return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_CLONED; + } else { + return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_UNKNOWN; + } + } } diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java index b4a935a74a..dc180d842e 100644 --- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java +++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java @@ -83,17 +83,6 @@ public abstract class ItemInfoWithIcon extends ItemInfo { public static final int FLAG_SYSTEM_MASK = FLAG_SYSTEM_YES | FLAG_SYSTEM_NO; /** - * Flag indicating that the icon is an {@link android.graphics.drawable.AdaptiveIconDrawable} - * that can be optimized in various way. - */ - public static final int FLAG_ADAPTIVE_ICON = 1 << 8; - - /** - * Flag indicating that the icon is badged. - */ - public static final int FLAG_ICON_BADGED = 1 << 9; - - /** * The icon is being installed. If {@link WorkspaceItemInfo#FLAG_RESTORED_ICON} or * {@link WorkspaceItemInfo#FLAG_AUTOINSTALL_ICON} is set, then the icon is either being * installed or is in a broken state. |