Android12 Launcher3显示所有应用列表

article/2025/7/29 12:46:07

Android12 Launcher3显示所有应用列表

1.前言:

最近在Android12Rom定制时需要显示所有桌面应用的图标,并且不能去掉抽屉,在手机上面抽屉和所有应该列表是两种不同模式,用户基可以自行选择,但是在自定义的launcher中这些和原生Rom一起定制时会出现,特别在Android12及以上的版本,这里就讲解一下不去掉抽屉的方式在桌面显示所有应用App图标.

1.修改config.xml

源码路径:packages/apps/launcher3/res/value/config.xml

添加以下代码:

<string name="app_filter_class" translatable="false"></string>
<resources><!-- Miscellaneous --><bool name="config_largeHeap">false</bool><bool name="allow_rotation">false</bool><integer name="extracted_color_gradient_alpha">153</integer><!-- A string pointer to the original app name string. This allows derived projects toeasily override the app name without providing all translations --><string name="derived_app_name" translatable="false">@string/app_name</string><!-- String representing the intent for search on the apps market. To specify a query, addq=<query> to the data to the intent --><string name="market_search_intent" translatable="false">market://search?c=apps</string><!-- String representing the intent to delete a package.--><string name="delete_package_intent" translatable="false">#Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;end</string><!-- String representing the fragment class for settings activity.--><string name="settings_fragment_name" translatable="false">com.android.launcher3.settings.SettingsActivity$LauncherSettingsFragment</string><!-- DragController --><item type="id" name="drag_event_parity" /><!-- AllApps & Launcher transitions --><!-- Out of 100, the percent to shrink the workspace during spring loaded mode. --><integer name="config_workspaceSpringLoadShrinkPercentage">90</integer><!-- The duration of the animation from search hint to text entry --><integer name="config_searchHintAnimationDuration">50</integer><!-- View tag key used to store SpringAnimation data. --><item type="id" name="spring_animation_tag" /><!-- Workspace --><!-- The duration (in ms) of the fade animation on the object outlines, used whenwe are dragging objects around on the home screen. --><integer name="config_dragOutlineFadeTime">900</integer><!-- The alpha value at which to show the most recent drop visualization outline. --><integer name="config_dragOutlineMaxAlpha">128</integer><!-- Parameters controlling the animation for when an item is dropped on the home screen,and it animates from its old position to the new one. --><integer name="config_dropAnimMinDuration">100</integer><integer name="config_dropAnimMaxDuration">500</integer><!-- The duration of the UserFolder opening and closing animation --><integer name="config_materialFolderExpandDuration">200</integer><integer name="config_folderDelay">30</integer><!-- The distance at which the animation should take the max duration --><integer name="config_dropAnimMaxDist">800</integer><!-- The duration of the caret animation --><integer name="config_caretAnimationDuration">200</integer><!-- Hotseat --><bool name="hotseat_transpose_layout_with_orientation">true</bool><!-- Various classes overriden by projects/build flavors. --><string name="app_filter_class" translatable="false"></string><string name="user_event_dispatcher_class" translatable="false"></string><string name="folder_name_provider_class" translatable="false"></string><string name="stats_log_manager_class" translatable="false"></string><string name="app_transition_manager_class" translatable="false"></string><string name="instant_app_resolver_class" translatable="false"></string><string name="main_process_initializer_class" translatable="false"></string><string name="app_launch_tracker_class" translatable="false"></string><string name="test_information_handler_class" translatable="false"></string><string name="launcher_activity_logic_class" translatable="false"></string><string name="prediction_model_class" translatable="false"></string><!-- View ID to use for QSB widget --><item type="id" name="qsb_widget" /><!-- View ID used by cell layout to jail its content --><item type="id" name="cell_layout_jail_id" /><!-- View IDs to store item highlight information --><item type="id" name="view_unhighlight_background" /><!-- Menu id for feature flags --><item type="id" name="menu_apply_flags" /><!-- Popup items --><integer name="config_popupOpenCloseDuration">150</integer><integer name="config_popupArrowOpenCloseDuration">40</integer><integer name="config_removeNotificationViewDuration">300</integer><!-- Default packages --><string name="wallpaper_picker_package" translatable="false"></string><string name="calendar_component_name" translatable="false"></string><string name="clock_component_name" translatable="false"></string><!-- Accessibility actions --><item type="id" name="action_remove" /><item type="id" name="action_uninstall" /><item type="id" name="action_reconfigure" /><item type="id" name="action_add_to_workspace" /><item type="id" name="action_move" /><item type="id" name="action_move_to_workspace" /><item type="id" name="action_move_screen_backwards" /><item type="id" name="action_move_screen_forwards" /><item type="id" name="action_resize" /><item type="id" name="action_deep_shortcuts" /><item type="id" name="action_shortcuts_and_notifications"/><item type="id" name="action_dismiss_notification" /><item type="id" name="action_remote_action_shortcut" /><item type="id" name="action_dismiss_prediction" /><item type="id" name="action_pin_prediction"/><!-- QSB IDs. DO not change --><item type="id" name="search_container_workspace" /><item type="id" name="search_container_all_apps" /><!-- Recents --><item type="id" name="overview_panel"/><!-- Whether to enable background preloading of task thumbnails. --><bool name="config_enableTaskSnapshotPreloading">true</bool><!-- Configuration resources --><item name="all_apps_spring_damping_ratio" type="dimen" format="float">0.75</item><item name="all_apps_spring_stiffness" type="dimen" format="float">600</item><item name="dismiss_task_trans_y_damping_ratio" type="dimen" format="float">0.73</item><item name="dismiss_task_trans_y_stiffness" type="dimen" format="float">800</item><item name="dismiss_task_trans_x_damping_ratio" type="dimen" format="float">0.73</item><item name="dismiss_task_trans_x_stiffness" type="dimen" format="float">800</item><item name="horizontal_spring_damping_ratio" type="dimen" format="float">0.8</item><item name="horizontal_spring_stiffness" type="dimen" format="float">250</item><item name="swipe_up_rect_scale_damping_ratio" type="dimen" format="float">0.75</item><item name="swipe_up_rect_scale_stiffness" type="dimen" format="float">200</item><item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item><item name="swipe_up_rect_xy_damping_ratio" type="dimen" format="float">0.8</item><item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">200</item><item name="staggered_damping_ratio" type="dimen" format="float">0.7</item><item name="staggered_stiffness" type="dimen" format="float">150</item><dimen name="unlock_staggered_velocity_dp_per_s">4dp</dimen><item name="hint_scale_damping_ratio" type="dimen" format="float">0.7</item><item name="hint_scale_stiffness" type="dimen" format="float">200</item><dimen name="hint_scale_velocity_dp_per_s">0.3dp</dimen><!-- Swipe up to home related --><dimen name="swipe_up_fling_min_visible_change">18dp</dimen><dimen name="swipe_up_y_overshoot">10dp</dimen><dimen name="swipe_up_max_workspace_trans_y">-60dp</dimen><array name="dynamic_resources"><item>@dimen/all_apps_spring_damping_ratio</item><item>@dimen/all_apps_spring_stiffness</item><item>@dimen/dismiss_task_trans_y_damping_ratio</item><item>@dimen/dismiss_task_trans_y_stiffness</item><item>@dimen/dismiss_task_trans_x_damping_ratio</item><item>@dimen/dismiss_task_trans_x_stiffness</item><item>@dimen/horizontal_spring_damping_ratio</item><item>@dimen/horizontal_spring_stiffness</item><item>@dimen/swipe_up_rect_scale_damping_ratio</item><item>@dimen/swipe_up_rect_scale_stiffness</item><item>@dimen/swipe_up_rect_xy_fling_friction</item><item>@dimen/swipe_up_rect_xy_damping_ratio</item><item>@dimen/swipe_up_rect_xy_stiffness</item><item>@dimen/staggered_damping_ratio</item><item>@dimen/staggered_stiffness</item><item>@dimen/unlock_staggered_velocity_dp_per_s</item><item>@dimen/swipe_up_fling_min_visible_change</item><item>@dimen/swipe_up_y_overshoot</item><item>@dimen/hint_scale_damping_ratio</item><item>@dimen/hint_scale_stiffness</item><item>@dimen/hint_scale_velocity_dp_per_s</item></array><string-array name="live_wallpapers_remove_sysui_scrims"></string-array><string name="calendar_component_name" translatable="false">com.android.calendar/com.android.calendar.AllInOneActivity</string><string name="clock_component_name" translatable="false">com.android.deskclock/com.android.deskclock.DeskClock</string><!--Add for dynamic icon feature: start--><!-- The default state of the dynamic icon, true: open, false: closed --><bool name="dynamic_calendar_default_state">true</bool><bool name="dynamic_clock_default_state">true</bool><!--Add for dynamic icon feature: end-->
</resources>

2.修改AppFilter:

源码路径:packages/apps/launcher3/src/com/android/launcher3/AppFilter.java

public class AppFilter implements ResourceBasedOverride {
private final Set<ComponentName> mFilteredComponents;.collect(Collectors.toSet());
}public static AppFilter newInstance(Context context) {return Overrides.getObject(AppFilter.class, context, R.string.app_filter_class);
}public boolean shouldShowApp(ComponentName app) {//显示所有App// return !mFilteredComponents.contains(app);//add startreturn true;//add end
}
}

3.修改SessionCommitReceiver:

源码路径:packages/apps/launcher3/src/com/android/launcher3/SessionCommitReceiver.java

核心修改如下:

    if (TextUtils.isEmpty(info.getAppPackageName())//add start// || info.getInstallReason() != PackageManager.INSTALL_REASON_USER//add end|| packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {packageInstallerCompat.removePromiseIconId(info.getSessionId());return;}
/** Copyright (C) 2008 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;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.text.TextUtils;import androidx.annotation.WorkerThread;import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.util.Executors;/*** BroadcastReceiver to handle session commit intent.*/
public class SessionCommitReceiver extends BroadcastReceiver {private static final String LOG = "SessionCommitReceiver";// Preference key for automatically adding icon to homescreen.public static final String ADD_ICON_PREFERENCE_KEY = "pref_add_icon_to_home";@Overridepublic void onReceive(Context context, Intent intent) {Executors.MODEL_EXECUTOR.execute(() -> processIntent(context, intent));}@WorkerThreadprivate static void processIntent(Context context, Intent intent) {if (!isEnabled(context)) {// User has decided to not add icons on homescreen.return;}SessionInfo info = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);if (!PackageInstaller.ACTION_SESSION_COMMITTED.equals(intent.getAction())|| info == null || user == null) {// Invalid intent.return;}InstallSessionHelper packageInstallerCompat = InstallSessionHelper.INSTANCE.get(context);packageInstallerCompat.restoreDbIfApplicable(info);if (TextUtils.isEmpty(info.getAppPackageName())//add start// || info.getInstallReason() != PackageManager.INSTALL_REASON_USER//add end|| packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {packageInstallerCompat.removePromiseIconId(info.getSessionId());return;}FileLog.d(LOG,"Adding package name to install queue. Package name: " + info.getAppPackageName()+ ", has app icon: " + (info.getAppIcon() != null)+ ", has app label: " + !TextUtils.isEmpty(info.getAppLabel()));ItemInstallQueue.INSTANCE.get(context).queueItem(info.getAppPackageName(), user);}public static boolean isEnabled(Context context) {return Utilities.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true);}
}

4.修改FeatureFlags:

源码路径:packages/apps/launcher3/src/com/android/launcher3/config/FeatureFlags.java

核心修改如下:

/*** true: All applications are displayed in the workspace. Turn off the display of the allapp list*/
public static final boolean REMOVE_DRAWER  = true;

5.修改AddWorkspaceItemsTask:

源码路径:packages/apps/launcher3/src/com/android/launcher3/model/AddWorkspaceItemsTask.java

package com.android.launcher3.model;import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller.SessionInfo;
import android.os.UserHandle;
import android.util.LongSparseArray;
import android.util.Pair;import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.config.FeatureFlags;
import java.util.ArrayList;
import java.util.List;/*** Task to add auto-created workspace items.*/
public class AddWorkspaceItemsTask extends BaseModelUpdateTask {private static final String LOG = "AddWorkspaceItemsTask";private final List<Pair<ItemInfo, Object>> mItemList;/*** @param itemList items to add on the workspace*/public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) {mItemList = itemList;}@Overridepublic void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {if (mItemList.isEmpty()) {return;}final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();final IntArray addedWorkspaceScreensFinal = new IntArray();synchronized(dataModel) {IntArray workspaceScreens = dataModel.collectWorkspaceScreens();List<ItemInfo> filteredItems = new ArrayList<>();for (Pair<ItemInfo, Object> entry : mItemList) {ItemInfo item = entry.first;if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {// Short-circuit this logic if the icon exists somewhere on the workspaceif (shortcutExists(dataModel, item.getIntent(), item.user)) {continue;}// b/139663018 Short-circuit this logic if the icon is a system app// add start/*     if(!FeatureFlags.REMOVE_DRAWER){if (PackageManagerHelper.isSystemApp(app.getContext(), item.getIntent())) {continue;}} */// add end}if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {if (item instanceof AppInfo) {item = ((AppInfo) item).makeWorkspaceItem();}}if (item != null) {filteredItems.add(item);}}InstallSessionHelper packageInstaller =InstallSessionHelper.INSTANCE.get(app.getContext());LauncherApps launcherApps = app.getContext().getSystemService(LauncherApps.class);for (ItemInfo item : filteredItems) {// Find appropriate space for the item.int[] coords = findSpaceForItem(app, dataModel, workspaceScreens,addedWorkspaceScreensFinal, item.spanX, item.spanY);int screenId = coords[0];ItemInfo itemInfo;if (item instanceof WorkspaceItemInfo || item instanceof FolderInfo ||item instanceof LauncherAppWidgetInfo) {itemInfo = item;} else if (item instanceof AppInfo) {itemInfo = ((AppInfo) item).makeWorkspaceItem();} else {throw new RuntimeException("Unexpected info type");}if (item instanceof WorkspaceItemInfo && ((WorkspaceItemInfo) item).isPromise()) {WorkspaceItemInfo workspaceInfo = (WorkspaceItemInfo) item;String packageName = item.getTargetComponent() != null? item.getTargetComponent().getPackageName() : null;if (packageName == null) {continue;}SessionInfo sessionInfo = packageInstaller.getActiveSessionInfo(item.user,packageName);if (!packageInstaller.verifySessionInfo(sessionInfo)) {FileLog.d(LOG, "Item info failed session info verification. "+ "Skipping : " + workspaceInfo);continue;}List<LauncherActivityInfo> activities = launcherApps.getActivityList(packageName, item.user);boolean hasActivity = activities != null && !activities.isEmpty();if (sessionInfo == null) {if (!hasActivity) {// Session was cancelled, do not add.continue;}} else {workspaceInfo.setProgressLevel((int) (sessionInfo.getProgress() * 100),PackageInstallInfo.STATUS_INSTALLING);}if (hasActivity) {// App was installed while launcher was in the background,// or app was already installed for another user.itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user).makeWorkspaceItem();if (shortcutExists(dataModel, itemInfo.getIntent(), itemInfo.user)) {// We need this additional check here since we treat all auto added// workspace items as promise icons. At this point we now have the// correct intent to compare against existing workspace icons.// Icon already exists on the workspace and should not be auto-added.continue;}WorkspaceItemInfo wii = (WorkspaceItemInfo) itemInfo;wii.title = "";wii.bitmap = app.getIconCache().getDefaultIcon(item.user);app.getIconCache().getTitleAndIcon(wii,((WorkspaceItemInfo) itemInfo).usingLowResIcon());}}// Add the shortcut to the dbgetModelWriter().addItemToDatabase(itemInfo,LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId,coords[1], coords[2]);// Save the WorkspaceItemInfo for binding in the workspaceaddedItemsFinal.add(itemInfo);// log bitmap and labelFileLog.d(LOG, "Adding item info to workspace: " + itemInfo);}}if (!addedItemsFinal.isEmpty()) {scheduleCallbackTask(new CallbackTask() {@Overridepublic void execute(Callbacks callbacks) {final ArrayList<ItemInfo> addAnimated = new ArrayList<>();final ArrayList<ItemInfo> addNotAnimated = new ArrayList<>();if (!addedItemsFinal.isEmpty()) {ItemInfo info = addedItemsFinal.get(addedItemsFinal.size() - 1);int lastScreenId = info.screenId;for (ItemInfo i : addedItemsFinal) {if (i.screenId == lastScreenId) {addAnimated.add(i);} else {addNotAnimated.add(i);}}}callbacks.bindAppsAdded(addedWorkspaceScreensFinal,addNotAnimated, addAnimated);}});}}/*** Returns true if the shortcuts already exists on the workspace. This must be called after* the workspace has been loaded. We identify a shortcut by its intent.*/protected boolean shortcutExists(BgDataModel dataModel, Intent intent, UserHandle user) {final String compPkgName, intentWithPkg, intentWithoutPkg;if (intent == null) {// Skip items with null intentsreturn true;}if (intent.getComponent() != null) {// If component is not null, an intent with null package will produce// the same result and should also be a match.compPkgName = intent.getComponent().getPackageName();if (intent.getPackage() != null) {intentWithPkg = intent.toUri(0);intentWithoutPkg = new Intent(intent).setPackage(null).toUri(0);} else {intentWithPkg = new Intent(intent).setPackage(compPkgName).toUri(0);intentWithoutPkg = intent.toUri(0);}} else {compPkgName = null;intentWithPkg = intent.toUri(0);intentWithoutPkg = intent.toUri(0);}boolean isLauncherAppTarget = PackageManagerHelper.isLauncherAppTarget(intent);synchronized (dataModel) {for (ItemInfo item : dataModel.itemsIdMap) {if (item instanceof WorkspaceItemInfo) {WorkspaceItemInfo info = (WorkspaceItemInfo) item;if (item.getIntent() != null && info.user.equals(user)) {Intent copyIntent = new Intent(item.getIntent());copyIntent.setSourceBounds(intent.getSourceBounds());String s = copyIntent.toUri(0);if (intentWithPkg.equals(s) || intentWithoutPkg.equals(s)) {return true;}// checking for existing promise icon with same package nameif (isLauncherAppTarget&& info.isPromise()&& info.hasStatusFlag(WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON)&& info.getTargetComponent() != null&& compPkgName != null&& compPkgName.equals(info.getTargetComponent().getPackageName())) {return true;}}}}}return false;}/*** Find a position on the screen for the given size or adds a new screen.* @return screenId and the coordinates for the item in an int array of size 3.*/protected int[] findSpaceForItem( LauncherAppState app, BgDataModel dataModel,IntArray workspaceScreens, IntArray addedWorkspaceScreensFinal, int spanX, int spanY) {LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();// Use sBgItemsIdMap as all the items are already loaded.synchronized (dataModel) {for (ItemInfo info : dataModel.itemsIdMap) {if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {ArrayList<ItemInfo> items = screenItems.get(info.screenId);if (items == null) {items = new ArrayList<>();screenItems.put(info.screenId, items);}items.add(info);}}}// Find appropriate space for the item.int screenId = 0;int[] cordinates = new int[2];boolean found = false;int screenCount = workspaceScreens.size();// First check the preferred screen.int preferredScreenIndex = workspaceScreens.isEmpty() ? 0 : 1;// add startif (FeatureFlags.REMOVE_DRAWER) {preferredScreenIndex = 0;}// add endif (preferredScreenIndex < screenCount) {screenId = workspaceScreens.get(preferredScreenIndex);found = findNextAvailableIconSpaceInScreen(app, screenItems.get(screenId), cordinates, spanX, spanY);}if (!found) {// Search on any of the screens starting from the first screen.for (int screen = 0; screen < screenCount; screen++) {screenId = workspaceScreens.get(screen);if (findNextAvailableIconSpaceInScreen(app, screenItems.get(screenId), cordinates, spanX, spanY)) {// We found a space for itfound = true;break;}}}if (!found) {// Still no position found. Add a new screen to the end.screenId = LauncherSettings.Settings.call(app.getContext().getContentResolver(),LauncherSettings.Settings.METHOD_NEW_SCREEN_ID).getInt(LauncherSettings.Settings.EXTRA_VALUE);// Save the screen id for binding in the workspaceworkspaceScreens.add(screenId);addedWorkspaceScreensFinal.add(screenId);// If we still can't find an empty space, then God help us all!!!if (!findNextAvailableIconSpaceInScreen(app, screenItems.get(screenId), cordinates, spanX, spanY)) {throw new RuntimeException("Can't find space to add the item");}}return new int[] {screenId, cordinates[0], cordinates[1]};}private boolean findNextAvailableIconSpaceInScreen(LauncherAppState app, ArrayList<ItemInfo> occupiedPos,int[] xy, int spanX, int spanY) {InvariantDeviceProfile profile = app.getInvariantDeviceProfile();GridOccupancy occupied = new GridOccupancy(profile.numColumns, profile.numRows);if (occupiedPos != null) {for (ItemInfo r : occupiedPos) {occupied.markCells(r, true);}}return occupied.findVacantCell(xy, spanX, spanY);}}

7.修改BaseModelUpdateTask:

源码路径:packages/apps/launcher3/src/com/android/launcher3/model/BaseModelUpdateTask.java

package com.android.launcher3.model;import android.util.Log;import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;/*** Extension of {@link ModelUpdateTask} with some utility methods*/
public abstract class BaseModelUpdateTask implements ModelUpdateTask {private static final boolean DEBUG_TASKS = false;private static final String TAG = "BaseModelUpdateTask";private LauncherAppState mApp;private LauncherModel mModel;private BgDataModel mDataModel;private AllAppsList mAllAppsList;private Executor mUiExecutor;public void init(LauncherAppState app, LauncherModel model,BgDataModel dataModel, AllAppsList allAppsList, Executor uiExecutor) {mApp = app;mModel = model;mDataModel = dataModel;mAllAppsList = allAppsList;mUiExecutor = uiExecutor;}@Overridepublic final void run() {if (!mModel.isModelLoaded()) {if (DEBUG_TASKS) {Log.d(TAG, "Ignoring model task since loader is pending=" + this);}// Loader has not yet run.//add start/*     if(!FeatureFlags.REMOVE_DRAWER){return;} *///add end}execute(mApp, mDataModel, mAllAppsList);}/*** Execute the actual task. Called on the worker thread.*/public abstract void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps);/*** Schedules a {@param task} to be executed on the current callbacks.*/public final void scheduleCallbackTask(final CallbackTask task) {for (final Callbacks cb : mModel.getCallbacks()) {mUiExecutor.execute(() -> task.execute(cb));}}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 callbacksreturn mModel.getWriter(false /* hasVerticalHotseat */, false /* verifyChanges */);}public void bindUpdatedWorkspaceItems(List<WorkspaceItemInfo> allUpdates) {// Bind workspace itemsList<WorkspaceItemInfo> workspaceUpdates = allUpdates.stream().filter(info -> info.id != ItemInfo.NO_ID).collect(Collectors.toList());if (!workspaceUpdates.isEmpty()) {scheduleCallbackTask(c -> c.bindWorkspaceItemsChanged(workspaceUpdates));}// Bind extra items if anyallUpdates.stream().mapToInt(info -> info.container).distinct().mapToObj(mDataModel.extraItems::get).filter(Objects::nonNull).forEach(this::bindExtraContainerItems);}public void bindExtraContainerItems(FixedContainerItems item) {FixedContainerItems copy = item.clone();scheduleCallbackTask(c -> c.bindExtraContainerItems(copy));}public void bindDeepShortcuts(BgDataModel dataModel) {final HashMap<ComponentKey, Integer> shortcutMapCopy =new HashMap<>(dataModel.deepShortcutMap);scheduleCallbackTask(callbacks -> callbacks.bindDeepShortcutMap(shortcutMapCopy));}public void bindUpdatedWidgets(BgDataModel dataModel) {final ArrayList<WidgetsListBaseEntry> widgets =dataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());scheduleCallbackTask(c -> c.bindAllWidgets(widgets));}public void deleteAndBindComponentsRemoved(final ItemInfoMatcher matcher) {getModelWriter().deleteItemsFromDatabase(matcher);// Call the components-removed callbackscheduleCallbackTask(c -> c.bindWorkspaceComponentsRemoved(matcher));}public void bindApplicationsIfNeeded() {if (mAllAppsList.getAndResetChangeFlag()) {AppInfo[] apps = mAllAppsList.copyData();int flags = mAllAppsList.getFlags();scheduleCallbackTask(c -> c.bindAllApplications(apps, flags));}}
}

8.修改ItemInstallQueue:

源码路径:packages/apps/launcher3/src/com/android/launcher3/model/ItemInstallQueue.java

package com.android.launcher3.model;import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.PersistedItemArray;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Class to maintain a queue of pending items to be added to the workspace.*/
public class ItemInstallQueue {private static final String LOG = "ItemInstallQueue";public static final int FLAG_ACTIVITY_PAUSED = 1;public static final int FLAG_LOADER_RUNNING = 2;public static final int FLAG_DRAG_AND_DROP = 4;private static final String TAG = "InstallShortcutReceiver";// The set of shortcuts that are pending installprivate static final String APPS_PENDING_INSTALL = "apps_to_install";public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;public static MainThreadInitializedObject<ItemInstallQueue> INSTANCE =new MainThreadInitializedObject<>(ItemInstallQueue::new);private final PersistedItemArray<PendingInstallShortcutInfo> mStorage =new PersistedItemArray<>(APPS_PENDING_INSTALL);private final Context mContext;// Determines whether to defer installing shortcuts immediately until// processAllPendingInstalls() is called.private int mInstallQueueDisabledFlags = 0;// Only accessed on worker threadprivate List<PendingInstallShortcutInfo> mItems;private ItemInstallQueue(Context context) {mContext = context;}@WorkerThreadprivate void ensureQueueLoaded() {Preconditions.assertWorkerThread();if (mItems == null) {mItems = mStorage.read(mContext, this::decode);}}@WorkerThreadpublic void addToQueue(PendingInstallShortcutInfo info) {ensureQueueLoaded();if (!mItems.contains(info)) {mItems.add(info);mStorage.write(mContext, mItems);}}@WorkerThreadprivate void flushQueueInBackground() {Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();if (launcher == null) {// Launcher not loadedreturn;}ensureQueueLoaded();if (mItems.isEmpty()) {return;}List<Pair<ItemInfo, Object>> installQueue = mItems.stream().map(info -> info.getItemInfo(mContext)).collect(Collectors.toList());// Add the items and clear queueif (!installQueue.isEmpty()) {// add loglauncher.getModel().addAndBindAddedWorkspaceItems(installQueue);}mItems.clear();mStorage.getFile(mContext).delete();}/*** Removes previously added items from the queue.*/@WorkerThreadpublic void removeFromInstallQueue(HashSet<String> packageNames, UserHandle user) {if (packageNames.isEmpty()) {return;}ensureQueueLoaded();if (mItems.removeIf(item ->item.user.equals(user) && packageNames.contains(getIntentPackage(item.intent)))) {mStorage.write(mContext, mItems);}}/*** Adds an item to the install queue*/public void queueItem(ShortcutInfo info) {queuePendingShortcutInfo(new PendingInstallShortcutInfo(info));}/*** Adds an item to the install queue*/public void queueItem(AppWidgetProviderInfo info, int widgetId) {queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, widgetId));}/*** Adds an item to the install queue*/public void queueItem(String packageName, UserHandle userHandle) {queuePendingShortcutInfo(new PendingInstallShortcutInfo(packageName, userHandle));}/*** Returns a stream of all pending shortcuts in the queue*/@WorkerThreadpublic Stream<ShortcutKey> getPendingShortcuts(UserHandle user) {ensureQueueLoaded();return mItems.stream().filter(item -> item.itemType == ITEM_TYPE_DEEP_SHORTCUT && user.equals(item.user)).map(item -> ShortcutKey.fromIntent(item.intent, user));}private void queuePendingShortcutInfo(PendingInstallShortcutInfo info) {final Exception stackTrace = new Exception();// Queue the item up for adding if launcher has not loaded properly yetMODEL_EXECUTOR.post(() -> {Pair<ItemInfo, Object> itemInfo = info.getItemInfo(mContext);if (itemInfo == null) {FileLog.d(LOG,"Adding PendingInstallShortcutInfo with no attached info to queue.",stackTrace);} else {FileLog.d(LOG,"Adding PendingInstallShortcutInfo to queue. Attached info: "+ itemInfo.first,stackTrace);}addToQueue(info);});flushInstallQueue();}/*** Pauses the push-to-model flow until unpaused. All items are held in the queue and* not added to the model.*/public void pauseModelPush(int flag) {mInstallQueueDisabledFlags |= flag;}/*** Adds all the queue items to the model if the use is completely resumed.*/public void resumeModelPush(int flag) {mInstallQueueDisabledFlags &= ~flag;flushInstallQueue();}private void flushInstallQueue() {if (mInstallQueueDisabledFlags != 0) {return;}MODEL_EXECUTOR.post(this::flushQueueInBackground);}private static class PendingInstallShortcutInfo extends ItemInfo {final Intent intent;@Nullable ShortcutInfo shortcutInfo;@Nullable AppWidgetProviderInfo providerInfo;/*** Initializes a PendingInstallShortcutInfo to represent a pending launcher target.*/public PendingInstallShortcutInfo(String packageName, UserHandle userHandle) {itemType = Favorites.ITEM_TYPE_APPLICATION;intent = new Intent().setPackage(packageName);user = userHandle;}/*** Initializes a PendingInstallShortcutInfo to represent a deep shortcut.*/public PendingInstallShortcutInfo(ShortcutInfo info) {itemType = Favorites.ITEM_TYPE_DEEP_SHORTCUT;intent = ShortcutKey.makeIntent(info);user = info.getUserHandle();shortcutInfo = info;}/*** Initializes a PendingInstallShortcutInfo to represent an app widget.*/public PendingInstallShortcutInfo(AppWidgetProviderInfo info, int widgetId) {itemType = Favorites.ITEM_TYPE_APPWIDGET;intent = new Intent().setComponent(info.provider).putExtra(EXTRA_APPWIDGET_ID, widgetId);user = info.getProfile();providerInfo = info;}@Overridepublic Intent getIntent() {return intent;}public Pair<ItemInfo, Object> getItemInfo(Context context) {switch (itemType) {case ITEM_TYPE_APPLICATION: {String packageName = intent.getPackage();List<LauncherActivityInfo> laiList =context.getSystemService(LauncherApps.class).getActivityList(packageName, user);final WorkspaceItemInfo si = new WorkspaceItemInfo();si.user = user;si.itemType = ITEM_TYPE_APPLICATION;LauncherActivityInfo lai;boolean usePackageIcon = laiList.isEmpty();if (usePackageIcon) {lai = null;si.intent = makeLaunchIntent(new ComponentName(packageName, "")).setPackage(packageName);si.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;} else {lai = laiList.get(0);si.intent = makeLaunchIntent(lai);}LauncherAppState.getInstance(context).getIconCache().getTitleAndIcon(si, () -> lai, usePackageIcon, false);return Pair.create(si, null);}case ITEM_TYPE_DEEP_SHORTCUT: {WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, context);LauncherAppState.getInstance(context).getIconCache().getShortcutIcon(itemInfo, shortcutInfo);return Pair.create(itemInfo, shortcutInfo);}case ITEM_TYPE_APPWIDGET: {LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo.fromProviderInfo(context, providerInfo);LauncherAppWidgetInfo widgetInfo = new LauncherAppWidgetInfo(intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0),info.provider);InvariantDeviceProfile idp = LauncherAppState.getIDP(context);widgetInfo.minSpanX = info.minSpanX;widgetInfo.minSpanY = info.minSpanY;widgetInfo.spanX = Math.min(info.spanX, idp.numColumns);widgetInfo.spanY = Math.min(info.spanY, idp.numRows);widgetInfo.user = user;return Pair.create(widgetInfo, providerInfo);}}return null;}@Overridepublic boolean equals(Object obj) {if (obj instanceof PendingInstallShortcutInfo) {PendingInstallShortcutInfo other = (PendingInstallShortcutInfo) obj;boolean userMatches = user.equals(other.user);boolean itemTypeMatches = itemType == other.itemType;boolean intentMatches = intent.toUri(0).equals(other.intent.toUri(0));boolean shortcutInfoMatches = shortcutInfo == null? other.shortcutInfo == null: other.shortcutInfo != null&& shortcutInfo.getId().equals(other.shortcutInfo.getId())&& shortcutInfo.getPackage().equals(other.shortcutInfo.getPackage());boolean providerInfoMatches = providerInfo == null? other.providerInfo == null: other.providerInfo != null&& providerInfo.provider.equals(other.providerInfo.provider);return userMatches&& itemTypeMatches&& intentMatches&& shortcutInfoMatches&& providerInfoMatches;}return false;}}private static String getIntentPackage(Intent intent) {return intent.getComponent() == null? intent.getPackage() : intent.getComponent().getPackageName();}private PendingInstallShortcutInfo decode(int itemType, UserHandle user, Intent intent) {switch (itemType) {case Favorites.ITEM_TYPE_APPLICATION:return new PendingInstallShortcutInfo(intent.getPackage(), user);case Favorites.ITEM_TYPE_DEEP_SHORTCUT: {List<ShortcutInfo> si = ShortcutKey.fromIntent(intent, user).buildRequest(mContext).query(ShortcutRequest.ALL);if (si.isEmpty()) {return null;} else {return new PendingInstallShortcutInfo(si.get(0));}}case Favorites.ITEM_TYPE_APPWIDGET: {int widgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0);AppWidgetProviderInfo info =AppWidgetManager.getInstance(mContext).getAppWidgetInfo(widgetId);if (info == null || !info.provider.equals(intent.getComponent())|| !info.getProfile().equals(user)) {return null;}return new PendingInstallShortcutInfo(info, widgetId);}default:Log.e(TAG, "Unknown item type");}return null;}
}

9.修改LoaderTask:

源码路径:packages/apps/launcher3/src/com/android/launcher3/model/LoaderTask.java

/** 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;import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO;
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;
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;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission;
import static com.android.launcher3.util.PackageManagerHelper.isSystemApp;import android.annotation.SuppressLint;
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;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.TimingLogger;
import android.util.Pair;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
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;
import com.android.launcher3.folder.FolderGridOrganizer;
import com.android.launcher3.folder.FolderNameInfos;
import com.android.launcher3.folder.FolderNameProvider;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherActivityCachingLogic;
import com.android.launcher3.icons.ShortcutCachingLogic;
import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.ImportDataTask;
import com.android.launcher3.qsb.QsbContainerView;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.PackageManagerHelper;
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.allapps.AppInfoComparator;import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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";private static final boolean DEBUG = true;protected final LauncherAppState mApp;private final AllAppsList mBgAllAppsList;protected final BgDataModel mBgDataModel;private final ModelDelegate mModelDelegate;private FirstScreenBroadcast mFirstScreenBroadcast;private final LoaderResults mResults;private final LauncherApps mLauncherApps;private final UserManager mUserManager;private final UserCache mUserCache;private final InstallSessionHelper mSessionHelper;private final IconCache mIconCache;private final UserManagerState mUserManagerState = new UserManagerState();protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>();private boolean mStopped;private final Set<PackageUserKey> mPendingPackages = new HashSet<>();private boolean mItemsDeleted = false;private String mDbName;public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,ModelDelegate modelDelegate, LoaderResults results) {mApp = app;mBgAllAppsList = bgAllAppsList;mBgDataModel = dataModel;mModelDelegate = modelDelegate;mResults = results;mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);mUserManager = mApp.getContext().getSystemService(UserManager.class);mUserCache = UserCache.INSTANCE.get(mApp.getContext());mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext());mIconCache = mApp.getIconCache();}protected synchronized void waitForIdle() {// 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.LooperIdleLock idleLock = mResults.newIdleLock(this);// Just in case mFlushingWorkerThread changes but we aren't woken up,// wait no longer than 1sec at a timewhile (!mStopped && idleLock.awaitLocked(1000));}private synchronized void verifyNotStopped() throws CancellationException {if (mStopped) {throw new CancellationException("Loader stopped");}}private void sendFirstScreenActiveInstallsBroadcast() {ArrayList<ItemInfo> firstScreenItems = new ArrayList<>();ArrayList<ItemInfo> allItems = mBgDataModel.getAllWorkspaceItems();// Screen set is never emptyfinal int firstScreen = mBgDataModel.collectWorkspaceScreens().get(0);filterCurrentWorkspaceItems(firstScreen, allItems, firstScreenItems,new ArrayList<>() /* otherScreenItems are ignored */);mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems);}public void run() {synchronized (this) {// Skip fast if we are already stopped.if (mStopped) {return;}}Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);TimingLogger logger = new TimingLogger(TAG, "run");try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {List<ShortcutInfo> allShortcuts = new ArrayList<>();loadWorkspace(allShortcuts);logASplit(logger, "loadWorkspace");// 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();logASplit(logger, "sanitizeData");}verifyNotStopped();mResults.bindWorkspace();logASplit(logger, "bindWorkspace");mModelDelegate.workspaceLoadComplete();// Notify the installer packages of packages with active installs on the first screen.sendFirstScreenActiveInstallsBroadcast();logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");// Take a breakwaitForIdle();logASplit(logger, "step 1 complete");verifyNotStopped();// second stepList<LauncherActivityInfo> allActivityList = loadAllApps();logASplit(logger, "loadAllApps");// add startif (FeatureFlags.REMOVE_DRAWER) {bindAllAppsToWorkspace();}// add endverifyNotStopped();mResults.bindAllApps();logASplit(logger, "bindAllApps");verifyNotStopped();IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();setIgnorePackages(updateHandler);updateHandler.updateIcons(allActivityList,LauncherActivityCachingLogic.newInstance(mApp.getContext()),mApp.getModel()::onPackageIconsUpdated);logASplit(logger, "update icon cache");if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {verifyNotStopped();logASplit(logger, "save shortcuts in icon cache");updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),mApp.getModel()::onPackageIconsUpdated);}// Take a breakwaitForIdle();logASplit(logger, "step 2 complete");verifyNotStopped();// third stepList<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();logASplit(logger, "loadDeepShortcuts");verifyNotStopped();mResults.bindDeepShortcuts();logASplit(logger, "bindDeepShortcuts");if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {verifyNotStopped();logASplit(logger, "save deep shortcuts in icon cache");updateHandler.updateIcons(allDeepShortcuts,new ShortcutCachingLogic(), (pkgs, user) -> { });}// Take a breakwaitForIdle();logASplit(logger, "step 3 complete");verifyNotStopped();// fourth stepList<ComponentWithLabelAndIcon> allWidgetsList =mBgDataModel.widgetsModel.update(mApp, null);logASplit(logger, "load widgets");verifyNotStopped();mResults.bindWidgets();logASplit(logger, "bindWidgets");verifyNotStopped();updateHandler.updateIcons(allWidgetsList,new ComponentWithIconCachingLogic(mApp.getContext(), true),mApp.getModel()::onWidgetLabelsUpdated);logASplit(logger, "save widgets in icon cache");// fifth stepif (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {loadFolderNames();}verifyNotStopped();updateHandler.finish();logASplit(logger, "finish icon update");mModelDelegate.modelLoadComplete();transaction.commit();} catch (CancellationException e) {// Loader stopped, ignorelogASplit(logger, "Cancelled");} finally {logger.dumpToLog();}TraceHelper.INSTANCE.endSection(traceToken);}public synchronized void stopLocked() {mStopped = true;this.notify();}private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI,null /* selection */);}protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri,String selection) {final Context context = mApp.getContext();final ContentResolver contentResolver = context.getContentResolver();final PackageManagerHelper pmHelper = new PackageManagerHelper(context);final boolean isSafeMode = pmHelper.isSafeMode();final boolean isSdCardReady = Utilities.isBootCompleted();final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);boolean clearDb = false;try {ImportDataTask.performImportIfPossible(context);} catch (Exception e) {// Migration failed. Clear workspace.clearDb = true;}if (!clearDb && (MULTI_DB_GRID_MIRATION_ALGO.get()? !GridSizeMigrationTaskV2.migrateGridIfNeeded(context): !GridSizeMigrationTask.migrateGridIfNeeded(context))) {// Migration failed. Clear workspace.clearDb = true;}if (clearDb) {Log.d(TAG, "loadWorkspace: resetting launcher database");LauncherSettings.Settings.call(contentResolver,LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);}Log.d(TAG, "loadWorkspace: loading default favorites");LauncherSettings.Settings.call(contentResolver,LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);synchronized (mBgDataModel) {mBgDataModel.clear();mPendingPackages.clear();final HashMap<PackageUserKey, SessionInfo> installingPkgs =mSessionHelper.getActiveSessions();installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);final PackageUserKey tempPackageKey = new PackageUserKey(null, null);mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();final LoaderCursor c = new LoaderCursor(contentResolver.query(contentUri, null, selection, null, null), contentUri,mApp, mUserManagerState);final Bundle extras = c.getExtras();mDbName = extras == null? null : extras.getString(LauncherSettings.Settings.EXTRA_DB_NAME);try {final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);final int appWidgetProviderIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_PROVIDER);final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);final int rankIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.RANK);final int optionsIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.OPTIONS);final int sourceContainerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_SOURCE);final LongSparseArray<Boolean> unlockedUsers = new LongSparseArray<>();mUserManagerState.init(mUserCache, mUserManager);for (UserHandle user : mUserCache.getUserProfiles()) {long serialNo = mUserCache.getSerialNumberForUser(user);boolean userUnlocked = mUserManager.isUserUnlocked(user);// We can only query for shortcuts when the user is unlocked.if (userUnlocked) {QueryResult pinnedShortcuts = new ShortcutRequest(context, user).query(ShortcutRequest.PINNED);if (pinnedShortcuts.wasSuccess()) {for (ShortcutInfo shortcut : pinnedShortcuts) {shortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut),shortcut);}} else {// Shortcut manager can fail due to some race condition when the// lock state changes too frequently. For the purpose of the loading// shortcuts, consider the user is still locked.userUnlocked = false;}}unlockedUsers.put(serialNo, userUnlocked);}WorkspaceItemInfo info;LauncherAppWidgetInfo appWidgetInfo;LauncherAppWidgetProviderInfo widgetProviderInfo;Intent intent;String targetPkg;while (!mStopped && c.moveToNext()) {try {if (c.user == null) {// User has been deleted, remove the item.c.markDeleted("User has been deleted");continue;}boolean allowMissingTarget = false;switch (c.itemType) {case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:intent = c.parseIntent();if (intent == null) {c.markDeleted("Invalid or null intent");continue;}int disabledState = mUserManagerState.isUserQuiet(c.serialNumber)? WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER : 0;ComponentName cn = intent.getComponent();targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();if (TextUtils.isEmpty(targetPkg) &&c.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {c.markDeleted("Only legacy shortcuts can have null package");continue;}// If there is no target package, its an implicit intent// (legacy shortcut) which is always validboolean validTarget = TextUtils.isEmpty(targetPkg) ||mLauncherApps.isPackageEnabled(targetPkg, c.user);// If it's a deep shortcut, we'll use pinned shortcuts to restore itif (cn != null && validTarget && c.itemType!= LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {// If the apk is present and the shortcut points to a specific// component.// If the component is already presentif (mLauncherApps.isActivityEnabled(cn, c.user)) {// no special handling necessary for this itemc.markRestored();} else {// Gracefully try to find a fallback activity.intent = pmHelper.getAppLaunchIntent(targetPkg, c.user);if (intent != null) {c.restoreFlag = 0;c.updater().put(LauncherSettings.Favorites.INTENT,intent.toUri(0)).commit();cn = intent.getComponent();} else {c.markDeleted("Unable to find a launch target");continue;}}}// else if cn == null => can't infer much, leave it// else if !validPkg => could be restored icon or missing sd-cardif (!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);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 flagc.restoreFlag |= WorkspaceItemInfo.FLAG_RESTORE_STARTED;c.updater().put(LauncherSettings.Favorites.RESTORED,c.restoreFlag).commit();} else {c.markDeleted("Unrestored app removed: " + targetPkg);continue;}} else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) {// Package is present but not available.disabledState |= WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE;// Add the icon on the workspace anyway.allowMissingTarget = true;} else if (!isSdCardReady) {// SdCard is not ready yet. Package might get available,// once it is ready.Log.d(TAG, "Missing pkg, will check later: " + targetPkg);mPendingPackages.add(new PackageUserKey(targetPkg, c.user));// Add the icon on the workspace anyway.allowMissingTarget = true;} else {// Do not wait for external media load anymore.c.markDeleted("Invalid package removed: " + targetPkg);continue;}}if ((c.restoreFlag & WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) != 0) {validTarget = false;}if (validTarget) {// The shortcut points to a valid target (either no target// or something which is ready to be used)c.markRestored();}boolean useLowResIcon = !c.isOnWorkspaceOrHotseat();if (c.restoreFlag != 0) {// Already verified above that user is same as default userinfo = c.getRestoredItemInfo(intent);} else if (c.itemType ==LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {info = c.getAppShortcutInfo(intent, allowMissingTarget, useLowResIcon);} else if (c.itemType ==LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {ShortcutKey key = ShortcutKey.fromIntent(intent, c.user);if (unlockedUsers.get(c.serialNumber)) {ShortcutInfo pinnedShortcut =shortcutKeyToPinnedShortcuts.get(key);if (pinnedShortcut == null) {// The shortcut is no longer valid.c.markDeleted("Pinned shortcut not found");continue;}info = new WorkspaceItemInfo(pinnedShortcut, context);// If the pinned deep shortcut is no longer published,// use the last saved icon instead of the default.mIconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon);if (pmHelper.isAppSuspended(pinnedShortcut.getPackage(), info.user)) {info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;}intent = info.getIntent();allDeepShortcuts.add(pinnedShortcut);} else {// Create a shortcut info in disabled mode for now.info = c.loadSimpleWorkspaceItem();info.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;}} else { // item type == ITEM_TYPE_SHORTCUTinfo = c.loadSimpleWorkspaceItem();// Shortcuts are only available on the primary profileif (!TextUtils.isEmpty(targetPkg)&& pmHelper.isAppSuspended(targetPkg, c.user)) {disabledState |= FLAG_DISABLED_SUSPENDED;}// App shortcuts that used to be automatically added to Launcher// didn't always have the correct intent flags set, so do that// hereif (intent.getAction() != null &&intent.getCategories() != null &&intent.getAction().equals(Intent.ACTION_MAIN) &&intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);}}if (info != null) {c.applyCommonProperties(info);info.intent = intent;info.rank = c.getInt(rankIndex);info.spanX = 1;info.spanY = 1;info.runtimeStatusFlags |= disabledState;if (isSafeMode && !isSystemApp(context, intent)) {info.runtimeStatusFlags |= FLAG_DISABLED_SAFEMODE;}LauncherActivityInfo activityInfo = c.getLauncherActivityInfo();if (activityInfo != null) {info.setProgressLevel(PackageManagerHelper.getLoadingProgress(activityInfo),PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);}if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {tempPackageKey.update(targetPkg, c.user);SessionInfo si = installingPkgs.get(tempPackageKey);if (si == null) {info.runtimeStatusFlags &=~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;} else if (activityInfo == null) {int installProgress = (int) (si.getProgress() * 100);info.setProgressLevel(installProgress,PackageInstallInfo.STATUS_INSTALLING);}}c.checkAndAddItem(info, mBgDataModel);} else {throw new RuntimeException("Unexpected null WorkspaceItemInfo");}break;case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id);c.applyCommonProperties(folderInfo);// Do not trim the folder label, as is was set by the user.folderInfo.title = c.getString(c.titleIndex);folderInfo.spanX = 1;folderInfo.spanY = 1;folderInfo.options = c.getInt(optionsIndex);// no special handling required for restored foldersc.markRestored();c.checkAndAddItem(folderInfo, mBgDataModel);break;case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:if (WidgetsModel.GO_DISABLE_WIDGETS) {c.markDeleted("Only legacy shortcuts can have null package");continue;}// Follow throughcase LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:// Read all Launcher-specific widget detailsboolean customWidget = c.itemType ==LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;int appWidgetId = c.getInt(appWidgetIdIndex);String savedProvider = c.getString(appWidgetProviderIndex);final ComponentName component;boolean isSearchWidget = (c.getInt(optionsIndex)& LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET) != 0;if (isSearchWidget) {component  = QsbContainerView.getSearchComponentName(context);if (component == null) {c.markDeleted("Discarding SearchWidget without packagename ");continue;}} else {component = ComponentName.unflattenFromString(savedProvider);}final boolean isIdValid = !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);final boolean wasProviderReady = !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);ComponentKey providerKey = new ComponentKey(component, c.user);if (!mWidgetProvidersMap.containsKey(providerKey)) {mWidgetProvidersMap.put(providerKey,widgetHelper.findProvider(component, c.user));}final AppWidgetProviderInfo provider =mWidgetProvidersMap.get(providerKey);final boolean isProviderReady = isValidProvider(provider);if (!isSafeMode && !customWidget &&wasProviderReady && !isProviderReady) {c.markDeleted("Deleting widget that isn't installed anymore: "+ provider);} else {if (isProviderReady) {appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,provider.provider);// The provider is available. So the widget is either// available or not available. We do not need to track// any future restore updates.int status = c.restoreFlag &~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED &~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;if (!wasProviderReady) {// 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;tempPackageKey.update(component.getPackageName(), c.user);SessionInfo si =installingPkgs.get(tempPackageKey);Integer installProgress = si == null? null: (int) (si.getProgress() * 100);if (c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED)) {// Restore has started once.} else if (installProgress != null) {// App restore has started. Update the flagappWidgetInfo.restoreStatus |=LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;} else if (!isSafeMode) {c.markDeleted("Unrestored widget removed: " + component);continue;}appWidgetInfo.installProgress =installProgress == null ? 0 : installProgress;}if (appWidgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) {appWidgetInfo.bindOptions = c.parseIntent();}c.applyCommonProperties(appWidgetInfo);appWidgetInfo.spanX = c.getInt(spanXIndex);appWidgetInfo.spanY = c.getInt(spanYIndex);appWidgetInfo.options = c.getInt(optionsIndex);appWidgetInfo.user = c.user;appWidgetInfo.sourceContainer = c.getInt(sourceContainerIndex);if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {c.markDeleted("Widget has invalid size: "+ appWidgetInfo.spanX + "x" + appWidgetInfo.spanY);continue;}widgetProviderInfo =widgetHelper.getLauncherAppWidgetInfo(appWidgetId);if (widgetProviderInfo != null&& (appWidgetInfo.spanX < widgetProviderInfo.minSpanX|| appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) {FileLog.d(TAG, "Widget " + widgetProviderInfo.getComponent()+ " minSizes not meet: span=" + appWidgetInfo.spanX+ "x" + appWidgetInfo.spanY + " minSpan="+ widgetProviderInfo.minSpanX + "x"+ widgetProviderInfo.minSpanY);logWidgetInfo(mApp.getInvariantDeviceProfile(),widgetProviderInfo);}if (!c.isOnWorkspaceOrHotseat()) {c.markDeleted("Widget found where container != " +"CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");continue;}if (!customWidget) {String providerName =appWidgetInfo.providerName.flattenToString();if (!providerName.equals(savedProvider) ||(appWidgetInfo.restoreStatus != c.restoreFlag)) {c.updater().put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,providerName).put(LauncherSettings.Favorites.RESTORED,appWidgetInfo.restoreStatus).commit();}}if (appWidgetInfo.restoreStatus !=LauncherAppWidgetInfo.RESTORE_COMPLETED) {appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(appWidgetInfo.providerName);appWidgetInfo.pendingItemInfo.user = appWidgetInfo.user;mIconCache.getTitleAndIconForApp(appWidgetInfo.pendingItemInfo, false);}c.checkAndAddItem(appWidgetInfo, mBgDataModel);}break;}} catch (Exception e) {Log.e(TAG, "Desktop items loading interrupted", e);}}} finally {IOUtils.closeSilently(c);}// Load delegate itemsmModelDelegate.loadItems(mUserManagerState, shortcutKeyToPinnedShortcuts);// Break early if we've stopped loadingif (mStopped) {mBgDataModel.clear();return;}// Remove dead itemsmItemsDeleted = c.commitDeleted();// Sort the folder items, update ranks, and make sure all preview items are high res.FolderGridOrganizer verifier =new FolderGridOrganizer(mApp.getInvariantDeviceProfile());for (FolderInfo folder : mBgDataModel.folders) {Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR);verifier.setFolderInfo(folder);int size = folder.contents.size();// 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) {WorkspaceItemInfo info = folder.contents.get(rank);info.rank = rank;if (info.usingLowResIcon()&& info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION&& verifier.isItemInPreview(info.rank)) {mIconCache.getTitleAndIcon(info, false);}}}c.commitRestoredItems();}}private void setIgnorePackages(IconCacheUpdateHandler updateHandler) {// Ignore packages which have a promise icon.synchronized (mBgDataModel) {for (ItemInfo info : mBgDataModel.itemsIdMap) {if (info instanceof WorkspaceItemInfo) {WorkspaceItemInfo si = (WorkspaceItemInfo) info;if (si.isPromise() && si.getTargetComponent() != null) {updateHandler.addPackagesToIgnore(si.user, si.getTargetComponent().getPackageName());}} else if (info instanceof LauncherAppWidgetInfo) {LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info;if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {updateHandler.addPackagesToIgnore(lawi.user, lawi.providerName.getPackageName());}}}}}private void sanitizeData() {Context context = mApp.getContext();ContentResolver contentResolver = context.getContentResolver();if (mItemsDeleted) {// Remove any empty folderint[] deletedFolderIds = LauncherSettings.Settings.call(contentResolver,LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS).getIntArray(LauncherSettings.Settings.EXTRA_VALUE);synchronized (mBgDataModel) {for (int folderId : deletedFolderIds) {mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));mBgDataModel.folders.remove(folderId);mBgDataModel.itemsIdMap.remove(folderId);}}}// Remove any ghost widgetsLauncherSettings.Settings.call(contentResolver,LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);// Update pinned state of model shortcutsmBgDataModel.updateShortcutPinnedState(context);if (!Utilities.isBootCompleted() && !mPendingPackages.isEmpty()) {context.registerReceiver(new SdCardAvailableReceiver(mApp, mPendingPackages),new IntentFilter(Intent.ACTION_BOOT_COMPLETED),null,MODEL_EXECUTOR.getHandler());}}private List<LauncherActivityInfo> loadAllApps() {final List<UserHandle> profiles = mUserCache.getUserProfiles();List<LauncherActivityInfo> allActivityList = new ArrayList<>();// Clear the list of appsmBgAllAppsList.clear();for (UserHandle user : profiles) {// Query for the set of appsfinal 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()) {return allActivityList;}boolean quietMode = mUserManagerState.isUserQuiet(user);// Create the ApplicationInfosfor (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);}allActivityList.addAll(apps);}if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {// get all active sessions and add them to the all apps listfor (PackageInstaller.SessionInfo info :mSessionHelper.getAllVerifiedSessions()) {mBgAllAppsList.addPromiseApp(mApp.getContext(),PackageInstallInfo.fromInstallingState(info));}}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);mBgAllAppsList.getAndResetChangeFlag();return allActivityList;}private List<ShortcutInfo> loadDeepShortcuts() {List<ShortcutInfo> allShortcuts = new ArrayList<>();mBgDataModel.deepShortcutMap.clear();if (mBgAllAppsList.hasShortcutHostPermission()) {for (UserHandle user : mUserCache.getUserProfiles()) {if (mUserManager.isUserUnlocked(user)) {List<ShortcutInfo> shortcuts = new ShortcutRequest(mApp.getContext(), user).query(ShortcutRequest.ALL);allShortcuts.addAll(shortcuts);mBgDataModel.updateDeepShortcutCounts(null, user, shortcuts);}}}return allShortcuts;}private void loadFolderNames() {FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext(),mBgAllAppsList.data, mBgDataModel.folders);synchronized (mBgDataModel) {for (int i = 0; i < mBgDataModel.folders.size(); i++) {FolderNameInfos suggestionInfos = new FolderNameInfos();FolderInfo info = mBgDataModel.folders.valueAt(i);if (info.suggestedFolderNames == null) {provider.getSuggestedFolderName(mApp.getContext(), info.contents,suggestionInfos);info.suggestedFolderNames = suggestionInfos;}}}}public static boolean isValidProvider(AppWidgetProviderInfo provider) {return (provider != null) && (provider.provider != null)&& (provider.provider.getPackageName() != null);}@SuppressLint("NewApi") // Already added API check.private static void logWidgetInfo(InvariantDeviceProfile idp,LauncherAppWidgetProviderInfo widgetProviderInfo) {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());}private static void logASplit(final TimingLogger logger, final String label) {logger.addSplit(label);if (DEBUG) {Log.d(TAG, label);}}//add startprivate void bindAllAppsToWorkspace(){if (mBgAllAppsList.data.size() > 0) {AppInfoComparator mAppNameComparator = new AppInfoComparator(mApp.getContext());ArrayList<AppInfo> appInfos = new ArrayList<AppInfo>(mBgAllAppsList.data);// 按照名称进行排序Collections.sort(appInfos, mAppNameComparator);ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();for (AppInfo info : appInfos) {installQueue.add(Pair.create((ItemInfo) info, null));}mApp.getModel().addAndBindAddedWorkspaceItems(installQueue);}}// end
}

10.修改PackageUpdatedTask:

源码路径:packages/apps/launcher3/src/com/android/launcher3/model/PackageUpdatedTask.java

package com.android.launcher3.model;import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_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;import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.util.Pair;import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
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.util.FlagOp;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.allapps.AppInfoComparator;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;/*** Handles updates due to changes in package manager (app installed/updated/removed)* or when a user availability changes.*/
public class PackageUpdatedTask extends BaseModelUpdateTask {private static final boolean DEBUG = false;private static final String TAG = "PackageUpdatedTask";public static final int OP_NONE = 0;public static final int OP_ADD = 1;public static final int OP_UPDATE = 2;public static final int OP_REMOVE = 3; // uninstalledpublic static final int OP_UNAVAILABLE = 4; // external media unmountedpublic static final int OP_SUSPEND = 5; // package suspendedpublic static final int OP_UNSUSPEND = 6; // package unsuspendedpublic static final int OP_USER_AVAILABILITY_CHANGE = 7; // user available/unavailableprivate final int mOp;private final UserHandle mUser;private final String[] mPackages;public PackageUpdatedTask(int op, UserHandle user, String... packages) {mOp = op;mUser = user;mPackages = packages;}@Overridepublic void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {final Context context = app.getContext();final IconCache iconCache = app.getIconCache();final String[] packages = mPackages;final int N = packages.length;final FlagOp flagOp;final HashSet<String> packageSet = new HashSet<>(Arrays.asList(packages));final ItemInfoMatcher matcher = mOp == OP_USER_AVAILABILITY_CHANGE? ItemInfoMatcher.ofUser(mUser) // We want to update all packages for this user: ItemInfoMatcher.ofPackages(packageSet, mUser);final HashSet<ComponentName> removedComponents = new HashSet<>();final HashMap<String, List<LauncherActivityInfo>> activitiesLists = new HashMap<>();switch (mOp) {case OP_ADD: {for (int i = 0; i < N; i++) {if (DEBUG) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);iconCache.updateIconsForPkg(packages[i], mUser);if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {appsList.removePackage(packages[i], mUser);}activitiesLists.put(packages[i], appsList.addPackage(context, packages[i], mUser));}flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);break;}case OP_UPDATE:try (SafeCloseable t =appsList.trackRemoves(a -> removedComponents.add(a.componentName))) {for (int i = 0; i < N; i++) {if (DEBUG) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);iconCache.updateIconsForPkg(packages[i], mUser);activitiesLists.put(packages[i], appsList.updatePackage(context, packages[i], mUser));app.getWidgetCache().removePackage(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.flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);break;case OP_REMOVE: {for (int i = 0; i < N; i++) {FileLog.d(TAG, "Removing app icon" + packages[i]);iconCache.removeIconsForPkg(packages[i], mUser);}// Fall through}case OP_UNAVAILABLE:for (int i = 0; i < N; i++) {if (DEBUG) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);appsList.removePackage(packages[i], mUser);app.getWidgetCache().removePackage(packages[i], mUser);}flagOp = FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);break;case OP_SUSPEND:case OP_UNSUSPEND:flagOp = mOp == OP_SUSPEND ?FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED) :FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED);if (DEBUG) Log.d(TAG, "mAllAppsList.(un)suspend " + N);appsList.updateDisabledFlags(matcher, flagOp);break;case OP_USER_AVAILABILITY_CHANGE: {UserManagerState ums = new UserManagerState();ums.init(UserCache.INSTANCE.get(context),context.getSystemService(UserManager.class));flagOp = ums.isUserQuiet(mUser)? FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER): FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER);appsList.updateDisabledFlags(matcher, flagOp);// We are not synchronizing here, as int operations are atomicappsList.setFlags(FLAG_QUIET_MODE_ENABLED, ums.isAnyProfileQuietModeEnabled());break;}default:flagOp = FlagOp.NO_OP;break;}bindApplicationsIfNeeded();final IntSet removedShortcuts = new IntSet();// Shortcuts to keep even if the corresponding app was removedfinal IntSet forceKeepShortcuts = new IntSet();// Update shortcut infosif (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {final ArrayList<WorkspaceItemInfo> updatedWorkspaceItems = new ArrayList<>();final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<>();// For system apps, package manager send OP_UPDATE when an app is enabled.final boolean isNewApkAvailable = mOp == OP_ADD || mOp == OP_UPDATE;synchronized (dataModel) {dataModel.forAllWorkspaceItemInfos(mUser, si -> {boolean infoUpdated = false;boolean shortcutUpdated = false;// Update shortcuts which use iconResource.if ((si.iconResource != null)&& packageSet.contains(si.iconResource.packageName)) {LauncherIcons li = LauncherIcons.obtain(context);BitmapInfo iconInfo = li.createIconBitmap(si.iconResource);li.recycle();if (iconInfo != null) {si.bitmap = iconInfo;infoUpdated = true;}}ComponentName cn = si.getTargetComponent();if (cn != null && matcher.matches(si, cn)) {String packageName = cn.getPackageName();if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)) {forceKeepShortcuts.add(si.id);if (mOp == OP_REMOVE) {return;}}if (si.isPromise() && isNewApkAvailable) {boolean isTargetValid = !cn.getClassName().equals(IconCache.EMPTY_CLASS_NAME);if (si.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {List<ShortcutInfo> shortcut =new ShortcutRequest(context, mUser).forPackage(cn.getPackageName(),si.getDeepShortcutId()).query(ShortcutRequest.PINNED);if (shortcut.isEmpty()) {isTargetValid = false;} else {si.updateFromDeepShortcutInfo(shortcut.get(0), context);infoUpdated = true;}} else if (isTargetValid) {isTargetValid = context.getSystemService(LauncherApps.class).isActivityEnabled(cn, mUser);}if (!isTargetValid && si.hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON)) {if (updateWorkspaceItemIntent(context, si, packageName)) {infoUpdated = true;} else if (si.hasPromiseIconUi()) {removedShortcuts.add(si.id);return;}} else if (!isTargetValid) {removedShortcuts.add(si.id);FileLog.e(TAG, "Restored shortcut no longer valid "+ si.getIntent());return;} else {si.status = WorkspaceItemInfo.DEFAULT;infoUpdated = true;}} else if (isNewApkAvailable && removedComponents.contains(cn)) {if (updateWorkspaceItemIntent(context, si, packageName)) {infoUpdated = true;}}if (isNewApkAvailable) {List<LauncherActivityInfo> activities = activitiesLists.get(packageName);si.setProgressLevel(activities == null || activities.isEmpty()? 100: PackageManagerHelper.getLoadingProgress(activities.get(0)),PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) {iconCache.getTitleAndIcon(si, si.usingLowResIcon());infoUpdated = true;}}int oldRuntimeFlags = si.runtimeStatusFlags;si.runtimeStatusFlags = flagOp.apply(si.runtimeStatusFlags);if (si.runtimeStatusFlags != oldRuntimeFlags) {shortcutUpdated = true;}}if (infoUpdated || shortcutUpdated) {updatedWorkspaceItems.add(si);}if (infoUpdated && si.id != ItemInfo.NO_ID) {getModelWriter().updateItemInDatabase(si);}});for (LauncherAppWidgetInfo widgetInfo : dataModel.appWidgets) {if (mUser.equals(widgetInfo.user)&& widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)&& packageSet.contains(widgetInfo.providerName.getPackageName())) {widgetInfo.restoreStatus &=~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY& ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;// adding this flag ensures that launcher shows 'click to setup'// if the widget has a config activity. In case there is no config// activity, it will be marked as 'restored' during bind.widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;widgets.add(widgetInfo);getModelWriter().updateItemInDatabase(widgetInfo);}}}bindUpdatedWorkspaceItems(updatedWorkspaceItems);if (!removedShortcuts.isEmpty()) {deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts));}if (!widgets.isEmpty()) {scheduleCallbackTask(c -> c.bindWidgetsRestored(widgets));}}final HashSet<String> removedPackages = new HashSet<>();if (mOp == OP_REMOVE) {// Mark all packages in the broadcast to be removedCollections.addAll(removedPackages, packages);// No need to update the removedComponents as// removedPackages is a super-set of removedComponents} else if (mOp == OP_UPDATE) {// Mark disabled packages in the broadcast to be removedfinal LauncherApps launcherApps = context.getSystemService(LauncherApps.class);for (int i=0; i<N; i++) {if (!launcherApps.isPackageEnabled(packages[i], mUser)) {removedPackages.add(packages[i]);}}}if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser).or(ItemInfoMatcher.ofComponents(removedComponents, mUser)).and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());deleteAndBindComponentsRemoved(removeMatch);// Remove any queued items from the install queueItemInstallQueue.INSTANCE.get(context).removeFromInstallQueue(removedPackages, mUser);}if (mOp == OP_ADD) {// Load widgets for the new package. Changes due to app updates are handled through// AppWidgetHost events, this is just to initialize the long-press options.for (int i = 0; i < N; i++) {dataModel.widgetsModel.update(app, new PackageUserKey(packages[i], mUser));}bindUpdatedWidgets(dataModel);}// add startif (FeatureFlags.REMOVE_DRAWER) {updateAllAppsToWorkspace(app, appsList);}// add end}/*** Updates {@param si}'s intent to point to a new ComponentName.* @return Whether the shortcut intent was changed.*/private boolean updateWorkspaceItemIntent(Context context,WorkspaceItemInfo si, String packageName) {if (si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {// Do not update intent for deep shortcuts as they contain additional information// about the shortcut.return false;}// Try to find the best match activity.Intent intent = new PackageManagerHelper(context).getAppLaunchIntent(packageName, mUser);if (intent != null) {si.intent = intent;si.status = WorkspaceItemInfo.DEFAULT;return true;}return false;}// add startpublic void updateAllAppsToWorkspace(LauncherAppState app , AllAppsList mBgAllAppsList){if (mBgAllAppsList.data.size() > 0) {AppInfoComparator mAppNameComparator = new AppInfoComparator(app.getContext());ArrayList<AppInfo> appInfos = new ArrayList<AppInfo>(mBgAllAppsList.data);Collections.sort(appInfos, mAppNameComparator);ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();for (AppInfo info : appInfos) {installQueue.add(Pair.create((ItemInfo) info, null));}app.getModel().addAndBindAddedWorkspaceItems(installQueue);}}// add end
}

11.实现效果如下:

在这里插入图片描述

在这里插入图片描述

12.总结:

从上面的截图可以看到基本上实现了桌面显示所有App应用图标,不同于抽屉模式还要向上滑动才能看到整个应用列表,这也很符合用户使用真实手机的习惯,而且安装了新App后会再桌面刷新,后面会讲解去掉抽屉显示所有应用列表.

  • 几处关键修改就是显示所有应用,在桌面加载和安装新应用后立即刷新
  • shouldShowApp
  • 在LoaderTask添加bindAllAppsToWorkspace()方法
  • 在PackageUpdatedTask添加updateAllAppsToWorkspace()方法

http://www.hkcw.cn/article/cVXRKWYtQS.shtml

相关文章

数据结构——图

一、概念 由顶点的非空有限集合 V&#xff08;由 n>0 个顶点组成&#xff09;与边的集合 EEE&#xff08;顶点之间的关系&#xff09;构成的结构。其形式化定义为 G(V,E)。 顶点&#xff08;Vertex&#xff09;&#xff1a;图中的数据元素通常称为顶点&#xff0c;在下面的…

【AI赋能,视界升级】智微智能S134 AI OPS,重构智慧大屏未来

智慧教室中&#xff0c;教师通过电子白板&#xff0c;4K高清课件、3D教学模型同步呈现&#xff0c;后排学生也能看清画面细节&#xff0c;课堂变得趣味十足&#xff1b;智能会议室里&#xff0c;会议内容、多人云会议多屏投放依旧畅通清晰&#xff0c;会议纪要自动生成Word/PPT…

ISCC-2025-web-wp

web 校赛 校赛靠着ENOCH师傅发力&#xff0c;也是一路躺进了区域赛&#xff0c;E师傅不好意思发这抽象比赛的wp(这比赛确实啥必到让人大开眼界&#xff0c;反正明年我是肯定不会打了)&#xff0c;我就顺手要过来连着区域赛的一起发了 web 150分 按照提示进入/includes/fla…

在CentOS7上使用tree查看目录树

文章目录 1. 利用yum安装tree2. 利用rpm安装tree2.1 下载tree的rpm包2.2 上传到云主机2.3 安装tree软件 3. 使用tree查看目录树4. 实战小结 1. 利用yum安装tree 执行命令&#xff1a;yum -y install tree CentOS7停止更新&#xff0c;即使更新镜像源&#xff0c;也无法正常安装…

【仿muduo库实现并发服务器】实现时间轮定时器

实现时间轮定时器 1.时间轮定时器原理2.项目中实现目的3.实现功能3.1构造定时任务类3.2构造时间轮定时器每秒钟往后移动添加定时任务刷新定时任务取消定时任务 4.完整代码 1.时间轮定时器原理 时间轮定时器的原理类似于时钟&#xff0c;比如现在12点&#xff0c;定一个3点的闹…

Webug4.0靶场通关笔记10- 第10关存储型XSS注入

目录 一、存储型XSS原理 二、代码审计 三、第10关 存储型XSS注入实战 1.打开靶场 2.渗透实战 本文通过《Webug4.0通关笔记系列》来进行Webug4.0靶场的渗透实战&#xff0c;本文讲解Webug4.0靶场第10关存储型XSS的渗透实战。 一、存储型XSS原理 存储型XSS&#xff08;Sto…

深入了解MCP基础与架构

一、引言 在人工智能技术以指数级速度渗透各行业领域的今天&#xff0c;我们正站在一个关键的技术拐点。当ChatGPT月活突破亿级、Gemini Pro实现多模态实时交互、Claude 3.5 Sonnet突破百万上下文长度&#xff0c;这些里程碑事件背后&#xff0c;一个崭新的大门逐步打开&#…

STM32F407VET6学习笔记9:编译输出固定大小.bin文件

今日学习如何输出固定大小的.bin编译文件 目录 Keil_V5 fromelf.exe 软件目录&#xff1a; 魔棒添加命令输出bin文件&#xff1a; 输出固定大小的bin文件&#xff1a; 计算bin文件大小&#xff1a; 安装 SRecord 工具集&#xff1a; 使用SRecord&#xff1a; 参考文章&#…

Spring Cloud 学习 —— 简单了解

Spring Cloud 简介 官方文档&#xff1a;https://docs.spring.io/spring-cloud-release/reference/index.html 在学习 Spring Cloud 之前&#xff0c;先了解一下什么是分布式系统&#xff1f; 分布式系统 分布式系统是由多个独立计算机&#xff08;节点&#xff09;通过网络…

FreeRTOS多任务系统①

多任务系统 回想一下我们以前在使用 51、STM32 单片机裸机(未使用实时操作系统)的时候一般都是在main 函数里面用 while(1)做一个大循环来完成所有的处理&#xff0c; 即应用程序是一个无限的循环&#xff0c; 循环中调用相应的函数完成所需的处理。 有时候我们也需要中断中完…

Celery简介

一、什么是异步任务队列 异步任务队列是指一种用于管理和调度异步执行任务的机制。具体来说&#xff0c;它允许将任务放入队列中&#xff0c;然后由后台进程异步处理这些任务&#xff0c;而不会阻塞主线程的执行。这种设计使得系统能够高效地处理耗时操作&#xff0c;同时保持…

【Livox雷达使用】

记录 目前livox雷达型号较多&#xff0c;适用范围广泛。后来出的雷达需要使用使用第二代SDK和驱动&#xff0c;如Mid360、HAP。之前在github上看有人问是否能一起安装&#xff0c;官方回答是可以的&#xff0c;我把livox SDK、livox_ros_driver和SDK2、driver2都下载了进行比较…

RS232转Profinet网关在检漏仪与西门子PLC里的应用

RS232转Profinet网关在检漏仪与西门子PLC里的应用 在工业自动化和控制领域&#xff0c;设备间的高效通信至关重要。RS232转Profinet网关作为一种关键的转换工具&#xff0c;能够将传统的RS232接口设备接入现代化的Profinet网络&#xff0c;从而实现数据的无缝传输和设备的远程…

公链地址生成曲线和算法

在区块链公链中&#xff0c;除了 ECDSA&#xff08;基于 secp256k1 曲线&#xff09; 和 EdDSA&#xff08;基于 Ed25519 曲线&#xff09; 之外&#xff0c;还有其他一些加密算法和椭圆曲线被用于生成公私钥对、签名验证或地址生成。这些算法和曲线的选择通常基于安全性、性能…

⭐ Unity AVProVideo插件自带播放器 脚本重构 实现视频激活重置功能

一、功能概述 本笔记记录直接修改插件自带的场景播放其中 原始的 MediaPlayerUI 脚本,实现激活时自动重置播放器的功能。 我用的插件版本是 AVPro Video - Ultra Edition 2.7.3 修改后的脚本将具备以下特性: 激活 GameObject 时自动重置播放位置到开头 可配置是否在重置后自…

C#命名类型前缀习惯改进

我这几天有一个疑惑&#xff0c;我之前用过一些变量命名&#xff0c;有些混乱&#xff0c;如string sql&#xff0c;string strSql&#xff0c;string sqlStr&#xff0c; string strName&#xff0c;string nameStr&#xff0c;bool boValid&#xff0c;stringbuilder sbFileN…

生成式AI如何重塑设计思维与品牌创新?从工具到认知革命的跃迁

当MidJourney生成的视觉方案出现在国际设计奖项的决赛名单&#xff0c;当Adobe Firefly成为设计师的标配工具&#xff0c;一个问题正从行业边缘走向中心&#xff1a;生成式人工智能&#xff08;GAI&#xff09;究竟在解构还是重构创意领域&#xff1f;作为深度参与AI与设计融合…

零知开源——STM32F407VET6驱动Flappy Bird游戏教程

简介 本教程使用STM32F407VET6零知增强板驱动3.5寸TFT触摸屏实现经典Flappy Bird游戏。通过触摸屏控制小鸟跳跃&#xff0c;躲避障碍物柱体&#xff0c;挑战最高分。项目涉及STM32底层驱动、图形库移植、触摸控制和游戏逻辑设计。 目录 简介 一、硬件准备 二、软件架构 三、…

超高频RFID读写器天线分类及应用场景

超高频RFID(Radio Frequency Identification,射频识别)技术作为一种先进的自动识别技术,已经在多个领域得到了广泛应用。作为RFID系统的重要组成部分,超高频RFID读写器天线不仅影响着系统的读取距离、读取速度和准确性,还决定了RFID系统的适应性和灵活性。本文将详细介绍…

第J2周:ResNet50V2算法实战与解析

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 batch_size32&#xff1a;每次训练取32张图像组成一个 batch img_size(224, 224)&#xff1a;图像输入大小匹配 ResNet50 的输入要求 epochs10&#xff1a;训练…