Merge "Fix ClassCastException in QuickstepModelDelegate" into sc-v2-dev
This commit is contained in:
commit
32ebd9f94f
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue