Merge "Import translations. DO NOT MERGE ANYWHERE" into tm-qpr-dev
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index c46926e..7c22726 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -94,6 +94,7 @@
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.ActiveGestureLog.CompoundString;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.SplitScreenBounds;
@@ -126,6 +127,9 @@
public class TouchInteractionService extends Service
implements ProtoTraceable<LauncherTraceProto.Builder> {
+ private static final String SUBSTRING_PREFIX = "; ";
+ private static final String NEWLINE_PREFIX = "\n\t\t\t-> ";
+
private static final String TAG = "TouchInteractionService";
private static final boolean BUBBLES_HOME_GESTURE_ENABLED =
@@ -619,8 +623,6 @@
mConsumer.onConsumerAboutToBeSwitched();
mGestureState = newGestureState;
mConsumer = newConsumer(prevGestureState, mGestureState, event);
-
- ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName());
mUncheckedConsumer = mConsumer;
} else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
&& mDeviceState.canTriggerAssistantAction(event)) {
@@ -628,8 +630,7 @@
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
// should not interrupt it. QuickSwitch assumes that interruption can only
// happen if the next gesture is also quick switch.
- mUncheckedConsumer = tryCreateAssistantInputConsumer(
- InputConsumer.NO_OP, mGestureState, event);
+ mUncheckedConsumer = tryCreateAssistantInputConsumer(mGestureState, event);
} else if (mDeviceState.canTriggerOneHandedAction(event)) {
// Consume gesture event for triggering one handed feature.
mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
@@ -676,17 +677,31 @@
ProtoTracer.INSTANCE.get(this).scheduleFrameUpdate();
}
- private InputConsumer tryCreateAssistantInputConsumer(InputConsumer base,
+ private InputConsumer tryCreateAssistantInputConsumer(
GestureState gestureState, MotionEvent motionEvent) {
- return mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())
- ? base
- : new AssistantInputConsumer(this, gestureState, base, mInputMonitorCompat,
- mDeviceState, motionEvent);
+ return tryCreateAssistantInputConsumer(
+ InputConsumer.NO_OP, gestureState, motionEvent, CompoundString.NO_OP);
+ }
+
+ private InputConsumer tryCreateAssistantInputConsumer(
+ InputConsumer base,
+ GestureState gestureState,
+ MotionEvent motionEvent,
+ CompoundString reasonString) {
+ if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("is gesture-blocked task, using base input consumer");
+ return base;
+ } else {
+ reasonString.append(SUBSTRING_PREFIX).append("using AssistantInputConsumer");
+ return new AssistantInputConsumer(
+ this, gestureState, base, mInputMonitorCompat, mDeviceState, motionEvent);
+ }
}
public GestureState createGestureState(GestureState previousGestureState) {
GestureState gestureState = new GestureState(mOverviewComponentObserver,
- ActiveGestureLog.INSTANCE.generateAndSetLogId());
+ ActiveGestureLog.INSTANCE.incrementLogId());
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
gestureState.updateRunningTask(previousGestureState.getRunningTask());
gestureState.updateLastStartedTaskId(previousGestureState.getLastStartedTaskId());
@@ -699,50 +714,88 @@
return gestureState;
}
- private InputConsumer newConsumer(GestureState previousGestureState,
- GestureState newGestureState, MotionEvent event) {
+ private InputConsumer newConsumer(
+ GestureState previousGestureState, GestureState newGestureState, MotionEvent event) {
AnimatedFloat progressProxy = mSwipeUpProxyProvider.apply(mGestureState);
if (progressProxy != null) {
- return new ProgressDelegateInputConsumer(this, mTaskAnimationManager,
- mGestureState, mInputMonitorCompat, progressProxy);
+ InputConsumer consumer = new ProgressDelegateInputConsumer(
+ this, mTaskAnimationManager, mGestureState, mInputMonitorCompat, progressProxy);
+
+ logInputConsumerSelectionReason(consumer, newCompoundString(
+ "mSwipeUpProxyProvider has been set, using ProgressDelegateInputConsumer"));
+
+ return consumer;
}
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
if (!mDeviceState.isUserUnlocked()) {
+ CompoundString reasonString = newCompoundString("device locked");
+ InputConsumer consumer;
if (canStartSystemGesture) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g. camera).
- return createDeviceLockedInputConsumer(newGestureState);
+ consumer = createDeviceLockedInputConsumer(
+ newGestureState, reasonString.append(SUBSTRING_PREFIX)
+ .append("can start system gesture"));
} else {
- return getDefaultInputConsumer();
+ consumer = getDefaultInputConsumer(
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("cannot start system gesture"));
}
+ logInputConsumerSelectionReason(consumer, reasonString);
+ return consumer;
}
+ CompoundString reasonString;
+ InputConsumer base;
// When there is an existing recents animation running, bypass systemState check as this is
// a followup gesture and the first gesture started in a valid system state.
- InputConsumer base = canStartSystemGesture
- || previousGestureState.isRecentsAnimationRunning()
- ? newBaseConsumer(previousGestureState, newGestureState, event)
- : getDefaultInputConsumer();
+ if (canStartSystemGesture || previousGestureState.isRecentsAnimationRunning()) {
+ reasonString = newCompoundString(canStartSystemGesture
+ ? "can start system gesture" : "recents animation was running")
+ .append(", trying to use base consumer");
+ base = newBaseConsumer(previousGestureState, newGestureState, event, reasonString);
+ } else {
+ reasonString = newCompoundString(
+ "cannot start system gesture and recents animation was not running")
+ .append(", trying to use default input consumer");
+ base = getDefaultInputConsumer(reasonString);
+ }
if (mDeviceState.isGesturalNavMode()) {
handleOrientationSetup(base);
}
if (mDeviceState.isFullyGesturalNavMode()) {
+ String reasonPrefix = "device is in gesture navigation mode";
if (mDeviceState.canTriggerAssistantAction(event)) {
- base = tryCreateAssistantInputConsumer(base, newGestureState, event);
+ reasonString.append(NEWLINE_PREFIX)
+ .append(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("gesture can trigger the assistant")
+ .append(", trying to use assistant input consumer");
+ base = tryCreateAssistantInputConsumer(base, newGestureState, event, reasonString);
}
// If Taskbar is present, we listen for long press to unstash it.
TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
if (tac != null) {
+ reasonString.append(NEWLINE_PREFIX)
+ .append(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("TaskbarActivityContext != null, using TaskbarStashInputConsumer");
base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat, tac);
}
if (mDeviceState.isBubblesExpanded()) {
+ reasonString = newCompoundString(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("bubbles expanded");
if (BUBBLES_HOME_GESTURE_ENABLED) {
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("bubbles can handle the home gesture")
+ .append(", trying to use default input consumer");
// Bubbles can handle home gesture itself.
- base = getDefaultInputConsumer();
+ base = getDefaultInputConsumer(reasonString);
} else {
// If Bubbles is expanded, use the overlay input consumer, which will close
// Bubbles instead of going all the way home when a swipe up is detected.
@@ -750,6 +803,9 @@
// expanded in the back. Make sure swipe up is not passed to bubbles in this
// case.
if (!mDeviceState.isNotificationPanelExpanded()) {
+ reasonString = newCompoundString(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("using SysUiOverlayInputConsumer");
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
@@ -757,6 +813,9 @@
}
if (mDeviceState.isSystemUiDialogShowing()) {
+ reasonString = newCompoundString(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("system dialog is showing, using SysUiOverlayInputConsumer");
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
@@ -764,44 +823,91 @@
if (mDeviceState.isScreenPinningActive()) {
+ reasonString = newCompoundString(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("screen pinning is active, using ScreenPinnedInputConsumer");
// Note: we only allow accessibility to wrap this, and it replaces the previous
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
base = new ScreenPinnedInputConsumer(this, newGestureState);
}
if (mDeviceState.canTriggerOneHandedAction(event)) {
- base = new OneHandedModeInputConsumer(this, mDeviceState, base,
- mInputMonitorCompat);
+ reasonString.append(NEWLINE_PREFIX)
+ .append(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("gesture can trigger one handed mode")
+ .append(", using OneHandedModeInputConsumer");
+ base = new OneHandedModeInputConsumer(
+ this, mDeviceState, base, mInputMonitorCompat);
}
if (mDeviceState.isAccessibilityMenuAvailable()) {
- base = new AccessibilityInputConsumer(this, mDeviceState, base,
- mInputMonitorCompat);
+ reasonString.append(NEWLINE_PREFIX)
+ .append(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("accessibility menu is available")
+ .append(", using AccessibilityInputConsumer");
+ base = new AccessibilityInputConsumer(
+ this, mDeviceState, base, mInputMonitorCompat);
}
} else {
+ String reasonPrefix = "device is not in gesture navigation mode";
if (mDeviceState.isScreenPinningActive()) {
- base = getDefaultInputConsumer();
+ reasonString = newCompoundString(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("screen pinning is active, trying to use default input consumer");
+ base = getDefaultInputConsumer(reasonString);
}
if (mDeviceState.canTriggerOneHandedAction(event)) {
- base = new OneHandedModeInputConsumer(this, mDeviceState, base,
- mInputMonitorCompat);
+ reasonString.append(NEWLINE_PREFIX)
+ .append(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("gesture can trigger one handed mode")
+ .append(", using OneHandedModeInputConsumer");
+ base = new OneHandedModeInputConsumer(
+ this, mDeviceState, base, mInputMonitorCompat);
}
}
+ logInputConsumerSelectionReason(base, reasonString);
return base;
}
+ private CompoundString newCompoundString(String substring) {
+ return new CompoundString(NEWLINE_PREFIX).append(substring);
+ }
+
+ private void logInputConsumerSelectionReason(
+ InputConsumer consumer, CompoundString reasonString) {
+ if (!FeatureFlags.ENABLE_INPUT_CONSUMER_REASON_LOGGING.get()) {
+ ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + consumer.getName());
+ return;
+ }
+ ActiveGestureLog.INSTANCE.addLog(new CompoundString("setInputConsumer: ")
+ .append(consumer.getName())
+ .append(". reason(s):")
+ .append(reasonString));
+ }
+
private void handleOrientationSetup(InputConsumer baseInputConsumer) {
baseInputConsumer.notifyOrientationSetup();
}
- private InputConsumer newBaseConsumer(GestureState previousGestureState,
- GestureState gestureState, MotionEvent event) {
+ private InputConsumer newBaseConsumer(
+ GestureState previousGestureState,
+ GestureState gestureState,
+ MotionEvent event,
+ CompoundString reasonString) {
if (mDeviceState.isKeyguardShowingOccluded()) {
// This handles apps showing over the lockscreen (e.g. camera)
- return createDeviceLockedInputConsumer(gestureState);
+ return createDeviceLockedInputConsumer(
+ gestureState,
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("keyguard is showing occluded")
+ .append(", trying to use device locked input consumer"));
}
+ reasonString.append(SUBSTRING_PREFIX).append("keyguard is not showing occluded");
// Use overview input consumer for sharesheets on top of home.
boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
&& gestureState.getRunningTask() != null
@@ -815,23 +921,46 @@
forceOverviewInputConsumer = gestureState.getRunningTask().isHomeTask();
}
+ boolean previousGestureAnimatedToLauncher =
+ previousGestureState.isRunningAnimationToLauncher();
+ // with shell-transitions, home is resumed during recents animation, so
+ // explicitly check against recents animation too.
+ boolean launcherResumedThroughShellTransition =
+ gestureState.getActivityInterface().isResumed()
+ && !previousGestureState.isRecentsAnimationRunning();
if (ENABLE_QUICKSTEP_LIVE_TILE.get()
&& gestureState.getActivityInterface().isInLiveTileMode()) {
return createOverviewInputConsumer(
- previousGestureState, gestureState, event, forceOverviewInputConsumer);
+ previousGestureState,
+ gestureState,
+ event,
+ forceOverviewInputConsumer,
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("is in live tile mode, trying to use overview input consumer"));
} else if (gestureState.getRunningTask() == null) {
- return getDefaultInputConsumer();
- } else if (previousGestureState.isRunningAnimationToLauncher()
- || (gestureState.getActivityInterface().isResumed()
- // with shell-transitions, home is resumed during recents animation, so
- // explicitly check against recents animation too.
- && !previousGestureState.isRecentsAnimationRunning())
+ return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
+ .append("running task == null"));
+ } else if (previousGestureAnimatedToLauncher
+ || launcherResumedThroughShellTransition
|| forceOverviewInputConsumer) {
return createOverviewInputConsumer(
- previousGestureState, gestureState, event, forceOverviewInputConsumer);
+ previousGestureState,
+ gestureState,
+ event,
+ forceOverviewInputConsumer,
+ reasonString.append(SUBSTRING_PREFIX)
+ .append(previousGestureAnimatedToLauncher
+ ? "previous gesture animated to launcher"
+ : (launcherResumedThroughShellTransition
+ ? "launcher resumed through a shell transition"
+ : "forceOverviewInputConsumer == true"))
+ .append(", trying to use overview input consumer"));
} else if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
- return getDefaultInputConsumer();
+ return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
+ .append("is gesture-blocked task, trying to use default input consumer"));
} else {
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("using OtherActivityInputConsumer");
return createOtherActivityInputConsumer(gestureState, event);
}
}
@@ -853,21 +982,34 @@
mInputMonitorCompat, mInputEventReceiver, disableHorizontalSwipe, factory);
}
- private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState) {
+ private InputConsumer createDeviceLockedInputConsumer(
+ GestureState gestureState, CompoundString reasonString) {
if (mDeviceState.isFullyGesturalNavMode() && gestureState.getRunningTask() != null) {
- return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
- gestureState, mInputMonitorCompat);
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("device is in gesture nav mode and running task != null")
+ .append(", using DeviceLockedInputConsumer");
+ return new DeviceLockedInputConsumer(
+ this, mDeviceState, mTaskAnimationManager, gestureState, mInputMonitorCompat);
} else {
- return getDefaultInputConsumer();
+ return getDefaultInputConsumer(reasonString
+ .append(SUBSTRING_PREFIX)
+ .append(mDeviceState.isFullyGesturalNavMode()
+ ? "running task == null" : "device is not in gesture nav mode")
+ .append(", trying to use default input consumer"));
}
}
- public InputConsumer createOverviewInputConsumer(GestureState previousGestureState,
- GestureState gestureState, MotionEvent event,
- boolean forceOverviewInputConsumer) {
+ public InputConsumer createOverviewInputConsumer(
+ GestureState previousGestureState,
+ GestureState gestureState,
+ MotionEvent event,
+ boolean forceOverviewInputConsumer,
+ CompoundString reasonString) {
StatefulActivity activity = gestureState.getActivityInterface().getCreatedActivity();
if (activity == null) {
- return getDefaultInputConsumer();
+ return getDefaultInputConsumer(
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("activity == null, trying to use default input consumer"));
}
if (activity.getRootView().hasWindowFocus()
@@ -876,9 +1018,13 @@
&& forceOverviewInputConsumer)
|| (ENABLE_QUICKSTEP_LIVE_TILE.get()
&& gestureState.getActivityInterface().isInLiveTileMode())) {
+ reasonString.append(SUBSTRING_PREFIX)
+ .append("overview should have focus, using OverviewInputConsumer");
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
+ reasonString.append(SUBSTRING_PREFIX).append(
+ "overview shouldn't have focus, using OverviewWithoutFocusInputConsumer");
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
return new OverviewWithoutFocusInputConsumer(activity, mDeviceState, gestureState,
mInputMonitorCompat, disableHorizontalSwipe);
@@ -906,13 +1052,21 @@
}
}
+ private @NonNull InputConsumer getDefaultInputConsumer() {
+ return getDefaultInputConsumer(CompoundString.NO_OP);
+ }
+
/**
* Returns the {@link ResetGestureInputConsumer} if user is unlocked, else NO_OP.
*/
- private @NonNull InputConsumer getDefaultInputConsumer() {
+ private @NonNull InputConsumer getDefaultInputConsumer(@NonNull CompoundString reasonString) {
if (mResetGestureInputConsumer != null) {
+ reasonString.append(SUBSTRING_PREFIX).append(
+ "mResetGestureInputConsumer initialized, using ResetGestureInputConsumer");
return mResetGestureInputConsumer;
} else {
+ reasonString.append(SUBSTRING_PREFIX).append(
+ "mResetGestureInputConsumer not initialized, using no-op input consumer");
// mResetGestureInputConsumer isn't initialized until onUserUnlocked(), so reset to
// NO_OP until then (we never want these to be null).
return InputConsumer.NO_OP;
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
index fabfc4b..be45f63 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
@@ -15,15 +15,23 @@
*/
package com.android.quickstep.util;
-import android.content.Context;
+import androidx.annotation.NonNull;
-import com.android.launcher3.logging.EventLogArray;
-import com.android.launcher3.util.MainThreadInitializedObject;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
/**
* A log to keep track of the active gesture.
*/
-public class ActiveGestureLog extends EventLogArray {
+public class ActiveGestureLog {
+
+ private static final int MAX_GESTURES_TRACKED = 10;
public static final ActiveGestureLog INSTANCE = new ActiveGestureLog();
@@ -33,7 +41,238 @@
*/
public static final String INTENT_EXTRA_LOG_TRACE_ID = "INTENT_EXTRA_LOG_TRACE_ID";
+ private static final int TYPE_ONE_OFF = 0;
+ private static final int TYPE_FLOAT = 1;
+ private static final int TYPE_INTEGER = 2;
+ private static final int TYPE_BOOL_TRUE = 3;
+ private static final int TYPE_BOOL_FALSE = 4;
+ private static final int TYPE_INPUT_CONSUMER = 5;
+
+ private final EventLog[] logs;
+ private int nextIndex;
+ private int mCurrentLogId = 100;
+
private ActiveGestureLog() {
- super("touch_interaction_log", 40);
+ this.logs = new EventLog[MAX_GESTURES_TRACKED];
+ this.nextIndex = 0;
+ }
+
+ public void addLog(String event) {
+ addLog(TYPE_ONE_OFF, event, 0, CompoundString.NO_OP);
+ }
+
+ public void addLog(String event, int extras) {
+ addLog(TYPE_INTEGER, event, extras, CompoundString.NO_OP);
+ }
+
+ public void addLog(String event, boolean extras) {
+ addLog(extras ? TYPE_BOOL_TRUE : TYPE_BOOL_FALSE, event, 0, CompoundString.NO_OP);
+ }
+
+ public void addLog(CompoundString compoundString) {
+ addLog(TYPE_INPUT_CONSUMER, "", 0, compoundString);
+ }
+
+ private void addLog(
+ int type, String event, float extras, @NonNull CompoundString compoundString) {
+ EventLog lastEventLog = logs[(nextIndex + logs.length - 1) % logs.length];
+ if (lastEventLog == null || mCurrentLogId != lastEventLog.logId) {
+ EventLog eventLog = new EventLog(mCurrentLogId);
+ EventEntry eventEntry = new EventEntry();
+
+ eventEntry.update(type, event, extras, compoundString);
+ eventLog.eventEntries.add(eventEntry);
+ logs[nextIndex] = eventLog;
+ nextIndex = (nextIndex + 1) % logs.length;
+ return;
+ }
+
+ // Update the last EventLog
+ List<EventEntry> lastEventEntries = lastEventLog.eventEntries;
+ EventEntry lastEntry = lastEventEntries.size() > 0
+ ? lastEventEntries.get(lastEventEntries.size() - 1) : null;
+ EventEntry secondLastEntry = lastEventEntries.size() > 1
+ ? lastEventEntries.get(lastEventEntries.size() - 2) : null;
+
+ // Update the last EventEntry if it's a duplicate
+ if (isEntrySame(lastEntry, type, event, compoundString)
+ && isEntrySame(secondLastEntry, type, event, compoundString)) {
+ lastEntry.update(type, event, extras, compoundString);
+ secondLastEntry.duplicateCount++;
+ return;
+ }
+ EventEntry eventEntry = new EventEntry();
+
+ eventEntry.update(type, event, extras, compoundString);
+ lastEventEntries.add(eventEntry);
+ }
+
+ public void clear() {
+ Arrays.fill(logs, null);
+ }
+
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "ActiveGestureLog history:");
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSSZ ", Locale.US);
+ Date date = new Date();
+
+ for (int i = 0; i < logs.length; i++) {
+ EventLog eventLog = logs[(nextIndex + logs.length - i - 1) % logs.length];
+ if (eventLog == null) {
+ continue;
+ }
+ writer.println(prefix + "\tLogs for logId: " + eventLog.logId);
+
+ List<EventEntry> eventEntries = eventLog.eventEntries;
+ for (int j = eventEntries.size() - 1; j >= 0; j--) {
+ EventEntry eventEntry = eventEntries.get(j);
+ date.setTime(eventEntry.time);
+
+ StringBuilder msg = new StringBuilder(prefix + "\t\t").append(sdf.format(date))
+ .append(eventEntry.event);
+ switch (eventEntry.type) {
+ case TYPE_BOOL_FALSE:
+ msg.append(": false");
+ break;
+ case TYPE_BOOL_TRUE:
+ msg.append(": true");
+ break;
+ case TYPE_FLOAT:
+ msg.append(": ").append(eventEntry.extras);
+ break;
+ case TYPE_INTEGER:
+ msg.append(": ").append((int) eventEntry.extras);
+ break;
+ case TYPE_INPUT_CONSUMER:
+ msg.append(eventEntry.mCompoundString);
+ break;
+ default: // fall out
+ }
+ if (eventEntry.duplicateCount > 0) {
+ msg.append(" & ").append(eventEntry.duplicateCount).append(" similar events");
+ }
+ writer.println(msg);
+ }
+ }
+ }
+
+ /**
+ * Increments and returns the current log ID. This should be used every time a new log trace
+ * is started.
+ */
+ public int incrementLogId() {
+ return mCurrentLogId++;
+ }
+
+ private boolean isEntrySame(
+ EventEntry entry, int type, String event, CompoundString compoundString) {
+ return entry != null
+ && entry.type == type
+ && entry.event.equals(event)
+ && entry.mCompoundString.equals(compoundString);
+ }
+
+ /** A single event entry. */
+ private static class EventEntry {
+
+ private int type;
+ private String event;
+ private float extras;
+ @NonNull private CompoundString mCompoundString;
+ private long time;
+ private int duplicateCount;
+
+ public void update(
+ int type,
+ String event,
+ float extras,
+ @NonNull CompoundString compoundString) {
+ this.type = type;
+ this.event = event;
+ this.extras = extras;
+ this.mCompoundString = compoundString;
+ time = System.currentTimeMillis();
+ duplicateCount = 0;
+ }
+ }
+
+ /** An entire log of entries associated with a single log ID */
+ private static class EventLog {
+
+ private final List<EventEntry> eventEntries = new ArrayList<>();
+ private final int logId;
+
+ protected EventLog(int logId) {
+ this.logId = logId;
+ }
+ }
+
+ /** A buildable string stored as an array for memory efficiency. */
+ public static class CompoundString {
+
+ public static final CompoundString NO_OP = new CompoundString();
+
+ private final List<String> mSubstrings;
+
+ private final boolean mIsNoOp;
+
+ private CompoundString() {
+ this(null);
+ }
+
+ public CompoundString(String substring) {
+ mIsNoOp = substring == null;
+ if (mIsNoOp) {
+ mSubstrings = null;
+ return;
+ }
+ mSubstrings = new ArrayList<>();
+ mSubstrings.add(substring);
+ }
+
+ public CompoundString append(CompoundString substring) {
+ if (mIsNoOp) {
+ return this;
+ }
+ mSubstrings.addAll(substring.mSubstrings);
+
+ return this;
+ }
+
+ public CompoundString append(String substring) {
+ if (mIsNoOp) {
+ return this;
+ }
+ mSubstrings.add(substring);
+
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ if (mIsNoOp) {
+ return "ERROR: cannot use No-Op compound string";
+ }
+ StringBuilder sb = new StringBuilder();
+ for (String substring : mSubstrings) {
+ sb.append(substring);
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsNoOp, mSubstrings);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CompoundString)) {
+ return false;
+ }
+ CompoundString other = (CompoundString) obj;
+ return mIsNoOp && other.mIsNoOp && Objects.equals(mSubstrings, other.mSubstrings);
+ }
}
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index d0dbaf4..616b08a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -75,6 +75,7 @@
import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
@@ -925,4 +926,12 @@
}
return options;
}
+
+ public static boolean bothNull(@Nullable Object a, @Nullable Object b) {
+ return a == null && b == null;
+ }
+
+ public static boolean bothNonNull(@Nullable Object a, @Nullable Object b) {
+ return a != null && b != null;
+ }
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index dd58e71..49466ad 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -63,6 +63,11 @@
* Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"),
* and set a default value for the flag. This will be the default value on Debug builds.
*/
+ public static final BooleanFlag ENABLE_INPUT_CONSUMER_REASON_LOGGING = getDebugFlag(
+ "ENABLE_INPUT_CONSUMER_REASON_LOGGING",
+ false,
+ "Log the reason why an Input Consumer was selected for a gesture.");
+
// When enabled the promise icon is visible in all apps while installation an app.
public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(
"PROMISE_APPS_IN_ALL_APPS", false, "Add promise icon in all-apps");
diff --git a/src/com/android/launcher3/logging/EventLogArray.java b/src/com/android/launcher3/logging/EventLogArray.java
deleted file mode 100644
index 3ecfb23..0000000
--- a/src/com/android/launcher3/logging/EventLogArray.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2019 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.logging;
-
-
-import android.util.Log;
-import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Random;
-
-/**
- * A utility class to record and log events. Events are stored in a fixed size array and old logs
- * are purged as new events come.
- */
-public class EventLogArray {
-
- private static final int TYPE_ONE_OFF = 0;
- private static final int TYPE_FLOAT = 1;
- private static final int TYPE_INTEGER = 2;
- private static final int TYPE_BOOL_TRUE = 3;
- private static final int TYPE_BOOL_FALSE = 4;
-
- private final String name;
- private final EventEntry[] logs;
- private int nextIndex;
- private int mLogId;
-
- public EventLogArray(String name, int size) {
- this.name = name;
- logs = new EventEntry[size];
- nextIndex = 0;
- }
-
- public void addLog(String event) {
- addLog(TYPE_ONE_OFF, event, 0);
- }
-
- public void addLog(String event, int extras) {
- addLog(TYPE_INTEGER, event, extras);
- }
-
- public void addLog(String event, boolean extras) {
- addLog(extras ? TYPE_BOOL_TRUE : TYPE_BOOL_FALSE, event, 0);
- }
-
- private void addLog(int type, String event, float extras) {
- // Merge the logs if its a duplicate
- int last = (nextIndex + logs.length - 1) % logs.length;
- int secondLast = (nextIndex + logs.length - 2) % logs.length;
- if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) {
- logs[last].update(type, event, extras, mLogId);
- logs[secondLast].duplicateCount++;
- return;
- }
-
- if (logs[nextIndex] == null) {
- logs[nextIndex] = new EventEntry();
- }
- logs[nextIndex].update(type, event, extras, mLogId);
- nextIndex = (nextIndex + 1) % logs.length;
- }
-
- public void clear() {
- Arrays.setAll(logs, (i) -> null);
- }
-
- public void dump(String prefix, PrintWriter writer) {
- writer.println(prefix + "EventLog (" + name + ") history:");
- SimpleDateFormat sdf = new SimpleDateFormat(" HH:mm:ss.SSSZ ", Locale.US);
- Date date = new Date();
-
- for (int i = 0; i < logs.length; i++) {
- EventEntry log = logs[(nextIndex + logs.length - i - 1) % logs.length];
- if (log == null) {
- continue;
- }
- date.setTime(log.time);
-
- StringBuilder msg = new StringBuilder(prefix).append(sdf.format(date))
- .append(log.event);
- switch (log.type) {
- case TYPE_BOOL_FALSE:
- msg.append(": false");
- break;
- case TYPE_BOOL_TRUE:
- msg.append(": true");
- break;
- case TYPE_FLOAT:
- msg.append(": ").append(log.extras);
- break;
- case TYPE_INTEGER:
- msg.append(": ").append((int) log.extras);
- break;
- default: // fall out
- }
- if (log.duplicateCount > 0) {
- msg.append(" & ").append(log.duplicateCount).append(" similar events");
- }
- msg.append(" traceId: ").append(log.traceId);
- writer.println(msg);
- }
- }
-
- /** Returns a 3 digit random number between 100-999 */
- public int generateAndSetLogId() {
- Random r = new Random();
- mLogId = r.nextInt(900) + 100;
- return mLogId;
- }
-
- private boolean isEntrySame(EventEntry entry, int type, String event) {
- return entry != null && entry.type == type && entry.event.equals(event);
- }
-
- /** A single event entry. */
- private static class EventEntry {
-
- private int type;
- private String event;
- private float extras;
- private long time;
- private int duplicateCount;
- private int traceId;
-
- public void update(int type, String event, float extras, int traceId) {
- this.type = type;
- this.event = event;
- this.extras = extras;
- this.traceId = traceId;
- time = System.currentTimeMillis();
- duplicateCount = 0;
- }
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index d474c06..5baa7d2 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -588,4 +588,16 @@
public static String getAppPackageName() {
return getInstrumentation().getContext().getPackageName();
}
+
+ @Test
+ public void testGetAppIconName() {
+ HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
+ assertEquals("Wrong app icon name.", icon.getIconName(), APP_NAME);
+ } finally {
+ allApps.unfreeze();
+ }
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index d221259..2687b28 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -18,6 +18,7 @@
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
@@ -86,4 +87,10 @@
protected String launchableType() {
return "app icon";
}
+
+ /** Return the app name of a icon */
+ @NonNull
+ public String getIconName() {
+ return getObject().getText();
+ }
}