Merge "Log the reason why a WorkspaceItemInfo was removed" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8eaf87e77b
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user