diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java index 481e20007e..630ef39627 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java +++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java @@ -15,6 +15,8 @@ */ package com.android.launcher3.uioverrides.flags; +import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG; + import androidx.annotation.NonNull; import com.android.launcher3.config.FeatureFlags.BooleanFlag; @@ -35,6 +37,21 @@ class DebugFlag extends BooleanFlag { this.description = description; } + /** + * Returns {@code true} if this flag's value has been modified from its default. + *

+ * This helps to identify which flags have been toggled in log dumps and bug reports to + * further help triaging and debugging. + */ + boolean currentValueModified() { + switch (defaultValue) { + case ENABLED: return !get(); + case TEAMFOOD: return TEAMFOOD_FLAG.get() != get(); + case DISABLED: return get(); + default: return true; + } + } + @Override public String toString() { return key + ": defaultValue=" + defaultValue + ", mCurrentValue=" + get(); diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java index 035beb4df1..915f4aeaf7 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java +++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java @@ -28,6 +28,11 @@ class DeviceFlag extends DebugFlag { mDefaultValueInCode = defaultValueInCode; } + @Override + boolean currentValueModified() { + return super.currentValueModified() || mDefaultValueInCode != get(); + } + @Override public String toString() { return super.toString() + ", mDefaultValueInCode=" + mDefaultValueInCode; diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java index 28d4bf8854..48d313e2d3 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java @@ -175,7 +175,7 @@ public class FlagsFactory { synchronized (sDebugFlags) { for (DebugFlag flag : sDebugFlags) { if (flag instanceof DeviceFlag) { - pw.println(" " + flag); + pw.println((flag.currentValueModified() ? " ->" : " ") + flag); } } } @@ -185,11 +185,11 @@ public class FlagsFactory { pw.println(" " + flag); } } - pw.println("DebugFlags:"); + pw.println(" DebugFlags:"); synchronized (sDebugFlags) { for (DebugFlag flag : sDebugFlags) { if (!(flag instanceof DeviceFlag)) { - pw.println(" " + flag); + pw.println((flag.currentValueModified() ? " ->" : " ") + flag); } } } diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java index 49ec85ecd4..575be5f8df 100644 --- a/quickstep/src/com/android/quickstep/GestureState.java +++ b/quickstep/src/com/android/quickstep/GestureState.java @@ -29,13 +29,15 @@ import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_HOME; import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_NEW_TASK; -import android.annotation.Nullable; import android.annotation.TargetApi; import android.content.Intent; import android.os.Build; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulActivity; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; @@ -303,6 +305,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * @return the running task for this gesture. */ + @Nullable public CachedTaskInfo getRunningTask() { return mRunningTask; } @@ -336,7 +339,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * Updates the running task for the gesture to be the given {@param runningTask}. */ - public void updateRunningTask(CachedTaskInfo runningTask) { + public void updateRunningTask(@NonNull CachedTaskInfo runningTask) { mRunningTask = runningTask; } diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java index 5784c379cd..feaa063d88 100644 --- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java @@ -276,8 +276,11 @@ public final class LauncherActivityInterface extends @Override public boolean isInLiveTileMode() { Launcher launcher = getCreatedActivity(); - return launcher != null && launcher.getStateManager().getState() == OVERVIEW && - launcher.isStarted(); + + return launcher != null + && launcher.getStateManager().getState() == OVERVIEW + && launcher.isStarted() + && TopTaskTracker.INSTANCE.get(launcher).getCachedTopTask(false).isHomeTask(); } @Override diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java index f1af2edda8..a2a6dde483 100644 --- a/quickstep/src/com/android/quickstep/TopTaskTracker.java +++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java @@ -29,6 +29,7 @@ import android.annotation.UserIdInt; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; @@ -178,6 +179,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta /** * Returns the CachedTaskInfo for the top most task */ + @NonNull @UiThread public CachedTaskInfo getCachedTopTask(boolean filterOnlyVisibleRecents) { if (filterOnlyVisibleRecents) { diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index b4fe5e4fca..0ad56fb7a7 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -854,7 +854,11 @@ public class TouchInteractionService extends Service { if (mTaskAnimationManager.isRecentsAnimationRunning()) { gestureState = new GestureState(mOverviewComponentObserver, ActiveGestureLog.INSTANCE.getLogId()); - taskInfo = previousGestureState.getRunningTask(); + TopTaskTracker.CachedTaskInfo previousTaskInfo = previousGestureState.getRunningTask(); + // previousTaskInfo can be null iff previousGestureState == GestureState.DEFAULT_STATE + taskInfo = previousTaskInfo != null + ? previousTaskInfo + : TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false); gestureState.updateRunningTask(taskInfo); gestureState.updateLastStartedTaskIds(previousGestureState.getLastStartedTaskIds()); gestureState.updatePreviouslyAppearedTaskIds( @@ -869,7 +873,7 @@ public class TouchInteractionService extends Service { // Log initial state for the gesture. ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current running task package name=") - .append(taskInfo == null ? "no running task" : taskInfo.getPackageName())); + .append(taskInfo.getPackageName())); ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current SystemUi state flags=") .append(mDeviceState.getSystemUiStateString())); return gestureState; @@ -1078,21 +1082,22 @@ public class TouchInteractionService extends Service { reasonString.append(SUBSTRING_PREFIX).append("keyguard is not showing occluded"); + TopTaskTracker.CachedTaskInfo runningTask = gestureState.getRunningTask(); // Use overview input consumer for sharesheets on top of home. boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted() - && gestureState.getRunningTask() != null - && gestureState.getRunningTask().isRootChooseActivity(); + && runningTask != null + && runningTask.isRootChooseActivity(); // In the case where we are in an excluded, translucent overlay, ignore it and treat the // running activity as the task behind the overlay. - TopTaskTracker.CachedTaskInfo otherVisibleTask = gestureState.getRunningTask() == null + TopTaskTracker.CachedTaskInfo otherVisibleTask = runningTask == null ? null - : gestureState.getRunningTask().otherVisibleTaskThisIsExcludedOver(); + : runningTask.otherVisibleTaskThisIsExcludedOver(); if (otherVisibleTask != null) { ActiveGestureLog.INSTANCE.addLog(new CompoundString("Changing active task to ") .append(otherVisibleTask.getPackageName()) .append(" because the previous task running on top of this one (") - .append(gestureState.getRunningTask().getPackageName()) + .append(runningTask.getPackageName()) .append(") was excluded from recents")); gestureState.updateRunningTask(otherVisibleTask); } @@ -1112,7 +1117,7 @@ public class TouchInteractionService extends Service { forceOverviewInputConsumer, reasonString.append(SUBSTRING_PREFIX) .append("is in live tile mode, trying to use overview input consumer")); - } else if (gestureState.getRunningTask() == null) { + } else if (runningTask == null) { return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX) .append("running task == null")); } else if (previousGestureAnimatedToLauncher @@ -1130,7 +1135,7 @@ public class TouchInteractionService extends Service { ? "launcher resumed through a shell transition" : "forceOverviewInputConsumer == true")) .append(", trying to use overview input consumer")); - } else if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) { + } else if (mDeviceState.isGestureBlockedTask(runningTask)) { return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX) .append("is gesture-blocked task, trying to use default input consumer")); } else { diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java index ee721446a4..43592943f7 100644 --- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java +++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java @@ -146,25 +146,16 @@ public class ActiveGestureErrorDetector { writer); break; case TASK_APPEARED: - errorDetected |= printErrorIfTrue( - !encounteredEvents.contains(GestureEvent.SET_END_TARGET_NEW_TASK), - prefix, - /* errorMessage= */ "onTasksAppeared called " - + "before/without setting end target to new task", - writer); errorDetected |= printErrorIfTrue( !encounteredEvents.contains(GestureEvent.EXPECTING_TASK_APPEARED), prefix, /* errorMessage= */ "onTasksAppeared was not expected to be called", writer); - break; - case EXPECTING_TASK_APPEARED: - errorDetected |= printErrorIfTrue( - !encounteredEvents.contains(GestureEvent.SET_END_TARGET_NEW_TASK), - prefix, - /* errorMessage= */ "expecting onTasksAppeared to be called " - + "before/without setting end target to new task", - writer); + if (encounteredEvents.contains(GestureEvent.EXPECTING_TASK_APPEARED)) { + // Remove both events so that we can properly detect following errors. + encounteredEvents.remove(GestureEvent.EXPECTING_TASK_APPEARED); + encounteredEvents.remove(GestureEvent.TASK_APPEARED); + } break; case LAUNCHER_DESTROYED: errorDetected |= printErrorIfTrue( @@ -282,6 +273,7 @@ public class ActiveGestureErrorDetector { case START_RECENTS_ANIMATION: lastStartRecentAnimationEventEntryTime = eventEntry.getTime(); break; + case EXPECTING_TASK_APPEARED: case MOTION_DOWN: case SET_END_TARGET: case SET_END_TARGET_HOME: diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 94183c407f..ab51a70942 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -35,6 +35,7 @@ import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITIO import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition; import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts; +import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED; import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR; import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported; @@ -106,6 +107,7 @@ import com.android.quickstep.TaskIconCache; import com.android.quickstep.TaskThumbnailCache; import com.android.quickstep.TaskUtils; import com.android.quickstep.TaskViewUtils; +import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.BorderAnimator; import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.RecentsOrientedState; @@ -859,6 +861,7 @@ public class TaskView extends FrameLayout implements Reusable { getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId()); if (ActivityManagerWrapper.getInstance() .startActivityFromRecents(mTask.key, opts.options)) { + ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED); RecentsView recentsView = getRecentsView(); if (recentsView.getRunningTaskViewId() != -1) { recentsView.onTaskLaunchedInLiveTileMode();