Android12 Launcher3显示所有应用列表
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()方法
相关文章:

Android12 Launcher3显示所有应用列表
Android12 Launcher3显示所有应用列表 1.前言: 最近在Android12Rom定制时需要显示所有桌面应用的图标,并且不能去掉抽屉,在手机上面抽屉和所有应该列表是两种不同模式,用户基可以自行选择,但是在自定义的launcher中这…...
24.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--认证微服务
SP.IdentityService 项目为微服务架构中的核心认证中心,采用 OpenIddict 框架实现 OAuth2.0 和 OpenID Connect 协议,提供完整的身份认证和授权解决方案。项目集成了 ASP.NET Core Identity 框架,实现了用户管理、角色权限控制等基础功能&…...
基于React Native开发鸿蒙新闻类应用的实战开发笔记
以下为基于React Native开发鸿蒙新闻资讯类应用的实战开发笔记,结合架构特性与踩坑经验,重点记录关键实现方案和技术决策: 一、环境搭建与工程初始化(关键步骤复盘) Node.js版本锁定 必须使用Node 18&…...
[Java 基础]运算符,将盒子套起来
在 Java 中,运算符(Operator)用于执行特定的操作,例如数学计算、赋值、比较等。运算符是 Java 语言的重要组成部分,能够帮助我们高效地操作数据。 1. 算术运算符 运算符说明示例结果加法5 38-减法5 - 32*乘法5 * 31…...

智能快递地址解析接口如何用PHP调用?
一、什么是智能快递地址解析接口 随着互联网技术的普及和电子商务的迅猛发展,网购已成为现代人日常生活的重要组成部分。然而,在这个便捷的背后,一个看似不起眼却影响深远的问题正悄然浮现——用户填写的快递地址格式混乱、信息不全甚至错漏…...

华为OD机试真题——模拟消息队列(2025B卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
2025 B卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《模拟消息队列》: 目录 题…...
c# 显示正在运行的线程数
在 C# 中,若想获取当前进程正在运行的线程数,可以使用 System.Diagnostics 命名空间中的 Process 类来实现。该方法适用于 Windows 平台,并能够获取当前进程的线程信息,包括线程总数和运行中的线程数量。 ✅ 方法一:使…...
MySQL 日志数据同步的详细教程
以下是 MySQL 日志数据同步的详细教程,主要介绍基于二进制日志(binlog)的主从复制和基于 GTID 的高级同步方案: 一、MySQL 二进制日志(binlog)同步基础 1. 二进制日志原理 binlog 是 MySQL 的事务性日志&am…...
2025 Java面试大全技术文章(面试题1)
数据类型与包装类 问题:Java中基本数据类型与包装类的区别是什么?自动装箱与拆箱的底层原理? 答案: 基本数据类型(如int、double)直接存储值,包装类(如Integer、Double)…...
docker 中 什么是「卷」?(Volume)
🗃️ 什么是「卷」?(Volume) 「卷」就是 Docker 里用来“保存数据”的一块空间,就像是一个外接硬盘,或者一个 USB 闪存。 容器本身是临时的,你一删它,它的数据也跟着没了。但卷是用…...
三维可视化和实时数据处理对前端性能要求以及优化渲染效率
在三维可视化(如 Three.js 场景)和实时数据处理(如每秒数百条设备状态更新)场景中,前端性能优化是确保用户体验的核心挑战。以下结合技术原理与行业实践,详细说明Web Workers和虚拟 DOM的优化机制ÿ…...

基于VU37P的高性能采集板卡
基于VU37P的高性能采集板卡是一款最大可提供20路ADC接收通道的高性能采集板卡。每路A/D通道支持1GS/s的采样率,分辨率为14bit,模拟输入带宽可达500MHz,交流耦合,输入阻抗50欧姆。 产品简介 可提供20路ADC接收通道的高性能采集板…...

2025-05-31 Python深度学习10——模型训练流程
文章目录 1 数据准备1.1 下载与预处理1.2 数据加载 2 模型构建2.1 自定义 CNN 模型2.2 GPU加速 3 训练配置3.1 损失函数3.2 优化器3.3 训练参数 4 训练循环4.1 训练模式 (model.train())4.2 评估模式 (model.eval()) 5 模型验证 本文环境: Pycharm 2025.1Python 3.1…...
卷积神经网络(CNN)、YOLO和人脸识别之间的关系
核心关系图解 TEXT 摄像头图像 → [YOLO:人脸检测] → 定位人脸位置 → [CNN:特征提取] → 人脸特征向量 → [人脸识别系统] → 身份匹配 通俗比喻 想象你在一个拥挤的火车站找人: YOLO 是你的"快速扫描眼": 一眼扫…...

K8S StatefulSet 快速开始
其实这篇文章的梗概已经写了很久了,中间我小孩出生了,从此人间多了一份牵挂。抽出一些时间去办理新生儿相关手续。初为人父确实艰辛,就像学技术一样,都需要有极大的耐心,付出很多的时间。 一、引子 1.1、独立的存储 …...
重新测试deepseek Jakarta EE 10编程能力
听说deepseek做了一个小更新,我重新测试了一下Jakarta EE 10编程能力;有点进步,遗漏的功能比以前少了。 采用Jakarta EE 10 编写员工信息表维护表,包括员工查询与搜索、员工列表、新增员工、删除员工,修改员工…...

nav2笔记-250603
合作背景: AMD与Open Navigation在过去几个月里进行了合作,旨在向ROS 2社区展示AMD强大的Ryzen AI、Embedded和Kria能力。 演示内容: 帖子提到,他们已经开始展示如何使用Ryzen AI为自主机器人产品提供动力,在各种现实世…...

指纹识别+精准化POC攻击
开发目的 解决漏洞扫描器的痛点 第一就是扫描量太大,对一个站点扫描了大量的无用 POC,浪费时间 指纹识别后还需要根据对应的指纹去进行 payload 扫描,非常的麻烦 开发思路 我们的思路分为大体分为指纹POC扫描 所以思路大概从这几个方面…...
LeetCode[404]左叶子之和
思路: 题目要求求出左叶子的和,左叶子的条件是左右节点为空且是左子树的叶子节点才叫左叶子节点,那么右子树的左叶子节点的和是什么呢?这样想就引出了递归的顺序,后序遍历,求出左右子树的节点和,…...

mac环境下的python、pycharm和pip安装使用
Python安装 Mac环境下的python安装 下载地址:https://www.jetbrains.com.cn/pycharm/ 一直点击下一步即可完成 在应用程序中会多了两个图标 IDLE 和 Python launcher IDLE支持在窗口中直接敲python命令并立即执行,双击即可打开 Python launcher双击打…...
C语言多级指针深度解析:从一级到三级的奥秘
资料合集下载链接: https://pan.quark.cn/s/472bbdfcd014 在C语言中,指针是理解内存和进行底层编程的关键。我们知道,一个一级指针存储的是一个变量的内存地址。但C语言的强大之处在于,指针本身也可以有自己的地址,而存储这个指针的地址的变量,就是一个更高层次…...
uni-app学习笔记十九--pages.json全局样式globalStyle设置
pages.json 页面路由 pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。 导航栏高度为 44px (不含状态栏),tabBar 高度为 50px (不含安全区)。 它类似微信小程序中app.json的页面管理部…...

BUUCTF[极客大挑战 2019]Havefun 1题解
BUUCTF[极客大挑战 2019]Havefun 1题解 题目分析解题理解代码逻辑:构造Payload: 总结 题目分析 生成靶机,进入网址: 首页几乎没有任何信息,公式化F12打开源码,发现一段被注释的源码: 下面我们…...
【基础】Unity中Camera组件知识点
一、投影模式 (Projection) 1. 透视模式 (Perspective) 原理:模拟人眼,近大远小(锥形体视锥) 核心参数: Field of View (FOV):垂直视场角 典型值:第一人称 60-90,驾驶舱 30-45 特…...

Tomcat优化篇
目录 一、Tomcat自身配置 1.Tomcat管理页面 2. 禁用AJP服务 3.Executor优化 4.三种运行模式 5.web.xml 6.Host标签 7.Context标签 8.启动速度优化 9.其他方面 二、JMeter测试 笔者推荐 一、Tomcat自身配置 1.Tomcat管理页面 我们可以打开Tomcat的管理页面ÿ…...

Temporal Fusion Transformer(TFT)扩散模型时间序列预测模型
1. TFT 简介 Temporal Fusion Transformer(TFT)模型是一种专为时间序列预测设计的高级深度学习模型。它结合了神经网络的多种机制处理时间序列数据中的复杂关系。TFT 由 Lim et al. 于 2019年提出,旨在处理时间序列中的不确定性和多尺度的依…...

【LangServe部署流程】5 分钟部署你的 AI 服务
目录 一、LangServe简介 二、环境准备 1. 安装必要依赖 2. 编写一个 LangChain 可运行链(Runnable) 3. 启动 LangServe 服务 4. 启动服务 5. 使用 API 进行调用 三、可选:访问交互式 Swagger 文档 四、基于 LangServe 的 RAG 应用部…...

攻防世界-unseping
进入环境 在获得的场景中发现PHP代码并进行分析 编写PHP编码 得到 Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozOiJwd2QiO319 将其传入 想执行ls,但是发现被过滤掉了 使用环境变量进行绕过 $a new…...
微软推出 Bing Video Creator,免费助力用户轻松创作 AI 视频
2025 年 6 月 2 日,微软正式在自家 Bing 应用中上线了一项名为 “Bing Video Creator” 的新功能,为广大用户带来了全新的创作体验。 Bing Video Creator 背靠 OpenAI 当红的 Sora 视频生成模型,用户只需输入文字描述,就能直接生…...
(13)java+ selenium->元素定位大法之By_partial_link_text
1.简介 在上一篇中我们说了link_text,目前我们接着看partial link text,顾名思义是通过链接定位的(官方说法:超链接文本定位)。我们在上一篇的文章末尾有提到,这种方式的定位属于模糊匹配定位,什么是partial link text呢,看到part这个单词我们就可以知道,当这个文字超…...