2017-06-06 10:46:59 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package com.android.launcher3.model;
|
|
|
|
|
|
2021-07-15 14:31:58 -07:00
|
|
|
import static com.android.launcher3.WorkspaceLayoutManager.LEFT_PANEL_ID;
|
2020-01-27 13:44:06 -08:00
|
|
|
import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO;
|
2020-06-08 17:06:09 -07:00
|
|
|
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
|
|
|
|
|
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;
|
2019-11-29 21:47:29 -08:00
|
|
|
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
|
2020-04-06 15:11:17 -07:00
|
|
|
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
|
|
|
|
|
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
|
|
|
|
|
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
|
2019-08-15 14:53:41 -07:00
|
|
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
2019-12-11 10:00:47 -08:00
|
|
|
import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission;
|
2019-07-17 15:12:56 -07:00
|
|
|
import static com.android.launcher3.util.PackageManagerHelper.isSystemApp;
|
2018-03-05 12:54:24 -08:00
|
|
|
|
2021-06-17 18:07:43 +01:00
|
|
|
import android.annotation.SuppressLint;
|
2017-06-06 10:46:59 -07:00
|
|
|
import android.appwidget.AppWidgetProviderInfo;
|
|
|
|
|
import android.content.ComponentName;
|
|
|
|
|
import android.content.ContentResolver;
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.IntentFilter;
|
|
|
|
|
import android.content.pm.LauncherActivityInfo;
|
2019-10-02 16:13:34 -07:00
|
|
|
import android.content.pm.LauncherApps;
|
2017-06-06 10:46:59 -07:00
|
|
|
import android.content.pm.PackageInstaller;
|
2018-03-26 17:30:50 -07:00
|
|
|
import android.content.pm.PackageInstaller.SessionInfo;
|
2020-06-08 17:06:09 -07:00
|
|
|
import android.content.pm.PackageManager;
|
2019-04-17 18:38:52 -07:00
|
|
|
import android.content.pm.ShortcutInfo;
|
2021-06-17 18:07:43 +01:00
|
|
|
import android.graphics.Point;
|
Render user's actual workspace in ThemePicker preview (Part 3)
go/grid-migration-preview
With this change, we can see actual grid migration in wallpaper preview.
The approach here: we use a tmp table (favorites_preview) here specifically for this preview (to write off the migration results), and load from this tmp table workspace items if migration is necessary and successful. Otherwise, we load from the current workspace.
UPDATED: this change should be completely compatible with the new multi-db grid migration algorithm. Here is why
1. In LauncherPreviewRender#renderScreenShot, I added a check to decide which grid migration preview method we should call. Once v2 preview method is implemented, it should be integrated with other parts of this change perfectly (the reason will be mentioned below).
2. While we have multiple DBs, mOpenHelper in LauncherProvider always points to the current db we are using. Queries using CONTENT_URI is routed to whatever DB mOpenHelper points to, so it works perfectly to directly operate on CONTENT_URI even when we use multi-db underneath the hood.
3. With 1 and 2 mentioned, I believe in order for this preview change to support multi-db, we only need to implement the V2 grid migration algorithm. Because most of what we are doing in this change is wrapped in GridSizeMigrationTask, it's perfectly safeguarded.
Bug: 144052839
Change-Id: Ie6d6048d77326f96546c8a180a7cd8f15b47e4c4
2020-01-12 01:07:59 -08:00
|
|
|
import android.net.Uri;
|
2020-10-14 11:17:04 -07:00
|
|
|
import android.os.Bundle;
|
2017-06-06 10:46:59 -07:00
|
|
|
import android.os.UserHandle;
|
2019-12-10 12:19:13 -08:00
|
|
|
import android.os.UserManager;
|
2017-06-06 10:46:59 -07:00
|
|
|
import android.text.TextUtils;
|
2021-02-24 14:25:45 -08:00
|
|
|
import android.util.ArrayMap;
|
2017-06-06 10:46:59 -07:00
|
|
|
import android.util.Log;
|
|
|
|
|
import android.util.LongSparseArray;
|
2019-10-14 14:06:38 -07:00
|
|
|
import android.util.TimingLogger;
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2021-06-17 18:07:43 +01:00
|
|
|
import com.android.launcher3.DeviceProfile;
|
|
|
|
|
import com.android.launcher3.InvariantDeviceProfile;
|
2017-06-06 10:46:59 -07:00
|
|
|
import com.android.launcher3.LauncherAppState;
|
|
|
|
|
import com.android.launcher3.LauncherModel;
|
|
|
|
|
import com.android.launcher3.LauncherSettings;
|
|
|
|
|
import com.android.launcher3.Utilities;
|
|
|
|
|
import com.android.launcher3.config.FeatureFlags;
|
|
|
|
|
import com.android.launcher3.folder.Folder;
|
2019-08-07 09:24:26 -07:00
|
|
|
import com.android.launcher3.folder.FolderGridOrganizer;
|
2020-06-19 18:31:18 -07:00
|
|
|
import com.android.launcher3.folder.FolderNameInfos;
|
2020-01-26 23:25:14 -08:00
|
|
|
import com.android.launcher3.folder.FolderNameProvider;
|
2020-02-06 11:28:01 -08:00
|
|
|
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
|
|
|
|
|
import com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic;
|
2018-12-27 13:58:25 -08:00
|
|
|
import com.android.launcher3.icons.IconCache;
|
2019-08-06 09:48:36 -07:00
|
|
|
import com.android.launcher3.icons.LauncherActivityCachingLogic;
|
2019-10-23 17:47:28 +00:00
|
|
|
import com.android.launcher3.icons.ShortcutCachingLogic;
|
2018-12-27 13:58:25 -08:00
|
|
|
import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
|
2017-06-06 10:46:59 -07:00
|
|
|
import com.android.launcher3.logging.FileLog;
|
2020-04-06 15:11:17 -07:00
|
|
|
import com.android.launcher3.model.data.AppInfo;
|
|
|
|
|
import com.android.launcher3.model.data.FolderInfo;
|
|
|
|
|
import com.android.launcher3.model.data.ItemInfo;
|
2021-01-12 19:30:02 +00:00
|
|
|
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
2020-04-06 15:11:17 -07:00
|
|
|
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
|
|
|
|
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
2019-12-09 14:55:56 -08:00
|
|
|
import com.android.launcher3.pm.InstallSessionHelper;
|
2019-09-20 12:51:37 -07:00
|
|
|
import com.android.launcher3.pm.PackageInstallInfo;
|
2019-12-10 12:19:13 -08:00
|
|
|
import com.android.launcher3.pm.UserCache;
|
2017-06-06 10:46:59 -07:00
|
|
|
import com.android.launcher3.provider.ImportDataTask;
|
2019-08-19 17:04:36 -07:00
|
|
|
import com.android.launcher3.qsb.QsbContainerView;
|
2017-06-06 10:46:59 -07:00
|
|
|
import com.android.launcher3.shortcuts.ShortcutKey;
|
2019-12-11 10:00:47 -08:00
|
|
|
import com.android.launcher3.shortcuts.ShortcutRequest;
|
|
|
|
|
import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult;
|
2017-06-06 10:46:59 -07:00
|
|
|
import com.android.launcher3.util.ComponentKey;
|
2019-07-17 15:12:56 -07:00
|
|
|
import com.android.launcher3.util.IOUtils;
|
2021-07-15 14:31:58 -07:00
|
|
|
import com.android.launcher3.util.IntArray;
|
2021-05-14 12:21:30 +02:00
|
|
|
import com.android.launcher3.util.IntSet;
|
2017-06-06 10:46:59 -07:00
|
|
|
import com.android.launcher3.util.LooperIdleLock;
|
|
|
|
|
import com.android.launcher3.util.PackageManagerHelper;
|
2019-09-16 21:38:28 -07:00
|
|
|
import com.android.launcher3.util.PackageUserKey;
|
2017-09-28 16:28:34 -07:00
|
|
|
import com.android.launcher3.util.TraceHelper;
|
2021-02-22 14:03:44 +00:00
|
|
|
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
2019-12-10 12:19:13 -08:00
|
|
|
import com.android.launcher3.widget.WidgetManagerHelper;
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.HashMap;
|
2020-08-22 02:09:42 -07:00
|
|
|
import java.util.HashSet;
|
2017-06-06 10:46:59 -07:00
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
2020-08-22 02:09:42 -07:00
|
|
|
import java.util.Set;
|
2017-06-06 10:46:59 -07:00
|
|
|
import java.util.concurrent.CancellationException;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Runnable for the thread that loads the contents of the launcher:
|
|
|
|
|
* - workspace icons
|
|
|
|
|
* - widgets
|
|
|
|
|
* - all apps icons
|
|
|
|
|
* - deep shortcuts within apps
|
|
|
|
|
*/
|
|
|
|
|
public class LoaderTask implements Runnable {
|
|
|
|
|
private static final String TAG = "LoaderTask";
|
|
|
|
|
|
2021-04-19 11:17:42 -07:00
|
|
|
private static final boolean DEBUG = true;
|
|
|
|
|
|
2020-02-24 13:50:29 -08:00
|
|
|
protected final LauncherAppState mApp;
|
2017-06-06 10:46:59 -07:00
|
|
|
private final AllAppsList mBgAllAppsList;
|
Render user's actual workspace in ThemePicker preview (Part 3)
go/grid-migration-preview
With this change, we can see actual grid migration in wallpaper preview.
The approach here: we use a tmp table (favorites_preview) here specifically for this preview (to write off the migration results), and load from this tmp table workspace items if migration is necessary and successful. Otherwise, we load from the current workspace.
UPDATED: this change should be completely compatible with the new multi-db grid migration algorithm. Here is why
1. In LauncherPreviewRender#renderScreenShot, I added a check to decide which grid migration preview method we should call. Once v2 preview method is implemented, it should be integrated with other parts of this change perfectly (the reason will be mentioned below).
2. While we have multiple DBs, mOpenHelper in LauncherProvider always points to the current db we are using. Queries using CONTENT_URI is routed to whatever DB mOpenHelper points to, so it works perfectly to directly operate on CONTENT_URI even when we use multi-db underneath the hood.
3. With 1 and 2 mentioned, I believe in order for this preview change to support multi-db, we only need to implement the V2 grid migration algorithm. Because most of what we are doing in this change is wrapped in GridSizeMigrationTask, it's perfectly safeguarded.
Bug: 144052839
Change-Id: Ie6d6048d77326f96546c8a180a7cd8f15b47e4c4
2020-01-12 01:07:59 -08:00
|
|
|
protected final BgDataModel mBgDataModel;
|
2020-07-27 17:50:33 -07:00
|
|
|
private final ModelDelegate mModelDelegate;
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2018-03-26 17:30:50 -07:00
|
|
|
private FirstScreenBroadcast mFirstScreenBroadcast;
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
private final LoaderResults mResults;
|
|
|
|
|
|
2019-10-02 16:13:34 -07:00
|
|
|
private final LauncherApps mLauncherApps;
|
2019-12-10 12:19:13 -08:00
|
|
|
private final UserManager mUserManager;
|
|
|
|
|
private final UserCache mUserCache;
|
|
|
|
|
|
2019-12-09 14:55:56 -08:00
|
|
|
private final InstallSessionHelper mSessionHelper;
|
2017-06-06 10:46:59 -07:00
|
|
|
private final IconCache mIconCache;
|
|
|
|
|
|
2020-06-08 17:06:09 -07:00
|
|
|
private final UserManagerState mUserManagerState = new UserManagerState();
|
|
|
|
|
|
2021-02-24 14:25:45 -08:00
|
|
|
protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>();
|
2020-07-13 23:13:00 -07:00
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
private boolean mStopped;
|
|
|
|
|
|
2020-08-03 12:07:50 -07:00
|
|
|
private final Set<PackageUserKey> mPendingPackages = new HashSet<>();
|
2020-08-04 17:28:46 -07:00
|
|
|
private boolean mItemsDeleted = false;
|
2020-10-14 11:17:04 -07:00
|
|
|
private String mDbName;
|
2020-08-04 17:28:46 -07:00
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,
|
2020-07-27 17:50:33 -07:00
|
|
|
ModelDelegate modelDelegate, LoaderResults results) {
|
2017-06-06 10:46:59 -07:00
|
|
|
mApp = app;
|
|
|
|
|
mBgAllAppsList = bgAllAppsList;
|
|
|
|
|
mBgDataModel = dataModel;
|
2020-07-27 17:50:33 -07:00
|
|
|
mModelDelegate = modelDelegate;
|
2017-06-06 10:46:59 -07:00
|
|
|
mResults = results;
|
|
|
|
|
|
2019-10-02 16:13:34 -07:00
|
|
|
mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);
|
2019-12-10 12:19:13 -08:00
|
|
|
mUserManager = mApp.getContext().getSystemService(UserManager.class);
|
|
|
|
|
mUserCache = UserCache.INSTANCE.get(mApp.getContext());
|
2019-12-09 14:55:56 -08:00
|
|
|
mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext());
|
2017-06-06 10:46:59 -07:00
|
|
|
mIconCache = mApp.getIconCache();
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 14:33:18 -07:00
|
|
|
protected synchronized void waitForIdle() {
|
2017-06-06 10:46:59 -07:00
|
|
|
// Wait until the either we're stopped or the other threads are done.
|
|
|
|
|
// This way we don't start loading all apps until the workspace has settled
|
|
|
|
|
// down.
|
2017-06-06 14:33:18 -07:00
|
|
|
LooperIdleLock idleLock = mResults.newIdleLock(this);
|
2017-06-06 10:46:59 -07:00
|
|
|
// Just in case mFlushingWorkerThread changes but we aren't woken up,
|
|
|
|
|
// wait no longer than 1sec at a time
|
|
|
|
|
while (!mStopped && idleLock.awaitLocked(1000));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private synchronized void verifyNotStopped() throws CancellationException {
|
|
|
|
|
if (mStopped) {
|
|
|
|
|
throw new CancellationException("Loader stopped");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-26 17:30:50 -07:00
|
|
|
private void sendFirstScreenActiveInstallsBroadcast() {
|
|
|
|
|
ArrayList<ItemInfo> firstScreenItems = new ArrayList<>();
|
2020-12-10 16:22:41 -08:00
|
|
|
ArrayList<ItemInfo> allItems = mBgDataModel.getAllWorkspaceItems();
|
2021-07-15 14:31:58 -07:00
|
|
|
|
2018-12-27 13:58:25 -08:00
|
|
|
// Screen set is never empty
|
2021-07-15 14:31:58 -07:00
|
|
|
IntArray allScreens = mBgDataModel.collectWorkspaceScreens();
|
|
|
|
|
final int firstScreen = allScreens.get(0);
|
|
|
|
|
|
|
|
|
|
IntSet firstScreens = IntSet.wrap(firstScreen);
|
|
|
|
|
if (firstScreen == LEFT_PANEL_ID && allScreens.size() >= 2) {
|
|
|
|
|
firstScreens.add(allScreens.get(1));
|
|
|
|
|
}
|
2018-12-27 13:58:25 -08:00
|
|
|
|
2021-07-15 14:31:58 -07:00
|
|
|
filterCurrentWorkspaceItems(firstScreens, allItems, firstScreenItems,
|
2018-03-26 17:30:50 -07:00
|
|
|
new ArrayList<>() /* otherScreenItems are ignored */);
|
|
|
|
|
mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
public void run() {
|
|
|
|
|
synchronized (this) {
|
|
|
|
|
// Skip fast if we are already stopped.
|
|
|
|
|
if (mStopped) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-16 11:32:41 -07:00
|
|
|
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
|
2020-02-10 12:47:42 -08:00
|
|
|
TimingLogger logger = new TimingLogger(TAG, "run");
|
2017-06-06 10:46:59 -07:00
|
|
|
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
|
2019-10-23 17:47:28 +00:00
|
|
|
List<ShortcutInfo> allShortcuts = new ArrayList<>();
|
|
|
|
|
loadWorkspace(allShortcuts);
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "loadWorkspace");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2021-03-02 10:54:53 -08:00
|
|
|
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
|
|
|
|
|
// sanitizeData should not be invoked if the workspace is loaded from a db different
|
|
|
|
|
// from the main db as defined in the invariant device profile.
|
|
|
|
|
// (e.g. both grid preview and minimal device mode uses a different db)
|
|
|
|
|
if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
|
|
|
|
|
verifyNotStopped();
|
|
|
|
|
sanitizeData();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "sanitizeData");
|
2021-03-02 10:54:53 -08:00
|
|
|
}
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
verifyNotStopped();
|
2021-06-23 12:36:18 -07:00
|
|
|
mResults.bindWorkspace(true /* incrementBindId */);
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "bindWorkspace");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2020-08-11 18:49:28 -07:00
|
|
|
mModelDelegate.workspaceLoadComplete();
|
2018-03-26 17:30:50 -07:00
|
|
|
// Notify the installer packages of packages with active installs on the first screen.
|
|
|
|
|
sendFirstScreenActiveInstallsBroadcast();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");
|
2018-03-26 17:30:50 -07:00
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
// Take a break
|
|
|
|
|
waitForIdle();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "step 1 complete");
|
2017-06-06 10:46:59 -07:00
|
|
|
verifyNotStopped();
|
|
|
|
|
|
|
|
|
|
// second step
|
2018-09-26 12:00:30 -07:00
|
|
|
List<LauncherActivityInfo> allActivityList = loadAllApps();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "loadAllApps");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
verifyNotStopped();
|
|
|
|
|
mResults.bindAllApps();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "bindAllApps");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
verifyNotStopped();
|
2018-09-21 14:41:05 -07:00
|
|
|
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
|
|
|
|
|
setIgnorePackages(updateHandler);
|
2018-11-05 17:05:35 -08:00
|
|
|
updateHandler.updateIcons(allActivityList,
|
2019-08-06 09:48:36 -07:00
|
|
|
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
|
2018-09-26 12:00:30 -07:00
|
|
|
mApp.getModel()::onPackageIconsUpdated);
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "update icon cache");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2019-10-23 17:47:28 +00:00
|
|
|
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
|
|
|
|
|
verifyNotStopped();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "save shortcuts in icon cache");
|
2019-10-23 17:47:28 +00:00
|
|
|
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
|
|
|
|
|
mApp.getModel()::onPackageIconsUpdated);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
// Take a break
|
|
|
|
|
waitForIdle();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "step 2 complete");
|
2017-06-06 10:46:59 -07:00
|
|
|
verifyNotStopped();
|
|
|
|
|
|
|
|
|
|
// third step
|
2019-10-23 17:47:28 +00:00
|
|
|
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "loadDeepShortcuts");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
verifyNotStopped();
|
|
|
|
|
mResults.bindDeepShortcuts();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "bindDeepShortcuts");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2019-10-23 17:47:28 +00:00
|
|
|
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
|
|
|
|
|
verifyNotStopped();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "save deep shortcuts in icon cache");
|
2019-10-23 17:47:28 +00:00
|
|
|
updateHandler.updateIcons(allDeepShortcuts,
|
|
|
|
|
new ShortcutCachingLogic(), (pkgs, user) -> { });
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
// Take a break
|
|
|
|
|
waitForIdle();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "step 3 complete");
|
2017-06-06 10:46:59 -07:00
|
|
|
verifyNotStopped();
|
|
|
|
|
|
|
|
|
|
// fourth step
|
2020-02-06 11:28:01 -08:00
|
|
|
List<ComponentWithLabelAndIcon> allWidgetsList =
|
|
|
|
|
mBgDataModel.widgetsModel.update(mApp, null);
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "load widgets");
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
verifyNotStopped();
|
|
|
|
|
mResults.bindWidgets();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "bindWidgets");
|
2018-09-26 12:00:30 -07:00
|
|
|
verifyNotStopped();
|
2019-10-01 16:35:17 +00:00
|
|
|
|
2020-02-06 11:28:01 -08:00
|
|
|
updateHandler.updateIcons(allWidgetsList,
|
|
|
|
|
new ComponentWithIconCachingLogic(mApp.getContext(), true),
|
|
|
|
|
mApp.getModel()::onWidgetLabelsUpdated);
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "save widgets in icon cache");
|
2018-09-26 12:00:30 -07:00
|
|
|
|
2020-01-26 23:25:14 -08:00
|
|
|
// fifth step
|
|
|
|
|
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
|
|
|
|
|
loadFolderNames();
|
|
|
|
|
}
|
2020-10-14 11:17:04 -07:00
|
|
|
|
2018-09-26 12:00:30 -07:00
|
|
|
verifyNotStopped();
|
|
|
|
|
updateHandler.finish();
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "finish icon update");
|
2018-09-26 12:00:30 -07:00
|
|
|
|
2020-10-13 13:37:28 -07:00
|
|
|
mModelDelegate.modelLoadComplete();
|
2017-06-06 10:46:59 -07:00
|
|
|
transaction.commit();
|
|
|
|
|
} catch (CancellationException e) {
|
2017-06-06 14:33:18 -07:00
|
|
|
// Loader stopped, ignore
|
2021-04-19 11:17:42 -07:00
|
|
|
logASplit(logger, "Cancelled");
|
2019-10-14 14:06:38 -07:00
|
|
|
} finally {
|
|
|
|
|
logger.dumpToLog();
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
2019-10-16 11:32:41 -07:00
|
|
|
TraceHelper.INSTANCE.endSection(traceToken);
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void stopLocked() {
|
|
|
|
|
mStopped = true;
|
|
|
|
|
this.notify();
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-31 12:12:14 -07:00
|
|
|
private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {
|
2020-08-03 12:07:50 -07:00
|
|
|
loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI,
|
|
|
|
|
null /* selection */);
|
Render user's actual workspace in ThemePicker preview (Part 3)
go/grid-migration-preview
With this change, we can see actual grid migration in wallpaper preview.
The approach here: we use a tmp table (favorites_preview) here specifically for this preview (to write off the migration results), and load from this tmp table workspace items if migration is necessary and successful. Otherwise, we load from the current workspace.
UPDATED: this change should be completely compatible with the new multi-db grid migration algorithm. Here is why
1. In LauncherPreviewRender#renderScreenShot, I added a check to decide which grid migration preview method we should call. Once v2 preview method is implemented, it should be integrated with other parts of this change perfectly (the reason will be mentioned below).
2. While we have multiple DBs, mOpenHelper in LauncherProvider always points to the current db we are using. Queries using CONTENT_URI is routed to whatever DB mOpenHelper points to, so it works perfectly to directly operate on CONTENT_URI even when we use multi-db underneath the hood.
3. With 1 and 2 mentioned, I believe in order for this preview change to support multi-db, we only need to implement the V2 grid migration algorithm. Because most of what we are doing in this change is wrapped in GridSizeMigrationTask, it's perfectly safeguarded.
Bug: 144052839
Change-Id: Ie6d6048d77326f96546c8a180a7cd8f15b47e4c4
2020-01-12 01:07:59 -08:00
|
|
|
}
|
|
|
|
|
|
2020-08-03 12:07:50 -07:00
|
|
|
protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri,
|
|
|
|
|
String selection) {
|
2017-06-06 10:46:59 -07:00
|
|
|
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();
|
2020-09-23 12:15:43 -07:00
|
|
|
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
boolean clearDb = false;
|
|
|
|
|
try {
|
|
|
|
|
ImportDataTask.performImportIfPossible(context);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// Migration failed. Clear workspace.
|
|
|
|
|
clearDb = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-27 13:44:06 -08:00
|
|
|
if (!clearDb && (MULTI_DB_GRID_MIRATION_ALGO.get()
|
|
|
|
|
? !GridSizeMigrationTaskV2.migrateGridIfNeeded(context)
|
|
|
|
|
: !GridSizeMigrationTask.migrateGridIfNeeded(context))) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// 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();
|
2020-08-03 12:07:50 -07:00
|
|
|
mPendingPackages.clear();
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2019-09-16 21:38:28 -07:00
|
|
|
final HashMap<PackageUserKey, SessionInfo> installingPkgs =
|
2019-12-09 14:55:56 -08:00
|
|
|
mSessionHelper.getActiveSessions();
|
2019-09-20 12:51:37 -07:00
|
|
|
installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);
|
|
|
|
|
|
2019-09-16 21:38:28 -07:00
|
|
|
final PackageUserKey tempPackageKey = new PackageUserKey(null, null);
|
2018-03-26 17:30:50 -07:00
|
|
|
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2019-04-17 18:38:52 -07:00
|
|
|
Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();
|
Render user's actual workspace in ThemePicker preview (Part 3)
go/grid-migration-preview
With this change, we can see actual grid migration in wallpaper preview.
The approach here: we use a tmp table (favorites_preview) here specifically for this preview (to write off the migration results), and load from this tmp table workspace items if migration is necessary and successful. Otherwise, we load from the current workspace.
UPDATED: this change should be completely compatible with the new multi-db grid migration algorithm. Here is why
1. In LauncherPreviewRender#renderScreenShot, I added a check to decide which grid migration preview method we should call. Once v2 preview method is implemented, it should be integrated with other parts of this change perfectly (the reason will be mentioned below).
2. While we have multiple DBs, mOpenHelper in LauncherProvider always points to the current db we are using. Queries using CONTENT_URI is routed to whatever DB mOpenHelper points to, so it works perfectly to directly operate on CONTENT_URI even when we use multi-db underneath the hood.
3. With 1 and 2 mentioned, I believe in order for this preview change to support multi-db, we only need to implement the V2 grid migration algorithm. Because most of what we are doing in this change is wrapped in GridSizeMigrationTask, it's perfectly safeguarded.
Bug: 144052839
Change-Id: Ie6d6048d77326f96546c8a180a7cd8f15b47e4c4
2020-01-12 01:07:59 -08:00
|
|
|
final LoaderCursor c = new LoaderCursor(
|
2020-08-03 12:07:50 -07:00
|
|
|
contentResolver.query(contentUri, null, selection, null, null), contentUri,
|
|
|
|
|
mApp, mUserManagerState);
|
2020-10-14 11:17:04 -07:00
|
|
|
final Bundle extras = c.getExtras();
|
|
|
|
|
mDbName = extras == null
|
|
|
|
|
? null : extras.getString(LauncherSettings.Settings.EXTRA_DB_NAME);
|
2017-06-06 10:46:59 -07:00
|
|
|
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);
|
2021-05-24 23:23:15 +01:00
|
|
|
final int sourceContainerIndex = c.getColumnIndexOrThrow(
|
|
|
|
|
LauncherSettings.Favorites.APPWIDGET_SOURCE);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
final LongSparseArray<Boolean> unlockedUsers = new LongSparseArray<>();
|
2020-06-08 17:06:09 -07:00
|
|
|
|
|
|
|
|
mUserManagerState.init(mUserCache, mUserManager);
|
|
|
|
|
|
2019-12-10 12:19:13 -08:00
|
|
|
for (UserHandle user : mUserCache.getUserProfiles()) {
|
|
|
|
|
long serialNo = mUserCache.getSerialNumberForUser(user);
|
2017-06-06 10:46:59 -07:00
|
|
|
boolean userUnlocked = mUserManager.isUserUnlocked(user);
|
|
|
|
|
|
|
|
|
|
// We can only query for shortcuts when the user is unlocked.
|
|
|
|
|
if (userUnlocked) {
|
2019-12-11 10:00:47 -08:00
|
|
|
QueryResult pinnedShortcuts = new ShortcutRequest(context, user)
|
|
|
|
|
.query(ShortcutRequest.PINNED);
|
2019-07-17 14:30:04 -07:00
|
|
|
if (pinnedShortcuts.wasSuccess()) {
|
2019-04-17 18:38:52 -07:00
|
|
|
for (ShortcutInfo shortcut : pinnedShortcuts) {
|
2017-06-06 10:46:59 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 16:03:06 -07:00
|
|
|
WorkspaceItemInfo info;
|
2017-06-06 10:46:59 -07:00
|
|
|
LauncherAppWidgetInfo appWidgetInfo;
|
2020-09-23 12:15:43 -07:00
|
|
|
LauncherAppWidgetProviderInfo widgetProviderInfo;
|
2017-06-06 10:46:59 -07:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 17:06:09 -07:00
|
|
|
int disabledState = mUserManagerState.isUserQuiet(c.serialNumber)
|
|
|
|
|
? WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER : 0;
|
2017-06-06 10:46:59 -07:00
|
|
|
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) ||
|
2019-10-02 16:13:34 -07:00
|
|
|
mLauncherApps.isPackageEnabled(targetPkg, c.user);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2019-09-16 18:09:24 -07:00
|
|
|
// 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) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// If the apk is present and the shortcut points to a specific
|
|
|
|
|
// component.
|
|
|
|
|
|
|
|
|
|
// If the component is already present
|
2019-10-02 16:13:34 -07:00
|
|
|
if (mLauncherApps.isActivityEnabled(cn, c.user)) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// no special handling necessary for this item
|
|
|
|
|
c.markRestored();
|
|
|
|
|
} else {
|
2018-09-05 12:48:13 -07:00
|
|
|
// 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();
|
2017-06-06 10:46:59 -07:00
|
|
|
} else {
|
2018-09-05 12:48:13 -07:00
|
|
|
c.markDeleted("Unable to find a launch target");
|
2017-06-06 10:46:59 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// else if cn == null => can't infer much, leave it
|
|
|
|
|
// else if !validPkg => could be restored icon or missing sd-card
|
|
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(targetPkg) && !validTarget) {
|
|
|
|
|
// Points to a valid app (superset of cn != null) but the apk
|
|
|
|
|
// is not available.
|
|
|
|
|
|
|
|
|
|
if (c.restoreFlag != 0) {
|
|
|
|
|
// Package is not yet available but might be
|
|
|
|
|
// installed later.
|
|
|
|
|
FileLog.d(TAG, "package not yet restored: " + targetPkg);
|
|
|
|
|
|
2019-09-16 21:38:28 -07:00
|
|
|
tempPackageKey.update(targetPkg, c.user);
|
2019-03-27 16:03:06 -07:00
|
|
|
if (c.hasRestoreFlag(WorkspaceItemInfo.FLAG_RESTORE_STARTED)) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// Restore has started once.
|
2019-09-16 21:38:28 -07:00
|
|
|
} else if (installingPkgs.containsKey(tempPackageKey)) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// App restore has started. Update the flag
|
2019-03-27 16:03:06 -07:00
|
|
|
c.restoreFlag |= WorkspaceItemInfo.FLAG_RESTORE_STARTED;
|
2019-04-09 14:20:30 -07:00
|
|
|
c.updater().put(LauncherSettings.Favorites.RESTORED,
|
|
|
|
|
c.restoreFlag).commit();
|
2017-06-06 10:46:59 -07:00
|
|
|
} else {
|
|
|
|
|
c.markDeleted("Unrestored app removed: " + targetPkg);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) {
|
|
|
|
|
// Package is present but not available.
|
2019-03-27 16:03:06 -07:00
|
|
|
disabledState |= WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE;
|
2017-06-06 10:46:59 -07:00
|
|
|
// 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);
|
2020-08-03 12:07:50 -07:00
|
|
|
mPendingPackages.add(new PackageUserKey(targetPkg, c.user));
|
2017-06-06 10:46:59 -07:00
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 16:03:06 -07:00
|
|
|
if ((c.restoreFlag & WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) != 0) {
|
2017-08-08 16:26:18 -07:00
|
|
|
validTarget = false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
if (validTarget) {
|
|
|
|
|
// The shortcut points to a valid target (either no target
|
|
|
|
|
// or something which is ready to be used)
|
|
|
|
|
c.markRestored();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-04 09:14:40 -08:00
|
|
|
boolean useLowResIcon = !c.isOnWorkspaceOrHotseat();
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
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)) {
|
2019-04-17 18:38:52 -07:00
|
|
|
ShortcutInfo pinnedShortcut =
|
2017-06-06 10:46:59 -07:00
|
|
|
shortcutKeyToPinnedShortcuts.get(key);
|
|
|
|
|
if (pinnedShortcut == null) {
|
|
|
|
|
// The shortcut is no longer valid.
|
|
|
|
|
c.markDeleted("Pinned shortcut not found");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-03-27 16:03:06 -07:00
|
|
|
info = new WorkspaceItemInfo(pinnedShortcut, context);
|
2018-11-29 12:13:47 -08:00
|
|
|
// If the pinned deep shortcut is no longer published,
|
|
|
|
|
// use the last saved icon instead of the default.
|
2020-02-06 11:28:01 -08:00
|
|
|
mIconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon);
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
if (pmHelper.isAppSuspended(
|
|
|
|
|
pinnedShortcut.getPackage(), info.user)) {
|
2017-10-30 13:52:20 -07:00
|
|
|
info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
2020-04-06 15:11:17 -07:00
|
|
|
intent = info.getIntent();
|
2019-10-23 17:47:28 +00:00
|
|
|
allDeepShortcuts.add(pinnedShortcut);
|
2017-06-06 10:46:59 -07:00
|
|
|
} else {
|
|
|
|
|
// Create a shortcut info in disabled mode for now.
|
2019-03-27 16:03:06 -07:00
|
|
|
info = c.loadSimpleWorkspaceItem();
|
2017-10-30 13:52:20 -07:00
|
|
|
info.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
} else { // item type == ITEM_TYPE_SHORTCUT
|
2019-03-27 16:03:06 -07:00
|
|
|
info = c.loadSimpleWorkspaceItem();
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
// Shortcuts are only available on the primary profile
|
|
|
|
|
if (!TextUtils.isEmpty(targetPkg)
|
|
|
|
|
&& pmHelper.isAppSuspended(targetPkg, c.user)) {
|
2017-10-30 13:52:20 -07:00
|
|
|
disabledState |= FLAG_DISABLED_SUSPENDED;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// App shortcuts that used to be automatically added to Launcher
|
|
|
|
|
// didn't always have the correct intent flags set, so do that
|
|
|
|
|
// 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;
|
2017-10-30 13:52:20 -07:00
|
|
|
info.runtimeStatusFlags |= disabledState;
|
2019-07-17 15:12:56 -07:00
|
|
|
if (isSafeMode && !isSystemApp(context, intent)) {
|
2017-10-30 13:52:20 -07:00
|
|
|
info.runtimeStatusFlags |= FLAG_DISABLED_SAFEMODE;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
2021-01-27 16:54:45 -08:00
|
|
|
LauncherActivityInfo activityInfo = c.getLauncherActivityInfo();
|
|
|
|
|
if (activityInfo != null) {
|
|
|
|
|
info.setProgressLevel(
|
|
|
|
|
PackageManagerHelper
|
|
|
|
|
.getLoadingProgress(activityInfo),
|
|
|
|
|
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
|
|
|
|
|
}
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {
|
2019-09-17 19:16:52 -07:00
|
|
|
tempPackageKey.update(targetPkg, c.user);
|
|
|
|
|
SessionInfo si = installingPkgs.get(tempPackageKey);
|
2021-01-12 19:30:02 +00:00
|
|
|
if (si == null) {
|
|
|
|
|
info.runtimeStatusFlags &=
|
2021-01-27 16:54:45 -08:00
|
|
|
~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
|
2021-01-12 19:30:02 +00:00
|
|
|
} else if (activityInfo == null) {
|
|
|
|
|
int installProgress = (int) (si.getProgress() * 100);
|
|
|
|
|
|
|
|
|
|
info.setProgressLevel(
|
|
|
|
|
installProgress,
|
|
|
|
|
PackageInstallInfo.STATUS_INSTALLING);
|
|
|
|
|
}
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.checkAndAddItem(info, mBgDataModel);
|
|
|
|
|
} else {
|
2019-03-27 16:03:06 -07:00
|
|
|
throw new RuntimeException("Unexpected null WorkspaceItemInfo");
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
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:
|
2019-09-11 16:51:50 -07:00
|
|
|
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
2017-07-03 13:50:52 -07:00
|
|
|
c.markDeleted("Only legacy shortcuts can have null package");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// Follow through
|
2017-06-06 10:46:59 -07:00
|
|
|
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);
|
2019-08-19 17:04:36 -07:00
|
|
|
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);
|
|
|
|
|
}
|
2017-06-06 10:46:59 -07:00
|
|
|
final boolean isIdValid = !c.hasRestoreFlag(
|
|
|
|
|
LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
|
|
|
|
|
final boolean wasProviderReady = !c.hasRestoreFlag(
|
|
|
|
|
LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);
|
|
|
|
|
|
2021-02-24 14:25:45 -08:00
|
|
|
ComponentKey providerKey = new ComponentKey(component, c.user);
|
|
|
|
|
if (!mWidgetProvidersMap.containsKey(providerKey)) {
|
|
|
|
|
mWidgetProvidersMap.put(providerKey,
|
|
|
|
|
widgetHelper.findProvider(component, c.user));
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
2021-02-24 14:25:45 -08:00
|
|
|
final AppWidgetProviderInfo provider =
|
|
|
|
|
mWidgetProvidersMap.get(providerKey);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
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 &
|
2017-06-14 11:02:27 -07:00
|
|
|
~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED &
|
|
|
|
|
~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
|
2017-06-06 10:46:59 -07:00
|
|
|
if (!wasProviderReady) {
|
|
|
|
|
// If provider was not previously ready, update the
|
|
|
|
|
// status and UI flag.
|
|
|
|
|
|
|
|
|
|
// 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;
|
2019-09-17 19:16:52 -07:00
|
|
|
|
|
|
|
|
tempPackageKey.update(component.getPackageName(), c.user);
|
2018-03-26 17:30:50 -07:00
|
|
|
SessionInfo si =
|
2019-09-17 19:16:52 -07:00
|
|
|
installingPkgs.get(tempPackageKey);
|
2018-03-26 17:30:50 -07:00
|
|
|
Integer installProgress = si == null
|
|
|
|
|
? null
|
|
|
|
|
: (int) (si.getProgress() * 100);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
|
|
|
|
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);
|
2019-08-19 17:04:36 -07:00
|
|
|
appWidgetInfo.options = c.getInt(optionsIndex);
|
2017-06-06 10:46:59 -07:00
|
|
|
appWidgetInfo.user = c.user;
|
2021-05-24 23:23:15 +01:00
|
|
|
appWidgetInfo.sourceContainer = c.getInt(sourceContainerIndex);
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2018-12-27 12:56:47 -08:00
|
|
|
if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
|
|
|
|
|
c.markDeleted("Widget has invalid size: "
|
|
|
|
|
+ appWidgetInfo.spanX + "x" + appWidgetInfo.spanY);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-09-23 12:15:43 -07:00
|
|
|
widgetProviderInfo =
|
|
|
|
|
widgetHelper.getLauncherAppWidgetInfo(appWidgetId);
|
|
|
|
|
if (widgetProviderInfo != null
|
|
|
|
|
&& (appWidgetInfo.spanX < widgetProviderInfo.minSpanX
|
|
|
|
|
|| appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) {
|
2021-06-17 18:07:43 +01:00
|
|
|
logDeleteWidgetInfo(mApp.getInvariantDeviceProfile(),
|
|
|
|
|
widgetProviderInfo);
|
|
|
|
|
|
2020-09-23 12:15:43 -07:00
|
|
|
// This can happen when display size changes.
|
|
|
|
|
c.markDeleted("Widget removed, min sizes not met: "
|
|
|
|
|
+ "span=" + appWidgetInfo.spanX + "x"
|
|
|
|
|
+ appWidgetInfo.spanY + " minSpan="
|
|
|
|
|
+ widgetProviderInfo.minSpanX + "x"
|
2020-12-04 15:12:26 -08:00
|
|
|
+ widgetProviderInfo.minSpanY);
|
2020-09-23 12:15:43 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
2017-06-06 10:46:59 -07:00
|
|
|
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) {
|
2021-06-29 15:10:17 +01:00
|
|
|
appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(
|
|
|
|
|
appWidgetInfo.providerName);
|
2017-06-06 10:46:59 -07:00
|
|
|
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 {
|
2019-07-17 15:12:56 -07:00
|
|
|
IOUtils.closeSilently(c);
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
2020-07-27 17:50:33 -07:00
|
|
|
// Load delegate items
|
2020-07-29 15:03:46 -07:00
|
|
|
mModelDelegate.loadItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
|
2020-07-27 17:50:33 -07:00
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
// Break early if we've stopped loading
|
|
|
|
|
if (mStopped) {
|
|
|
|
|
mBgDataModel.clear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove dead items
|
2020-08-03 12:07:50 -07:00
|
|
|
mItemsDeleted = c.commitDeleted();
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2019-03-04 09:14:40 -08:00
|
|
|
// Sort the folder items, update ranks, and make sure all preview items are high res.
|
2019-08-07 09:24:26 -07:00
|
|
|
FolderGridOrganizer verifier =
|
|
|
|
|
new FolderGridOrganizer(mApp.getInvariantDeviceProfile());
|
2017-06-06 10:46:59 -07:00
|
|
|
for (FolderInfo folder : mBgDataModel.folders) {
|
|
|
|
|
Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR);
|
|
|
|
|
verifier.setFolderInfo(folder);
|
2019-03-04 09:14:40 -08:00
|
|
|
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.
|
|
|
|
|
for (int rank = 0; rank < size; ++rank) {
|
2019-03-27 16:03:06 -07:00
|
|
|
WorkspaceItemInfo info = folder.contents.get(rank);
|
2019-03-04 09:14:40 -08:00
|
|
|
info.rank = rank;
|
2017-06-06 10:46:59 -07:00
|
|
|
|
2018-08-20 15:01:03 -07:00
|
|
|
if (info.usingLowResIcon()
|
2017-06-06 10:46:59 -07:00
|
|
|
&& info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
|
|
|
|
|
&& verifier.isItemInPreview(info.rank)) {
|
|
|
|
|
mIconCache.getTitleAndIcon(info, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.commitRestoredItems();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-21 14:41:05 -07:00
|
|
|
private void setIgnorePackages(IconCacheUpdateHandler updateHandler) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// Ignore packages which have a promise icon.
|
|
|
|
|
synchronized (mBgDataModel) {
|
|
|
|
|
for (ItemInfo info : mBgDataModel.itemsIdMap) {
|
2019-03-27 16:03:06 -07:00
|
|
|
if (info instanceof WorkspaceItemInfo) {
|
|
|
|
|
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
|
2017-06-06 10:46:59 -07:00
|
|
|
if (si.isPromise() && si.getTargetComponent() != null) {
|
2020-02-06 11:28:01 -08:00
|
|
|
updateHandler.addPackagesToIgnore(
|
|
|
|
|
si.user, si.getTargetComponent().getPackageName());
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
} else if (info instanceof LauncherAppWidgetInfo) {
|
|
|
|
|
LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info;
|
|
|
|
|
if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
|
2020-02-06 11:28:01 -08:00
|
|
|
updateHandler.addPackagesToIgnore(
|
|
|
|
|
lawi.user, lawi.providerName.getPackageName());
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-04 17:28:46 -07:00
|
|
|
private void sanitizeData() {
|
|
|
|
|
Context context = mApp.getContext();
|
2020-08-03 12:07:50 -07:00
|
|
|
ContentResolver contentResolver = context.getContentResolver();
|
2020-08-04 17:28:46 -07:00
|
|
|
if (mItemsDeleted) {
|
2020-08-03 12:07:50 -07:00
|
|
|
// Remove any empty folder
|
|
|
|
|
int[] deletedFolderIds = LauncherSettings.Settings
|
|
|
|
|
.call(contentResolver,
|
|
|
|
|
LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
|
|
|
|
|
.getIntArray(LauncherSettings.Settings.EXTRA_VALUE);
|
2020-12-10 16:22:41 -08:00
|
|
|
synchronized (mBgDataModel) {
|
|
|
|
|
for (int folderId : deletedFolderIds) {
|
|
|
|
|
mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
|
|
|
|
|
mBgDataModel.folders.remove(folderId);
|
|
|
|
|
mBgDataModel.itemsIdMap.remove(folderId);
|
|
|
|
|
}
|
2020-08-03 12:07:50 -07:00
|
|
|
}
|
2021-03-02 10:54:53 -08:00
|
|
|
|
2020-08-04 17:28:46 -07:00
|
|
|
}
|
2021-03-02 10:54:53 -08:00
|
|
|
// Remove any ghost widgets
|
|
|
|
|
LauncherSettings.Settings.call(contentResolver,
|
|
|
|
|
LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);
|
2020-08-04 17:28:46 -07:00
|
|
|
|
|
|
|
|
// Update pinned state of model shortcuts
|
|
|
|
|
mBgDataModel.updateShortcutPinnedState(context);
|
2020-08-03 12:07:50 -07:00
|
|
|
|
|
|
|
|
if (!Utilities.isBootCompleted() && !mPendingPackages.isEmpty()) {
|
|
|
|
|
context.registerReceiver(
|
|
|
|
|
new SdCardAvailableReceiver(mApp, mPendingPackages),
|
|
|
|
|
new IntentFilter(Intent.ACTION_BOOT_COMPLETED),
|
|
|
|
|
null,
|
|
|
|
|
MODEL_EXECUTOR.getHandler());
|
|
|
|
|
}
|
2020-08-04 17:28:46 -07:00
|
|
|
}
|
|
|
|
|
|
2018-09-26 12:00:30 -07:00
|
|
|
private List<LauncherActivityInfo> loadAllApps() {
|
2019-12-10 12:19:13 -08:00
|
|
|
final List<UserHandle> profiles = mUserCache.getUserProfiles();
|
2018-09-26 12:00:30 -07:00
|
|
|
List<LauncherActivityInfo> allActivityList = new ArrayList<>();
|
2017-06-06 10:46:59 -07:00
|
|
|
// Clear the list of apps
|
|
|
|
|
mBgAllAppsList.clear();
|
|
|
|
|
for (UserHandle user : profiles) {
|
|
|
|
|
// Query for the set of apps
|
|
|
|
|
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
|
|
|
|
|
// Fail if we don't have any apps
|
|
|
|
|
// TODO: Fix this. Only fail for the current user.
|
|
|
|
|
if (apps == null || apps.isEmpty()) {
|
2018-09-26 12:00:30 -07:00
|
|
|
return allActivityList;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
2020-06-08 17:06:09 -07:00
|
|
|
boolean quietMode = mUserManagerState.isUserQuiet(user);
|
2017-06-06 10:46:59 -07:00
|
|
|
// Create the ApplicationInfos
|
|
|
|
|
for (int i = 0; i < apps.size(); i++) {
|
|
|
|
|
LauncherActivityInfo app = apps.get(i);
|
|
|
|
|
// This builds the icon bitmaps.
|
|
|
|
|
mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
|
|
|
|
|
}
|
2018-09-26 12:00:30 -07:00
|
|
|
allActivityList.addAll(apps);
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
2019-09-11 16:51:50 -07:00
|
|
|
if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
|
2017-06-06 10:46:59 -07:00
|
|
|
// get all active sessions and add them to the all apps list
|
|
|
|
|
for (PackageInstaller.SessionInfo info :
|
2019-12-09 14:55:56 -08:00
|
|
|
mSessionHelper.getAllVerifiedSessions()) {
|
2017-06-06 10:46:59 -07:00
|
|
|
mBgAllAppsList.addPromiseApp(mApp.getContext(),
|
2019-09-20 12:51:37 -07:00
|
|
|
PackageInstallInfo.fromInstallingState(info));
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 17:06:09 -07:00
|
|
|
mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED,
|
|
|
|
|
mUserManagerState.isAnyProfileQuietModeEnabled());
|
|
|
|
|
mBgAllAppsList.setFlags(FLAG_HAS_SHORTCUT_PERMISSION,
|
|
|
|
|
hasShortcutsPermission(mApp.getContext()));
|
|
|
|
|
mBgAllAppsList.setFlags(FLAG_QUIET_MODE_CHANGE_PERMISSION,
|
|
|
|
|
mApp.getContext().checkSelfPermission("android.permission.MODIFY_QUIET_MODE")
|
|
|
|
|
== PackageManager.PERMISSION_GRANTED);
|
|
|
|
|
|
2019-07-17 20:35:56 -07:00
|
|
|
mBgAllAppsList.getAndResetChangeFlag();
|
2018-09-26 12:00:30 -07:00
|
|
|
return allActivityList;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
2019-10-23 17:47:28 +00:00
|
|
|
private List<ShortcutInfo> loadDeepShortcuts() {
|
|
|
|
|
List<ShortcutInfo> allShortcuts = new ArrayList<>();
|
2017-06-06 10:46:59 -07:00
|
|
|
mBgDataModel.deepShortcutMap.clear();
|
2020-06-08 17:06:09 -07:00
|
|
|
|
|
|
|
|
if (mBgAllAppsList.hasShortcutHostPermission()) {
|
2019-12-10 12:19:13 -08:00
|
|
|
for (UserHandle user : mUserCache.getUserProfiles()) {
|
2017-06-06 10:46:59 -07:00
|
|
|
if (mUserManager.isUserUnlocked(user)) {
|
2019-12-11 10:00:47 -08:00
|
|
|
List<ShortcutInfo> shortcuts = new ShortcutRequest(mApp.getContext(), user)
|
|
|
|
|
.query(ShortcutRequest.ALL);
|
2019-10-23 17:47:28 +00:00
|
|
|
allShortcuts.addAll(shortcuts);
|
2018-10-19 14:21:05 -07:00
|
|
|
mBgDataModel.updateDeepShortcutCounts(null, user, shortcuts);
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-23 17:47:28 +00:00
|
|
|
return allShortcuts;
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|
|
|
|
|
|
2020-01-26 23:25:14 -08:00
|
|
|
private void loadFolderNames() {
|
2020-02-19 09:14:49 -08:00
|
|
|
FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext(),
|
|
|
|
|
mBgAllAppsList.data, mBgDataModel.folders);
|
2020-01-26 23:25:14 -08:00
|
|
|
|
|
|
|
|
synchronized (mBgDataModel) {
|
|
|
|
|
for (int i = 0; i < mBgDataModel.folders.size(); i++) {
|
2020-06-19 18:31:18 -07:00
|
|
|
FolderNameInfos suggestionInfos = new FolderNameInfos();
|
2020-01-26 23:25:14 -08:00
|
|
|
FolderInfo info = mBgDataModel.folders.valueAt(i);
|
|
|
|
|
if (info.suggestedFolderNames == null) {
|
2020-02-07 20:06:34 -08:00
|
|
|
provider.getSuggestedFolderName(mApp.getContext(), info.contents,
|
|
|
|
|
suggestionInfos);
|
2020-06-19 18:31:18 -07:00
|
|
|
info.suggestedFolderNames = suggestionInfos;
|
2020-01-26 23:25:14 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 10:46:59 -07:00
|
|
|
public static boolean isValidProvider(AppWidgetProviderInfo provider) {
|
|
|
|
|
return (provider != null) && (provider.provider != null)
|
|
|
|
|
&& (provider.provider.getPackageName() != null);
|
|
|
|
|
}
|
2021-04-19 11:17:42 -07:00
|
|
|
|
2021-06-17 18:07:43 +01:00
|
|
|
@SuppressLint("NewApi") // Already added API check.
|
|
|
|
|
private static void logDeleteWidgetInfo(InvariantDeviceProfile idp,
|
|
|
|
|
LauncherAppWidgetProviderInfo widgetProviderInfo) {
|
|
|
|
|
FileLog.d(TAG, "Deleting " + widgetProviderInfo.getComponent()
|
|
|
|
|
+ " due to min size constraint");
|
|
|
|
|
Point cellSize = new Point();
|
|
|
|
|
for (DeviceProfile deviceProfile : idp.supportedProfiles) {
|
|
|
|
|
deviceProfile.getCellSize(cellSize);
|
|
|
|
|
FileLog.d(TAG, "DeviceProfile available width: " + deviceProfile.availableWidthPx
|
|
|
|
|
+ ", available height: " + deviceProfile.availableHeightPx
|
|
|
|
|
+ ", cellLayoutBorderSpacingPx: " + deviceProfile.cellLayoutBorderSpacingPx
|
|
|
|
|
+ ", cellSize: " + cellSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StringBuilder widgetDimension = new StringBuilder();
|
|
|
|
|
widgetDimension.append("Widget dimensions:\n")
|
|
|
|
|
.append("minResizeWidth: ")
|
|
|
|
|
.append(widgetProviderInfo.minResizeWidth)
|
|
|
|
|
.append("\n")
|
|
|
|
|
.append("minResizeHeight: ")
|
|
|
|
|
.append(widgetProviderInfo.minResizeHeight)
|
|
|
|
|
.append("\n")
|
|
|
|
|
.append("defaultWidth: ")
|
|
|
|
|
.append(widgetProviderInfo.minWidth)
|
|
|
|
|
.append("\n")
|
|
|
|
|
.append("defaultHeight: ")
|
|
|
|
|
.append(widgetProviderInfo.minHeight)
|
|
|
|
|
.append("\n");
|
|
|
|
|
if (Utilities.ATLEAST_S) {
|
|
|
|
|
widgetDimension.append("targetCellWidth: ")
|
|
|
|
|
.append(widgetProviderInfo.targetCellWidth)
|
|
|
|
|
.append("\n")
|
|
|
|
|
.append("targetCellHeight: ")
|
|
|
|
|
.append(widgetProviderInfo.targetCellHeight)
|
|
|
|
|
.append("\n")
|
|
|
|
|
.append("maxResizeWidth: ")
|
|
|
|
|
.append(widgetProviderInfo.maxResizeWidth)
|
|
|
|
|
.append("\n")
|
|
|
|
|
.append("maxResizeHeight: ")
|
|
|
|
|
.append(widgetProviderInfo.maxResizeHeight)
|
|
|
|
|
.append("\n");
|
|
|
|
|
}
|
|
|
|
|
FileLog.d(TAG, widgetDimension.toString());
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-19 11:17:42 -07:00
|
|
|
private static void logASplit(final TimingLogger logger, final String label) {
|
|
|
|
|
logger.addSplit(label);
|
|
|
|
|
if (DEBUG) {
|
|
|
|
|
Log.d(TAG, label);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-06 10:46:59 -07:00
|
|
|
}
|