Merge "Fix ClassCastException in QuickstepModelDelegate" into sc-v2-dev

This commit is contained in:
TreeHugger Robot 2021-11-25 04:00:37 +00:00 committed by Android (Google) Code Review
commit 32ebd9f94f
5 changed files with 153 additions and 13 deletions

View File

@ -161,8 +161,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
}
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
for (ItemInfo info : itemsIdMap) {
FolderInfo parent = info.container > 0
? (FolderInfo) itemsIdMap.get(info.container) : null;
FolderInfo parent = getContainer(info, itemsIdMap);
StatsLogCompatManager.writeSnapshot(info.buildProto(parent), instanceId);
}
additionalSnapshotEvents(instanceId);
@ -199,8 +198,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
}
for (ItemInfo info : itemsIdMap) {
FolderInfo parent = info.container > 0
? (FolderInfo) itemsIdMap.get(info.container) : null;
FolderInfo parent = getContainer(info, itemsIdMap);
LauncherAtom.ItemInfo itemInfo = info.buildProto(parent);
Log.d(TAG, itemInfo.toString());
StatsEvent statsEvent = StatsLogCompatManager.buildStatsEvent(itemInfo,
@ -222,6 +220,22 @@ public class QuickstepModelDelegate extends ModelDelegate {
}
}
private static FolderInfo getContainer(ItemInfo info, IntSparseArrayMap<ItemInfo> itemsIdMap) {
if (info.container > 0) {
ItemInfo containerInfo = itemsIdMap.get(info.container);
if (!(containerInfo instanceof FolderInfo)) {
Log.e(TAG, String.format(
"Item info: %s found with invalid container: %s",
info,
containerInfo));
} else {
return (FolderInfo) containerInfo;
}
}
return null;
}
@Override
public void validateData() {
super.validateData();

View File

@ -31,6 +31,8 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace;
@ -215,6 +217,19 @@ public class BgDataModel {
}
public synchronized void addItem(Context context, ItemInfo item, boolean newItem) {
addItem(context, item, newItem, null);
}
public synchronized void addItem(
Context context, ItemInfo item, boolean newItem, @Nullable LoaderMemoryLogger logger) {
if (logger != null) {
logger.addLog(
Log.DEBUG,
TAG,
String.format("Adding item to ID map: %s", item.toString()),
/* stackTrace= */ null);
}
itemsIdMap.put(item.id, item);
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:

View File

@ -383,18 +383,23 @@ public class LoaderCursor extends CursorWrapper {
info.cellY = getInt(cellYIndex);
}
public void checkAndAddItem(ItemInfo info, BgDataModel dataModel) {
checkAndAddItem(info, dataModel, null);
}
/**
* Adds the {@param info} to {@param dataModel} if it does not overlap with any other item,
* otherwise marks it for deletion.
*/
public void checkAndAddItem(ItemInfo info, BgDataModel dataModel) {
public void checkAndAddItem(
ItemInfo info, BgDataModel dataModel, LoaderMemoryLogger logger) {
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
// Ensure that it is a valid intent. An exception here will
// cause the item loading to get skipped
ShortcutKey.fromItemInfo(info);
}
if (checkItemPlacement(info)) {
dataModel.addItem(mContext, info, false);
dataModel.addItem(mContext, info, false, logger);
} else {
markDeleted("Item position overlap");
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2021 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 android.util.Log;
import androidx.annotation.Nullable;
import java.util.ArrayList;
/**
* Helper logger that collects logs while {@code LoaderTask#run} executes and prints them all iff
* an exception is caught in {@code LoaderTask#run}.
*/
public class LoaderMemoryLogger {
private static final String TAG = "LoaderMemoryLogger";
private final ArrayList<LogEntry> mLogEntries = new ArrayList<>();
protected LoaderMemoryLogger() {}
protected void addLog(int logLevel, String tag, String log) {
addLog(logLevel, tag, log, null);
}
protected void addLog(
int logLevel, String tag, String log, Exception stackTrace) {
switch (logLevel) {
case Log.ASSERT:
case Log.ERROR:
case Log.DEBUG:
case Log.INFO:
case Log.VERBOSE:
case Log.WARN:
mLogEntries.add(new LogEntry(logLevel, tag, log, stackTrace));
break;
default:
throw new IllegalArgumentException("Invalid log level provided: " + logLevel);
}
}
protected void clearLogs() {
mLogEntries.clear();
}
protected void printLogs() {
for (LogEntry logEntry : mLogEntries) {
String tag = String.format("%s: %s", TAG, logEntry.mLogTag);
String logString = logEntry.mStackStrace == null
? logEntry.mLogString
: String.format(
"%s\n%s",
logEntry.mLogString,
Log.getStackTraceString(logEntry.mStackStrace));
Log.println(logEntry.mLogLevel, tag, logString);
}
clearLogs();
}
private static class LogEntry {
protected final int mLogLevel;
protected final String mLogTag;
protected final String mLogString;
@Nullable protected final Exception mStackStrace;
protected LogEntry(
int logLevel, String logTag, String logString, @Nullable Exception stackStrace) {
mLogLevel = logLevel;
mLogTag = logTag;
mLogString = logString;
mStackStrace = stackStrace;
}
}
}

View File

@ -52,6 +52,8 @@ import android.util.Log;
import android.util.LongSparseArray;
import android.util.TimingLogger;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
@ -197,11 +199,12 @@ public class LoaderTask implements Runnable {
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
TimingLogger logger = new TimingLogger(TAG, "run");
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
Trace.beginSection("LoadWorkspace");
try {
loadWorkspace(allShortcuts);
loadWorkspace(allShortcuts, memoryLogger);
} finally {
Trace.endSection();
}
@ -311,9 +314,13 @@ public class LoaderTask implements Runnable {
mModelDelegate.modelLoadComplete();
transaction.commit();
memoryLogger.clearLogs();
} catch (CancellationException e) {
// Loader stopped, ignore
logASplit(logger, "Cancelled");
} catch (Exception e) {
memoryLogger.printLogs();
throw e;
} finally {
logger.dumpToLog();
}
@ -325,13 +332,21 @@ public class LoaderTask implements Runnable {
this.notify();
}
private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {
private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, LoaderMemoryLogger logger) {
loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI,
null /* selection */);
null /* selection */, logger);
}
protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri,
String selection) {
protected void loadWorkspace(
List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
loadWorkspace(allDeepShortcuts, contentUri, selection, null);
}
protected void loadWorkspace(
List<ShortcutInfo> allDeepShortcuts,
Uri contentUri,
String selection,
@Nullable LoaderMemoryLogger logger) {
final Context context = mApp.getContext();
final ContentResolver contentResolver = context.getContentResolver();
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
@ -635,7 +650,7 @@ public class LoaderTask implements Runnable {
}
}
c.checkAndAddItem(info, mBgDataModel);
c.checkAndAddItem(info, mBgDataModel, logger);
} else {
throw new RuntimeException("Unexpected null WorkspaceItemInfo");
}
@ -654,7 +669,7 @@ public class LoaderTask implements Runnable {
// no special handling required for restored folders
c.markRestored();
c.checkAndAddItem(folderInfo, mBgDataModel);
c.checkAndAddItem(folderInfo, mBgDataModel, logger);
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: