Merge "Don't rely on nav mode change listener for oriented state" into ub-launcher3-rvc-dev
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 527bfc3..60afddb 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -52,7 +52,7 @@
android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
- android:taskAffinity="${packageName}.launcher"
+ android:taskAffinity=""
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index b2286f1..00b0951 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -99,7 +99,6 @@
android:name="com.android.quickstep.interaction.GestureSandboxActivity"
android:autoRemoveFromRecents="true"
android:excludeFromRecents="true"
- android:taskAffinity="${packageName}.launcher"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="com.android.quickstep.action.GESTURE_SANDBOX" />
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index f881610..0113570 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -18,12 +18,12 @@
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALL_APPS_RANKED;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
import android.content.ComponentName;
import android.content.Context;
-import android.os.Process;
import androidx.annotation.NonNull;
@@ -36,9 +36,10 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
-import com.android.launcher3.hybridhotseat.HotseatFileLog;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.shortcuts.ShortcutKey;
@@ -50,6 +51,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.OptionalInt;
import java.util.stream.IntStream;
/**
@@ -304,6 +306,41 @@
}
/**
+ * Logs ranking info for launched app within all apps prediction.
+ * Only applicable when {@link ItemInfo#itemType} is one of the followings:
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
+ */
+ public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
+ if (itemInfo.getTargetComponent() == null || itemInfo.user == null
+ || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
+ return;
+ }
+
+ Launcher launcher = Launcher.getLauncher(mAppsView.getContext());
+ final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+ final List<ComponentKeyMapper> predictedApps = getCurrentState().apps;
+ OptionalInt rank = IntStream.range(0, predictedApps.size())
+ .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+ .findFirst();
+ if (!rank.isPresent()) {
+ return;
+ }
+
+ LauncherAtom.ItemInfo.Builder atomBuilder = LauncherAtom.ItemInfo.newBuilder();
+ atomBuilder.setRank(rank.getAsInt());
+ atomBuilder.setContainerInfo(
+ LauncherAtom.ContainerInfo.newBuilder().setPredictionContainer(
+ LauncherAtom.PredictionContainer.newBuilder().build()).build());
+ launcher.getStatsLogManager().log(LAUNCHER_ALL_APPS_RANKED, instanceId,
+ atomBuilder.build());
+ }
+
+
+ /**
* Fill in predicted_rank field based on app prediction.
* Only applicable when {@link ItemInfo#itemType} is one of the followings:
* {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
@@ -313,17 +350,6 @@
public static void fillInPredictedRank(
@NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
- HotseatFileLog hotseatFileLog = HotseatFileLog.INSTANCE.getNoCreate();
-
- if (hotseatFileLog != null && itemInfo != null && Utilities.IS_DEBUG_DEVICE) {
- final String pkg = itemInfo.getTargetComponent() != null
- ? itemInfo.getTargetComponent().getPackageName() : "unknown";
- hotseatFileLog.log("UserEvent",
- "appLaunch: packageName:" + pkg + ",isWorkApp:" + (itemInfo.user != null
- && !Process.myUserHandle().equals(itemInfo.user))
- + ",launchLocation:" + itemInfo.container);
- }
-
final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
|| (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index 5d807d3..522a2dc 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -265,7 +265,7 @@
requiresMigration ? R.string.hotseat_tip_no_empty_slots
: R.string.hotseat_auto_enrolled),
mHotseat.getTop());
- mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_ONLY_TIP);
+ mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_ONLY_TIP);
finishOnboarding();
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 96be5df..2b3f395 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -112,13 +112,13 @@
mHotseatEduController.moveHotseatItems();
mHotseatEduController.finishOnboarding();
- mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_ACCEPT);
+ mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_ACCEPT);
}
private void onDismiss(View v) {
mHotseatEduController.showDimissTip();
mHotseatEduController.finishOnboarding();
- mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_DENY);
+ mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_DENY);
handleClose(true);
}
@@ -212,7 +212,7 @@
}
AbstractFloatingView.closeAllOpenViews(mLauncher);
attachToContainer();
- mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_SEEN);
+ mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_SEEN);
animateOpen();
populatePreview(predictions);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 6ca07bb..30a34e4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.hybridhotseat.HotseatEduController.SETTINGS_ACTION;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -29,6 +30,7 @@
import android.app.prediction.AppTargetEvent;
import android.content.ComponentName;
import android.content.Intent;
+import android.os.Process;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -52,6 +54,8 @@
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -185,7 +189,6 @@
/**
* Returns if hotseat client has predictions
- * @return
*/
public boolean hasPredictions() {
return !mComponentKeyMappers.isEmpty();
@@ -358,6 +361,7 @@
updateDependencies();
bindItems(items, false, null);
}
+
private void setPredictedApps(List<AppTarget> appTargets) {
mComponentKeyMappers.clear();
if (appTargets.isEmpty()) {
@@ -635,6 +639,48 @@
mHotseat.fillInLogContainerData(childInfo, child, parents);
}
+ /**
+ * Logs rank info based on current list of predicted items
+ */
+ public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
+ if (Utilities.IS_DEBUG_DEVICE) {
+ final String pkg = itemInfo.getTargetComponent() != null
+ ? itemInfo.getTargetComponent().getPackageName() : "unknown";
+ HotseatFileLog.INSTANCE.get(mLauncher).log("UserEvent",
+ "appLaunch: packageName:" + pkg + ",isWorkApp:" + (itemInfo.user != null
+ && !Process.myUserHandle().equals(itemInfo.user))
+ + ",launchLocation:" + itemInfo.container);
+ }
+
+ final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+
+ final List<ComponentKeyMapper> predictedApps = new ArrayList<>(mComponentKeyMappers);
+ OptionalInt rank = IntStream.range(0, predictedApps.size())
+ .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+ .findFirst();
+ if (!rank.isPresent()) {
+ return;
+ }
+ LauncherAtom.PredictedHotseatContainer.Builder containerBuilder =
+ LauncherAtom.PredictedHotseatContainer.newBuilder();
+ LauncherAtom.ItemInfo.Builder atomBuilder = LauncherAtom.ItemInfo.newBuilder();
+ int cardinality = 0;
+ for (PredictedAppIcon icon : getPredictedIcons()) {
+ ItemInfo info = (ItemInfo) icon.getTag();
+ cardinality |= 1 << info.screenId;
+ }
+ containerBuilder.setCardinality(cardinality);
+ atomBuilder.setRank(rank.getAsInt());
+ if (itemInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
+ containerBuilder.setIndex(rank.getAsInt());
+ }
+ atomBuilder.setContainerInfo(
+ LauncherAtom.ContainerInfo.newBuilder().setPredictedHotseatContainer(
+ containerBuilder).build());
+ mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_RANKED, instanceId,
+ atomBuilder.build());
+ }
+
private class PinPrediction extends SystemShortcut<QuickstepLauncher> {
private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index 0ace4cc..597c17b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -57,7 +57,7 @@
LauncherAccessibilityDelegate.AccessibilityActionHandler {
private static final int RING_SHADOW_COLOR = 0x99000000;
- private static final float RING_EFFECT_RATIO = 0.08f;
+ private static final float RING_EFFECT_RATIO = 0.095f;
boolean mIsDrawingDot = false;
private final DeviceProfile mDeviceProfile;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 77d71a3..0e690eb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -29,6 +29,7 @@
import android.content.Intent;
import android.content.res.Configuration;
+import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -41,10 +42,12 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.hybridhotseat.HotseatEduController;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
+import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -89,11 +92,18 @@
SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2);
@Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (mHotseatPredictionController != null) {
+ mHotseatPredictionController.createPredictor();
+ }
+ }
+
+ @Override
protected void setupViews() {
super.setupViews();
if (FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) {
mHotseatPredictionController = new HotseatPredictionController(this);
- mHotseatPredictionController.createPredictor();
}
}
@@ -112,6 +122,15 @@
}
@Override
+ protected void logAppLaunch(ItemInfo info, InstanceId instanceId) {
+ super.logAppLaunch(info, instanceId);
+ if (mHotseatPredictionController != null) {
+ mHotseatPredictionController.logLaunchedAppRankingInfo(info, instanceId);
+ }
+ PredictionUiStateManager.INSTANCE.get(this).logLaunchedAppRankingInfo(info, instanceId);
+ }
+
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
onStateOrResumeChanging(false /* inTransition */);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 966e25b..4cc8256 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
+import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.PointF;
@@ -59,6 +60,8 @@
private boolean mDidTouchStartInNavBar;
private boolean mReachedOverview;
+ private boolean mIsOverviewRehidden;
+ private boolean mIsHomeStaggeredAnimFinished;
// The last recorded displacement before we reached overview.
private PointF mStartDisplacement = new PointF();
@@ -144,6 +147,13 @@
}
}
+ // Used if flinging back to home after reaching overview
+ private void maybeSwipeInteractionToHomeComplete() {
+ if (mIsHomeStaggeredAnimFinished && mIsOverviewRehidden) {
+ onSwipeInteractionCompleted(NORMAL, Touch.FLING);
+ }
+ }
+
@Override
protected boolean handlingOverviewAnim() {
return mDidTouchStartInNavBar && super.handlingOverviewAnim();
@@ -180,9 +190,17 @@
stateManager.goToState(NORMAL, true,
() -> onSwipeInteractionCompleted(NORMAL, Touch.FLING));
} else {
+ mIsHomeStaggeredAnimFinished = mIsOverviewRehidden = false;
+
StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim(
mLauncher, velocity, false /* animateOverviewScrim */);
- staggeredWorkspaceAnim.start();
+ staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ mIsHomeStaggeredAnimFinished = true;
+ maybeSwipeInteractionToHomeComplete();
+ }
+ }).start();
// StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
stateManager.cancelAnimation();
@@ -191,8 +209,10 @@
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
AnimatorSet anim = stateManager.createAtomicAnimation(
stateManager.getState(), NORMAL, config);
- anim.addListener(AnimationSuccessListener.forRunnable(
- () -> onSwipeInteractionCompleted(NORMAL, Touch.SWIPE)));
+ anim.addListener(AnimationSuccessListener.forRunnable(() -> {
+ mIsOverviewRehidden = true;
+ maybeSwipeInteractionToHomeComplete();
+ }));
anim.start();
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 6751723..edefbe1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -120,9 +120,7 @@
@Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
- ((RecentsView) getCreatedActivity().getOverviewPanel())
- .setLayoutRotation(deviceState.getCurrentActiveRotation(),
- deviceState.getDisplayRotation());
+ notifyRecentsOfOrientation(deviceState);
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
@Override
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index 177f9a0..ed07062 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -19,6 +19,7 @@
import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
+import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -70,10 +71,19 @@
// Add overview actions to the menu when in in-place rotate landscape mode.
if (!canLauncherRotate && isInLandscape) {
- for (TaskShortcutFactory actionMenuOption : ACTION_MENU_OPTIONS) {
- SystemShortcut shortcut = actionMenuOption.getShortcut(activity, taskView);
- if (shortcut != null) {
- shortcuts.add(shortcut);
+ // Add screenshot action to task menu.
+ SystemShortcut screenshotShortcut = TaskShortcutFactory.SCREENSHOT
+ .getShortcut(activity, taskView);
+ if (screenshotShortcut != null) {
+ shortcuts.add(screenshotShortcut);
+ }
+
+ // Add modal action only if display orientation is the same as the device orientation.
+ if (orientedState.getDisplayRotation() == ROTATION_0) {
+ SystemShortcut modalShortcut = TaskShortcutFactory.MODAL
+ .getShortcut(activity, taskView);
+ if (modalShortcut != null) {
+ shortcuts.add(modalShortcut);
}
}
}
@@ -104,11 +114,6 @@
TaskShortcutFactory.WELLBEING
};
- private static final TaskShortcutFactory[] ACTION_MENU_OPTIONS = new TaskShortcutFactory[]{
- TaskShortcutFactory.SCREENSHOT,
- TaskShortcutFactory.MODAL
- };
-
/**
* Overlay on each task handling Overview Action Buttons.
*/
@@ -139,8 +144,12 @@
/**
* Called when the current task is interactive for the user
*/
- public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix) {
+ public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
+ boolean rotated) {
final boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
+
+ mActionsView.updateDisabledFlags(DISABLED_ROTATED, rotated);
+
getActionsView().setCallbacks(new OverlayUICallbacks() {
@Override
public void onShare() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
index 4eae437..ff051b6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
@@ -196,7 +196,8 @@
WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
future, animStartedListener, mHandler, true /* scaleUp */,
taskKey.displayId);
- mTarget.getStatsLogManager().log(mLauncherEvent, mTaskView.getItemInfo());
+ mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
+ .log(mLauncherEvent);
}
}
}
@@ -296,8 +297,8 @@
};
mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler());
dismissTaskMenuView(mTarget);
- mTarget.getStatsLogManager().log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP,
- mTaskView.getItemInfo());
+ mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
+ .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 14215a1..a9f138e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -267,10 +267,6 @@
if (!mPassedSlopOnThisGesture && passedSlop) {
mPassedSlopOnThisGesture = true;
}
- // Until passing slop, we don't know what direction we're going, so assume we might
- // be quick switching to avoid translating recents away when continuing the gesture.
- boolean isLikelyToStartNewTask = !mPassedSlopOnThisGesture
- || horizontalDist > upDist;
if (!mPassedPilferInputSlop) {
if (passedSlop) {
@@ -304,6 +300,13 @@
}
if (mDeviceState.isFullyGesturalNavMode()) {
+ // Until passing slop, we don't know what direction we're going, so assume
+ // we're quick switching to avoid translating recents away when continuing
+ // the gesture.
+ boolean haveNotPassedSlopOnContinuedGesture =
+ !mPassedSlopOnThisGesture && mPassedPilferInputSlop;
+ boolean isLikelyToStartNewTask = haveNotPassedSlopOnContinuedGesture
+ || horizontalDist > upDist;
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|| isLikelyToStartNewTask);
mMotionPauseDetector.addPosition(ev);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index 11fee2f..32b1c58 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -36,8 +36,6 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
-import java.util.function.Predicate;
-
/**
* Input consumer for handling touch on the recents/Launcher activity.
*/
@@ -50,8 +48,6 @@
private final InputMonitorCompat mInputMonitor;
private final int[] mLocationOnScreen = new int[2];
- private final boolean mProxyTouch;
- private final Predicate<MotionEvent> mEventReceiver;
private final boolean mStartingInActivityBounds;
private boolean mTargetHandledTouch;
@@ -64,15 +60,7 @@
mActivityInterface = gestureState.getActivityInterface();
mTarget = activity.getDragLayer();
- if (startingInActivityBounds) {
- mEventReceiver = mTarget::dispatchTouchEvent;
- mProxyTouch = true;
- } else {
- // Only proxy touches to controllers if we are starting touch from nav bar.
- mEventReceiver = mTarget::proxyTouchEvent;
- mTarget.getLocationOnScreen(mLocationOnScreen);
- mProxyTouch = mTarget.prepareProxyEventStarting();
- }
+ mTarget.getLocationOnScreen(mLocationOnScreen);
}
@Override
@@ -87,10 +75,6 @@
@Override
public void onMotionEvent(MotionEvent ev) {
- if (!mProxyTouch) {
- return;
- }
-
int flags = ev.getEdgeFlags();
if (!mStartingInActivityBounds) {
ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR);
@@ -99,7 +83,7 @@
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "OverviewInputConsumer");
}
- boolean handled = mEventReceiver.test(ev);
+ boolean handled = mTarget.proxyTouchEvent(ev, mStartingInActivityBounds);
ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
ev.setEdgeFlags(flags);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 8daa982..3cafd42 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -175,6 +175,11 @@
return mAnimators;
}
+ public StaggeredWorkspaceAnim addAnimatorListener(Animator.AnimatorListener listener) {
+ mAnimators.addListener(listener);
+ return this;
+ }
+
/**
* Starts the animation.
*/
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java
index 6b99f90..0979c07 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java
@@ -232,7 +232,7 @@
launcher, parent);
view.init(launcher);
launcher.getDragLayer().addView(view);
- launcher.getStatsLogManager().log(LAUNCHER_ALL_APPS_EDU_SHOWN);
+ launcher.getStatsLogManager().logger().log(LAUNCHER_ALL_APPS_EDU_SHOWN);
view.requestLayout();
view.playAnimation();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
index 95eb10f..a2da398 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
@@ -24,7 +24,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
@@ -39,6 +38,7 @@
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
+import com.android.quickstep.util.LayoutUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -68,6 +68,15 @@
public static final int HIDDEN_GESTURE_RUNNING = 1 << 4;
public static final int HIDDEN_NO_RECENTS = 1 << 5;
+ @IntDef(flag = true, value = {
+ DISABLED_SCROLLING,
+ DISABLED_ROTATED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ActionsDisabledFlags { }
+
+ public static final int DISABLED_SCROLLING = 1 << 0;
+ public static final int DISABLED_ROTATED = 1 << 1;
+
private static final int INDEX_CONTENT_ALPHA = 0;
private static final int INDEX_VISIBILITY_ALPHA = 1;
private static final int INDEX_FULLSCREEN_ALPHA = 2;
@@ -78,6 +87,9 @@
@ActionsHiddenFlags
private int mHiddenFlags;
+ @ActionsDisabledFlags
+ protected int mDisabledFlags;
+
protected T mCallbacks;
public OverviewActionsView(Context context) {
@@ -117,7 +129,6 @@
@Override
public void onClick(View view) {
if (mCallbacks == null) {
- Log.d("OverviewActionsView", "Callbacks null onClick");
return;
}
int id = view.getId();
@@ -158,6 +169,25 @@
setVisibility(isHidden ? INVISIBLE : VISIBLE);
}
+ /**
+ * Updates the proper disabled flag to indicate whether OverviewActionsView should be enabled.
+ * Ignores DISABLED_ROTATED flag for determining enabled. Flag is used to enable/disable
+ * buttons individually, currently done for select button in subclass.
+ *
+ * @param disabledFlags The flag to update.
+ * @param enable Whether to enable the disable flag: True will cause view to be disabled.
+ */
+ public void updateDisabledFlags(@ActionsDisabledFlags int disabledFlags, boolean enable) {
+ if (enable) {
+ mDisabledFlags |= disabledFlags;
+ } else {
+ mDisabledFlags &= ~disabledFlags;
+ }
+ //
+ boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
+ LayoutUtils.setViewEnabled(this, isEnabled);
+ }
+
public AlphaProperty getContentAlpha() {
return mMultiValueAlpha.getProperty(INDEX_CONTENT_ALPHA);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index caff713..99afe39 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -208,7 +208,7 @@
}
};
- protected final RecentsOrientedState mOrientationState;
+ protected RecentsOrientedState mOrientationState;
protected final BaseActivityInterface mSizeStrategy;
protected RecentsAnimationController mRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
@@ -371,11 +371,17 @@
private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
(inMultiWindowMode) -> {
- if (!inMultiWindowMode && mOverviewStateEnabled) {
- // TODO: Re-enable layout transitions for addition of the unpinned task
- reloadIfNeeded();
- }
- };
+ if (mOrientationState != null) {
+ mOrientationState.setMultiWindowMode(inMultiWindowMode);
+ setLayoutRotation(mOrientationState.getTouchRotation(),
+ mOrientationState.getDisplayRotation());
+ rotateAllChildTasks();
+ }
+ if (!inMultiWindowMode && mOverviewStateEnabled) {
+ // TODO: Re-enable layout transitions for addition of the unpinned task
+ reloadIfNeeded();
+ }
+ };
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr,
BaseActivityInterface sizeStrategy) {
@@ -488,7 +494,8 @@
return;
}
mModel.getIconCache().clear();
- reset();
+ unloadVisibleTaskData();
+ loadVisibleTaskData();
}
public void init(OverviewActionsView actionsView) {
@@ -622,14 +629,14 @@
@Override
protected void onPageBeginTransition() {
super.onPageBeginTransition();
- LayoutUtils.setViewEnabled(mActionsView, false);
+ mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
}
@Override
protected void onPageEndTransition() {
super.onPageEndTransition();
if (isClearAllHidden()) {
- LayoutUtils.setViewEnabled(mActionsView, true);
+ mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
}
if (getNextPage() > 0) {
setSwipeDownShouldLaunchApp(true);
@@ -840,7 +847,6 @@
private void resetPaddingFromTaskSize() {
DeviceProfile dp = mActivity.getDeviceProfile();
- mOrientationState.setMultiWindowMode(dp.isMultiWindowMode);
getTaskSize(mTempRect);
mTaskWidth = mTempRect.width();
mTaskHeight = mTempRect.height();
@@ -1346,8 +1352,8 @@
ComponentKey compKey = TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key);
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
endState.logAction, Direction.UP, index, compKey);
- mActivity.getStatsLogManager().log(
- LAUNCHER_TASK_DISMISS_SWIPE_UP, taskView.getItemInfo());
+ mActivity.getStatsLogManager().logger().withItemInfo(taskView.getItemInfo())
+ .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
}
}
@@ -1638,7 +1644,7 @@
: View.LAYOUT_DIRECTION_RTL);
mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
mActivity.getDragLayer().recreateControllers();
- boolean isInLandscape = touchRotation != 0
+ boolean isInLandscape = mOrientationState.getTouchRotation() != 0
|| mOrientationState.getLauncherRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
!mOrientationState.canLauncherRotate() && isInLandscape);
@@ -1727,6 +1733,8 @@
setPivotY(mTempPointF.y);
setTaskModalness(mTaskModalness);
updatePageOffsets();
+ setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO
+ : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
}
private void updatePageOffsets() {
@@ -1939,8 +1947,8 @@
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
endState.logAction, Direction.DOWN, indexOfChild(tv),
TaskUtils.getLaunchComponentKeyForTask(task.key));
- mActivity.getStatsLogManager().log(
- LAUNCHER_TASK_LAUNCH_SWIPE_DOWN, tv.getItemInfo());
+ mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
+ .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
}
} else {
onTaskLaunched(false);
@@ -2110,6 +2118,12 @@
return mClearAllButton;
}
+ @Override
+ protected boolean onOverscroll(int amount) {
+ // overscroll should only be accepted on -1 direction (for clear all button)
+ if ((amount > 0 && !mIsRtl) || (amount < 0 && mIsRtl)) return false;
+ return super.onOverscroll(amount);
+ }
/**
* @return How many pixels the running task is offset on the currently laid out dominant axis.
@@ -2207,7 +2221,6 @@
boolean inPlaceLandscape = !mOrientationState.canLauncherRotate()
&& mOrientationState.getTouchRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape);
- LayoutUtils.setViewEnabled(mActionsView, true);
}
@Nullable
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index 26fb563..b2f937f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -357,10 +357,9 @@
}
private void updateOverlay() {
- // The overlay doesn't really work when the screenshot is rotated, so don't add it.
- if (mOverlayEnabled && !mPreviewPositionHelper.mIsOrientationChanged
- && mBitmapShader != null && mThumbnailData != null) {
- mOverlay.initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix);
+ if (mOverlayEnabled && mBitmapShader != null && mThumbnailData != null) {
+ mOverlay.initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
+ mPreviewPositionHelper.mIsOrientationChanged);
} else {
mOverlay.reset();
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 3b1210e..411bab4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -214,7 +214,8 @@
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
TaskUtils.getLaunchComponentKeyForTask(getTask().key));
- mActivity.getStatsLogManager().log(LAUNCHER_TASK_LAUNCH_TAP, getItemInfo());
+ mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
+ .log(LAUNCHER_TASK_LAUNCH_TAP);
});
mCurrentFullscreenParams = new FullscreenDrawParams(context);
@@ -432,7 +433,8 @@
getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
} else {
mMenuView = TaskMenuView.showForTask(this);
- mActivity.getStatsLogManager().log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS, getItemInfo());
+ mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
+ .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
UserEventDispatcher.newInstance(getContext()).logActionOnItem(action, Direction.NONE,
LauncherLogProto.ItemType.TASK_ICON);
if (mMenuView != null) {
@@ -975,6 +977,9 @@
}
void updateCurrentFullscreenParams(PreviewPositionHelper previewPositionHelper) {
+ if (getRecentsView() == null) {
+ return;
+ }
mCurrentFullscreenParams.setProgress(
mFullscreenProgress,
getRecentsView().getScaleX(),
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 2b11ca0..0f2955b 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -17,7 +17,9 @@
<string name="task_overlay_factory_class" translatable="false"/>
<!-- Activities which block home gesture -->
- <string-array name="gesture_blocking_activities" translatable="false"/>
+ <string-array name="gesture_blocking_activities" translatable="false">
+ <item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
+ </string-array>
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index ebb44e2..54894f0 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -30,7 +30,6 @@
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.InstanceId;
@@ -42,11 +41,13 @@
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.LogConfig;
import com.android.systemui.shared.system.SysUiStatsLog;
import java.util.ArrayList;
+import java.util.OptionalInt;
/**
* This class calls StatsLog compile time generated methods.
@@ -73,28 +74,27 @@
sContext = context;
}
- /**
- * Logs a {@link EventEnum}.
- */
@Override
- public void log(EventEnum event) {
- log(event, DEFAULT_INSTANCE_ID, null);
+ public StatsLogger logger() {
+ return new StatsCompatLogger();
}
/**
- * Logs an event and accompanying {@link InstanceId}.
+ * Logs an event.
+ *
+ * @param event an enum implementing EventEnum interface.
+ * @param atomInfo item typically containing app or task launch related information.
*/
- @Override
- public void log(EventEnum event, InstanceId instanceId) {
- log(event, instanceId, null);
- }
-
- /**
- * Logs an event and accompanying {@link ItemInfo}.
- */
- @Override
- public void log(EventEnum event, @Nullable ItemInfo info) {
- log(event, DEFAULT_INSTANCE_ID, info);
+ public void log(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo) {
+ LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
+ new BaseModelUpdateTask() {
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel,
+ AllAppsList apps) {
+ write(event, instanceId, atomInfo, LAUNCHER_UICHANGED__DST_STATE__HOME,
+ LAUNCHER_UICHANGED__DST_STATE__BACKGROUND, OptionalInt.empty());
+ }
+ });
}
/**
@@ -108,21 +108,7 @@
int dstState) {
write(event, DEFAULT_INSTANCE_ID,
atomItemInfo == null ? LauncherAtom.ItemInfo.getDefaultInstance() : atomItemInfo,
- null,
- srcState,
- dstState);
- }
-
- /**
- * Logs an event and accompanying {@link InstanceId} and {@link LauncherAtom.ItemInfo}.
- */
- @Override
- public void log(EventEnum event, InstanceId instanceId,
- @Nullable ItemInfo info) {
- logInternal(event, instanceId, info,
- LAUNCHER_UICHANGED__DST_STATE__HOME,
- LAUNCHER_UICHANGED__DST_STATE__BACKGROUND,
- DEFAULT_PAGE_INDEX);
+ srcState, dstState, OptionalInt.empty());
}
/**
@@ -138,71 +124,18 @@
position /* position_picked = 4; */);
}
- /**
- * Logs an event and accompanying {@link LauncherState}s. If either of the state refers
- * to workspace state, then use pageIndex to pass in index of workspace.
- */
- @Override
- public void log(EventEnum event, int srcState, int dstState, int pageIndex) {
- logInternal(event, DEFAULT_INSTANCE_ID, null, srcState, dstState, pageIndex);
- }
-
- /**
- * Logs an event and accompanying {@link InstanceId} and {@link ItemInfo}.
- */
- private void logInternal(EventEnum event, InstanceId instanceId,
- @Nullable ItemInfo info, int srcState, int dstState, int pageIndex) {
-
- LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
- new BaseModelUpdateTask() {
- @Override
- public void execute(LauncherAppState app, BgDataModel dataModel,
- AllAppsList apps) {
- writeEvent(event, instanceId, info, srcState, dstState, pageIndex,
- dataModel.folders);
- }
- });
- }
-
- private static void writeEvent(EventEnum event, InstanceId instanceId,
- @Nullable ItemInfo info, int srcState, int dstState, int pageIndex,
- IntSparseArrayMap<FolderInfo> folders) {
-
- if (!Utilities.ATLEAST_R) {
- return;
- }
- LauncherAtom.ItemInfo atomInfo = LauncherAtom.ItemInfo.getDefaultInstance();
- if (info != null) {
- if (info.container >= 0) {
- atomInfo = info.buildProto(folders.get(info.container));
- } else {
- atomInfo = info.buildProto();
- }
- } else {
- if (srcState == LAUNCHER_UICHANGED__DST_STATE__HOME
- || dstState == LAUNCHER_UICHANGED__SRC_STATE__HOME) {
- atomInfo = LauncherAtom.ItemInfo.newBuilder().setContainerInfo(
- LauncherAtom.ContainerInfo.newBuilder().setWorkspace(
- LauncherAtom.WorkspaceContainer.newBuilder().setPageIndex(pageIndex)
- )).build();
- }
- }
- write(event, instanceId, atomInfo, info, srcState, dstState);
- }
-
- private static void write(EventEnum event, InstanceId instanceId,
+ private void write(EventEnum event, InstanceId instanceId,
LauncherAtom.ItemInfo atomInfo,
- @Nullable ItemInfo info,
- int srcState, int dstState) {
+ int srcState, int dstState, OptionalInt mRank) {
if (IS_VERBOSE) {
String name = (event instanceof Enum) ? ((Enum) event).name() :
event.getId() + "";
Log.d(TAG, instanceId == DEFAULT_INSTANCE_ID
- ? String.format("\n%s (State:%s->%s) \n%s\n%s", name, getStateString(srcState),
- getStateString(dstState), info, atomInfo)
- : String.format("\n%s (State:%s->%s) (InstanceId:%s)\n%s\n%s", name,
- getStateString(srcState), getStateString(dstState), instanceId, info,
+ ? String.format("\n%s (State:%s->%s)\n%s", name, getStateString(srcState),
+ getStateString(dstState), atomInfo)
+ : String.format("\n%s (State:%s->%s) (InstanceId:%s)\n%s", name,
+ getStateString(srcState), getStateString(dstState), instanceId,
atomInfo));
}
@@ -227,7 +160,7 @@
getPageId(atomInfo, true) /* page_id_parent */,
getHierarchy(atomInfo) /* hierarchy */,
atomInfo.getIsWork() /* is_work_profile */,
- atomInfo.getRank() /* rank */,
+ mRank.orElse(atomInfo.getRank()) /* rank */,
atomInfo.getFolderIcon().getFromLabelState().getNumber() /* fromState */,
atomInfo.getFolderIcon().getToLabelState().getNumber() /* toState */,
atomInfo.getFolderIcon().getLabelInfo() /* edittext */,
@@ -260,7 +193,8 @@
writeSnapshot(atomInfo, mInstanceId);
}
for (FolderInfo fInfo : folders) {
- for (ItemInfo info : fInfo.contents) {
+ ArrayList<WorkspaceItemInfo> folderContents = (ArrayList) fInfo.contents.clone();
+ for (ItemInfo info : folderContents) {
LauncherAtom.ItemInfo atomInfo = info.buildProto(fInfo);
writeSnapshot(atomInfo, mInstanceId);
}
@@ -300,6 +234,72 @@
info.getWidget().getSpanY());
}
+ /**
+ * Helps to construct and write statsd compatible log message.
+ */
+ private class StatsCompatLogger implements StatsLogger {
+ private ItemInfo mItemInfo = new ItemInfo();
+ private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
+ private OptionalInt mRank = OptionalInt.empty();
+ private int mSrcState = LAUNCHER_UICHANGED__SRC_STATE__HOME;
+ private int mDstState = LAUNCHER_UICHANGED__DST_STATE__BACKGROUND;
+
+ @Override
+ public StatsLogger withItemInfo(ItemInfo itemInfo) {
+ this.mItemInfo = itemInfo;
+ return this;
+ }
+
+ @Override
+ public StatsLogger withInstanceId(InstanceId instanceId) {
+ this.mInstanceId = instanceId;
+ return this;
+ }
+
+ @Override
+ public StatsLogger withRank(int rank) {
+ this.mRank = OptionalInt.of(rank);
+ return this;
+ }
+
+ @Override
+ public StatsLogger withSrcState(int srcState) {
+ this.mSrcState = srcState;
+ return this;
+ }
+
+ @Override
+ public StatsLogger withDstState(int dstState) {
+ this.mDstState = dstState;
+ return this;
+ }
+
+ @Override
+ public void log(EventEnum event) {
+ if (!Utilities.ATLEAST_R) {
+ return;
+ }
+
+ if (mItemInfo.container < 0) {
+ // Item is not within a folder. Write to StatsLog in same thread.
+ write(event, mInstanceId, mItemInfo.buildProto(), mSrcState, mDstState, mRank);
+ } else {
+ // Item is inside the folder, fetch folder info in a BG thread
+ // and then write to StatsLog.
+ LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
+ new BaseModelUpdateTask() {
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel,
+ AllAppsList apps) {
+ FolderInfo folderInfo = dataModel.folders.get(mItemInfo.container);
+ write(event, mInstanceId, mItemInfo.buildProto(folderInfo),
+ mSrcState, mDstState, mRank);
+ }
+ });
+ }
+ }
+ }
+
private static int getCardinality(LauncherAtom.ItemInfo info) {
return info.getContainerInfo().getContainerCase().equals(PREDICTED_HOTSEAT_CONTAINER)
? info.getContainerInfo().getPredictedHotseatContainer().getCardinality()
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index 3f58e01..cefab1b 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -74,17 +74,14 @@
/**
* Recursively sets view and all children enabled/disabled.
- * @param viewGroup Top most parent view to change.
+ * @param view Top most parent view to change.
* @param enabled True = enable, False = disable.
*/
- public static void setViewEnabled(ViewGroup viewGroup, boolean enabled) {
- viewGroup.setEnabled(enabled);
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- View child = viewGroup.getChildAt(i);
- if (child instanceof ViewGroup) {
- setViewEnabled((ViewGroup) child, enabled);
- } else {
- child.setEnabled(enabled);
+ public static void setViewEnabled(View view, boolean enabled) {
+ view.setEnabled(enabled);
+ if (view instanceof ViewGroup) {
+ for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
+ setViewEnabled(((ViewGroup) view).getChildAt(i), enabled);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 2acc49c..68636cb 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -120,7 +120,6 @@
private final ContentResolver mContentResolver;
private final SharedPreferences mSharedPrefs;
private final OrientationEventListener mOrientationListener;
- private final BaseActivityInterface mSizeStrategy;
private final Matrix mTmpMatrix = new Matrix();
@@ -137,7 +136,6 @@
mContext = context;
mContentResolver = context.getContentResolver();
mSharedPrefs = Utilities.getPrefs(context);
- mSizeStrategy = sizeStrategy;
mOrientationListener = new OrientationEventListener(context) {
@Override
public void onOrientationChanged(int degrees) {
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index bec3050..19e278b 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -244,13 +244,17 @@
@Override
protected void updateSysUiColors() {
- // Use a light system UI (dark icons) if all apps is behind at least half of the
- // status bar.
- boolean forceChange = mShelfTop <= mLauncher.getDeviceProfile().getInsets().top / 2f;
- if (forceChange) {
- mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !mIsScrimDark);
+ if (mDrawingFlatColor) {
+ super.updateSysUiColors();
} else {
- mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, 0);
+ // Use a light system UI (dark icons) if all apps is behind at least half of the
+ // status bar.
+ boolean forceChange = mShelfTop <= mLauncher.getDeviceProfile().getInsets().top / 2f;
+ if (forceChange) {
+ mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !mIsScrimDark);
+ } else {
+ mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, 0);
+ }
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index a343e7c..bd8ab08 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -120,6 +120,9 @@
TestCommandReceiver.callCommand(TestCommandReceiver.DISABLE_TEST_LAUNCHER);
UiDevice.getInstance(getInstrumentation()).executeShellCommand(
getLauncherCommand(getLauncherInMyProcess()));
+ // b/143488140
+ mDevice.pressHome();
+ mDevice.waitForIdle();
}
}
};
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a922183..ac00488 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -50,7 +50,7 @@
<item name="folderFillColor">#CDFFFFFF</item>
<item name="folderIconBorderColor">?android:attr/colorPrimary</item>
<item name="folderTextColor">#FF212121</item>
- <item name="folderHintColor">#FF616161</item>
+ <item name="folderHintColor">#89616161</item>
<item name="loadingIconColor">#CCFFFFFF</item>
<item name="iconOnlyShortcutColor">?android:attr/textColorSecondary</item>
<item name="workProfileOverlayTextColor">#FF212121</item>
@@ -106,7 +106,7 @@
<item name="folderFillColor">#DD3C4043</item> <!-- 87% GM2 800 -->
<item name="folderIconBorderColor">#FF80868B</item>
<item name="folderTextColor">@android:color/white</item>
- <item name="folderHintColor">#FFCCCCCC</item>
+ <item name="folderHintColor">#89CCCCCC</item>
<item name="isMainColorDark">true</item>
<item name="loadingIconColor">#99FFFFFF</item>
<item name="iconOnlyShortcutColor">#B3FFFFFF</item>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 88dbfd6..9cb8cf2 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -43,6 +43,8 @@
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.logging.InstanceId;
+import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -188,7 +190,8 @@
}
getUserEventDispatcher().logAppLaunch(v, intent, user);
if (item != null) {
- getStatsLogManager().log(LAUNCHER_APP_LAUNCH_TAP, item);
+ InstanceId instanceId = new InstanceIdSequence().newInstanceId();
+ logAppLaunch(item, instanceId);
}
return true;
} catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
@@ -198,6 +201,11 @@
return false;
}
+ protected void logAppLaunch(ItemInfo info, InstanceId instanceId) {
+ getStatsLogManager().logger().withItemInfo(info).withInstanceId(instanceId)
+ .log(LAUNCHER_APP_LAUNCH_TAP);
+ }
+
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info,
@Nullable String sourceContainer) {
try {
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index d75d712..2857497 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -126,11 +126,9 @@
d.dragInfo.container = NO_ID;
}
super.onDrop(d, options);
- mStatsLogManager.log(
- mControlType == ControlType.REMOVE_TARGET
- ? LAUNCHER_ITEM_DROPPED_ON_REMOVE
- : LAUNCHER_ITEM_DROPPED_ON_CANCEL,
- d.logInstanceId);
+ mStatsLogManager.logger().withInstanceId(d.logInstanceId)
+ .log(mControlType == ControlType.REMOVE_TARGET ? LAUNCHER_ITEM_DROPPED_ON_REMOVE
+ : LAUNCHER_ITEM_DROPPED_ON_CANCEL);
}
@Override
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 60abc66..e39e89c 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -148,6 +148,7 @@
iconSize = p.iconSize;
iconShapePath = p.iconShapePath;
landscapeIconSize = p.landscapeIconSize;
+ iconBitmapSize = p.iconBitmapSize;
iconTextSize = p.iconTextSize;
numHotseatIcons = p.numHotseatIcons;
numAllAppsColumns = p.numAllAppsColumns;
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index fbac0bd..499b54f 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -220,9 +220,11 @@
d.dragSource = new DeferredOnComplete(d.dragSource, getContext());
super.onDrop(d, options);
if (mCurrentAccessibilityAction == UNINSTALL) {
- mStatsLogManager.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL, d.logInstanceId);
+ mStatsLogManager.logger().withInstanceId(d.logInstanceId)
+ .log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL);
} else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
- mStatsLogManager.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST, d.logInstanceId);
+ mStatsLogManager.logger().withInstanceId(d.logInstanceId)
+ .log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST);
}
}
@@ -348,10 +350,12 @@
mDragObject.dragInfo.user, PackageManager.MATCH_UNINSTALLED_PACKAGES) == null) {
mDragObject.dragSource = mOriginal;
mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, true);
- mStatsLogManager.log(LAUNCHER_ITEM_UNINSTALL_COMPLETED, mDragObject.logInstanceId);
+ mStatsLogManager.logger().withInstanceId(mDragObject.logInstanceId)
+ .log(LAUNCHER_ITEM_UNINSTALL_COMPLETED);
} else {
sendFailure();
- mStatsLogManager.log(LAUNCHER_ITEM_UNINSTALL_CANCELLED, mDragObject.logInstanceId);
+ mStatsLogManager.logger().withInstanceId(mDragObject.logInstanceId)
+ .log(LAUNCHER_ITEM_UNINSTALL_CANCELLED);
}
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 4198e9f..fb58f21 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -415,11 +415,9 @@
// Always enter the spring loaded mode
mLauncher.getStateManager().goToState(SPRING_LOADED);
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED,
- dragObject.logInstanceId,
- dragObject.originalDragInfo
- );
+ mStatsLogManager.logger().withItemInfo(dragObject.originalDragInfo)
+ .withInstanceId(dragObject.logInstanceId)
+ .log(LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED);
}
public void deferRemoveExtraEmptyScreen() {
@@ -1646,10 +1644,8 @@
Rect folderLocation = new Rect();
float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
target.removeView(v);
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED,
- d.logInstanceId,
- destInfo);
+ mStatsLogManager.logger().withItemInfo(destInfo).withInstanceId(d.logInstanceId)
+ .log(LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED);
FolderIcon fi = mLauncher.addFolder(target, container, screenId, targetCell[0],
targetCell[1]);
destInfo.cellX = -1;
@@ -1687,10 +1683,8 @@
if (dropOverView instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) dropOverView;
if (fi.acceptDrop(d.dragInfo)) {
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
- d.logInstanceId,
- fi.mInfo);
+ mStatsLogManager.logger().withItemInfo(fi.mInfo).withInstanceId(d.logInstanceId)
+ .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
fi.onDrop(d, false /* itemReturnedOnFailedDrop */);
// if the drag started here, we need to remove it from the workspace
@@ -1893,10 +1887,8 @@
mLauncher.getStateManager().goToState(
NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
- d.logInstanceId,
- d.dragInfo);
+ mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId)
+ .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
}
if (d.stateAnnouncer != null && !droppedOnOriginalCell) {
@@ -2434,10 +2426,9 @@
// widgets/shortcuts/folders in a slightly different way
mLauncher.addPendingItem(pendingInfo, container, screenId, mTargetCell,
item.spanX, item.spanY);
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
- d.logInstanceId,
- d.dragInfo);
+ mStatsLogManager.logger().withItemInfo(d.dragInfo)
+ .withInstanceId(d.logInstanceId)
+ .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
}
};
boolean isWidget = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
@@ -2526,10 +2517,8 @@
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view, this);
resetTransitionTransform();
}
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
- d.logInstanceId,
- d.dragInfo);
+ mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId)
+ .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 1dd81e8..a9b030e 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -159,7 +159,9 @@
StateAnimationConfig config, PendingAnimation builder) {
float targetProgress = toState.getVerticalProgress(mLauncher);
if (Float.compare(mProgress, targetProgress) == 0) {
- setAlphas(toState, config, builder);
+ if (!config.onlyPlayAtomicComponent()) {
+ setAlphas(toState, config, builder);
+ }
// Fail fast
onProgressAnimationEnd();
return;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 530010e..7998c2d 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -1337,8 +1337,8 @@
if (d.stateAnnouncer != null) {
d.stateAnnouncer.completeAction(R.string.item_moved);
}
- mStatsLogManager
- .log(LAUNCHER_ITEM_DROP_COMPLETED, d.logInstanceId, d.dragInfo);
+ mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId)
+ .log(LAUNCHER_ITEM_DROP_COMPLETED);
}
// This is used so the item doesn't immediately appear in the folder when added. In one case
@@ -1443,7 +1443,7 @@
if (hasFocus) {
startEditingFolderName();
} else {
- mStatsLogManager.log(LAUNCHER_FOLDER_LABEL_UPDATED, mInfo);
+ mStatsLogManager.logger().withItemInfo(mInfo).log(LAUNCHER_FOLDER_LABEL_UPDATED);
logFolderLabelState();
mFolderName.dispatchBackKey();
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 2be5883..b40b1e2 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -448,8 +448,8 @@
return;
}
mInfo.setTitle(nameInfos[0].getLabel());
- StatsLogManager.newInstance(getContext())
- .log(LAUNCHER_FOLDER_LABEL_UPDATED, instanceId, mInfo);
+ StatsLogManager.newInstance(getContext()).logger().withItemInfo(mInfo)
+ .withInstanceId(instanceId).log(LAUNCHER_FOLDER_LABEL_UPDATED);
onTitleChanged(mInfo.title);
mFolder.mFolderName.setText(mInfo.title);
mFolder.mLauncher.getModelWriter().updateItemInDatabase(mInfo);
diff --git a/src/com/android/launcher3/folder/FolderNameEditText.java b/src/com/android/launcher3/folder/FolderNameEditText.java
index edf2c70..6038a05 100644
--- a/src/com/android/launcher3/folder/FolderNameEditText.java
+++ b/src/com/android/launcher3/folder/FolderNameEditText.java
@@ -70,8 +70,11 @@
for (int i = 0; i < cnt; i++) {
cInfo[i] = new CompletionInfo(i, i, suggestList.get(i));
}
- post(() -> getContext().getSystemService(InputMethodManager.class)
- .displayCompletions(this, cInfo));
+ // post it to future frame so that onSelectionChanged, onFocusChanged, all other
+ // TextView flag change and IME animation has settled. Ideally, there should be IMM
+ // callback to notify when the IME animation and state handling is finished.
+ postDelayed(() -> getContext().getSystemService(InputMethodManager.class)
+ .displayCompletions(this, cInfo), 40 /* 2~3 frame delay */);
}
/**
diff --git a/src/com/android/launcher3/logging/InstanceIdSequence.java b/src/com/android/launcher3/logging/InstanceIdSequence.java
index a4b7953..ee6a5a4 100644
--- a/src/com/android/launcher3/logging/InstanceIdSequence.java
+++ b/src/com/android/launcher3/logging/InstanceIdSequence.java
@@ -45,6 +45,13 @@
}
/**
+ * Constructs a sequence with identifiers [1, InstanceId.INSTANCE_ID_MAX].
+ */
+ public InstanceIdSequence() {
+ this(InstanceId.INSTANCE_ID_MAX);
+ }
+
+ /**
* Gets the next instance from the sequence. Safe for concurrent use.
* @return new InstanceId
*/
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index fee91b0..a0e6bfc 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -143,7 +143,28 @@
LAUNCHER_HOTSEAT_EDU_DENY(481),
@UiEvent(doc = "Hotseat education tip shown")
- LAUNCHER_HOTSEAT_EDU_ONLY_TIP(482);
+ LAUNCHER_HOTSEAT_EDU_ONLY_TIP(482),
+
+ @UiEvent(doc = "App launch ranking logged for all apps predictions")
+ LAUNCHER_ALL_APPS_RANKED(552),
+
+ @UiEvent(doc = "App launch ranking logged for hotseat predictions)")
+ LAUNCHER_HOTSEAT_RANKED(553),
+
+ @UiEvent(doc = "User tapped on the screenshot button on overview)")
+ LAUNCHER_OVERVIEW_ACTIONS_SCREENSHOT(580),
+
+ @UiEvent(doc = "User tapped on the select button on overview)")
+ LAUNCHER_OVERVIEW_ACTIONS_SELECT(581),
+
+ @UiEvent(doc = "User tapped on the share button on overview")
+ LAUNCHER_OVERVIEW_ACTIONS_SHARE(582),
+
+ @UiEvent(doc = "User tapped on the close button in select mode")
+ LAUNCHER_SELECT_MODE_CLOSE(583),
+
+ @UiEvent(doc = "User tapped on the highlight items in select mode")
+ LAUNCHER_SELECT_MODE_ITEM(584);
// ADD MORE
private final int mId;
@@ -175,6 +196,62 @@
}
}
+ /**
+ * Helps to construct and write the log message.
+ */
+ public interface StatsLogger {
+
+ /**
+ * Sets log fields from provided {@link ItemInfo}.
+ */
+ default StatsLogger withItemInfo(ItemInfo itemInfo) {
+ return this;
+ }
+
+
+ /**
+ * Sets {@link InstanceId} of log message.
+ */
+ default StatsLogger withInstanceId(InstanceId instanceId) {
+ return this;
+ }
+
+ /**
+ * Sets rank field of log message.
+ */
+ default StatsLogger withRank(int rank) {
+ return this;
+ }
+
+ /**
+ * Sets source launcher state field of log message.
+ */
+ default StatsLogger withSrcState(int srcState) {
+ return this;
+ }
+
+ /**
+ * Sets destination launcher state field of log message.
+ */
+ default StatsLogger withDstState(int dstState) {
+ return this;
+ }
+
+ /**
+ * Builds the final message and logs it as {@link EventEnum}.
+ */
+ default void log(EventEnum event) {
+ }
+ }
+
+ /**
+ * Returns new logger object.
+ */
+ public StatsLogger logger() {
+ return new StatsLogger() {
+ };
+ }
+
protected LogStateProvider mStateProvider;
/**
@@ -195,26 +272,9 @@
* Logs an event.
*
* @param event an enum implementing EventEnum interface.
+ * @param atomInfo item typically containing app or task launch related information.
*/
- public void log(EventEnum event) {
- }
-
- /**
- * Logs an event.
- *
- * @param event an enum implementing EventEnum interface.
- * @param instanceId an identifier obtained from an InstanceIdSequence.
- */
- public void log(EventEnum event, InstanceId instanceId) {
- }
-
- /**
- * Logs an event.
- *
- * @param event an enum implementing EventEnum interface.
- * @param itemInfo item typically containing app or task launch related information.
- */
- public void log(EventEnum event, @Nullable ItemInfo itemInfo) {
+ public void log(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo) {
}
/**
@@ -228,16 +288,6 @@
}
/**
- * Logs an event.
- *
- * @param event an enum implementing EventEnum interface.
- * @param instanceId an identifier obtained from an InstanceIdSequence.
- * @param itemInfo item typically containing app or task launch related information.
- */
- public void log(EventEnum event, InstanceId instanceId, @Nullable ItemInfo itemInfo) {
- }
-
- /**
* Log an event with ranked-choice information along with package. Does nothing if event.getId()
* <= 0.
*
@@ -251,13 +301,6 @@
}
/**
- * Logs an event and accompanying {@link LauncherState}s. If either of the state refers
- * to workspace state, then use pageIndex to pass in index of workspace.
- */
- public void log(EventEnum event, int srcState, int dstState, int pageIndex) {
- }
-
- /**
* Logs snapshot, or impression of the current workspace.
*/
public void logSnapshot() {
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index f1b63f2..835f72d 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -107,8 +107,8 @@
try {
intent.send(null, 0, null, null, null, null, activityOptions);
launcher.getUserEventDispatcher().logNotificationLaunch(view, intent);
- launcher.getStatsLogManager()
- .log(LAUNCHER_NOTIFICATION_LAUNCH_TAP, mItemInfo);
+ launcher.getStatsLogManager().logger().withItemInfo(mItemInfo)
+ .log(LAUNCHER_NOTIFICATION_LAUNCH_TAP);
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 8e60c27..61829c0 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -77,8 +77,8 @@
@Override
public void onClick(View view) {
AbstractFloatingView.closeAllOpenViews(mTarget);
- mTarget.getStatsLogManager()
- .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP, mItemInfo);
+ mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
+ .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP);
final String actionIdentity = mAction.getTitle() + ", "
+ mItemInfo.getTargetComponent().getPackageName();
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 59d24de..fd292a3 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -119,7 +119,8 @@
widgetsBottomSheet.populateAndShow(mItemInfo);
mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.WIDGETS_BUTTON, view);
- mTarget.getStatsLogManager().log(LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP, mItemInfo);
+ mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
+ .log(LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP);
}
}
@@ -140,8 +141,8 @@
mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.APPINFO_TARGET, view);
- mTarget.getStatsLogManager()
- .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP, mItemInfo);
+ mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
+ .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP);
}
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index de16941..8486666 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -113,7 +113,8 @@
if (!folder.isOpen() && !folder.isDestroyed()) {
// Open the requested folder
folder.animateOpen();
- StatsLogManager.newInstance(v.getContext()).log(LAUNCHER_FOLDER_OPEN, folder.mInfo);
+ StatsLogManager.newInstance(v.getContext()).logger().withItemInfo(folder.mInfo)
+ .log(LAUNCHER_FOLDER_OPEN);
}
}
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index 7270ce2..4fa658e 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -174,7 +174,7 @@
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- mLauncher.getStatsLogManager().log(LAUNCHER_WORKSPACE_LONGPRESS);
+ mLauncher.getStatsLogManager().logger().log(LAUNCHER_WORKSPACE_LONGPRESS);
OptionsPopupView.showDefaultOptions(mLauncher, mTouchDownPoint.x, mTouchDownPoint.y);
} else {
cancelLongPress();
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index f54edc2..b010b4b 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -90,13 +90,23 @@
}
};
- // Touch is being dispatched through the normal view dispatch system
- private static final int TOUCH_DISPATCHING_VIEW = 1 << 0;
+ // Touch coming from normal view system is being dispatched.
+ private static final int TOUCH_DISPATCHING_FROM_VIEW = 1 << 0;
// Touch is being dispatched through the normal view dispatch system, and started at the
- // system gesture region
- private static final int TOUCH_DISPATCHING_GESTURE = 1 << 1;
- // Touch is being dispatched through a proxy from InputMonitor
- private static final int TOUCH_DISPATCHING_PROXY = 1 << 2;
+ // system gesture region. In this case we prevent internal gesture handling and only allow
+ // normal view event handling.
+ private static final int TOUCH_DISPATCHING_FROM_VIEW_GESTURE_REGION = 1 << 1;
+ // Touch coming from InputMonitor proxy is being dispatched 'only to gestures'. Note that both
+ // this and view-system can be active at the same time where view-system would go to the views,
+ // and this would go to the gestures.
+ // Note that this is not set when events are coming from proxy, but going through full dispatch
+ // process (both views and gestures) to allow view-system to easily take over in case it
+ // comes later.
+ private static final int TOUCH_DISPATCHING_FROM_PROXY = 1 << 2;
+ // ACTION_DOWN has been dispatched to child views and ACTION_UP or ACTION_CANCEL is pending.
+ // Note that the event source can either be view-dispatching or proxy-dispatching based on if
+ // TOUCH_DISPATCHING_VIEW is present or not.
+ private static final int TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS = 1 << 3;
protected final float[] mTmpXY = new float[2];
protected final float[] mTmpRectPoints = new float[4];
@@ -204,7 +214,8 @@
protected boolean findActiveController(MotionEvent ev) {
mActiveController = null;
- if ((mTouchDispatchState & (TOUCH_DISPATCHING_GESTURE | TOUCH_DISPATCHING_PROXY)) == 0) {
+ if ((mTouchDispatchState & (TOUCH_DISPATCHING_FROM_VIEW_GESTURE_REGION
+ | TOUCH_DISPATCHING_FROM_PROXY)) == 0) {
// Only look for controllers if we are not dispatching from gesture area and proxy is
// not active
mActiveController = findControllerToHandleTouch(ev);
@@ -283,19 +294,28 @@
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case ACTION_DOWN: {
- mTouchDispatchState |= TOUCH_DISPATCHING_VIEW;
+ if ((mTouchDispatchState & TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS) != 0) {
+ // Cancel the previous touch
+ int action = ev.getAction();
+ ev.setAction(ACTION_CANCEL);
+ super.dispatchTouchEvent(ev);
+ ev.setAction(action);
+ }
+ mTouchDispatchState |= TOUCH_DISPATCHING_FROM_VIEW
+ | TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS;
if (isEventInLauncher(ev)) {
- mTouchDispatchState &= ~TOUCH_DISPATCHING_GESTURE;
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_FROM_VIEW_GESTURE_REGION;
} else {
- mTouchDispatchState |= TOUCH_DISPATCHING_GESTURE;
+ mTouchDispatchState |= TOUCH_DISPATCHING_FROM_VIEW_GESTURE_REGION;
}
break;
}
case ACTION_CANCEL:
case ACTION_UP:
- mTouchDispatchState &= ~TOUCH_DISPATCHING_GESTURE;
- mTouchDispatchState &= ~TOUCH_DISPATCHING_VIEW;
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_FROM_VIEW_GESTURE_REGION;
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_FROM_VIEW;
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS;
break;
}
super.dispatchTouchEvent(ev);
@@ -305,43 +325,53 @@
}
/**
- * Called before we are about to receive proxy events.
- *
- * @return false if we can't handle proxy at this time
- */
- public boolean prepareProxyEventStarting() {
- mProxyTouchController = null;
- if ((mTouchDispatchState & TOUCH_DISPATCHING_VIEW) != 0 && mActiveController != null) {
- // We are already dispatching using view system and have an active controller, we can't
- // handle another controller.
-
- // This flag was already cleared in proxy ACTION_UP or ACTION_CANCEL. Added here just
- // to be safe
- mTouchDispatchState &= ~TOUCH_DISPATCHING_PROXY;
- return false;
- }
-
- mTouchDispatchState |= TOUCH_DISPATCHING_PROXY;
- return true;
- }
-
- /**
* Proxies the touch events to the gesture handlers
*/
- public boolean proxyTouchEvent(MotionEvent ev) {
- boolean handled;
- if (mProxyTouchController != null) {
- handled = mProxyTouchController.onControllerTouchEvent(ev);
+ public boolean proxyTouchEvent(MotionEvent ev, boolean allowViewDispatch) {
+ int actionMasked = ev.getActionMasked();
+ boolean isViewDispatching = (mTouchDispatchState & TOUCH_DISPATCHING_FROM_VIEW) != 0;
+
+ // Only do view dispatch if another view-dispatching is not running, or we already started
+ // proxy-dispatching before. Note that view-dispatching can always take over the proxy
+ // dispatching at anytime, but not vice-versa.
+ allowViewDispatch = allowViewDispatch && !isViewDispatching
+ && (actionMasked == ACTION_DOWN
+ || ((mTouchDispatchState & TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS) != 0));
+
+ if (allowViewDispatch) {
+ mTouchDispatchState |= TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS;
+ super.dispatchTouchEvent(ev);
+
+ if (actionMasked == ACTION_UP || actionMasked == ACTION_CANCEL) {
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_TO_VIEW_IN_PROGRESS;
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_FROM_PROXY;
+ }
+ return true;
} else {
- mProxyTouchController = findControllerToHandleTouch(ev);
- handled = mProxyTouchController != null;
+ boolean handled;
+ if (mProxyTouchController != null) {
+ handled = mProxyTouchController.onControllerTouchEvent(ev);
+ } else {
+ if (actionMasked == ACTION_DOWN) {
+ if (isViewDispatching && mActiveController != null) {
+ // A controller is already active, we can't initiate our own controller
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_FROM_PROXY;
+ } else {
+ // We will control the handler via proxy
+ mTouchDispatchState |= TOUCH_DISPATCHING_FROM_PROXY;
+ }
+ }
+ if ((mTouchDispatchState & TOUCH_DISPATCHING_FROM_PROXY) != 0) {
+ mProxyTouchController = findControllerToHandleTouch(ev);
+ }
+ handled = mProxyTouchController != null;
+ }
+ if (actionMasked == ACTION_UP || actionMasked == ACTION_CANCEL) {
+ mProxyTouchController = null;
+ mTouchDispatchState &= ~TOUCH_DISPATCHING_FROM_PROXY;
+ }
+ return handled;
}
- int action = ev.getAction();
- if (action == ACTION_UP || action == ACTION_CANCEL) {
- mProxyTouchController = null;
- mTouchDispatchState &= ~TOUCH_DISPATCHING_PROXY;
- }
- return handled;
}
/**
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 5431ba1..d558781 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -86,7 +86,7 @@
return false;
}
if (item.mEventId.getId() > 0) {
- mLauncher.getStatsLogManager().log(item.mEventId);
+ mLauncher.getStatsLogManager().logger().log(item.mEventId);
}
if (item.mClickListener.onLongClick(view)) {
close(true);