Merge "Log the reason why a WorkspaceItemInfo was removed" into tm-dev am: 8eaf87e77b am: 13d50111c6 am: fa19bc6d12

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/18298829

Change-Id: I54ea931b4f08d58c3092994bd35f42b2f00bc560
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-05-18 21:49:16 +00:00
committed by Automerger Merge Worker
12 changed files with 67 additions and 31 deletions
@@ -160,7 +160,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
// Remove the item from launcher and the db, we can ignore the containerInfo in this call
// because we already remove the drag view from the folder (if the drag originated from
// a folder) in Folder.beginDrag()
mLauncher.removeItem(view, item, true /* deleteFromDb */);
mLauncher.removeItem(view, item, true /* deleteFromDb */, "removed by accessibility drop");
mLauncher.getWorkspace().stripEmptyScreens();
mLauncher.getDragLayer()
.announceForAccessibility(getContext().getString(R.string.item_removed));
+21 -8
View File
@@ -1956,6 +1956,19 @@ public class Launcher extends StatefulActivity<LauncherState>
* @param deleteFromDb whether or not to delete this item from the db.
*/
public boolean removeItem(View v, final ItemInfo itemInfo, boolean deleteFromDb) {
return removeItem(v, itemInfo, deleteFromDb, null);
}
/**
* Unbinds the view for the specified item, and removes the item and all its children.
*
* @param v the view being removed.
* @param itemInfo the {@link ItemInfo} for this view.
* @param deleteFromDb whether or not to delete this item from the db.
* @param reason the resaon for removal.
*/
public boolean removeItem(View v, final ItemInfo itemInfo, boolean deleteFromDb,
@Nullable final String reason) {
if (itemInfo instanceof WorkspaceItemInfo) {
// Remove the shortcut from the folder before removing it from launcher
View folderIcon = mWorkspace.getHomescreenIconByItemId(itemInfo.container);
@@ -1965,7 +1978,7 @@ public class Launcher extends StatefulActivity<LauncherState>
mWorkspace.removeWorkspaceItem(v);
}
if (deleteFromDb) {
getModelWriter().deleteItemFromDatabase(itemInfo);
getModelWriter().deleteItemFromDatabase(itemInfo, reason);
}
} else if (itemInfo instanceof FolderInfo) {
final FolderInfo folderInfo = (FolderInfo) itemInfo;
@@ -1980,7 +1993,7 @@ public class Launcher extends StatefulActivity<LauncherState>
final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
mWorkspace.removeWorkspaceItem(v);
if (deleteFromDb) {
getModelWriter().deleteWidgetInfo(widgetInfo, getAppWidgetHost());
getModelWriter().deleteWidgetInfo(widgetInfo, getAppWidgetHost(), reason);
}
} else {
return false;
@@ -2399,8 +2412,7 @@ public class Launcher extends StatefulActivity<LauncherState>
if (FeatureFlags.IS_STUDIO_BUILD) {
throw (new RuntimeException(desc));
} else {
Log.d(TAG, desc);
getModelWriter().deleteItemFromDatabase(item);
getModelWriter().deleteItemFromDatabase(item, desc);
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.MISSING_PROMISE_ICON,
TAG + "bindItems failed for item=" + item);
@@ -2480,7 +2492,8 @@ public class Launcher extends StatefulActivity<LauncherState>
if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
item.providerName = QsbContainerView.getSearchComponentName(this);
if (item.providerName == null) {
getModelWriter().deleteItemFromDatabase(item);
getModelWriter().deleteItemFromDatabase(item,
"search widget removed because search component cannot be found");
return null;
}
}
@@ -2531,10 +2544,10 @@ public class Launcher extends StatefulActivity<LauncherState>
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
&& (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
if (appWidgetInfo == null) {
FileLog.d(TAG, "Removing restored widget: id=" + item.appWidgetId
getModelWriter().deleteItemFromDatabase(item,
"Removing restored widget: id=" + item.appWidgetId
+ " belongs to component " + item.providerName + " user " + item.user
+ ", as the provider is null and " + removalReason);
getModelWriter().deleteItemFromDatabase(item);
return null;
}
@@ -2604,7 +2617,7 @@ public class Launcher extends StatefulActivity<LauncherState>
// Verify that we own the widget
if (appWidgetInfo == null) {
FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
getModelWriter().deleteWidgetInfo(item, getAppWidgetHost());
getModelWriter().deleteWidgetInfo(item, getAppWidgetHost(), removalReason);
return null;
}
+3 -1
View File
@@ -477,7 +477,9 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
}
if (!removedIds.isEmpty()) {
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedIds));
deleteAndBindComponentsRemoved(
ItemInfoMatcher.ofItemIds(removedIds),
"removed because install session failed");
}
}
});
+5 -3
View File
@@ -3068,7 +3068,8 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
if (info instanceof LauncherAppWidgetInfo) {
LauncherAppWidgetInfo appWidgetInfo = (LauncherAppWidgetInfo) info;
if (appWidgetInfo.appWidgetId == appWidgetId) {
mLauncher.removeItem(view, appWidgetInfo, true);
mLauncher.removeItem(view, appWidgetInfo, true,
"widget is removed in response to widget remove broadcast");
return true;
}
}
@@ -3318,8 +3319,9 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
*
* @param matcher the matcher generated by the caller.
*/
public void persistRemoveItemsByMatcher(Predicate<ItemInfo> matcher) {
mLauncher.getModelWriter().deleteItemsFromDatabase(matcher);
public void persistRemoveItemsByMatcher(Predicate<ItemInfo> matcher,
@Nullable final String reason) {
mLauncher.getModelWriter().deleteItemsFromDatabase(matcher, reason);
removeItemsByMatcher(matcher);
}
@@ -100,7 +100,8 @@ public class LauncherDelegate {
}
// Remove the folder
mLauncher.removeItem(folder.mFolderIcon, info, true /* deleteFromDb */);
mLauncher.removeItem(folder.mFolderIcon, info, true /* deleteFromDb */,
"folder removed because there's only 1 item in it");
if (folder.mFolderIcon instanceof DropTarget) {
folder.mDragController.removeDropTarget((DropTarget) folder.mFolderIcon);
}
@@ -17,6 +17,8 @@ package com.android.launcher3.model;
import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
@@ -128,8 +130,9 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask {
scheduleCallbackTask(c -> c.bindAllWidgets(widgets));
}
public void deleteAndBindComponentsRemoved(final Predicate<ItemInfo> matcher) {
getModelWriter().deleteItemsFromDatabase(matcher);
public void deleteAndBindComponentsRemoved(final Predicate<ItemInfo> matcher,
@Nullable final String reason) {
getModelWriter().deleteItemsFromDatabase(matcher, reason);
// Call the components-removed callback
scheduleCallbackTask(c -> c.bindWorkspaceComponentsRemoved(matcher));
@@ -23,8 +23,10 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
@@ -272,27 +274,30 @@ public class ModelWriter {
/**
* Removes the specified item from the database
*/
public void deleteItemFromDatabase(ItemInfo item) {
deleteItemsFromDatabase(Arrays.asList(item));
public void deleteItemFromDatabase(ItemInfo item, @Nullable final String reason) {
deleteItemsFromDatabase(Arrays.asList(item), reason);
}
/**
* Removes all the items from the database matching {@param matcher}.
*/
public void deleteItemsFromDatabase(Predicate<ItemInfo> matcher) {
public void deleteItemsFromDatabase(@NonNull final Predicate<ItemInfo> matcher,
@Nullable final String reason) {
deleteItemsFromDatabase(StreamSupport.stream(mBgDataModel.itemsIdMap.spliterator(), false)
.filter(matcher).collect(Collectors.toList()));
.filter(matcher).collect(Collectors.toList()), reason);
}
/**
* Removes the specified items from the database
*/
public void deleteItemsFromDatabase(final Collection<? extends ItemInfo> items) {
public void deleteItemsFromDatabase(final Collection<? extends ItemInfo> items,
@Nullable final String reason) {
ModelVerifier verifier = new ModelVerifier();
FileLog.d(TAG, "removing items from db " + items.stream().map(
(item) -> item.getTargetComponent() == null ? ""
: item.getTargetComponent().getPackageName()).collect(
Collectors.joining(",")));
Collectors.joining(","))
+ ". Reason: [" + (TextUtils.isEmpty(reason) ? "unknown" : reason) + "]");
notifyDelete(items);
enqueueDeleteRunnable(() -> {
for (ItemInfo item : items) {
@@ -328,14 +333,15 @@ public class ModelWriter {
/**
* Deletes the widget info and the widget id.
*/
public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host) {
public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host,
@Nullable final String reason) {
notifyDelete(Collections.singleton(info));
if (host != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
enqueueDeleteRunnable(() -> host.deleteAppWidgetId(info.appWidgetId));
}
deleteItemFromDatabase(info);
deleteItemFromDatabase(info, reason);
}
private void notifyDelete(Collection<? extends ItemInfo> items) {
@@ -311,7 +311,9 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
bindUpdatedWorkspaceItems(updatedWorkspaceItems);
if (!removedShortcuts.isEmpty()) {
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts));
deleteAndBindComponentsRemoved(
ItemInfoMatcher.ofItemIds(removedShortcuts),
"removed because the target component is invalid");
}
if (!widgets.isEmpty()) {
@@ -340,7 +342,8 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
Predicate<ItemInfo> removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
.or(ItemInfoMatcher.ofComponents(removedComponents, mUser))
.and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());
deleteAndBindComponentsRemoved(removeMatch);
deleteAndBindComponentsRemoved(removeMatch,
"removed because the corresponding package or component is removed");
// Remove any queued items from the install queue
ItemInstallQueue.INSTANCE.get(context)
@@ -108,7 +108,8 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask {
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(
nonPinnedIds.stream()
.map(id -> new ShortcutKey(mPackageName, mUser, id))
.collect(Collectors.toSet())));
.collect(Collectors.toSet())),
"removed because the shortcut is no longer available in shortcut service");
}
}
@@ -96,7 +96,9 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask {
}
bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
if (!removedKeys.isEmpty()) {
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys));
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys),
"removed during unlock because it's no longer available"
+ " (possibly due to clear data)");
}
// Remove shortcut id map for that user
@@ -176,7 +176,8 @@ public class ItemClickHandler {
.setNeutralButton(R.string.abandoned_clean_this,
(d, i) -> launcher.getWorkspace()
.persistRemoveItemsByMatcher(ItemInfoMatcher.ofPackages(
Collections.singleton(packageName), user)))
Collections.singleton(packageName), user),
"user explicitly removes the promise app icon"))
.create().show();
}
@@ -259,7 +260,8 @@ public class ItemClickHandler {
// Remove the icon if launcher is successfully initialized
launcher.getWorkspace().persistRemoveItemsByMatcher(ItemInfoMatcher
.ofShortcutKeys(Collections.singleton(ShortcutKey
.fromItemInfo(shortcut))));
.fromItemInfo(shortcut))),
"user explicitly removes disabled shortcut");
})
.create()
.show();
@@ -457,7 +457,8 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
}
// Remove and rebind the current widget (which was inflated in the wrong
// orientation), but don't delete it from the database
mLauncher.removeItem(this, info, false /* deleteFromDb */);
mLauncher.removeItem(this, info, false /* deleteFromDb */,
"widget removed because of configuration change");
mLauncher.bindAppWidget(info);
}