Merge "Revert "Prevent dragging widgets to another page in tests when starting a drag."" into tm-qpr-dev
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index 1aa5d03..9a000d6 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -41,8 +41,10 @@
*/
public class WidgetsModel {
- // True is the widget support is disabled.
+ // True if the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = true;
+ // True if the shortcut support is disabled.
+ public static final boolean GO_DISABLE_SHORTCUTS = true;
public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
private static final ArrayList<WidgetsListBaseEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 3b4a28b..198a676 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -43,4 +43,9 @@
<!-- Accessibility actions -->
<item type="id" name="action_move_to_top_or_left" />
<item type="id" name="action_move_to_bottom_or_right" />
+
+ <!-- The max scale for the wallpaper when it's zoomed in -->
+ <item name="config_wallpaperMaxScale" format="float" type="dimen">
+ @*android:dimen/config_wallpaperMaxScale
+ </item>
</resources>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 521b3fe..9a1ed4d 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -42,7 +42,7 @@
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
-import static com.android.launcher3.statehandlers.DepthController.DEPTH;
+import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
@@ -57,6 +57,8 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.app.ActivityOptions;
+import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -83,6 +85,7 @@
import android.view.View;
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
+import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
@@ -123,8 +126,6 @@
import com.android.quickstep.util.WorkspaceRevealAnim;
import com.android.quickstep.views.FloatingWidgetView;
import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.system.ActivityCompat;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.BlurUtils;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -134,7 +135,6 @@
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
-import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.wm.shell.startingsurface.IStartingWindowListener;
import java.util.ArrayList;
@@ -293,8 +293,10 @@
RemoteAnimationAdapterCompat adapterCompat =
new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay,
mLauncher.getIApplicationThread());
- return new ActivityOptionsWrapper(
- ActivityOptionsCompat.makeRemoteAnimation(adapterCompat), onEndCallback);
+ ActivityOptions options = ActivityOptions.makeRemoteAnimation(
+ adapterCompat.getWrapped(),
+ adapterCompat.getRemoteTransition().getTransition());
+ return new ActivityOptionsWrapper(options, onEndCallback);
}
/**
@@ -384,7 +386,7 @@
@Override
public void onAnimationStart(Animator animation) {
mLauncher.addOnResumeCallback(() ->
- ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
+ ObjectAnimator.ofFloat(mLauncher.getDepthController(), STATE_DEPTH,
mLauncher.getStateManager().getState().getDepth(
mLauncher)).start());
}
@@ -408,7 +410,7 @@
@Override
public void onAnimationStart(Animator animation) {
mLauncher.addOnResumeCallback(() ->
- ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
+ ObjectAnimator.ofFloat(mLauncher.getDepthController(), STATE_DEPTH,
mLauncher.getStateManager().getState().getDepth(
mLauncher)).start());
}
@@ -1051,7 +1053,7 @@
&& BlurUtils.supportsBlursOnWindows();
MyDepthController depthController = new MyDepthController(mLauncher);
- ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController, DEPTH,
+ ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController, STATE_DEPTH,
BACKGROUND_APP.getDepth(mLauncher))
.setDuration(APP_LAUNCH_DURATION);
@@ -1092,8 +1094,8 @@
mWallpaperOpenRunner = createWallpaperOpenRunner(false /* fromUnlock */);
RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
- definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
- WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
+ definition.addRemoteAnimation(WindowManager.TRANSIT_OLD_WALLPAPER_OPEN,
+ WindowConfiguration.ACTIVITY_TYPE_STANDARD,
new RemoteAnimationAdapterCompat(
new LauncherAnimationRunner(mHandler, mWallpaperOpenRunner,
false /* startAtFrontOfQueue */),
@@ -1103,7 +1105,7 @@
if (KEYGUARD_ANIMATION.get()) {
mKeyguardGoingAwayRunner = createWallpaperOpenRunner(true /* fromUnlock */);
definition.addRemoteAnimation(
- WindowManagerWrapper.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+ WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
new RemoteAnimationAdapterCompat(
new LauncherAnimationRunner(
mHandler, mKeyguardGoingAwayRunner,
@@ -1112,7 +1114,7 @@
mLauncher.getIApplicationThread()));
}
- new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
+ mLauncher.registerRemoteAnimations(definition.getWrapped());
}
}
@@ -1148,7 +1150,7 @@
return;
}
if (hasControlRemoteAppTransitionPermission()) {
- new ActivityCompat(mLauncher).unregisterRemoteAnimations();
+ mLauncher.unregisterRemoteAnimations();
// Also clear strong references to the runners registered with the remote animation
// definition so we don't have to wait for the system gc
@@ -1594,7 +1596,8 @@
true /* animateOverviewScrim */, launcherView).getAnimators());
if (!areAllTargetsTranslucent(appTargets)) {
- anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
+ anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController(),
+ STATE_DEPTH,
BACKGROUND_APP.getDepth(mLauncher), NORMAL.getDepth(mLauncher)));
}
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index a0cf6cb..9a682c6 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -15,14 +15,16 @@
*/
package com.android.launcher3.popup;
+import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
+
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
import android.util.Log;
import android.view.View;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
@@ -70,9 +72,10 @@
}
RecentsView recentsView = mTarget.getOverviewPanel();
+ StatsLogManager.EventEnum splitEvent = getLogEventForPosition(mPosition.stagePosition);
recentsView.initiateSplitSelect(
new SplitSelectSource(mOriginalView, new BitmapDrawable(bitmap), intent,
- mPosition, mItemInfo.user));
+ mPosition, mItemInfo, splitEvent));
}
}
@@ -82,15 +85,18 @@
public final Drawable drawable;
public final Intent intent;
public final SplitPositionOption position;
- public final UserHandle user;
+ public final ItemInfo mItemInfo;
+ public final StatsLogManager.EventEnum splitEvent;
public SplitSelectSource(View view, Drawable drawable, Intent intent,
- SplitPositionOption position, UserHandle user) {
+ SplitPositionOption position, ItemInfo itemInfo,
+ StatsLogManager.EventEnum splitEvent) {
this.view = view;
this.drawable = drawable;
this.intent = intent;
this.position = position;
- this.user = user;
+ this.mItemInfo = itemInfo;
+ this.splitEvent = splitEvent;
}
}
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java b/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
deleted file mode 100644
index 8c11081..0000000
--- a/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2018 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.statehandlers;
-
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS;
-import static com.android.quickstep.AnimatedFloat.VALUE;
-
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.statemanager.StateManager.StateHandler;
-import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.UiThreadHelper;
-import com.android.quickstep.AnimatedFloat;
-import com.android.quickstep.SystemUiProxy;
-
-/**
- * State handler for animating back button alpha in two-button nav mode.
- */
-public class BackButtonAlphaHandler implements StateHandler<LauncherState> {
-
- private final QuickstepLauncher mLauncher;
- private final AnimatedFloat mBackAlpha = new AnimatedFloat(this::updateBackAlpha);
-
- public BackButtonAlphaHandler(QuickstepLauncher launcher) {
- mLauncher = launcher;
- }
-
- @Override
- public void setState(LauncherState state) { }
-
- @Override
- public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
- PendingAnimation animation) {
- if (DisplayController.getNavigationMode(mLauncher) != TWO_BUTTONS) {
- return;
- }
-
- mBackAlpha.value = SystemUiProxy.INSTANCE.get(mLauncher).getLastNavButtonAlpha();
- animation.setFloat(mBackAlpha, VALUE,
- mLauncher.shouldBackButtonBeHidden(toState) ? 0 : 1, LINEAR);
- }
-
- private void updateBackAlpha() {
- UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
- QuickstepLauncher.SET_BACK_BUTTON_ALPHA, mBackAlpha.value, false /* animate */);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 4b8b5f7..e3fd3f9 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -165,7 +165,8 @@
float toDepth = toState.getDepth(mLauncher);
if (Float.compare(mDepth, toDepth) != 0) {
- animation.setFloat(this, DEPTH, toDepth, config.getInterpolator(ANIM_DEPTH, LINEAR));
+ animation.setFloat(this, STATE_DEPTH, toDepth,
+ config.getInterpolator(ANIM_DEPTH, LINEAR));
}
}
@@ -179,7 +180,7 @@
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
mIgnoreStateChangesDuringMultiWindowAnimation = true;
- ObjectAnimator mwAnimation = ObjectAnimator.ofFloat(this, DEPTH,
+ ObjectAnimator mwAnimation = ObjectAnimator.ofFloat(this, STATE_DEPTH,
mLauncher.getStateManager().getState().getDepth(mLauncher, isInMultiWindowMode))
.setDuration(300);
mwAnimation.addListener(new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 520487e..a219ac6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -15,9 +15,10 @@
*/
package com.android.launcher3.taskbar;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
+
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
-import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
import android.animation.Animator;
import android.animation.AnimatorSet;
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 4fda50e..a90af04 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -17,6 +17,7 @@
import static android.view.View.AccessibilityDelegate;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
@@ -42,7 +43,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
@@ -69,6 +69,7 @@
import android.view.View.OnClickListener;
import android.view.View.OnHoverListener;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -88,7 +89,6 @@
import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -167,7 +167,7 @@
// Variables for moving nav buttons to a separate window above IME
private boolean mAreNavButtonsInSeparateWindow = false;
private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
- private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
+ private final ViewTreeObserver.OnComputeInternalInsetsListener mSeparateWindowInsetsComputer =
this::onComputeInsetsForSeparateWindow;
private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
@@ -827,14 +827,14 @@
mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
- ViewTreeObserverWrapper.addOnComputeInsetsListener(
- mSeparateWindowParent.getViewTreeObserver(), mSeparateWindowInsetsComputer);
+ mSeparateWindowParent.getViewTreeObserver().addOnComputeInternalInsetsListener(
+ mSeparateWindowInsetsComputer);
}
@Override
public void onViewDetachedFromWindow(View view) {
mSeparateWindowParent.removeOnAttachStateChangeListener(this);
- ViewTreeObserverWrapper.removeOnComputeInsetsListener(
+ mSeparateWindowParent.getViewTreeObserver().removeOnComputeInternalInsetsListener(
mSeparateWindowInsetsComputer);
}
});
@@ -862,7 +862,7 @@
mContext.getDragLayer().addView(mNavButtonsView);
}
- private void onComputeInsetsForSeparateWindow(ViewTreeObserverWrapper.InsetsInfo insetsInfo) {
+ private void onComputeInsetsForSeparateWindow(ViewTreeObserver.InternalInsetsInfo insetsInfo) {
addVisibleButtonsRegion(mSeparateWindowParent, insetsInfo.touchableRegion);
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 3b1e677..8697b69 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -80,7 +80,7 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.TraceHelper;
@@ -868,6 +868,10 @@
btv.post(() -> mControllers.taskbarPopupController.showForIcon(btv));
}
+ public boolean isInApp() {
+ return mControllers.taskbarStashController.isInApp();
+ }
+
protected void dumpLogs(String prefix, PrintWriter pw) {
pw.println(prefix + "TaskbarActivityContext:");
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 97029fe..9a1e064 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -32,6 +32,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
+import android.util.Pair;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
@@ -42,7 +43,6 @@
import androidx.annotation.Nullable;
import com.android.internal.logging.InstanceId;
-import com.android.internal.logging.InstanceIdSequence;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DragSource;
@@ -69,6 +69,7 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.quickstep.util.LogUtils;
import com.android.systemui.shared.recents.model.Task;
import java.io.PrintWriter;
@@ -359,11 +360,11 @@
}
if (clipDescription != null && intent != null) {
+ Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
+ LogUtils.getShellShareableInstanceId();
// Need to share the same InstanceId between launcher3 and WM Shell (internal).
- InstanceId internalInstanceId = new InstanceIdSequence(
- com.android.launcher3.logging.InstanceId.INSTANCE_ID_MAX).newInstanceId();
- com.android.launcher3.logging.InstanceId launcherInstanceId =
- new com.android.launcher3.logging.InstanceId(internalInstanceId.getId());
+ InstanceId internalInstanceId = instanceIds.first;
+ com.android.launcher3.logging.InstanceId launcherInstanceId = instanceIds.second;
intent.putExtra(ClipDescription.EXTRA_LOGGING_INSTANCE_ID, internalInstanceId);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index ee17ad0..7e75779 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -24,6 +24,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewTreeObserver;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -32,9 +33,6 @@
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.views.BaseDragLayer;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInsetsListener;
/**
* Top-level ViewGroup that hosts the TaskbarView as well as Views created by it such as Folder.
@@ -42,7 +40,8 @@
public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
private final TaskbarBackgroundRenderer mBackgroundRenderer;
- private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
+ private final ViewTreeObserver.OnComputeInternalInsetsListener mTaskbarInsetsComputer =
+ this::onComputeTaskbarInsets;
// Initialized in init.
private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
@@ -80,7 +79,7 @@
mControllers = mControllerCallbacks.getTouchControllers();
}
- private void onComputeTaskbarInsets(InsetsInfo insetsInfo) {
+ private void onComputeTaskbarInsets(ViewTreeObserver.InternalInsetsInfo insetsInfo) {
if (mControllerCallbacks != null) {
mControllerCallbacks.updateInsetsTouchability(insetsInfo);
}
@@ -88,7 +87,7 @@
protected void onDestroy(boolean forceDestroy) {
if (forceDestroy) {
- ViewTreeObserverWrapper.removeOnComputeInsetsListener(mTaskbarInsetsComputer);
+ getViewTreeObserver().removeOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
}
}
@@ -99,8 +98,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- ViewTreeObserverWrapper.addOnComputeInsetsListener(getViewTreeObserver(),
- mTaskbarInsetsComputer);
+ getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index ec9760c..025fe7a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -17,12 +17,12 @@
import android.content.res.Resources;
import android.graphics.Rect;
+import android.view.ViewTreeObserver;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.AnimatedFloat;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
import java.io.PrintWriter;
@@ -157,9 +157,9 @@
/**
* Called to update the touchable insets.
- * @see InsetsInfo#setTouchableInsets(int)
+ * @see ViewTreeObserver.InternalInsetsInfo#setTouchableInsets(int)
*/
- public void updateInsetsTouchability(InsetsInfo insetsInfo) {
+ public void updateInsetsTouchability(ViewTreeObserver.InternalInsetsInfo insetsInfo) {
mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 48fde8f..7b2b7ec 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -20,6 +20,11 @@
import android.view.InsetsFrameProvider
import android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES
import android.view.InsetsState
+import android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT
+import android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR
+import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME
+import android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD
import android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION
@@ -29,9 +34,6 @@
import com.android.launcher3.anim.AlphaUpdateListener
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.quickstep.KtR
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo
-import com.android.systemui.shared.system.WindowManagerWrapper
-import com.android.systemui.shared.system.WindowManagerWrapper.*
import java.io.PrintWriter
/**
@@ -55,8 +57,7 @@
this.controllers = controllers
windowLayoutParams = context.windowLayoutParams
- val wmWrapper: WindowManagerWrapper = getInstance()
- wmWrapper.setProvidesInsetsTypes(
+ setProvidesInsetsTypes(
windowLayoutParams,
intArrayOf(
ITYPE_EXTRA_NAVIGATION_BAR,
@@ -108,10 +109,22 @@
}
/**
- * Called to update the touchable insets.
- * @see InsetsInfo.setTouchableInsets
+ * Sets {@param providesInsetsTypes} as the inset types provided by {@param params}.
+ * @param params The window layout params.
+ * @param providesInsetsTypes The inset types we would like this layout params to provide.
*/
- fun updateInsetsTouchability(insetsInfo: InsetsInfo) {
+ fun setProvidesInsetsTypes(params: WindowManager.LayoutParams, providesInsetsTypes: IntArray) {
+ params.providedInsets = arrayOfNulls<InsetsFrameProvider>(providesInsetsTypes.size);
+ for (i in providesInsetsTypes.indices) {
+ params.providedInsets[i] = InsetsFrameProvider(providesInsetsTypes[i]);
+ }
+ }
+
+ /**
+ * Called to update the touchable insets.
+ * @see InternalInsetsInfo.setTouchableInsets
+ */
+ fun updateInsetsTouchability(insetsInfo: ViewTreeObserver.InternalInsetsInfo) {
insetsInfo.touchableRegion.setEmpty()
// Always have nav buttons be touchable
controllers.navbarButtonsViewController.addVisibleButtonsRegion(
@@ -120,18 +133,18 @@
var insetsIsTouchableRegion = true
if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
// Let touches pass through us.
- insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (controllers.navbarButtonsViewController.isImeVisible) {
- insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (!controllers.uiController.isTaskbarTouchable) {
// Let touches pass through us.
- insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (controllers.taskbarDragController.isSystemDragInProgress) {
// Let touches pass through us.
- insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_ALL_APPS)) {
// Let touches pass through us.
- insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (controllers.taskbarViewController.areIconsVisible()
|| AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL)
|| context.isNavBarKidsModeActive
@@ -139,15 +152,15 @@
// Taskbar has some touchable elements, take over the full taskbar area
insetsInfo.setTouchableInsets(
if (context.isTaskbarWindowFullscreen) {
- InsetsInfo.TOUCHABLE_INSETS_FRAME
+ TOUCHABLE_INSETS_FRAME
} else {
insetsInfo.touchableRegion.set(contentRegion)
- InsetsInfo.TOUCHABLE_INSETS_REGION
+ TOUCHABLE_INSETS_REGION
}
)
insetsIsTouchableRegion = false
} else {
- insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
}
context.excludeFromMagnificationRegion(insetsIsTouchableRegion)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 80b3c1d..bc69088 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -45,6 +45,7 @@
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.RecentsActivity;
@@ -83,7 +84,7 @@
// It's destruction/creation will be managed by the activity.
private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
new NonDestroyableScopedUnfoldTransitionProgressProvider();
- private DisplayController.NavigationMode mNavMode;
+ private NavigationMode mNavMode;
private TaskbarActivityContext mTaskbarActivityContext;
private StatefulActivity mActivity;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 7b4501a..49d0873 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -15,14 +15,20 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
+
+import android.content.ClipDescription;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.graphics.Point;
+import android.os.Bundle;
+import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
+import com.android.internal.logging.InstanceId;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.LauncherSettings;
@@ -47,6 +53,7 @@
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.LogUtils;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -263,8 +270,14 @@
@Override
public void onClick(View view) {
- AbstractFloatingView.closeAllOpenViews(mTarget);
+ Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
+ LogUtils.getShellShareableInstanceId();
+ mTarget.getStatsLogManager().logger()
+ .withItemInfo(mItemInfo)
+ .withInstanceId(instanceIds.second)
+ .log(getLogEventForPosition(mPosition.stagePosition));
+ AbstractFloatingView.closeAllOpenViews(mTarget);
if (mItemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo;
SystemUiProxy.INSTANCE.get(mTarget).startShortcut(
@@ -272,7 +285,8 @@
workspaceItemInfo.getDeepShortcutId(),
mPosition.stagePosition,
null,
- workspaceItemInfo.user);
+ workspaceItemInfo.user,
+ instanceIds.first);
} else {
SystemUiProxy.INSTANCE.get(mTarget).startIntent(
mTarget.getSystemService(LauncherApps.class).getMainActivityLaunchIntent(
@@ -281,7 +295,8 @@
mItemInfo.user),
new Intent(),
mPosition.stagePosition,
- null);
+ null,
+ instanceIds.first);
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
index f131595..c10b57a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
@@ -17,24 +17,29 @@
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DEEP_SHORTCUTS;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.SHORTCUTS_AND_NOTIFICATIONS;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
import android.content.Intent;
import android.content.pm.LauncherApps;
+import android.util.Pair;
import android.view.KeyEvent;
import android.view.View;
+import com.android.internal.logging.InstanceId;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.ShortcutUtil;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.LogUtils;
import java.util.List;
@@ -49,10 +54,12 @@
public static final int MOVE_TO_BOTTOM_OR_RIGHT = R.id.action_move_to_bottom_or_right;
private final LauncherApps mLauncherApps;
+ private final StatsLogManager mStatsLogManager;
public TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context) {
super(context);
mLauncherApps = context.getSystemService(LauncherApps.class);
+ mStatsLogManager = context.getStatsLogManager();
mActions.put(DEEP_SHORTCUTS, new LauncherAction(DEEP_SHORTCUTS,
R.string.action_deep_shortcut, KeyEvent.KEYCODE_S));
@@ -82,7 +89,14 @@
&& (action == MOVE_TO_TOP_OR_LEFT || action == MOVE_TO_BOTTOM_OR_RIGHT)) {
WorkspaceItemInfo info = (WorkspaceItemInfo) item;
int side = action == MOVE_TO_TOP_OR_LEFT
- ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
+ ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
+
+ Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
+ LogUtils.getShellShareableInstanceId();
+ mStatsLogManager.logger()
+ .withItemInfo(item)
+ .withInstanceId(instanceIds.second)
+ .log(getLogEventForPosition(side));
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
SystemUiProxy.INSTANCE.get(mContext).startShortcut(
@@ -90,14 +104,15 @@
info.getDeepShortcutId(),
side,
/* bundleOpts= */ null,
- info.user);
+ info.user,
+ instanceIds.first);
} else {
SystemUiProxy.INSTANCE.get(mContext).startIntent(
mLauncherApps.getMainActivityLaunchIntent(
item.getIntent().getComponent(),
/* startActivityOptions= */null,
item.user),
- new Intent(), side, null);
+ new Intent(), side, null, instanceIds.first);
}
return true;
} else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index d9d55e7..d60bf8c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -32,6 +32,7 @@
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;
+import android.view.InsetsController;
import android.view.View;
import android.view.ViewConfiguration;
@@ -46,7 +47,6 @@
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy;
-import com.android.systemui.shared.system.WindowManagerWrapper;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -96,7 +96,7 @@
* How long to stash/unstash when manually invoked via long press.
*/
public static final long TASKBAR_STASH_DURATION =
- WindowManagerWrapper.ANIMATION_DURATION_RESIZE;
+ InsetsController.ANIMATION_DURATION_RESIZE;
/**
* How long to stash/unstash when keyboard is appearing/disappearing.
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
index c76180e..a1385c4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
@@ -17,15 +17,16 @@
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_BACK;
+import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
-
import android.content.Context;
import android.graphics.Insets;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.WindowInsets;
import com.android.launcher3.AbstractFloatingView;
@@ -47,9 +48,6 @@
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInsetsListener;
/**
* Window context for the taskbar all apps overlay.
@@ -163,7 +161,7 @@
/** Root drag layer for this context. */
private static class TaskbarAllAppsDragLayer extends
- BaseDragLayer<TaskbarAllAppsContext> implements OnComputeInsetsListener {
+ BaseDragLayer<TaskbarAllAppsContext> implements OnComputeInternalInsetsListener {
private TaskbarAllAppsDragLayer(Context context) {
super(context, null, 1);
@@ -174,14 +172,13 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- ViewTreeObserverWrapper.addOnComputeInsetsListener(
- getViewTreeObserver(), this);
+ getViewTreeObserver().addOnComputeInternalInsetsListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- ViewTreeObserverWrapper.removeOnComputeInsetsListener(this);
+ getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
}
@Override
@@ -207,7 +204,7 @@
}
@Override
- public void onComputeInsets(InsetsInfo inoutInfo) {
+ public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
if (mActivity.mDragController.isSystemDragInProgress()) {
inoutInfo.touchableRegion.setEmpty();
inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index c9bc260..cf0cae4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -17,22 +17,21 @@
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
-import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
-import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.NO_OFFSET;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_WIDGET_PICKER_DEPTH;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
@@ -45,9 +44,9 @@
import static com.android.launcher3.testing.shared.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
-import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS;
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.util.BaseDepthController.WIDGET_DEPTH;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.animation.AnimatorSet;
@@ -72,7 +71,6 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -80,6 +78,7 @@
import com.android.launcher3.QuickstepAccessibilityDelegate;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -96,7 +95,6 @@
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
-import com.android.launcher3.statehandlers.BackButtonAlphaHandler;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.statemanager.StateManager.StateHandler;
@@ -114,16 +112,15 @@
import com.android.launcher3.uioverrides.touchcontrollers.TwoButtonNavbarTouchController;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.util.PendingRequestArgs;
import com.android.launcher3.util.PendingSplitSelectInfo;
import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.TouchController;
-import com.android.launcher3.util.UiThreadHelper;
-import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsModel;
@@ -137,11 +134,11 @@
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TISBindHelper;
+import com.android.quickstep.util.ViewCapture;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.unfold.UnfoldTransitionFactory;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
@@ -164,17 +161,6 @@
SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", false);
public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false;
- /**
- * Reusable command for applying the shelf height on the background thread.
- */
- public static final AsyncCommand SET_SHELF_HEIGHT = (context, arg1, arg2) ->
- SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2);
- /**
- * Reusable command for applying the back button alpha on the background thread.
- */
- public static final AsyncCommand SET_BACK_BUTTON_ALPHA =
- (context, arg1, arg2) -> SystemUiProxy.INSTANCE.get(context).setNavBarButtonAlpha(
- Float.intBitsToFloat(arg1), arg2 != 0);
private FixedContainerItems mAllAppsPredictions;
private HotseatPredictionController mHotseatPredictionController;
@@ -195,6 +181,8 @@
*/
private PendingSplitSelectInfo mPendingSplitSelectInfo = null;
+ private SafeCloseable mViewCapture;
+
@Override
protected void setupViews() {
super.setupViews();
@@ -203,7 +191,7 @@
RecentsView overviewPanel = (RecentsView) getOverviewPanel();
SplitSelectStateController controller =
new SplitSelectStateController(this, mHandler, getStateManager(),
- getDepthController());
+ getDepthController(), getStatsLogManager());
overviewPanel.init(mActionsView, controller);
mActionsView.updateDimension(getDeviceProfile(), overviewPanel.getLastComputedTaskSize());
mActionsView.updateVerticalMargin(DisplayController.getNavigationMode(this));
@@ -295,11 +283,6 @@
@Override
protected void onActivityFlagsChanged(int changeBits) {
- if ((changeBits
- & (ACTIVITY_STATE_WINDOW_FOCUSED | ACTIVITY_STATE_TRANSITION_ACTIVE)) != 0) {
- onLauncherStateOrFocusChanged();
- }
-
if ((changeBits & ACTIVITY_STATE_STARTED) != 0) {
mDepthController.setActivityStarted(isStarted());
}
@@ -362,8 +345,7 @@
boolean visible = (state == NORMAL || state == OVERVIEW)
&& (willUserBeActive || isUserActive())
&& !profile.isVerticalBarLayout();
- UiThreadHelper.runAsyncCommand(this, SET_SHELF_HEIGHT, visible ? 1 : 0,
- profile.hotseatBarSizePx);
+ SystemUiProxy.INSTANCE.get(this).setShelfHeight(visible, profile.hotseatBarSizePx);
}
}
if (state == NORMAL && !inTransition) {
@@ -410,6 +392,7 @@
super.onDestroy();
mHotseatPredictionController.destroy();
+ mViewCapture.close();
}
@Override
@@ -509,6 +492,7 @@
}
addMultiWindowModeChangedListener(mDepthController);
initUnfoldTransitionProgressProvider();
+ mViewCapture = ViewCapture.INSTANCE.get(this).startCapture(getWindow());
}
@Override
@@ -602,6 +586,11 @@
public void onWidgetsTransition(float progress) {
super.onWidgetsTransition(progress);
onTaskbarInAppDisplayProgressUpdate(progress, WIDGETS_PAGE_PROGRESS_INDEX);
+ if (ENABLE_WIDGET_PICKER_DEPTH.get() && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ WIDGET_DEPTH.set(getDepthController(),
+ Utilities.mapToRange(progress, 0f, 1f, 0f, getDeviceProfile().bottomSheetDepth,
+ EMPHASIZED));
+ }
}
private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {
@@ -723,7 +712,6 @@
super.collectStateHandlers(out);
out.add(getDepthController());
out.add(new RecentsViewStateController(this));
- out.add(new BackButtonAlphaHandler(this));
}
public DepthController getDepthController() {
@@ -782,39 +770,6 @@
}
@Override
- public void onDragLayerHierarchyChanged() {
- onLauncherStateOrFocusChanged();
- }
-
- public boolean shouldBackButtonBeHidden(LauncherState toState) {
- NavigationMode mode = DisplayController.getNavigationMode(this);
- boolean shouldBackButtonBeHidden = mode.hasGestures
- && toState.hasFlag(FLAG_HIDE_BACK_BUTTON)
- && hasWindowFocus()
- && (getActivityFlags() & ACTIVITY_STATE_TRANSITION_ACTIVE) == 0;
- if (shouldBackButtonBeHidden) {
- // Show the back button if there is a floating view visible.
- shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenViewWithType(this,
- TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null;
- }
- return shouldBackButtonBeHidden;
- }
-
- /**
- * Sets the back button visibility based on the current state/window focus.
- */
- private void onLauncherStateOrFocusChanged() {
- boolean shouldBackButtonBeHidden = shouldBackButtonBeHidden(getStateManager().getState());
- if (DisplayController.getNavigationMode(this) == TWO_BUTTONS) {
- UiThreadHelper.setBackButtonAlphaAsync(this, SET_BACK_BUTTON_ALPHA,
- shouldBackButtonBeHidden ? 0f : 1f, true /* animate */);
- }
- if (getDragLayer() != null) {
- getRootView().setDisallowBackGesture(shouldBackButtonBeHidden);
- }
- }
-
- @Override
public void finishBindingItems(IntSet pagesBoundFirst) {
super.finishBindingItems(pagesBoundFirst);
// Instantiate and initialize WellbeingModel now that its loading won't interfere with
@@ -844,8 +799,8 @@
? mAppTransitionManager.getActivityLaunchOptions(v)
: super.getActivityLaunchOptions(v, item);
if (mLastTouchUpTime > 0) {
- ActivityOptionsCompat.setLauncherSourceInfo(
- activityOptions.options, mLastTouchUpTime);
+ activityOptions.options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER,
+ mLastTouchUpTime);
}
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
activityOptions.options.setLaunchDisplayId(
@@ -943,8 +898,8 @@
outState.putIBinder(PENDING_SPLIT_SELECT_INFO, ObjectWrapper.wrap(
new PendingSplitSelectInfo(
splitSelectStateController.getInitialTaskId(),
- splitSelectStateController.getActiveSplitStagePosition()
- )
+ splitSelectStateController.getActiveSplitStagePosition(),
+ splitSelectStateController.getSplitEvent())
));
outState.putInt(RUNTIME_STATE, OVERVIEW.ordinal);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 5cddd07..420c64a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -33,7 +33,6 @@
import android.util.Pair;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimatorListeners;
@@ -71,7 +70,10 @@
// DepthController to prevent optimizations which might occlude the layers behind
mLauncher.getDepthController().setHasContentBehindLauncher(state.overviewUi);
- handleSplitSelectionState(state, null);
+ PendingAnimation builder =
+ new PendingAnimation(state.getTransitionDuration(mLauncher, true));
+
+ handleSplitSelectionState(state, builder, /* animate */false);
}
@Override
@@ -92,7 +94,7 @@
builder.addListener(AnimatorListeners.forSuccessCallback(() ->
mLauncher.getDepthController().setHasContentBehindLauncher(toState.overviewUi)));
- handleSplitSelectionState(toState, builder);
+ handleSplitSelectionState(toState, builder, /* animate */true);
setAlphas(builder, config, toState);
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
@@ -105,8 +107,7 @@
* will add animations to builder.
*/
private void handleSplitSelectionState(@NonNull LauncherState toState,
- @Nullable PendingAnimation builder) {
- boolean animate = builder != null;
+ @NonNull PendingAnimation builder, boolean animate) {
PagedOrientationHandler orientationHandler =
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
Pair<FloatProperty, FloatProperty> taskViewsFloat =
@@ -115,18 +116,15 @@
mLauncher.getDeviceProfile());
if (toState == OVERVIEW_SPLIT_SELECT) {
- // Animation to "dismiss" selected taskView
- PendingAnimation splitSelectInitAnimation = mRecentsView.createSplitSelectInitAnimation(
+ mRecentsView.createSplitSelectInitAnimation(builder,
toState.getTransitionDuration(mLauncher, true /* isToState */));
// Add properties to shift remaining taskViews to get out of placeholder view
- splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.first,
+ builder.setFloat(mRecentsView, taskViewsFloat.first,
toState.getSplitSelectTranslation(mLauncher), LINEAR);
- splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
+ builder.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
if (!animate) {
- splitSelectInitAnimation.buildAnim().start();
- } else {
- builder.add(splitSelectInitAnimation.buildAnim());
+ builder.buildAnim().start();
}
mRecentsView.applySplitPrimaryScrollOffset();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index e21f14f..fd184c6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -16,7 +16,6 @@
package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import android.content.Context;
@@ -26,7 +25,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.util.Themes;
/**
@@ -44,9 +42,9 @@
@Override
public <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) {
- return context.getDeviceProfile().isTablet
- ? 500
- : isToState ? 600 : 300;
+ return isToState
+ ? context.getDeviceProfile().allAppsOpenDuration
+ : context.getDeviceProfile().allAppsCloseDuration;
}
@Override
@@ -83,15 +81,7 @@
protected <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfile.DeviceProfileListenable>
float getDepthUnchecked(DEVICE_PROFILE_CONTEXT context) {
if (context.getDeviceProfile().isTablet) {
- // The goal is to set wallpaper to zoom at workspaceContentScale when in AllApps.
- // When depth is 0, wallpaper zoom is set to maxWallpaperScale.
- // When depth is 1, wallpaper zoom is set to 1.
- // For depth to achieve zoom set to maxWallpaperScale * workspaceContentScale:
- float maxWallpaperScale = context.getResources().getFloat(
- com.android.internal.R.dimen.config_wallpaperMaxScale);
- return Utilities.mapToRange(
- maxWallpaperScale * context.getDeviceProfile().workspaceContentScale,
- maxWallpaperScale, 1f, 0f, 1f, LINEAR);
+ return context.getDeviceProfile().bottomSheetDepth;
} else {
// The scrim fades in at approximately 50% of the swipe gesture.
// This means that the depth should be greater than 1, in order to fully zoom out.
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 872e64a..f5161aa 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -79,6 +79,14 @@
private static final int PER_PAGE_SCROLL_DURATION = 150;
private static final int MAX_PAGE_SCROLL_DURATION = 750;
+ private static final int OVERVIEW_TO_SPLIT_ACTIONS_FADE_START = 0;
+ private static final int OVERVIEW_TO_SPLIT_ACTIONS_FADE_END = 83;
+
+ private static final float OVERVIEW_TO_SPLIT_ACTIONS_FADE_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_ACTIONS_FADE_START / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_ACTIONS_FADE_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_ACTIONS_FADE_END / SplitScreenSelectState.ENTER_DURATION;
+
// Due to use of physics, duration may differ between devices so we need to calculate and
// cache the value.
private int mHintToNormalDuration = -1;
@@ -188,6 +196,10 @@
AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config);
} else if (fromState == NORMAL && toState == ALL_APPS) {
AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
+ } else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) {
+ config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR,
+ OVERVIEW_TO_SPLIT_ACTIONS_FADE_START_OFFSET,
+ OVERVIEW_TO_SPLIT_ACTIONS_FADE_END_OFFSET));
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
index e79d56b..2bc3c3e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
@@ -16,6 +16,8 @@
package com.android.launcher3.uioverrides.states;
+import android.content.Context;
+
import com.android.launcher3.Launcher;
import com.android.quickstep.views.RecentsView;
@@ -24,6 +26,10 @@
* pinned and user is selecting the second one
*/
public class SplitScreenSelectState extends OverviewState {
+ public static final int ENTER_DURATION = 866;
+ public static final int EXIT_DURATION = 500;
+ // TODO: Add ability to differentiate between Split > Home and Split > Confirmed timings
+
public SplitScreenSelectState(int id) {
super(id);
}
@@ -38,4 +44,9 @@
RecentsView recentsView = launcher.getOverviewPanel();
return recentsView.getSplitSelectTranslation();
}
+
+ @Override
+ public int getTransitionDuration(Context context, boolean isToState) {
+ return isToState ? ENTER_DURATION : EXIT_DURATION;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index e5cd53a..56ac4c5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -45,7 +45,7 @@
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.RecentsView;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index ca7f633..c49848a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -236,7 +236,8 @@
PendingAnimation pa;
if (goingUp) {
currentInterpolator = Interpolators.LINEAR;
- pa = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
+ pa = new PendingAnimation(maxDuration);
+ mRecentsView.createTaskDismissAnimation(pa, mTaskBeingDragged,
true /* animateTaskView */, true /* removeTask */, maxDuration,
false /* dismissingForSplitSelection*/);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index b7a50fc..a389035 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -50,7 +50,6 @@
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FINISH_RECENTS_ANIMATION;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -87,6 +86,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import com.android.internal.util.LatencyTracker;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
@@ -127,7 +127,6 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
-import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -340,6 +339,8 @@
return ActiveGestureErrorDetector.GestureEvent.STATE_CAPTURE_SCREENSHOT;
} else if (stateFlag == STATE_HANDLER_INVALIDATED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_HANDLER_INVALIDATED;
+ } else if (stateFlag == STATE_LAUNCHER_DRAWN) {
+ return ActiveGestureErrorDetector.GestureEvent.STATE_LAUNCHER_DRAWN;
}
return null;
}
@@ -620,8 +621,8 @@
Object traceToken = TraceHelper.INSTANCE.beginSection("logToggleRecents",
TraceHelper.FLAG_IGNORE_BINDERS);
- LatencyTrackerCompat.logToggleRecents(
- mContext, (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
+ LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
+ (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
TraceHelper.INSTANCE.endSection(traceToken);
// This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
@@ -825,10 +826,6 @@
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
super.onRecentsAnimationStart(controller, targets);
- ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "startRecentsAnimationCallback",
- /* extras= */ targets.apps.length,
- /* gestureEvent= */ START_RECENTS_ANIMATION);
mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
@@ -879,11 +876,6 @@
// properly cleaned up the screenshot without accidentally using it.
mDeferredCleanupRecentsAnimationController = mRecentsAnimationController;
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
-
- if (mRecentsAnimationTargets != null) {
- setDividerShown(true /* shown */, false /* immediate */);
- }
-
// Defer clearing the controller and the targets until after we've updated the state
mRecentsAnimationController = null;
mRecentsAnimationTargets = null;
@@ -1781,10 +1773,6 @@
boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted;
mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
- if (mRecentsAnimationTargets != null && wasVisible) {
- setDividerShown(true /* shown */, true /* immediate */);
- }
-
// Leave the pending invisible flag, as it may be used by wallpaper open animation.
if (mActivity != null) {
mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 6354282..315a91e 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -55,7 +55,7 @@
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index ba61574..466abbe 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -16,7 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
+import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
import static com.android.quickstep.fallback.RecentsState.HOME;
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 38bf1fd..bcd9687 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -20,6 +20,9 @@
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_HOME;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_LAST_TASK;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_NEW_TASK;
import android.annotation.Nullable;
import android.annotation.TargetApi;
@@ -330,6 +333,20 @@
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "setEndTarget " + mEndTarget,
/* gestureEvent= */ SET_END_TARGET);
+ switch (mEndTarget) {
+ case HOME:
+ ActiveGestureLog.INSTANCE.trackEvent(SET_END_TARGET_HOME);
+ break;
+ case NEW_TASK:
+ ActiveGestureLog.INSTANCE.trackEvent(SET_END_TARGET_NEW_TASK);
+ break;
+ case LAST_TASK:
+ ActiveGestureLog.INSTANCE.trackEvent(SET_END_TARGET_LAST_TASK);
+ break;
+ case RECENTS:
+ default:
+ // No-Op
+ }
if (isAtomic) {
mStateCallback.setState(STATE_END_TARGET_ANIMATION_FINISHED);
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 4ceafeb..1127e2c 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -45,7 +45,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java
index 56e7fb5..a68bea2 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java
@@ -116,7 +116,13 @@
if (gestureEvent == null) {
continue;
}
- ActiveGestureLog.INSTANCE.trackEvent(gestureEvent);
+ if (gestureEvent.mLogEvent && gestureEvent.mTrackEvent) {
+ ActiveGestureLog.INSTANCE.addLog(gestureEvent.name(), gestureEvent);
+ } else if (gestureEvent.mLogEvent) {
+ ActiveGestureLog.INSTANCE.addLog(gestureEvent.name());
+ } else if (gestureEvent.mTrackEvent) {
+ ActiveGestureLog.INSTANCE.trackEvent(gestureEvent);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 47c5dd0..1b05fd2 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -34,7 +34,7 @@
import com.android.launcher3.R;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.window.CachedDisplayInfo;
import java.io.PrintWriter;
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 1e7e89e..57a26ee 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -144,7 +144,7 @@
RunnableList callbackList = null;
if (taskView != null) {
taskView.setEndQuickswitchCuj(true);
- callbackList = taskView.launchTaskAnimated();
+ callbackList = taskView.launchTasks();
}
if (callbackList != null) {
@@ -193,7 +193,20 @@
}
}
- if (activityInterface.switchToRecentsIfVisible(() -> scheduleNextTask(cmd))) {
+ final Runnable completeCallback = () -> {
+ if (cmd.type == TYPE_SHOW_NEXT_FOCUS) {
+ RecentsView rv = activityInterface.getVisibleRecentsView();
+ // When the overview is launched via alt tab (cmd type is TYPE_SHOW_NEXT_FOCUS),
+ // the touch mode somehow is not change to false by the Android framework.
+ // The subsequent tab to go through tasks in overview can only be dispatched to
+ // focuses views, while focus can only be requested in
+ // {@link View#requestFocusNoSearch(int, Rect)} when touch mode is false. To note,
+ // here we launch overview from home.
+ rv.getViewRootImpl().touchModeChanged(false);
+ }
+ scheduleNextTask(cmd);
+ };
+ if (activityInterface.switchToRecentsIfVisible(completeCallback)) {
// If successfully switched, wait until animation finishes
return false;
}
@@ -268,6 +281,13 @@
RecentsView rv =
mOverviewComponentObserver.getActivityInterface().getVisibleRecentsView();
if (rv != null) {
+ // When the overview is launched via alt tab (cmd type is TYPE_SHOW_NEXT_FOCUS),
+ // the touch mode somehow is not change to false by the Android framework.
+ // The subsequent tab to go through tasks in overview can only be dispatched to
+ // focuses views, while focus can only be requested in
+ // {@link View#requestFocusNoSearch(int, Rect)} when touch mode is false. To note,
+ // here we launch overview with live tile.
+ rv.getViewRootImpl().touchModeChanged(false);
// Ensure that recents view has focus so that it receives the followup key inputs
TaskView taskView = rv.getNextTaskView();
if (taskView == null) {
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 813e687..dea4e48 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -20,6 +20,7 @@
import android.annotation.TargetApi;
import android.app.ActivityManager;
+import android.app.KeyguardManager;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
@@ -27,11 +28,10 @@
import androidx.annotation.VisibleForTesting;
-import com.android.quickstep.util.GroupTask;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.quickstep.util.GroupTask;
import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.wm.shell.recents.IRecentTasksListener;
import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.util.SplitBounds;
@@ -49,7 +49,7 @@
private static final TaskLoadResult INVALID_RESULT = new TaskLoadResult(-1, false, 0);
- private final KeyguardManagerCompat mKeyguardManager;
+ private final KeyguardManager mKeyguardManager;
private final LooperExecutor mMainThreadExecutor;
private final SystemUiProxy mSysUiProxy;
@@ -66,8 +66,8 @@
// Tasks are stored in order of least recently launched to most recently launched.
private ArrayList<ActivityManager.RunningTaskInfo> mRunningTasks;
- public RecentTasksList(LooperExecutor mainThreadExecutor,
- KeyguardManagerCompat keyguardManager, SystemUiProxy sysUiProxy) {
+ public RecentTasksList(LooperExecutor mainThreadExecutor, KeyguardManager keyguardManager,
+ SystemUiProxy sysUiProxy) {
mMainThreadExecutor = mainThreadExecutor;
mKeyguardManager = keyguardManager;
mChangeId = 1;
@@ -254,8 +254,12 @@
TaskLoadResult allTasks = new TaskLoadResult(requestId, loadKeysOnly, rawTasks.size());
for (GroupedRecentTaskInfo rawTask : rawTasks) {
- ActivityManager.RecentTaskInfo taskInfo1 = rawTask.mTaskInfo1;
- ActivityManager.RecentTaskInfo taskInfo2 = rawTask.mTaskInfo2;
+ if (rawTask.getType() == GroupedRecentTaskInfo.TYPE_FREEFORM) {
+ // TODO: add entry for freeform tasks
+ continue;
+ }
+ ActivityManager.RecentTaskInfo taskInfo1 = rawTask.getTaskInfo1();
+ ActivityManager.RecentTaskInfo taskInfo2 = rawTask.getTaskInfo2();
Task.TaskKey task1Key = new Task.TaskKey(taskInfo1);
Task task1 = loadKeysOnly
? new Task(task1Key)
@@ -272,7 +276,7 @@
task2.setLastSnapshotData(taskInfo2);
}
final SplitConfigurationOptions.SplitBounds launcherSplitBounds =
- convertSplitBounds(rawTask.mSplitBounds);
+ convertSplitBounds(rawTask.getSplitBounds());
allTasks.add(new GroupTask(task1, task2, launcherSplitBounds));
}
@@ -310,8 +314,8 @@
mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId);
writer.println(prefix + " rawTasks=[");
for (GroupedRecentTaskInfo task : rawTasks) {
- writer.println(prefix + " t1=" + task.mTaskInfo1.taskId
- + " t2=" + (task.mTaskInfo2 != null ? task.mTaskInfo2.taskId : "-1"));
+ writer.println(prefix + " t1=" + task.getTaskInfo1().taskId
+ + " t2=" + (task.getTaskInfo2() != null ? task.getTaskInfo2().taskId : "-1"));
}
writer.println(prefix + " ]");
}
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 3e3a431..c879494 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -30,6 +30,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.app.ActivityOptions;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -77,7 +78,6 @@
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -131,7 +131,7 @@
SplitSelectStateController controller =
new SplitSelectStateController(this, mHandler, getStateManager(),
- null /* depthController */);
+ /* depthController */ null, getStatsLogManager());
mDragLayer.recreateControllers();
mFallbackRecentsView.init(mActionsView, controller);
@@ -263,8 +263,10 @@
wrapper, RECENTS_LAUNCH_DURATION,
RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
- STATUS_BAR_TRANSITION_PRE_DELAY, getIApplicationThread());
- final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(
- ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
+ final ActivityOptions options = ActivityOptions.makeRemoteAnimation(
+ adapterCompat.getWrapped(),
+ adapterCompat.getRemoteTransition().getTransition());
+ final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(options,
onEndCallback);
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
activityOptions.options.setLaunchDisplayId(
@@ -406,8 +408,10 @@
RemoteAnimationAdapterCompat adapterCompat =
new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0,
getIApplicationThread());
- startHomeIntentSafely(this,
- ActivityOptionsCompat.makeRemoteAnimation(adapterCompat).toBundle());
+ ActivityOptions options = ActivityOptions.makeRemoteAnimation(
+ adapterCompat.getWrapped(),
+ adapterCompat.getRemoteTransition().getTransition());
+ startHomeIntentSafely(this, options.toBundle());
}
private final RemoteAnimationFactory mAnimationToHomeFactory =
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 887fd54..b233521 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
import android.graphics.Rect;
import android.util.ArraySet;
@@ -28,6 +29,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Preconditions;
+import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@@ -113,6 +115,10 @@
homeContentInsets, minimizedHomeBounds);
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
+ ActiveGestureLog.INSTANCE.addLog(
+ /* event= */ "RecentsAnimationCallbacks.onAnimationStart",
+ /* extras= */ targets.apps.length,
+ /* gestureEvent= */ START_RECENTS_ANIMATION);
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(mController, targets);
}
@@ -137,7 +143,8 @@
@Override
public void onTasksAppeared(RemoteAnimationTargetCompat[] apps) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
- ActiveGestureLog.INSTANCE.addLog("onTasksAppeared");
+ ActiveGestureLog.INSTANCE.addLog("onTasksAppeared",
+ ActiveGestureErrorDetector.GestureEvent.TASK_APPEARED);
for (RecentsAnimationListener listener : getListeners()) {
listener.onTasksAppeared(apps);
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index b6cfbb0..e87fdad 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -23,9 +23,9 @@
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
-import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
-import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
-import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS;
+import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
+import static com.android.launcher3.util.NavigationMode.TWO_BUTTONS;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -67,7 +67,7 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SettingsCache;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.NavBarPosition;
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 3074dbb..3053474 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -22,6 +22,7 @@
import android.annotation.TargetApi;
import android.app.ActivityManager;
+import android.app.KeyguardManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
@@ -40,7 +41,6 @@
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -75,7 +75,8 @@
private RecentsModel(Context context) {
mContext = context;
mTaskList = new RecentTasksList(MAIN_EXECUTOR,
- new KeyguardManagerCompat(context), SystemUiProxy.INSTANCE.get(context));
+ context.getSystemService(KeyguardManager.class),
+ SystemUiProxy.INSTANCE.get(context));
IconProvider iconProvider = new IconProvider(context);
mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider);
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 2186a3b..f8b6966 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -23,8 +23,8 @@
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
-import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import android.content.Context;
import android.content.res.Resources;
@@ -35,8 +35,8 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 8e9ff2f..944e2f9 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -17,8 +17,8 @@
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
-import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.app.ActivityManager;
import android.app.PendingIntent;
@@ -32,8 +32,10 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
+import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
@@ -43,8 +45,9 @@
import android.view.SurfaceControl;
import android.window.IOnBackInvokedCallback;
-import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.Info;
+import androidx.annotation.WorkerThread;
+
+import com.android.internal.logging.InstanceId;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -72,12 +75,14 @@
/**
* Holds the reference to SystemUI.
*/
-public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayInfoChangeListener {
+public class SystemUiProxy implements ISystemUiProxy {
private static final String TAG = SystemUiProxy.class.getSimpleName();
public static final MainThreadInitializedObject<SystemUiProxy> INSTANCE =
new MainThreadInitializedObject<>(SystemUiProxy::new);
+ private static final int MSG_SET_SHELF_HEIGHT = 1;
+
private ISystemUiProxy mSystemUiProxy;
private IPip mPip;
private ISysuiUnlockAnimationController mSysuiUnlockAnimationController;
@@ -106,26 +111,16 @@
// Used to dedupe calls to SystemUI
private int mLastShelfHeight;
private boolean mLastShelfVisible;
- private float mLastNavButtonAlpha;
- private boolean mLastNavButtonAnimate;
- private boolean mHasNavButtonAlphaBeenSet = false;
- private Runnable mPendingSetNavButtonAlpha = null;
- private Context mContext;
+
+ private final Context mContext;
+ private final Handler mAsyncHandler;
// TODO(141886704): Find a way to remove this
private int mLastSystemUiStateFlags;
public SystemUiProxy(Context context) {
- DisplayController.INSTANCE.get(context).addChangeListener(this);
mContext = context;
- }
-
- @Override
- public void onDisplayInfoChanged(Context context, Info info, int flags) {
- if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
- // Whenever the nav mode changes, force reset the nav button alpha
- setNavBarButtonAlpha(1f, false);
- }
+ mAsyncHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessageAsync);
}
@Override
@@ -205,11 +200,6 @@
if (mBackAnimation != null && mBackToLauncherCallback != null) {
setBackToLauncherCallback(mBackToLauncherCallback);
}
-
- if (mPendingSetNavButtonAlpha != null) {
- mPendingSetNavButtonAlpha.run();
- mPendingSetNavButtonAlpha = null;
- }
}
public void clearProxy() {
@@ -272,31 +262,6 @@
}
}
- public float getLastNavButtonAlpha() {
- return mLastNavButtonAlpha;
- }
-
- @Override
- public void setNavBarButtonAlpha(float alpha, boolean animate) {
- boolean changed = Float.compare(alpha, mLastNavButtonAlpha) != 0
- || animate != mLastNavButtonAnimate
- || !mHasNavButtonAlphaBeenSet;
- if (changed) {
- if (mSystemUiProxy == null) {
- mPendingSetNavButtonAlpha = () -> setNavBarButtonAlpha(alpha, animate);
- } else {
- mLastNavButtonAlpha = alpha;
- mLastNavButtonAnimate = animate;
- mHasNavButtonAlphaBeenSet = true;
- try {
- mSystemUiProxy.setNavBarButtonAlpha(alpha, animate);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed call setNavBarButtonAlpha", e);
- }
- }
- }
- }
-
@Override
public void onStatusBarMotionEvent(MotionEvent event) {
if (mSystemUiProxy != null) {
@@ -481,12 +446,20 @@
* Sets the shelf height.
*/
public void setShelfHeight(boolean visible, int shelfHeight) {
+ Message.obtain(mAsyncHandler, MSG_SET_SHELF_HEIGHT,
+ visible ? 1 : 0 , shelfHeight).sendToTarget();
+ }
+
+ @WorkerThread
+ private void setShelfHeightAsync(int visibleInt, int shelfHeight) {
+ boolean visible = visibleInt != 0;
boolean changed = visible != mLastShelfVisible || shelfHeight != mLastShelfHeight;
- if (mPip != null && changed) {
+ IPip pip = mPip;
+ if (pip != null && changed) {
mLastShelfVisible = visible;
mLastShelfHeight = shelfHeight;
try {
- mPip.setShelfHeight(visible, shelfHeight);
+ pip.setShelfHeight(visible, shelfHeight);
} catch (RemoteException e) {
Log.w(TAG, "Failed call setShelfHeight visible: " + visible
+ " height: " + shelfHeight, e);
@@ -567,11 +540,11 @@
/** Start multiple tasks in split-screen simultaneously. */
public void startTasks(int mainTaskId, Bundle mainOptions, int sideTaskId, Bundle sideOptions,
@SplitConfigurationOptions.StagePosition int sidePosition, float splitRatio,
- RemoteTransitionCompat remoteTransition) {
+ RemoteTransitionCompat remoteTransition, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startTasks(mainTaskId, mainOptions, sideTaskId, sideOptions,
- sidePosition, splitRatio, remoteTransition.getTransition());
+ sidePosition, splitRatio, remoteTransition.getTransition(), instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startTask");
}
@@ -583,11 +556,11 @@
*/
public void startTasksWithLegacyTransition(int mainTaskId, Bundle mainOptions, int sideTaskId,
Bundle sideOptions, @SplitConfigurationOptions.StagePosition int sidePosition,
- float splitRatio, RemoteAnimationAdapter adapter) {
+ float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startTasksWithLegacyTransition(mainTaskId, mainOptions, sideTaskId,
- sideOptions, sidePosition, splitRatio, adapter);
+ sideOptions, sidePosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startTasksWithLegacyTransition");
}
@@ -597,11 +570,12 @@
public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent,
Intent fillInIntent, int taskId, Bundle mainOptions, Bundle sideOptions,
@SplitConfigurationOptions.StagePosition int sidePosition, float splitRatio,
- RemoteAnimationAdapter adapter) {
+ RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startIntentAndTaskWithLegacyTransition(pendingIntent, fillInIntent,
- taskId, mainOptions, sideOptions, sidePosition, splitRatio, adapter);
+ taskId, mainOptions, sideOptions, sidePosition, splitRatio, adapter,
+ instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startIntentAndTaskWithLegacyTransition");
}
@@ -611,11 +585,11 @@
public void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo, int taskId,
Bundle mainOptions, Bundle sideOptions,
@SplitConfigurationOptions.StagePosition int sidePosition, float splitRatio,
- RemoteAnimationAdapter adapter) {
+ RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startShortcutAndTaskWithLegacyTransition(shortcutInfo, taskId,
- mainOptions, sideOptions, sidePosition, splitRatio, adapter);
+ mainOptions, sideOptions, sidePosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startShortcutAndTaskWithLegacyTransition");
}
@@ -623,11 +597,11 @@
}
public void startShortcut(String packageName, String shortcutId, int position,
- Bundle options, UserHandle user) {
+ Bundle options, UserHandle user, InstanceId instanceId) {
if (mSplitScreen != null) {
try {
mSplitScreen.startShortcut(packageName, shortcutId, position, options,
- user);
+ user, instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startShortcut");
}
@@ -635,10 +609,10 @@
}
public void startIntent(PendingIntent intent, Intent fillInIntent, int position,
- Bundle options) {
+ Bundle options, InstanceId instanceId) {
if (mSplitScreen != null) {
try {
- mSplitScreen.startIntent(intent, fillInIntent, position, options);
+ mSplitScreen.startIntent(intent, fillInIntent, position, options, instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startIntent");
}
@@ -895,12 +869,21 @@
if (mRecentTasks != null
&& mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) {
try {
- return new ArrayList<ActivityManager.RunningTaskInfo>(
- Arrays.asList(mRecentTasks.getRunningTasks(numTasks)));
+ return new ArrayList<>(Arrays.asList(mRecentTasks.getRunningTasks(numTasks)));
} catch (RemoteException e) {
Log.w(TAG, "Failed call getRunningTasks", e);
}
}
return new ArrayList<>();
}
+
+ private boolean handleMessageAsync(Message msg) {
+ switch (msg.what) {
+ case MSG_SET_SHELF_HEIGHT:
+ setShelfHeightAsync(msg.arg1, msg.arg2);
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 5fb806d..b9a1b06 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -36,12 +36,9 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
-import com.android.quickstep.util.ActiveGestureErrorDetector;
-import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -138,8 +135,6 @@
// handling this call entirely
return;
}
- ActiveGestureLog.INSTANCE.addLog("TaskAnimationManager.startRecentsAnimation",
- ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION);
mController = controller;
mTargets = targets;
mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId());
@@ -233,7 +228,8 @@
RemoteTransitionCompat transition = new RemoteTransitionCompat(mCallbacks,
mController != null ? mController.getController() : null,
mCtx.getIApplicationThread());
- final ActivityOptions options = ActivityOptionsCompat.makeRemoteTransition(transition);
+ final ActivityOptions options = ActivityOptions.makeRemoteTransition(
+ transition.getTransition());
// Allowing to pause Home if Home is top activity and Recents is not Home. So when user
// start home when recents animation is playing, the home activity can be resumed again
// to let the transition controller collect Home activity.
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index a0860ee..eae79df 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -16,6 +16,8 @@
package com.android.quickstep;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SELECTIONS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
@@ -26,9 +28,12 @@
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
+import android.os.RemoteException;
import android.os.SystemProperties;
+import android.util.Log;
import android.view.View;
import android.view.WindowInsets;
+import android.view.WindowManagerGlobal;
import android.window.SplashScreen;
import androidx.annotation.Nullable;
@@ -52,8 +57,6 @@
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.Collections;
import java.util.List;
@@ -121,6 +124,7 @@
}
class FreeformSystemShortcut extends SystemShortcut<BaseDraggingActivity> {
+ private static final String TAG = "FreeformSystemShortcut";
private Handler mHandler;
@@ -193,7 +197,7 @@
taskId, thumbnail, taskBounds));
}
};
- WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
+ overridePendingAppTransitionMultiThumbFuture(
future, animStartedListener, mHandler, true /* scaleUp */,
taskKey.displayId);
mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
@@ -201,8 +205,27 @@
}
}
+ /**
+ * Overrides a pending app transition.
+ */
+ private void overridePendingAppTransitionMultiThumbFuture(
+ AppTransitionAnimationSpecsFuture animationSpecFuture, Runnable animStartedCallback,
+ Handler animStartedCallbackHandler, boolean scaleUp, int displayId) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .overridePendingAppTransitionMultiThumbFuture(
+ animationSpecFuture.getFuture(),
+ RecentsTransition.wrapStartedListener(animStartedCallbackHandler,
+ animStartedCallback), scaleUp, displayId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to override pending app transition (multi-thumbnail future): ",
+ e);
+ }
+ }
+
private ActivityOptions makeLaunchOptions(Activity activity) {
- ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
+ ActivityOptions activityOptions = ActivityOptions.makeBasic();
+ activityOptions.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
// Arbitrary bounds only because freeform is in dev mode right now
final View decorView = activity.getWindow().getDecorView();
final WindowInsets insets = decorView.getRootWindowInsets();
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 556b99e..a96524e 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -36,7 +36,7 @@
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.statehandlers.DepthController.DEPTH;
+import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -367,7 +367,7 @@
});
if (depthController != null) {
- out.setFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(baseActivity),
+ out.setFloat(depthController, STATE_DEPTH, BACKGROUND_APP.getDepth(baseActivity),
TOUCH_RESPONSE_INTERPOLATOR);
}
}
@@ -668,7 +668,7 @@
for (int i = 0; i < nonApps.length; ++i) {
final RemoteAnimationTargetCompat targ = nonApps[i];
final SurfaceControl leash = targ.leash;
- if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
+ if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null && leash.isValid()) {
auxiliarySurfaces.add(leash);
hasSurfaceToAnimate = true;
}
@@ -681,7 +681,9 @@
dockFadeAnimator.addUpdateListener(valueAnimator -> {
float progress = valueAnimator.getAnimatedFraction();
for (SurfaceControl leash : auxiliarySurfaces) {
- t.setAlpha(leash, shown ? progress : 1 - progress);
+ if (leash != null && leash.isValid()) {
+ t.setAlpha(leash, shown ? progress : 1 - progress);
+ }
}
t.apply();
});
@@ -702,7 +704,9 @@
public void onAnimationEnd(Animator animation) {
if (!shown) {
for (SurfaceControl leash : auxiliarySurfaces) {
- t.hide(leash);
+ if (leash != null && leash.isValid()) {
+ t.hide(leash);
+ }
}
t.apply();
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ba4f549..4923948 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -100,6 +100,7 @@
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.SplitScreenBounds;
+import com.android.quickstep.util.ViewCapture;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -461,7 +462,8 @@
mOverviewComponentObserver = new OverviewComponentObserver(this, mDeviceState);
mOverviewCommandHelper = new OverviewCommandHelper(this,
mOverviewComponentObserver, mTaskAnimationManager);
- mResetGestureInputConsumer = new ResetGestureInputConsumer(mTaskAnimationManager);
+ mResetGestureInputConsumer = new ResetGestureInputConsumer(
+ mTaskAnimationManager, mTaskbarManager::getCurrentActivityContext);
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mInputConsumer.registerInputConsumer();
onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
@@ -707,16 +709,19 @@
}
public GestureState createGestureState(GestureState previousGestureState) {
- GestureState gestureState = new GestureState(mOverviewComponentObserver,
- ActiveGestureLog.INSTANCE.incrementLogId());
+ final GestureState gestureState;
TopTaskTracker.CachedTaskInfo taskInfo;
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
+ gestureState = new GestureState(mOverviewComponentObserver,
+ ActiveGestureLog.INSTANCE.getLogId());
taskInfo = previousGestureState.getRunningTask();
gestureState.updateRunningTask(taskInfo);
gestureState.updateLastStartedTaskId(previousGestureState.getLastStartedTaskId());
gestureState.updatePreviouslyAppearedTaskIds(
previousGestureState.getPreviouslyAppearedTaskIds());
} else {
+ gestureState = new GestureState(mOverviewComponentObserver,
+ ActiveGestureLog.INSTANCE.incrementLogId());
taskInfo = TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false);
gestureState.updateRunningTask(taskInfo);
}
@@ -1213,6 +1218,8 @@
createdOverviewActivity.getDeviceProfile().dump(this, "", pw);
}
mTaskbarManager.dumpLogs("", pw);
+
+ ViewCapture.INSTANCE.get(this).dump(pw, fd);
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
index 3e01ed0..8a87f63 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
@@ -22,7 +22,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.NavBarPosition;
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 7337132..1e0ceed 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -114,8 +114,11 @@
RecentsState currentState = mActivity.getStateManager().getState();
if (isSplitSelectionState(state) && !isSplitSelectionState(currentState)) {
- setter.add(mRecentsView.createSplitSelectInitAnimation(
- state.getTransitionDuration(mActivity, true /* isToState */)).buildAnim());
+ int duration = state.getTransitionDuration(mActivity, true /* isToState */);
+ // TODO (b/246851887): Pass in setter as a NO_ANIM PendingAnimation instead
+ PendingAnimation pa = new PendingAnimation(duration);
+ mRecentsView.createSplitSelectInitAnimation(pa, duration);
+ setter.add(pa.buildAnim());
}
Pair<FloatProperty, FloatProperty> taskViewsFloat =
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 7c96bf8..93eb0f1 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -33,6 +33,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.popup.QuickstepSystemShortcut;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -54,6 +55,8 @@
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
implements StateListener<RecentsState> {
+ private static final int TASK_DISMISS_DURATION = 150;
+
@Nullable
private Task mHomeTask;
@@ -105,8 +108,9 @@
if (mHomeTask != null && endTarget == RECENTS && animatorSet != null) {
TaskView tv = getTaskViewByTaskId(mHomeTask.key.id);
if (tv != null) {
- PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150,
- false /* dismissingForSplitSelection*/);
+ PendingAnimation pa = new PendingAnimation(TASK_DISMISS_DURATION);
+ createTaskDismissAnimation(pa, tv, true, false,
+ TASK_DISMISS_DURATION, false /* dismissingForSplitSelection*/);
pa.addEndListener(e -> setCurrentTask(-1));
AnimatorPlaybackController controller = pa.createPlaybackController();
controller.dispatchOnStart();
@@ -210,8 +214,9 @@
@Override
public void initiateSplitSelect(TaskView taskView,
- @SplitConfigurationOptions.StagePosition int stagePosition) {
- super.initiateSplitSelect(taskView, stagePosition);
+ @SplitConfigurationOptions.StagePosition int stagePosition,
+ StatsLogManager.EventEnum splitEvent) {
+ super.initiateSplitSelect(taskView, stagePosition, splitEvent);
mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
index d34b40b..349f4d2 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
@@ -17,18 +17,25 @@
import android.view.MotionEvent;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.TaskAnimationManager;
+import java.util.function.Supplier;
+
/**
* A NO_OP input consumer which also resets any pending gesture
*/
public class ResetGestureInputConsumer implements InputConsumer {
private final TaskAnimationManager mTaskAnimationManager;
+ private final Supplier<TaskbarActivityContext> mActivityContextSupplier;
- public ResetGestureInputConsumer(TaskAnimationManager taskAnimationManager) {
+ public ResetGestureInputConsumer(
+ TaskAnimationManager taskAnimationManager,
+ Supplier<TaskbarActivityContext> activityContextSupplier) {
mTaskAnimationManager = taskAnimationManager;
+ mActivityContextSupplier = activityContextSupplier;
}
@Override
@@ -40,7 +47,9 @@
public void onMotionEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN
&& mTaskAnimationManager.isRecentsAnimationRunning()) {
- mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
+ TaskbarActivityContext tac = mActivityContextSupplier.get();
+ mTaskAnimationManager.finishRunningRecentsAnimation(
+ /* toHome= */ tac != null && !tac.isInApp());
}
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 4badf30..e7bf7e2 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -44,10 +44,10 @@
import androidx.annotation.Nullable;
import com.android.launcher3.R;
-import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 99553e8..2ccdfa3 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -46,8 +46,8 @@
import com.android.launcher3.model.DeviceGridState;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SettingsCache;
import org.xmlpull.v1.XmlPullParser;
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 54f632a..53e0c2b 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -33,9 +33,10 @@
* Enums associated to gesture navigation events.
*/
public enum GestureEvent {
- MOTION_DOWN, MOTION_UP, SET_END_TARGET, ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION,
+ MOTION_DOWN, MOTION_UP, SET_END_TARGET, SET_END_TARGET_HOME, SET_END_TARGET_LAST_TASK,
+ SET_END_TARGET_NEW_TASK, ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION,
FINISH_RECENTS_ANIMATION, CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK,
- CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT,
+ CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED,
/**
* These GestureEvents are specifically associated to state flags that get set in
@@ -46,7 +47,19 @@
STATE_GESTURE_STARTED, STATE_GESTURE_COMPLETED, STATE_GESTURE_CANCELLED,
STATE_END_TARGET_ANIMATION_FINISHED, STATE_RECENTS_SCROLLING_FINISHED,
STATE_CAPTURE_SCREENSHOT, STATE_SCREENSHOT_CAPTURED, STATE_HANDLER_INVALIDATED,
- STATE_RECENTS_ANIMATION_CANCELED
+ STATE_RECENTS_ANIMATION_CANCELED, STATE_LAUNCHER_DRAWN(true, false);
+
+ public final boolean mLogEvent;
+ public final boolean mTrackEvent;
+
+ GestureEvent() {
+ this(false, true);
+ }
+
+ GestureEvent(boolean logEvent, boolean trackEvent) {
+ mLogEvent = logEvent;
+ mTrackEvent = trackEvent;
+ }
}
private ActiveGestureErrorDetector() {}
@@ -111,6 +124,25 @@
+ "being set.",
writer);
break;
+ case SCROLLER_ANIMATION_ABORTED:
+ errorDetected |= printErrorIfTrue(
+ encounteredEvents.contains(GestureEvent.SET_END_TARGET_HOME)
+ && !encounteredEvents.contains(
+ GestureEvent.ON_SETTLED_ON_END_TARGET),
+ /* errorMessage= */ prefix + "\t\trecents view scroller animation "
+ + "aborted after setting end target HOME, but before"
+ + " settling on end target.",
+ writer);
+ break;
+ case TASK_APPEARED:
+ errorDetected |= printErrorIfTrue(
+ !encounteredEvents.contains(GestureEvent.SET_END_TARGET_LAST_TASK)
+ && !encounteredEvents.contains(
+ GestureEvent.SET_END_TARGET_NEW_TASK),
+ /* errorMessage= */ prefix + "\t\tonTasksAppeared called "
+ + "before/without setting end target to last or new task",
+ writer);
+ break;
case STATE_GESTURE_COMPLETED:
errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(GestureEvent.MOTION_UP),
@@ -161,6 +193,7 @@
break;
case MOTION_DOWN:
case SET_END_TARGET:
+ case SET_END_TARGET_HOME:
case START_RECENTS_ANIMATION:
case SET_ON_PAGE_TRANSITION_END_CALLBACK:
case CANCEL_CURRENT_ANIMATION:
@@ -168,6 +201,7 @@
case STATE_END_TARGET_ANIMATION_FINISHED:
case STATE_CAPTURE_SCREENSHOT:
case STATE_HANDLER_INVALIDATED:
+ case STATE_LAUNCHER_DRAWN:
default:
// No-Op
}
@@ -264,6 +298,21 @@
+ "the task screenshot wasn't cleaned up.",
writer);
+ errorDetected |= printErrorIfTrue(
+ /* condition= */ encounteredEvents.contains(
+ GestureEvent.SET_END_TARGET_LAST_TASK)
+ && !encounteredEvents.contains(GestureEvent.TASK_APPEARED),
+ /* errorMessage= */ prefix + "\t\tend target set to last task, but "
+ + "onTaskAppeared wasn't called.",
+ writer);
+ errorDetected |= printErrorIfTrue(
+ /* condition= */ encounteredEvents.contains(
+ GestureEvent.SET_END_TARGET_NEW_TASK)
+ && !encounteredEvents.contains(GestureEvent.TASK_APPEARED),
+ /* errorMessage= */ prefix + "\t\tend target set to new task, but "
+ + "onTaskAppeared wasn't called.",
+ writer);
+
if (!errorDetected) {
writer.println(prefix + "\t\tNo errors detected.");
}
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
index 40eb31b..23fdd58 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
@@ -161,16 +161,14 @@
ArrayList<EventLog> eventLogs = new ArrayList<>();
for (int i = 0; i < logs.length; i++) {
- EventLog eventLog = logs[(nextIndex + logs.length - i - 1) % logs.length];
+ EventLog eventLog = logs[(nextIndex + i) % logs.length];
if (eventLog == null) {
continue;
}
eventLogs.add(eventLog);
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);
+ for (EventEntry eventEntry : eventLog.eventEntries) {
date.setTime(eventEntry.time);
StringBuilder msg = new StringBuilder(prefix + "\t\t").append(sdf.format(date))
@@ -215,6 +213,11 @@
return mCurrentLogId++;
}
+ /** Returns the current log ID. This should be used when a log trace is being reused. */
+ public int getLogId() {
+ return mCurrentLogId;
+ }
+
private boolean isEntrySame(
EventEntry entry,
int type,
diff --git a/quickstep/src/com/android/quickstep/util/BaseDepthController.java b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
index 4030630..29ae9a1 100644
--- a/quickstep/src/com/android/quickstep/util/BaseDepthController.java
+++ b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
@@ -24,6 +24,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.MultiPropertyFactory;
import com.android.systemui.shared.system.BlurUtils;
/**
@@ -31,7 +32,7 @@
*/
public class BaseDepthController {
- public static final FloatProperty<BaseDepthController> DEPTH =
+ private static final FloatProperty<BaseDepthController> DEPTH =
new FloatProperty<BaseDepthController>("depth") {
@Override
public void setValue(BaseDepthController depthController, float depth) {
@@ -44,6 +45,19 @@
}
};
+ private static final MultiPropertyFactory<BaseDepthController> DEPTH_PROPERTY_FACTORY =
+ new MultiPropertyFactory<>("depthProperty", DEPTH, Float::max);
+
+ private static final int DEPTH_INDEX_STATE_TRANSITION = 1;
+ private static final int DEPTH_INDEX_WIDGET = 2;
+
+ /** Property to set the depth for state transition. */
+ public static final FloatProperty<BaseDepthController> STATE_DEPTH =
+ DEPTH_PROPERTY_FACTORY.get(DEPTH_INDEX_STATE_TRANSITION);
+ /** Property to set the depth for widget picker. */
+ public static final FloatProperty<BaseDepthController> WIDGET_DEPTH =
+ DEPTH_PROPERTY_FACTORY.get(DEPTH_INDEX_WIDGET);
+
protected final Launcher mLauncher;
/**
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index d0856be..f7136a5 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -23,7 +23,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.LauncherActivityInterface;
public class LayoutUtils {
diff --git a/quickstep/src/com/android/quickstep/util/LogUtils.kt b/quickstep/src/com/android/quickstep/util/LogUtils.kt
new file mode 100644
index 0000000..bad8506
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/LogUtils.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 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.quickstep.util
+
+import android.util.Pair
+import com.android.internal.logging.InstanceIdSequence
+import com.android.launcher3.logging.InstanceId
+
+object LogUtils {
+ /**
+ * @return a [Pair] of two InstanceIds but with different types, one that can be used by framework
+ * (if needing to pass through an intent or such) and one used in Launcher
+ */
+ @JvmStatic
+ fun getShellShareableInstanceId():
+ Pair<com.android.internal.logging.InstanceId, InstanceId> {
+ val internalInstanceId = InstanceIdSequence(InstanceId.INSTANCE_ID_MAX).newInstanceId()
+ val launcherInstanceId = InstanceId(internalInstanceId.id)
+ return Pair(internalInstanceId, launcherInstanceId)
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
index 527a6d2..59c8263 100644
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -15,12 +15,12 @@
*/
package com.android.quickstep.util;
-import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
+import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import android.view.Surface;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.NavigationMode;
/**
* Utility class to check nav bar position.
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index fc44b99..e928b27 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -21,7 +21,7 @@
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
+import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import android.content.SharedPreferences;
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 7efb1a5..efbe783 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -38,12 +38,16 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import androidx.annotation.Nullable;
+import com.android.internal.logging.InstanceId;
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager;
@@ -74,10 +78,12 @@
private final Context mContext;
private final Handler mHandler;
+ private StatsLogManager mStatsLogManager;
private final SystemUiProxy mSystemUiProxy;
private final StateManager mStateManager;
private final DepthController mDepthController;
private @StagePosition int mStagePosition;
+ private ItemInfo mItemInfo;
private Intent mInitialTaskIntent;
private int mInitialTaskId = INVALID_TASK_ID;
private int mSecondTaskId = INVALID_TASK_ID;
@@ -88,11 +94,14 @@
/** If not null, this is the TaskView we want to launch from */
@Nullable
private GroupedTaskView mLaunchingTaskView;
+ /** Represents where split is intended to be invoked from. */
+ private StatsLogManager.EventEnum mSplitEvent;
public SplitSelectStateController(Context context, Handler handler, StateManager stateManager,
- DepthController depthController) {
+ DepthController depthController, StatsLogManager statsLogManager) {
mContext = context;
mHandler = handler;
+ mStatsLogManager = statsLogManager;
mSystemUiProxy = SystemUiProxy.INSTANCE.get(mContext);
mStateManager = stateManager;
mDepthController = depthController;
@@ -101,19 +110,25 @@
/**
* To be called after first task selected
*/
- public void setInitialTaskSelect(int taskId, @StagePosition int stagePosition) {
+ public void setInitialTaskSelect(int taskId, @StagePosition int stagePosition,
+ StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
mInitialTaskId = taskId;
- mStagePosition = stagePosition;
- mInitialTaskIntent = null;
- mUser = null;
+ setInitialData(stagePosition, splitEvent, itemInfo);
}
public void setInitialTaskSelect(Intent intent, @StagePosition int stagePosition,
- @Nullable UserHandle user) {
+ @NonNull ItemInfo itemInfo, StatsLogManager.EventEnum splitEvent) {
mInitialTaskIntent = intent;
+ mUser = itemInfo.user;
+ mItemInfo = itemInfo;
+ setInitialData(stagePosition, splitEvent, itemInfo);
+ }
+
+ private void setInitialData(@StagePosition int stagePosition,
+ StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
+ mItemInfo = itemInfo;
mStagePosition = stagePosition;
- mInitialTaskId = INVALID_TASK_ID;
- mUser = user;
+ mSplitEvent = splitEvent;
}
/**
@@ -137,8 +152,16 @@
FLAG_MUTABLE, null /* options */, mUser)
: PendingIntent.getActivity(mContext, 0, mInitialTaskIntent, FLAG_MUTABLE));
+ Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
+ LogUtils.getShellShareableInstanceId();
launchTasks(mInitialTaskId, pendingIntent, fillInIntent, mSecondTaskId, mStagePosition,
- callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO);
+ callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
+ instanceIds.first);
+
+ mStatsLogManager.logger()
+ .withItemInfo(mItemInfo)
+ .withInstanceId(instanceIds.second)
+ .log(mSplitEvent);
}
@@ -174,7 +197,7 @@
public void launchTasks(int taskId1, int taskId2, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
launchTasks(taskId1, null /* taskPendingIntent */, null /* fillInIntent */, taskId2,
- stagePosition, callback, freezeTaskList, splitRatio);
+ stagePosition, callback, freezeTaskList, splitRatio, null);
}
/**
@@ -183,10 +206,14 @@
* fill in intent with a taskId2 are set.
* @param taskPendingIntent is null when split is initiated from Overview
* @param stagePosition representing location of task1
+ * @param shellInstanceId loggingId to be used by shell, will be non-null for actions that create
+ * a split instance, null for cases that bring existing instaces to the
+ * foreground (quickswitch, launching previous pairs from overview)
*/
public void launchTasks(int taskId1, @Nullable PendingIntent taskPendingIntent,
@Nullable Intent fillInIntent, int taskId2, @StagePosition int stagePosition,
- Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
+ Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio,
+ @Nullable InstanceId shellInstanceId) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "launchSplitTasks");
// Assume initial task is for top/left part of screen
@@ -200,7 +227,8 @@
mSystemUiProxy.startTasks(taskIds[0], null /* mainOptions */, taskIds[1],
null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT, splitRatio,
new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR,
- ActivityThread.currentActivityThread().getApplicationThread()));
+ ActivityThread.currentActivityThread().getApplicationThread()),
+ shellInstanceId);
// TODO(b/237635859): handle intent/shortcut + task with shell transition
} else {
RemoteSplitLaunchAnimationRunner animationRunner =
@@ -218,18 +246,18 @@
if (taskPendingIntent == null) {
mSystemUiProxy.startTasksWithLegacyTransition(taskIds[0], mainOpts.toBundle(),
taskIds[1], null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
- splitRatio, adapter);
+ splitRatio, adapter, shellInstanceId);
} else {
final ShortcutInfo shortcutInfo = getShortcutInfo(mInitialTaskIntent,
taskPendingIntent.getCreatorUserHandle());
if (shortcutInfo != null) {
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(shortcutInfo, taskId2,
mainOpts.toBundle(), null /* sideOptions */, stagePosition, splitRatio,
- adapter);
+ adapter, shellInstanceId);
} else {
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(taskPendingIntent,
fillInIntent, taskId2, mainOpts.toBundle(), null /* sideOptions */,
- stagePosition, splitRatio, adapter);
+ stagePosition, splitRatio, adapter, shellInstanceId);
}
}
}
@@ -239,6 +267,10 @@
return mStagePosition;
}
+ public StatsLogManager.EventEnum getSplitEvent() {
+ return mSplitEvent;
+ }
+
public void setRecentsAnimationRunning(boolean running) {
this.mRecentsAnimationRunning = running;
}
@@ -358,6 +390,8 @@
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
+ mItemInfo = null;
+ mSplitEvent = null;
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 0a49008..1a026fc 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep.util;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.deltaRotation;
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
@@ -25,7 +27,6 @@
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
import static com.android.quickstep.util.RecentsOrientedState.preDisplayRotation;
-import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
import android.animation.TimeInterpolator;
import android.content.Context;
diff --git a/quickstep/src/com/android/quickstep/util/ViewCapture.java b/quickstep/src/com/android/quickstep/util/ViewCapture.java
new file mode 100644
index 0000000..6071bc8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/ViewCapture.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2022 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.quickstep.util;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.Executors.createAndStartNewLooper;
+
+import static java.util.stream.Collectors.toList;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.Trace;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Base64OutputStream;
+import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnDrawListener;
+import android.view.Window;
+
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.view.ViewCaptureData.ExportedData;
+import com.android.launcher3.view.ViewCaptureData.FrameData;
+import com.android.launcher3.view.ViewCaptureData.ViewNode;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Utility class for capturing view data every frame
+ */
+public class ViewCapture {
+
+ private static final String TAG = "ViewCapture";
+
+ // Number of frames to keep in memory
+ private static final int MEMORY_SIZE = 2000;
+ // Initial size of the reference pool. This is at least be 5 * total number of views in
+ // Launcher. This allows the first free frames avoid object allocation during view capture.
+ private static final int INIT_POOL_SIZE = 300;
+
+ public static final MainThreadInitializedObject<ViewCapture> INSTANCE =
+ new MainThreadInitializedObject<>(ViewCapture::new);
+
+ private final List<WindowListener> mListeners = new ArrayList<>();
+
+ private final Context mContext;
+ private final LooperExecutor mExecutor;
+
+ // Pool used for capturing view tree on the UI thread.
+ private ViewRef mPool = new ViewRef();
+
+ private ViewCapture(Context context) {
+ mContext = context;
+ if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
+ Looper looper = createAndStartNewLooper("ViewCapture",
+ Process.THREAD_PRIORITY_FOREGROUND);
+ mExecutor = new LooperExecutor(looper);
+ mExecutor.execute(this::initPool);
+ } else {
+ mExecutor = UI_HELPER_EXECUTOR;
+ }
+ }
+
+ @UiThread
+ private void addToPool(ViewRef start, ViewRef end) {
+ end.next = mPool;
+ mPool = start;
+ }
+
+ @WorkerThread
+ private void initPool() {
+ ViewRef start = new ViewRef();
+ ViewRef current = start;
+
+ for (int i = 0; i < INIT_POOL_SIZE; i++) {
+ current.next = new ViewRef();
+ current = current.next;
+ }
+
+ ViewRef finalCurrent = current;
+ MAIN_EXECUTOR.execute(() -> addToPool(start, finalCurrent));
+ }
+
+ /**
+ * Attaches the ViewCapture to the provided window and returns a handle to detach the listener
+ */
+ public SafeCloseable startCapture(Window window) {
+ String title = window.getAttributes().getTitle().toString();
+ String name = TextUtils.isEmpty(title) ? window.toString() : title;
+ return startCapture(window.getDecorView(), name);
+ }
+
+ /**
+ * Attaches the ViewCapture to the provided window and returns a handle to detach the listener
+ */
+ public SafeCloseable startCapture(View view, String name) {
+ if (!FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
+ return () -> { };
+ }
+
+ WindowListener listener = new WindowListener(view, name);
+ mExecutor.execute(() -> MAIN_EXECUTOR.execute(listener::attachToRoot));
+ mListeners.add(listener);
+ return () -> {
+ mListeners.remove(listener);
+ listener.destroy();
+ };
+ }
+
+ /**
+ * Dumps all the active view captures
+ */
+ public void dump(PrintWriter writer, FileDescriptor out) {
+ if (!FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
+ return;
+ }
+ ViewIdProvider idProvider = new ViewIdProvider(mContext.getResources());
+
+ // Collect all the tasks first so that all the tasks are posted on the executor
+ List<Pair<String, Future<ExportedData>>> tasks = mListeners.stream()
+ .map(l -> Pair.create(l.name, mExecutor.submit(() -> l.dumpToProto(idProvider))))
+ .collect(toList());
+
+ tasks.forEach(pair -> {
+ writer.println();
+ writer.println(" ContinuousViewCapture:");
+ writer.println(" window " + pair.first + ":");
+ writer.println(" pkg:" + mContext.getPackageName());
+ writer.print(" data:");
+ writer.flush();
+ try (OutputStream os = new FileOutputStream(out)) {
+ ExportedData data = pair.second.get();
+ OutputStream encodedOS = new GZIPOutputStream(new Base64OutputStream(os,
+ Base64.NO_CLOSE | Base64.NO_PADDING | Base64.NO_WRAP));
+ data.writeTo(encodedOS);
+ encodedOS.close();
+ os.flush();
+ } catch (Exception e) {
+ Log.e(TAG, "Error capturing proto", e);
+ }
+ writer.println();
+ writer.println("--end--");
+ });
+ }
+
+ private class WindowListener implements OnDrawListener {
+
+ private final View mRoot;
+ public final String name;
+
+ private final Handler mHandler;
+ private final ViewRef mViewRef = new ViewRef();
+
+ private int mFrameIndexBg = -1;
+ private final long[] mFrameTimesBg = new long[MEMORY_SIZE];
+ private final ViewPropertyRef[] mNodesBg = new ViewPropertyRef[MEMORY_SIZE];
+
+ private boolean mDestroyed = false;
+
+ WindowListener(View view, String name) {
+ mRoot = view;
+ this.name = name;
+ mHandler = new Handler(mExecutor.getLooper(), this::captureViewPropertiesBg);
+ }
+
+ @Override
+ public void onDraw() {
+ Trace.beginSection("view_capture");
+ captureViewTree(mRoot, mViewRef);
+ Message m = Message.obtain(mHandler);
+ m.obj = mViewRef.next;
+ mHandler.sendMessage(m);
+ Trace.endSection();
+ }
+
+ /**
+ * Captures the View property on the background thread, and transfer all the ViewRef objects
+ * back to the pool
+ */
+ @WorkerThread
+ private boolean captureViewPropertiesBg(Message msg) {
+ ViewRef start = (ViewRef) msg.obj;
+ long time = msg.getWhen();
+ if (start == null) {
+ return false;
+ }
+ mFrameIndexBg++;
+ if (mFrameIndexBg >= MEMORY_SIZE) {
+ mFrameIndexBg = 0;
+ }
+ mFrameTimesBg[mFrameIndexBg] = time;
+
+ ViewPropertyRef recycle = mNodesBg[mFrameIndexBg];
+
+ ViewPropertyRef result = null;
+ ViewPropertyRef resultEnd = null;
+
+ ViewRef current = start;
+ ViewRef last = start;
+ while (current != null) {
+ ViewPropertyRef propertyRef = recycle;
+ if (propertyRef == null) {
+ propertyRef = new ViewPropertyRef();
+ } else {
+ recycle = recycle.next;
+ propertyRef.next = null;
+ }
+
+ propertyRef.transfer(current);
+ last = current;
+ current = current.next;
+
+ if (result == null) {
+ result = propertyRef;
+ resultEnd = result;
+ } else {
+ resultEnd.next = propertyRef;
+ resultEnd = propertyRef;
+ }
+ }
+ mNodesBg[mFrameIndexBg] = result;
+ ViewRef end = last;
+ MAIN_EXECUTOR.execute(() -> addToPool(start, end));
+ return true;
+ }
+
+ void attachToRoot() {
+ if (mRoot.isAttachedToWindow()) {
+ mRoot.getViewTreeObserver().addOnDrawListener(this);
+ } else {
+ mRoot.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (!mDestroyed) {
+ mRoot.getViewTreeObserver().addOnDrawListener(WindowListener.this);
+ }
+ mRoot.removeOnAttachStateChangeListener(this);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) { }
+ });
+ }
+ }
+
+ void destroy() {
+ mRoot.getViewTreeObserver().removeOnDrawListener(this);
+ mDestroyed = true;
+ }
+
+ @WorkerThread
+ private ExportedData dumpToProto(ViewIdProvider idProvider) {
+ ExportedData.Builder dataBuilder = ExportedData.newBuilder();
+ ArrayList<Class> classList = new ArrayList<>();
+
+ int size = (mNodesBg[MEMORY_SIZE - 1] == null) ? mFrameIndexBg + 1 : MEMORY_SIZE;
+ for (int i = size - 1; i >= 0; i--) {
+ int index = (MEMORY_SIZE + mFrameIndexBg - i) % MEMORY_SIZE;
+ ViewNode.Builder nodeBuilder = ViewNode.newBuilder();
+ mNodesBg[index].toProto(idProvider, classList, nodeBuilder);
+ dataBuilder.addFrameData(FrameData.newBuilder()
+ .setNode(nodeBuilder)
+ .setTimestamp(mFrameTimesBg[index]));
+ }
+ return dataBuilder
+ .addAllClassname(classList.stream().map(Class::getName).collect(toList()))
+ .build();
+ }
+
+ private ViewRef captureViewTree(View view, ViewRef start) {
+ ViewRef ref;
+ if (mPool != null) {
+ ref = mPool;
+ mPool = mPool.next;
+ ref.next = null;
+ } else {
+ ref = new ViewRef();
+ }
+ ref.view = view;
+ start.next = ref;
+ if (view instanceof ViewGroup) {
+ ViewRef result = ref;
+ ViewGroup parent = (ViewGroup) view;
+ int childCount = ref.childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ result = captureViewTree(parent.getChildAt(i), result);
+ }
+ return result;
+ } else {
+ ref.childCount = 0;
+ return ref;
+ }
+ }
+ }
+
+ private static class ViewPropertyRef {
+ // We store reference in memory to avoid generating and storing too many strings
+ public Class clazz;
+ public int hashCode;
+ public int childCount = 0;
+
+ public int id;
+ public int left, top, right, bottom;
+ public int scrollX, scrollY;
+
+ public float translateX, translateY;
+ public float scaleX, scaleY;
+ public float alpha;
+ public float elevation;
+
+ public int visibility;
+ public boolean willNotDraw;
+ public boolean clipChildren;
+
+ public ViewPropertyRef next;
+
+ public void transfer(ViewRef viewRef) {
+ childCount = viewRef.childCount;
+
+ View view = viewRef.view;
+ viewRef.view = null;
+
+ clazz = view.getClass();
+ hashCode = view.hashCode();
+ id = view.getId();
+ left = view.getLeft();
+ top = view.getTop();
+ right = view.getRight();
+ bottom = view.getBottom();
+ scrollX = view.getScrollX();
+ scrollY = view.getScrollY();
+
+ translateX = view.getTranslationX();
+ translateY = view.getTranslationY();
+ scaleX = view.getScaleX();
+ scaleY = view.getScaleY();
+ alpha = view.getAlpha();
+
+ visibility = view.getVisibility();
+ willNotDraw = view.willNotDraw();
+ elevation = view.getElevation();
+ }
+
+ /**
+ * Converts the data to the proto representation and returns the next property ref
+ * at the end of the iteration.
+ * @return
+ */
+ public ViewPropertyRef toProto(ViewIdProvider idProvider, ArrayList<Class> classList,
+ ViewNode.Builder outBuilder) {
+ int classnameIndex = classList.indexOf(clazz);
+ if (classnameIndex < 0) {
+ classnameIndex = classList.size();
+ classList.add(clazz);
+ }
+ outBuilder
+ .setClassnameIndex(classnameIndex)
+ .setHashcode(hashCode)
+ .setId(idProvider.getName(id))
+ .setLeft(left)
+ .setTop(top)
+ .setWidth(right - left)
+ .setHeight(bottom - top)
+ .setTranslationX(translateX)
+ .setTranslationY(translateY)
+ .setScaleX(scaleX)
+ .setScaleY(scaleY)
+ .setAlpha(alpha)
+ .setVisibility(visibility)
+ .setWillNotDraw(willNotDraw)
+ .setElevation(elevation)
+ .setClipChildren(clipChildren);
+
+ ViewPropertyRef result = next;
+ for (int i = 0; (i < childCount) && (result != null); i++) {
+ ViewNode.Builder childBuilder = ViewNode.newBuilder();
+ result = result.toProto(idProvider, classList, childBuilder);
+ outBuilder.addChildren(childBuilder);
+ }
+ return result;
+ }
+ }
+
+ private static class ViewRef {
+ public View view;
+ public int childCount = 0;
+ public ViewRef next;
+ }
+
+ private static final class ViewIdProvider {
+
+ private final SparseArray<String> mNames = new SparseArray<>();
+ private final Resources mRes;
+
+ ViewIdProvider(Resources res) {
+ mRes = res;
+ }
+
+ String getName(int id) {
+ String name = mNames.get(id);
+ if (name == null) {
+ if (id >= 0) {
+ try {
+ name = mRes.getResourceTypeName(id) + '/' + mRes.getResourceEntryName(id);
+ } catch (Resources.NotFoundException e) {
+ name = "id/" + "0x" + Integer.toHexString(id).toUpperCase();
+ }
+ } else {
+ name = "NO_ID";
+ }
+ mNames.put(id, name);
+ }
+ return name;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index c3bf041..c211d7a 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -2,8 +2,10 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
import android.animation.ValueAnimator;
import android.content.Context;
@@ -24,12 +26,12 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.uioverrides.states.SplitScreenSelectState;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.util.MultiValueUpdateListener;
@@ -49,6 +51,31 @@
* TODO: Figure out how to copy thumbnail data from existing TaskView to this view.
*/
public class FloatingTaskView extends FrameLayout {
+ private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START = 0;
+ private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END = 133;
+ private static final int OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START = 167;
+ private static final int OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END = 250;
+ private static final int OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START = 0;
+ private static final int OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END = 417;
+
+ private static final float OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END
+ / SplitScreenSelectState.ENTER_DURATION;
public static final FloatProperty<FloatingTaskView> PRIMARY_TRANSLATE_OFFSCREEN =
new FloatProperty<FloatingTaskView>("floatingTaskPrimaryTranslateOffscreen") {
@@ -224,26 +251,49 @@
RectF floatingTaskViewBounds = new RectF();
if (fadeWithThumbnail) {
- animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
- 0, 1, ACCEL);
- animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA,
- 1, 0, DEACCEL_3);
+ // This code block runs when animating from Overview > OverviewSplitSelect
+ // And for the second thumbnail on confirm
+
+ // FloatingTaskThumbnailView: thumbnail fades out to transparent
+ animation.setViewAlpha(mThumbnailView, 0, clampToProgress(LINEAR,
+ OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET,
+ OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET));
+
+ // SplitPlaceholderView: gray background fades in at the same time, then new icon fades
+ // in
+ animation.setViewAlpha(mSplitPlaceholderView, 1, clampToProgress(LINEAR,
+ OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET,
+ OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET));
+ animation.setViewAlpha(mSplitPlaceholderView.getIconView(), 1, clampToProgress(
+ LINEAR, OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START_OFFSET,
+ OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END_OFFSET));
} else if (isStagedTask) {
+ // This code block runs when animating from Normal > OverviewSplitSelect
+ // and for the first thumbnail on confirm
+
// Fade in the placeholder view when split is initiated from homescreen / all apps
- // icons.
if (mSplitPlaceholderView.getAlpha() == 0) {
- animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
- 0.3f, 1, ACCEL);
+ animation.setViewAlpha(mSplitPlaceholderView, 0.3f, INSTANT);
+ animation.setViewAlpha(mSplitPlaceholderView, 1, ACCEL);
}
}
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
- final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, LINEAR);
- final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, LINEAR);
+ // SplitPlaceholderView: rectangle translates and stretches to new position
+ final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration,
+ clampToProgress(DEACCEL_2, OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
+ OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration,
+ clampToProgress(DEACCEL_2, OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
+ OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0,
- animDuration, LINEAR);
+ animDuration, clampToProgress(DEACCEL_2,
+ OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
+ OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0,
- animDuration, LINEAR);
+ animDuration, clampToProgress(DEACCEL_2,
+ OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
+ OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
@Override
public void onUpdate(float percent, boolean initOnly) {
// Calculate the icon position.
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 2539ed6..44ea0a0 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -1,5 +1,6 @@
package com.android.quickstep.views;
+import static com.android.launcher3.AbstractFloatingView.getAnyView;
import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
@@ -13,6 +14,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -162,6 +164,21 @@
}
}
+ @Override
+ protected boolean showTaskMenuWithContainer(IconView iconView) {
+ boolean showedTaskMenu = super.showTaskMenuWithContainer(iconView);
+ if (iconView == mIconView2 && showedTaskMenu && !mActivity.getDeviceProfile().isTablet) {
+ // Adjust the position of the secondary task's menu view (only on phones)
+ TaskMenuView taskMenuView = getAnyView(mActivity, AbstractFloatingView.TYPE_TASK_MENU);
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ getRecentsView().getPagedOrientationHandler()
+ .setSecondaryTaskMenuPosition(mSplitBoundsConfig, this,
+ deviceProfile, mTaskIdAttributeContainer[0].getThumbnailView(),
+ taskMenuView);
+ }
+ return showedTaskMenu;
+ }
+
@Nullable
@Override
public RunnableList launchTaskAnimated() {
@@ -250,8 +267,7 @@
@Override
public void setOverlayEnabled(boolean overlayEnabled) {
- super.setOverlayEnabled(overlayEnabled);
- mSnapshotView2.setOverlayEnabled(overlayEnabled);
+ // Intentional no-op to prevent setting smart actions overlay on thumbnails
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index de7ccad..364cf7b 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -33,6 +33,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.popup.QuickstepSystemShortcut;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateListener;
@@ -94,7 +95,7 @@
if (recoveryData.getStagedTaskId() == taskId) {
initiateSplitSelect(
getTaskViewByTaskId(recoveryData.getStagedTaskId()),
- recoveryData.getStagePosition()
+ recoveryData.getStagePosition(), recoveryData.getSource()
);
mActivity.finishSplitSelectRecovery();
}
@@ -104,7 +105,6 @@
@Override
public void reset() {
super.reset();
-
setLayoutRotation(Surface.ROTATION_0, Surface.ROTATION_0);
}
@@ -192,8 +192,9 @@
@Override
public void initiateSplitSelect(TaskView taskView,
- @SplitConfigurationOptions.StagePosition int stagePosition) {
- super.initiateSplitSelect(taskView, stagePosition);
+ @SplitConfigurationOptions.StagePosition int stagePosition,
+ StatsLogManager.EventEnum splitEvent) {
+ super.initiateSplitSelect(taskView, stagePosition, splitEvent);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 62ec0ef..08a17c4 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -32,9 +32,9 @@
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
import com.android.quickstep.util.LayoutUtils;
@@ -53,7 +53,9 @@
HIDDEN_NON_ZERO_ROTATION,
HIDDEN_NO_TASKS,
HIDDEN_NO_RECENTS,
- HIDDEN_SPLIT_SCREEN})
+ HIDDEN_SPLIT_SCREEN,
+ HIDDEN_SPLIT_SELECT_ACTIVE
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface ActionsHiddenFlags { }
@@ -61,6 +63,7 @@
public static final int HIDDEN_NO_TASKS = 1 << 1;
public static final int HIDDEN_NO_RECENTS = 1 << 2;
public static final int HIDDEN_SPLIT_SCREEN = 1 << 3;
+ public static final int HIDDEN_SPLIT_SELECT_ACTIVE = 1 << 4;
@IntDef(flag = true, value = {
DISABLED_SCROLLING,
@@ -79,6 +82,11 @@
private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3;
private static final int INDEX_SHARE_TARGET_ALPHA = 4;
+ public @interface SplitButtonDisabledFlags { }
+
+ public static final int FLAG_IS_NOT_TABLET = 1 << 0;
+ public static final int FLAG_SINGLE_TASK = 1 << 1;
+
private MultiValueAlpha mMultiValueAlpha;
private Button mSplitButton;
@@ -88,6 +96,9 @@
@ActionsDisabledFlags
protected int mDisabledFlags;
+ @SplitButtonDisabledFlags
+ private int mSplitButtonDisabledFlags;
+
@Nullable
protected T mCallbacks;
@@ -182,6 +193,20 @@
LayoutUtils.setViewEnabled(this, isEnabled);
}
+ /**
+ * Updates the proper flags to indicate whether the "Split screen" button should be enabled.
+ *
+ * @param flag The flag to update.
+ * @param enable Whether to enable the disable flag: True will cause view to be disabled.
+ */
+ public void updateSplitButtonFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
+ if (enable) {
+ mSplitButtonDisabledFlags |= flag;
+ } else {
+ mSplitButtonDisabledFlags &= ~flag;
+ }
+ }
+
public AlphaProperty getContentAlpha() {
return mMultiValueAlpha.getProperty(INDEX_CONTENT_ALPHA);
}
@@ -263,12 +288,17 @@
0, 0, 0);
}
- public void setSplitButtonVisible(boolean visible) {
+ /**
+ * Shows/hides the "Split" button based on the status of mHiddenFlags.
+ */
+ public void updateSplitButtonVisibility() {
if (mSplitButton == null) {
return;
}
-
- mSplitButton.setVisibility(visible ? VISIBLE : GONE);
- findViewById(R.id.action_split_space).setVisibility(visible ? VISIBLE : GONE);
+ boolean shouldBeVisible = mSplitButtonDisabledFlags == 0
+ // and neither of these flags are active
+ && (mHiddenFlags & (HIDDEN_SPLIT_SCREEN | HIDDEN_SPLIT_SELECT_ACTIVE)) == 0;
+ mSplitButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
+ findViewById(R.id.action_split_space).setVisibility(shouldBeVisible ? VISIBLE : GONE);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f00e858..28a358e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -35,15 +35,18 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_85;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
-import static com.android.launcher3.statehandlers.DepthController.DEPTH;
+import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@@ -52,10 +55,13 @@
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
+import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
+import static com.android.quickstep.views.OverviewActionsView.FLAG_SINGLE_TASK;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -129,12 +135,14 @@
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.cache.HandlerRunnable;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.popup.QuickstepSystemShortcut;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.uioverrides.states.SplitScreenSelectState;
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
@@ -162,6 +170,8 @@
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.ViewUtils;
+import com.android.quickstep.util.ActiveGestureErrorDetector;
+import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
@@ -409,6 +419,54 @@
private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f;
private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f;
+ private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_START = 67;
+ private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_OFFSET = 16;
+ private static final int SPRING_DISMISS_TRANSLATION_DURATION = 500;
+
+ private static final float INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_OFFSET
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float END_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
+ (float) SPRING_DISMISS_TRANSLATION_DURATION
+ / SplitScreenSelectState.ENTER_DURATION;
+
+ private static final int OVERVIEW_TO_SPLIT_ICON_FADE_START = 0;
+ private static final int OVERVIEW_TO_SPLIT_ICON_FADE_END = 83;
+ private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START = 167;
+ private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END = 250;
+ private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START = 217;
+ private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END = 300;
+ private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START = 167;
+ private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END = 500;
+
+ private static final float OVERVIEW_TO_SPLIT_ICON_FADE_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_ICON_FADE_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_ICON_FADE_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_ICON_FADE_END
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START
+ / SplitScreenSelectState.ENTER_DURATION;
+ private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END_OFFSET =
+ (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END
+ / SplitScreenSelectState.ENTER_DURATION;
+
private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
protected final RecentsOrientedState mOrientationState;
@@ -1233,6 +1291,8 @@
@Override
protected void onPageEndTransition() {
super.onPageEndTransition();
+ ActiveGestureLog.INSTANCE.addLog(
+ "onPageEndTransition: current page index updated", mCurrentPage);
if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
}
@@ -1423,6 +1483,12 @@
updateGridProperties();
}
+ @Override
+ protected void onScrollerAnimationAborted() {
+ ActiveGestureLog.INSTANCE.addLog("scroller animation aborted",
+ ActiveGestureErrorDetector.GestureEvent.SCROLLER_ANIMATION_ABORTED);
+ }
+
protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
@@ -2794,11 +2860,11 @@
RectF startingTaskRect = new RectF();
if (mSplitHiddenTaskView != null) {
- // Split staging is initiated, hide the original TaskView thumbnail.
- // Toggled back on in resetFromSplitSelectionState().
+ // Split staging is initiated
mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE);
- anim.addFloat(mSplitHiddenTaskView, TaskView.ICON_ALPHA, 1, 0,
- clampToProgress(LINEAR, 0, 0.167f));
+ anim.setViewAlpha(mSplitHiddenTaskView.getIconView(), 0, clampToProgress(LINEAR,
+ OVERVIEW_TO_SPLIT_ICON_FADE_START_OFFSET,
+ OVERVIEW_TO_SPLIT_ICON_FADE_END_OFFSET));
mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
mSplitHiddenTaskView.getThumbnail(),
mSplitHiddenTaskView.getThumbnail().getThumbnail(),
@@ -2815,9 +2881,19 @@
false /* fadeWithThumbnail */, true /* isStagedTask */);
}
+ // SplitInstructionsView: animate in
mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
mSplitInstructionsView.setAlpha(0);
- anim.addFloat(mSplitInstructionsView, SplitInstructionsView.ALPHA_FLOAT, 0, 1, ACCEL);
+ anim.setViewAlpha(mSplitInstructionsView, 1, clampToProgress(LINEAR,
+ OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START_OFFSET,
+ OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END_OFFSET));
+ anim.setViewAlpha(mSplitInstructionsView.getTextView(), 1, clampToProgress(LINEAR,
+ OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START_OFFSET,
+ OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END_OFFSET));
+ anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1,
+ clampToProgress(EMPHASIZED_DECELERATE,
+ OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START_OFFSET,
+ OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END_OFFSET));
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
@@ -2844,17 +2920,16 @@
* @param dismissingForSplitSelection task dismiss animation is used for entering split
* selection state from app icon
*/
- public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView,
+ public void createTaskDismissAnimation(PendingAnimation anim, TaskView dismissedTaskView,
boolean animateTaskView, boolean shouldRemoveTask, long duration,
boolean dismissingForSplitSelection) {
if (mPendingAnimation != null) {
mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
}
- PendingAnimation anim = new PendingAnimation(duration);
int count = getPageCount();
if (count == 0) {
- return anim;
+ return;
}
boolean showAsGrid = showAsGrid();
@@ -3099,11 +3174,33 @@
// Animate task with index >= dismissed index and in the same row as the
// dismissed index or next focused index. Offset successive task dismissal
// durations for a staggered effect.
- float animationStartProgress = Utilities.boundToRange(
- INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- * ++distanceFromDismissedTask, 0f,
- dismissTranslationInterpolationEnd);
+ distanceFromDismissedTask++;
+ boolean isStagingFocusedTask =
+ isFocusedTaskDismissed && nextFocusedTaskView == null;
+ int staggerColumn = isStagingFocusedTask
+ ? (int) Math.ceil(distanceFromDismissedTask / 2f)
+ : distanceFromDismissedTask;
+ // Set timings based on if user is initiating splitscreen on the focused task,
+ // or splitting/dismissing some other task.
+ float animationStartProgress = isStagingFocusedTask
+ ? Utilities.boundToRange(
+ INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ * staggerColumn, 0f, dismissTranslationInterpolationEnd)
+ : Utilities.boundToRange(
+ INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ * staggerColumn, 0f, dismissTranslationInterpolationEnd);
+ float animationEndProgress = isStagingFocusedTask
+ ? Utilities.boundToRange(
+ INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ + END_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ * staggerColumn,
+ 0f, dismissTranslationInterpolationEnd)
+ : dismissTranslationInterpolationEnd;
+ Interpolator dismissInterpolator = isStagingFocusedTask ? OVERSHOOT_0_85 : LINEAR;
+
if (taskView == nextFocusedTaskView) {
// Enlarge the task to be focused next, and translate into focus position.
float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
@@ -3126,7 +3223,7 @@
} else {
float primaryTranslation =
nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
- if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
+ if (isStagingFocusedTask) {
// Moves less if focused task is not in scroll position.
int focusedTaskScroll = getScrollForPage(dismissedIndex);
int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
@@ -3142,8 +3239,8 @@
anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(),
mIsRtl ? primaryTranslation : -primaryTranslation,
- clampToProgress(LINEAR, animationStartProgress,
- dismissTranslationInterpolationEnd));
+ clampToProgress(dismissInterpolator, animationStartProgress,
+ animationEndProgress));
}
}
}
@@ -3375,7 +3472,6 @@
mPendingAnimation = null;
}
});
- return anim;
}
/**
@@ -3387,11 +3483,11 @@
private void updateCurrentTaskActionsVisibility() {
boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
- if (isCurrentSplit) {
- return;
- }
- mActionsView.setSplitButtonVisible(
- mActivity.getDeviceProfile().isTablet && getTaskViewCount() > 1);
+ mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
+ mActionsView.updateSplitButtonFlags(FLAG_IS_NOT_TABLET,
+ !mActivity.getDeviceProfile().isTablet);
+ mActionsView.updateSplitButtonFlags(FLAG_SINGLE_TASK, getTaskViewCount() <= 1);
+ mActionsView.updateSplitButtonVisibility();
}
/**
@@ -3543,8 +3639,10 @@
}
public void dismissTask(TaskView taskView, boolean animateTaskView, boolean removeTask) {
- runDismissAnimation(createTaskDismissAnimation(taskView, animateTaskView, removeTask,
- DISMISS_TASK_DURATION, false /* dismissingForSplitSelection*/));
+ PendingAnimation pa = new PendingAnimation(DISMISS_TASK_DURATION);
+ createTaskDismissAnimation(pa, taskView, animateTaskView, removeTask, DISMISS_TASK_DURATION,
+ false /* dismissingForSplitSelection*/);
+ runDismissAnimation(pa);
}
@SuppressWarnings("unused")
@@ -4053,16 +4151,21 @@
}
}
+ /**
+ * Primarily used by overview actions to initiate split from focused task, logs the source
+ * of split invocation as such.
+ */
public void initiateSplitSelect(TaskView taskView) {
int defaultSplitPosition = mOrientationHandler
.getDefaultSplitPosition(mActivity.getDeviceProfile());
- initiateSplitSelect(taskView, defaultSplitPosition);
+ initiateSplitSelect(taskView, defaultSplitPosition, LAUNCHER_OVERVIEW_ACTIONS_SPLIT);
}
- public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition) {
+ public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition,
+ StatsLogManager.EventEnum splitEvent) {
mSplitHiddenTaskView = taskView;
mSplitSelectStateController.setInitialTaskSelect(taskView.getTask().key.id,
- stagePosition);
+ stagePosition, splitEvent, taskView.getItemInfo());
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
@@ -4073,17 +4176,21 @@
public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
mSplitSelectSource = splitSelectSource;
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
- splitSelectSource.position.stagePosition, splitSelectSource.user);
+ splitSelectSource.position.stagePosition, splitSelectSource.mItemInfo,
+ splitSelectSource.splitEvent);
}
- public PendingAnimation createSplitSelectInitAnimation(int duration) {
+ /**
+ * Modifies a PendingAnimation with the animations for entering split staging
+ */
+ public void createSplitSelectInitAnimation(PendingAnimation builder, int duration) {
if (mSplitHiddenTaskView != null) {
- return createTaskDismissAnimation(mSplitHiddenTaskView, true, false, duration,
+ // Splitting from Overview
+ createTaskDismissAnimation(builder, mSplitHiddenTaskView, true, false, duration,
true /* dismissingForSplitSelection*/);
} else {
- PendingAnimation anim = new PendingAnimation(duration);
- createInitialSplitSelectAnimation(anim);
- return anim;
+ // Splitting from Home
+ createInitialSplitSelectAnimation(builder);
}
}
@@ -4195,8 +4302,6 @@
resetTaskVisuals();
mSplitHiddenTaskViewIndex = -1;
if (mSplitHiddenTaskView != null) {
- // Toggle thumbnail visibility back on (turned off in
- // createInitialSplitSelectAnimation()).
mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE);
mSplitHiddenTaskView = null;
}
@@ -4413,7 +4518,7 @@
DepthController depthController = getDepthController();
if (depthController != null) {
- ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController, DEPTH,
+ ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController, STATE_DEPTH,
BACKGROUND_APP.getDepth(mActivity));
anim.play(depthAnimator);
}
diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
index 7d94505..27ec01a 100644
--- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
@@ -16,7 +16,7 @@
package com.android.quickstep.views;
-import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import android.content.Context;
import android.util.AttributeSet;
@@ -25,6 +25,7 @@
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
@@ -40,18 +41,18 @@
*/
public class SplitInstructionsView extends FrameLayout {
private final StatefulActivity mLauncher;
+ private AppCompatTextView mTextView;
- public static final FloatProperty<SplitInstructionsView> ALPHA_FLOAT =
- new FloatProperty<SplitInstructionsView>("SplitInstructionsAlpha") {
+ public static final FloatProperty<SplitInstructionsView> UNFOLD =
+ new FloatProperty<SplitInstructionsView>("SplitInstructionsUnfold") {
@Override
public void setValue(SplitInstructionsView splitInstructionsView, float v) {
- splitInstructionsView.setVisibility(v != 0 ? VISIBLE : GONE);
- splitInstructionsView.setAlpha(v);
+ splitInstructionsView.setScaleY(v);
}
@Override
public Float get(SplitInstructionsView splitInstructionsView) {
- return splitInstructionsView.getAlpha();
+ return splitInstructionsView.getScaleY();
}
};
@@ -77,6 +78,14 @@
false
);
+ splitInstructionsView.mTextView = splitInstructionsView.findViewById(
+ R.id.split_instructions_text);
+
+ // Since textview overlays base view, and we sometimes manipulate the alpha of each
+ // simultaneously, force overlapping rendering to false prevents redrawing of pixels,
+ // improving performance at the cost of some accuracy.
+ splitInstructionsView.forceHasOverlappingRendering(false);
+
dragLayer.addView(splitInstructionsView);
return splitInstructionsView;
}
@@ -120,4 +129,8 @@
return 0;
}
}
+
+ public AppCompatTextView getTextView() {
+ return mTextView;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
index 28080d4..08004dc 100644
--- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
@@ -22,7 +22,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.FloatProperty;
import android.util.TypedValue;
import android.widget.FrameLayout;
@@ -33,20 +32,6 @@
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Rect mTempRect = new Rect();
- public static final FloatProperty<SplitPlaceholderView> ALPHA_FLOAT =
- new FloatProperty<SplitPlaceholderView>("SplitViewAlpha") {
- @Override
- public void setValue(SplitPlaceholderView splitPlaceholderView, float v) {
- splitPlaceholderView.setVisibility(v != 0 ? VISIBLE : GONE);
- splitPlaceholderView.setAlpha(v);
- }
-
- @Override
- public Float get(SplitPlaceholderView splitPlaceholderView) {
- return splitPlaceholderView.getAlpha();
- }
- };
-
@Nullable
private IconView mIconView;
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index c1711d1..6815745 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,8 +16,6 @@
package com.android.quickstep.views;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
import android.animation.Animator;
@@ -156,23 +154,6 @@
mTaskContainer.getThumbnailView(), overscrollShift, deviceProfile));
setY(pagedOrientationHandler.getTaskMenuY(
adjustedY, mTaskContainer.getThumbnailView(), overscrollShift));
-
- // TODO(b/193432925) temporary menu placement for split screen task menus
- TaskIdAttributeContainer[] taskIdAttributeContainers =
- mTaskView.getTaskIdAttributeContainers();
- if (taskIdAttributeContainers[0].getStagePosition() != STAGE_POSITION_UNDEFINED) {
- if (mTaskContainer.getStagePosition() != STAGE_POSITION_BOTTOM_OR_RIGHT) {
- return;
- }
- Rect r = new Rect();
- mTaskContainer.getThumbnailView().getBoundsOnScreen(r);
- if (deviceProfile.isLandscape) {
- setX(r.left);
- } else {
- setY(r.top);
-
- }
- }
}
public void onRotationChanged() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index f4b3d98..d7a8599 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -16,11 +16,11 @@
package com.android.quickstep.views;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index a84ea63..ee8489d 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -32,6 +32,7 @@
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
+import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -48,6 +49,7 @@
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Handler;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
@@ -99,7 +101,6 @@
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -323,19 +324,6 @@
}
};
- public static final FloatProperty<TaskView> ICON_ALPHA =
- new FloatProperty<TaskView>("iconAlpha") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.mIconView.setAlpha(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mIconView.getAlpha();
- }
- };
-
@Nullable
protected Task mTask;
protected TaskThumbnailView mSnapshotView;
@@ -659,12 +647,12 @@
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
// Indicate success once the system has indicated that the transition has started
- ActivityOptions opts = ActivityOptionsCompat.makeCustomAnimation(
- getContext(), 0, 0, () -> callback.accept(true), MAIN_EXECUTOR.getHandler());
+ ActivityOptions opts = makeCustomAnimation(getContext(), 0, 0,
+ () -> callback.accept(true), MAIN_EXECUTOR.getHandler());
opts.setLaunchDisplayId(
getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
if (freezeTaskList) {
- ActivityOptionsCompat.setFreezeRecentTasksList(opts);
+ opts.setFreezeRecentTasksReordering();
}
// TODO(b/202826469): Replace setSplashScreenStyle with setDisableStartingWindow.
opts.setSplashScreenStyle(mSnapshotView.shouldShowSplashView()
@@ -687,14 +675,29 @@
}
/**
+ * Returns ActivityOptions for overriding task transition animation.
+ */
+ private ActivityOptions makeCustomAnimation(Context context, int enterResId,
+ int exitResId, final Runnable callback, final Handler callbackHandler) {
+ return ActivityOptions.makeCustomTaskAnimation(context, enterResId, exitResId,
+ callbackHandler,
+ elapsedRealTime -> {
+ if (callback != null) {
+ callbackHandler.post(callback);
+ }
+ }, null /* finishedListener */);
+ }
+
+ /**
* Launch of the current task (both live and inactive tasks) with an animation.
*/
- public void launchTasks() {
+ public RunnableList launchTasks() {
RecentsView recentsView = getRecentsView();
RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
+ RunnableList runnableList = new RunnableList();
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask() && remoteTargetHandles != null) {
if (!mIsClickableAsLiveTile) {
- return;
+ return runnableList;
}
mIsClickableAsLiveTile = false;
@@ -721,7 +724,7 @@
// here, try to launch the task as a non live tile task.
launchTaskAnimated();
mIsClickableAsLiveTile = true;
- return;
+ return runnableList;
}
AnimatorSet anim = new AnimatorSet();
@@ -746,13 +749,24 @@
launchTaskAnimated();
}
mIsClickableAsLiveTile = true;
+ runEndCallback();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ runEndCallback();
+ }
+
+ private void runEndCallback() {
+ runnableList.executeAllAndDestroy();
}
});
anim.start();
recentsView.onTaskLaunchedInLiveTileMode();
} else {
- launchTaskAnimated();
+ return launchTaskAnimated();
}
+ return runnableList;
}
/**
@@ -1483,7 +1497,8 @@
}
public void initiateSplitSelect(SplitPositionOption splitPositionOption) {
- getRecentsView().initiateSplitSelect(this, splitPositionOption.stagePosition);
+ getRecentsView().initiateSplitSelect(this, splitPositionOption.stagePosition,
+ getLogEventForPosition(splitPositionOption.stagePosition));
}
/**
diff --git a/quickstep/tests/src/com/android/quickstep/DeviceProfileTest.kt b/quickstep/tests/src/com/android/quickstep/DeviceProfileTest.kt
deleted file mode 100644
index 9977207..0000000
--- a/quickstep/tests/src/com/android/quickstep/DeviceProfileTest.kt
+++ /dev/null
@@ -1,1479 +0,0 @@
-/*
- * Copyright (C) 2022 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.quickstep
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.launcher3.DeviceProfileBaseTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Tests for DeviceProfile.
- */
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class DeviceProfileTest : DeviceProfileBaseTest() {
-
- @Test
- fun phonePortrait3Button() {
- initializeVarsForPhone(isGestureMode = false)
- val dp = newDP()
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1080.0px (411.42856dp)\n" +
- "\theightPx: 2400.0px (914.2857dp)\n" +
- "\tavailableWidthPx: 1080.0px (411.42856dp)\n" +
- "\tavailableHeightPx: 2156.0px (821.3333dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 118.0px (44.95238dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 126.0px (48.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(80.0, 104.0)dp\n" +
- "\tcellWidthPx: 210.0px (80.0dp)\n" +
- "\tcellHeightPx: 272.0px (103.61905dp)\n" +
- "\tgetCellSize().x: 210.0px (80.0dp)\n" +
- "\tgetCellSize().y: 272.0px (103.61905dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.top: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.right: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 28.0px (10.666667dp)\n" +
- "\ticonSizePx: 157.0px (59.809525dp)\n" +
- "\ticonTextSizePx: 36.0px (13.714286dp)\n" +
- "\ticonDrawablePaddingPx: 17.0px (6.4761906dp)\n" +
- "\tfolderCellWidthPx: 210.0px (80.0dp)\n" +
- "\tfolderCellHeightPx: 247.0px (94.09524dp)\n" +
- "\tfolderChildIconSizePx: 158.0px (60.190475dp)\n" +
- "\tfolderChildTextSizePx: 37.0px (14.095238dp)\n" +
- "\tfolderChildDrawablePaddingPx: 13.0px (4.952381dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 42.0px (16.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 146.0px (55.61905dp)\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsIconSizePx: 157.0px (59.809525dp)\n" +
- "\tallAppsIconTextSizePx: 37.0px (14.095238dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tallAppsCellHeightPx: 314.0px (119.61905dp)\n" +
- "\tallAppsCellWidthPx: 210.0px (80.0dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 4\n" +
- "\tallAppsLeftRightPadding: 57.0px (21.714285dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 511.0px (194.66667dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 177.0px (67.42857dp)\n" +
- "\thotseatBarBottomSpacePx: 147.0px (56.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 74.0px (28.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 334.0px (127.2381dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 83.0px (31.619047dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 83.0px (31.619047dp)\n" +
- "\tnumShownHotseatIcons: 4\n" +
- "\thotseatBorderSpace: 95.0px (36.190475dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 913.0px (347.8095dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 57.0px (21.714285dp)\n" +
- "\tworkspacePadding.left: 29.0px (11.047619dp)\n" +
- "\tworkspacePadding.top: 67.0px (25.52381dp)\n" +
- "\tworkspacePadding.right: 29.0px (11.047619dp)\n" +
- "\tworkspacePadding.bottom: 504.0px (192.0dp)\n" +
- "\ticonScale: 0.9981516px (0.38024822dp)\n" +
- "\tcellScaleToFit : 0.9981516px (0.38024822dp)\n" +
- "\textraSpace: 211.0px (80.38095dp)\n" +
- "\tunscaled extraSpace: 211.39073px (80.5298dp)\n" +
- "\tmaxEmptySpace: 315.0px (120.0dp)\n" +
- "\tworkspaceTopPadding: 95.0px (36.190475dp)\n" +
- "\tworkspaceBottomPadding: 116.0px (44.190475dp)\n" +
- "\toverviewTaskMarginPx: 42.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 168.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 63.0px (24.0dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 42.0px (16.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 84.0px (32.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1689.0px (643.4286dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.81892747px (0.31197238dp)\n" +
- "\tgetCellLayoutHeight(): 1585.0px (603.8095dp)\n" +
- "\tgetCellLayoutWidth(): 1022.0px (389.33334dp)\n")
- }
-
- @Test
- fun phonePortrait() {
- initializeVarsForPhone()
- val dp = newDP()
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1080.0px (411.42856dp)\n" +
- "\theightPx: 2400.0px (914.2857dp)\n" +
- "\tavailableWidthPx: 1080.0px (411.42856dp)\n" +
- "\tavailableHeightPx: 2219.0px (845.3333dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 118.0px (44.95238dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 63.0px (24.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(80.0, 104.0)dp\n" +
- "\tcellWidthPx: 210.0px (80.0dp)\n" +
- "\tcellHeightPx: 272.0px (103.61905dp)\n" +
- "\tgetCellSize().x: 210.0px (80.0dp)\n" +
- "\tgetCellSize().y: 272.0px (103.61905dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.top: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.right: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 28.0px (10.666667dp)\n" +
- "\ticonSizePx: 157.0px (59.809525dp)\n" +
- "\ticonTextSizePx: 36.0px (13.714286dp)\n" +
- "\ticonDrawablePaddingPx: 17.0px (6.4761906dp)\n" +
- "\tfolderCellWidthPx: 210.0px (80.0dp)\n" +
- "\tfolderCellHeightPx: 247.0px (94.09524dp)\n" +
- "\tfolderChildIconSizePx: 158.0px (60.190475dp)\n" +
- "\tfolderChildTextSizePx: 37.0px (14.095238dp)\n" +
- "\tfolderChildDrawablePaddingPx: 13.0px (4.952381dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 42.0px (16.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 146.0px (55.61905dp)\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsIconSizePx: 157.0px (59.809525dp)\n" +
- "\tallAppsIconTextSizePx: 37.0px (14.095238dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tallAppsCellHeightPx: 314.0px (119.61905dp)\n" +
- "\tallAppsCellWidthPx: 210.0px (80.0dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 4\n" +
- "\tallAppsLeftRightPadding: 57.0px (21.714285dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 511.0px (194.66667dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 177.0px (67.42857dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 95.0px (36.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 334.0px (127.2381dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 83.0px (31.619047dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 83.0px (31.619047dp)\n" +
- "\tnumShownHotseatIcons: 4\n" +
- "\thotseatBorderSpace: 95.0px (36.190475dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 913.0px (347.8095dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 57.0px (21.714285dp)\n" +
- "\tworkspacePadding.left: 29.0px (11.047619dp)\n" +
- "\tworkspacePadding.top: 67.0px (25.52381dp)\n" +
- "\tworkspacePadding.right: 29.0px (11.047619dp)\n" +
- "\tworkspacePadding.bottom: 567.0px (216.0dp)\n" +
- "\ticonScale: 0.9981516px (0.38024822dp)\n" +
- "\tcellScaleToFit : 0.9981516px (0.38024822dp)\n" +
- "\textraSpace: 211.0px (80.38095dp)\n" +
- "\tunscaled extraSpace: 211.39073px (80.5298dp)\n" +
- "\tmaxEmptySpace: 315.0px (120.0dp)\n" +
- "\tworkspaceTopPadding: 95.0px (36.190475dp)\n" +
- "\tworkspaceBottomPadding: 116.0px (44.190475dp)\n" +
- "\toverviewTaskMarginPx: 42.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 168.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 63.0px (24.0dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 42.0px (16.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 84.0px (32.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1689.0px (643.4286dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.81892747px (0.31197238dp)\n" +
- "\tgetCellLayoutHeight(): 1585.0px (603.8095dp)\n" +
- "\tgetCellLayoutWidth(): 1022.0px (389.33334dp)\n")
- }
-
- @Test
- fun tabletLandscape3Button() {
- initializeVarsForTablet(isLandscape = true, isGestureMode = false)
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2560.0px (1280.0dp)\n" +
- "\theightPx: 1600.0px (800.0dp)\n" +
- "\tavailableWidthPx: 2560.0px (1280.0dp)\n" +
- "\tavailableHeightPx: 1496.0px (748.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(120.0, 104.0)dp\n" +
- "\tcellWidthPx: 240.0px (120.0dp)\n" +
- "\tcellHeightPx: 208.0px (104.0dp)\n" +
- "\tgetCellSize().x: 240.0px (120.0dp)\n" +
- "\tgetCellSize().y: 208.0px (104.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.top: 32.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 59.0px (29.5dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tfolderCellWidthPx: 240.0px (120.0dp)\n" +
- "\tfolderCellHeightPx: 208.0px (104.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 16.0px (8.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 32.0px (16.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 104.0px (52.0dp)\n" +
- "\tallAppsShiftRange: 1496.0px (748.0dp)\n" +
- "\tallAppsTopPadding: 104.0px (52.0dp)\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 284.0px (142.0dp)\n" +
- "\tallAppsCellWidthPx: 252.0px (126.0dp)\n" +
- "\tallAppsBorderSpacePxX: 32.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 64.0px (32.0dp)\n" +
- "\tallAppsLeftRightMargin: 380.0px (190.0dp)\n" +
- "\thotseatBarSizePx: 200.0px (100.0dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 80.0px (40.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 705.0px (352.5dp)\n" +
- "\thotseatQsbSpace: 64.0px (32.0dp)\n" +
- "\thotseatQsbHeight: 126.0px (63.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: -8.0px (-4.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 73.0px (36.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 954.0px (477.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 705.0px (352.5dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 36.0px (18.0dp)\n" +
- "\tisQsbInline: true\n" +
- "\thotseatQsbWidth: 619.0px (309.5dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 120.0px (60.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)\n" +
- "\tworkspacePadding.left: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.bottom: 237.0px (118.5dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 104.0px (52.0dp)\n" +
- "\tunscaled extraSpace: 104.0px (52.0dp)\n" +
- "\tmaxEmptySpace: 200.0px (100.0dp)\n" +
- "\tworkspaceTopPadding: 32.0px (16.0dp)\n" +
- "\tworkspaceBottomPadding: 72.0px (36.0dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 96.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 88.0px (44.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 88.0px (44.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 128.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 40.0px (20.0dp)\n" +
- "\toverviewActionsHeight: 96.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 72.0px (36.0dp)\n" +
- "\toverviewPageSpacing: 88.0px (44.0dp)\n" +
- "\toverviewRowSpacing: 72.0px (36.0dp)\n" +
- "\toverviewGridSideMargin: 128.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 64.0px (32.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76250994px (0.38125497dp)\n" +
- "\tgetCellLayoutHeight(): 1259.0px (629.5dp)\n" +
- "\tgetCellLayoutWidth(): 2198.0px (1099.0dp)\n")
- }
-
- @Test
- fun tabletLandscape() {
- initializeVarsForTablet(isLandscape = true)
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2560.0px (1280.0dp)\n" +
- "\theightPx: 1600.0px (800.0dp)\n" +
- "\tavailableWidthPx: 2560.0px (1280.0dp)\n" +
- "\tavailableHeightPx: 1496.0px (748.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(120.0, 104.0)dp\n" +
- "\tcellWidthPx: 240.0px (120.0dp)\n" +
- "\tcellHeightPx: 208.0px (104.0dp)\n" +
- "\tgetCellSize().x: 240.0px (120.0dp)\n" +
- "\tgetCellSize().y: 208.0px (104.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.top: 32.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 59.0px (29.5dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tfolderCellWidthPx: 240.0px (120.0dp)\n" +
- "\tfolderCellHeightPx: 208.0px (104.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 16.0px (8.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 32.0px (16.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 104.0px (52.0dp)\n" +
- "\tallAppsShiftRange: 1496.0px (748.0dp)\n" +
- "\tallAppsTopPadding: 104.0px (52.0dp)\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 284.0px (142.0dp)\n" +
- "\tallAppsCellWidthPx: 252.0px (126.0dp)\n" +
- "\tallAppsBorderSpacePxX: 32.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 64.0px (32.0dp)\n" +
- "\tallAppsLeftRightMargin: 380.0px (190.0dp)\n" +
- "\thotseatBarSizePx: 200.0px (100.0dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 80.0px (40.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 64.0px (32.0dp)\n" +
- "\thotseatQsbHeight: 126.0px (63.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: -8.0px (-4.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 73.0px (36.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 1040.0px (520.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 300.0px (150.0dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 100.0px (50.0dp)\n" +
- "\tisQsbInline: true\n" +
- "\thotseatQsbWidth: 640.0px (320.0dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 120.0px (60.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)\n" +
- "\tworkspacePadding.left: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.bottom: 237.0px (118.5dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 104.0px (52.0dp)\n" +
- "\tunscaled extraSpace: 104.0px (52.0dp)\n" +
- "\tmaxEmptySpace: 200.0px (100.0dp)\n" +
- "\tworkspaceTopPadding: 32.0px (16.0dp)\n" +
- "\tworkspaceBottomPadding: 72.0px (36.0dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 96.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 88.0px (44.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 88.0px (44.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 128.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 40.0px (20.0dp)\n" +
- "\toverviewActionsHeight: 96.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 72.0px (36.0dp)\n" +
- "\toverviewPageSpacing: 88.0px (44.0dp)\n" +
- "\toverviewRowSpacing: 72.0px (36.0dp)\n" +
- "\toverviewGridSideMargin: 128.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 64.0px (32.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76250994px (0.38125497dp)\n" +
- "\tgetCellLayoutHeight(): 1259.0px (629.5dp)\n" +
- "\tgetCellLayoutWidth(): 2198.0px (1099.0dp)\n")
- }
-
- @Test
- fun tabletPortrait3Button() {
- initializeVarsForTablet(isGestureMode = false)
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1600.0px (800.0dp)\n" +
- "\theightPx: 2560.0px (1280.0dp)\n" +
- "\tavailableWidthPx: 1600.0px (800.0dp)\n" +
- "\tavailableHeightPx: 2456.0px (1228.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(102.0, 120.0)dp\n" +
- "\tcellWidthPx: 204.0px (102.0dp)\n" +
- "\tcellHeightPx: 240.0px (120.0dp)\n" +
- "\tgetCellSize().x: 204.0px (102.0dp)\n" +
- "\tgetCellSize().y: 240.0px (120.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 72.0px (36.0dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tfolderCellWidthPx: 240.0px (120.0dp)\n" +
- "\tfolderCellHeightPx: 208.0px (104.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 16.0px (8.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 32.0px (16.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 704.0px (352.0dp)\n" +
- "\tallAppsShiftRange: 1936.0px (968.0dp)\n" +
- "\tallAppsTopPadding: 624.0px (312.0dp)\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 316.0px (158.0dp)\n" +
- "\tallAppsCellWidthPx: 192.0px (96.0dp)\n" +
- "\tallAppsBorderSpacePxX: 16.0px (8.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 56.0px (28.0dp)\n" +
- "\tallAppsLeftRightMargin: 128.0px (64.0dp)\n" +
- "\thotseatBarSizePx: 358.0px (179.0dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 72.0px (36.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 558.0px (279.0dp)\n" +
- "\thotseatQsbSpace: 64.0px (32.0dp)\n" +
- "\thotseatQsbHeight: 126.0px (63.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 158.0px (79.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 150.0px (75.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 558.0px (279.0dp)\n" +
- "\tnumShownHotseatIcons: 5\n" +
- "\thotseatBorderSpace: 73.0px (36.5dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1300.0px (650.0dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 120.0px (60.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)\n" +
- "\tworkspacePadding.left: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.top: 87.0px (43.5dp)\n" +
- "\tworkspacePadding.right: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.bottom: 513.0px (256.5dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 362.0px (181.0dp)\n" +
- "\tunscaled extraSpace: 362.0px (181.0dp)\n" +
- "\tmaxEmptySpace: 19998.0px (9999.0dp)\n" +
- "\tworkspaceTopPadding: 159.0px (79.5dp)\n" +
- "\tworkspaceBottomPadding: 203.0px (101.5dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 96.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 88.0px (44.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 88.0px (44.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 128.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 48.0px (24.0dp)\n" +
- "\toverviewActionsHeight: 96.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 72.0px (36.0dp)\n" +
- "\toverviewPageSpacing: 88.0px (44.0dp)\n" +
- "\toverviewRowSpacing: 72.0px (36.0dp)\n" +
- "\toverviewGridSideMargin: 128.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 220.0px (110.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 96.0px (48.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1986.0px (993.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76616377px (0.38308188dp)\n" +
- "\tgetCellLayoutHeight(): 1856.0px (928.0dp)\n" +
- "\tgetCellLayoutWidth(): 1528.0px (764.0dp)\n")
- }
-
- @Test
- fun tabletPortrait() {
- initializeVarsForTablet()
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1600.0px (800.0dp)\n" +
- "\theightPx: 2560.0px (1280.0dp)\n" +
- "\tavailableWidthPx: 1600.0px (800.0dp)\n" +
- "\tavailableHeightPx: 2456.0px (1228.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(102.0, 120.0)dp\n" +
- "\tcellWidthPx: 204.0px (102.0dp)\n" +
- "\tcellHeightPx: 240.0px (120.0dp)\n" +
- "\tgetCellSize().x: 204.0px (102.0dp)\n" +
- "\tgetCellSize().y: 240.0px (120.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 72.0px (36.0dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tfolderCellWidthPx: 240.0px (120.0dp)\n" +
- "\tfolderCellHeightPx: 208.0px (104.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 16.0px (8.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 32.0px (16.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 704.0px (352.0dp)\n" +
- "\tallAppsShiftRange: 1936.0px (968.0dp)\n" +
- "\tallAppsTopPadding: 624.0px (312.0dp)\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 316.0px (158.0dp)\n" +
- "\tallAppsCellWidthPx: 192.0px (96.0dp)\n" +
- "\tallAppsBorderSpacePxX: 16.0px (8.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 56.0px (28.0dp)\n" +
- "\tallAppsLeftRightMargin: 128.0px (64.0dp)\n" +
- "\thotseatBarSizePx: 358.0px (179.0dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 72.0px (36.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 64.0px (32.0dp)\n" +
- "\thotseatQsbHeight: 126.0px (63.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 158.0px (79.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 150.0px (75.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 150.0px (75.0dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 116.0px (58.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1300.0px (650.0dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 120.0px (60.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)\n" +
- "\tworkspacePadding.left: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.top: 87.0px (43.5dp)\n" +
- "\tworkspacePadding.right: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.bottom: 513.0px (256.5dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 362.0px (181.0dp)\n" +
- "\tunscaled extraSpace: 362.0px (181.0dp)\n" +
- "\tmaxEmptySpace: 19998.0px (9999.0dp)\n" +
- "\tworkspaceTopPadding: 159.0px (79.5dp)\n" +
- "\tworkspaceBottomPadding: 203.0px (101.5dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 96.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 88.0px (44.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 88.0px (44.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 128.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 48.0px (24.0dp)\n" +
- "\toverviewActionsHeight: 96.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 72.0px (36.0dp)\n" +
- "\toverviewPageSpacing: 88.0px (44.0dp)\n" +
- "\toverviewRowSpacing: 72.0px (36.0dp)\n" +
- "\toverviewGridSideMargin: 128.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 220.0px (110.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 96.0px (48.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1986.0px (993.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76616377px (0.38308188dp)\n" +
- "\tgetCellLayoutHeight(): 1856.0px (928.0dp)\n" +
- "\tgetCellLayoutWidth(): 1528.0px (764.0dp)\n")
- }
-
- @Test
- fun twoPanelLandscape3Button() {
- initializeVarsForTwoPanel(isLandscape = true, isGestureMode = false)
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2208.0px (841.1429dp)\n" +
- "\theightPx: 1840.0px (700.9524dp)\n" +
- "\tavailableWidthPx: 2208.0px (841.1429dp)\n" +
- "\tavailableHeightPx: 1730.0px (659.0476dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 110.0px (41.904762dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(80.0, 102.0)dp\n" +
- "\tcellWidthPx: 210.0px (80.0dp)\n" +
- "\tcellHeightPx: 267.0px (101.71429dp)\n" +
- "\tgetCellSize().x: 210.0px (80.0dp)\n" +
- "\tgetCellSize().y: 267.0px (101.71429dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 52.0px (19.809525dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 52.0px (19.809525dp)\n" +
- "\tcellLayoutPaddingPx.left: 26.0px (9.904762dp)\n" +
- "\tcellLayoutPaddingPx.top: 18.0px (6.857143dp)\n" +
- "\tcellLayoutPaddingPx.right: 26.0px (9.904762dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 26.0px (9.904762dp)\n" +
- "\ticonSizePx: 157.0px (59.809525dp)\n" +
- "\ticonTextSizePx: 36.0px (13.714286dp)\n" +
- "\ticonDrawablePaddingPx: 17.0px (6.4761906dp)\n" +
- "\tfolderCellWidthPx: 210.0px (80.0dp)\n" +
- "\tfolderCellHeightPx: 247.0px (94.09524dp)\n" +
- "\tfolderChildIconSizePx: 158.0px (60.190475dp)\n" +
- "\tfolderChildTextSizePx: 37.0px (14.095238dp)\n" +
- "\tfolderChildDrawablePaddingPx: 13.0px (4.952381dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 42.0px (16.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsShiftRange: 1730.0px (659.0476dp)\n" +
- "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsIconSizePx: 157.0px (59.809525dp)\n" +
- "\tallAppsIconTextSizePx: 37.0px (14.095238dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 210.0px (80.0dp)\n" +
- "\tallAppsBorderSpacePxX: 52.0px (19.809525dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 137.0px (52.190475dp)\n" +
- "\tallAppsLeftRightMargin: 207.0px (78.85714dp)\n" +
- "\thotseatBarSizePx: 417.0px (158.85715dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 177.0px (67.42857dp)\n" +
- "\thotseatBarBottomSpacePx: 53.0px (20.190475dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 744.0px (283.42856dp)\n" +
- "\thotseatQsbSpace: 74.0px (28.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 197.0px (75.04762dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 43.0px (16.380953dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 106.0px (40.38095dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 744.0px (283.42856dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 83.0px (31.619047dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1467.0px (558.8571dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 158.0px (60.190475dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 79.0px (30.095238dp)\n" +
- "\tworkspacePadding.left: 53.0px (20.190475dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 53.0px (20.190475dp)\n" +
- "\tworkspacePadding.bottom: 461.0px (175.61905dp)\n" +
- "\ticonScale: 0.99864316px (0.3804355dp)\n" +
- "\tcellScaleToFit : 0.99864316px (0.3804355dp)\n" +
- "\textraSpace: 57.0px (21.714285dp)\n" +
- "\tunscaled extraSpace: 57.077446px (21.74379dp)\n" +
- "\tmaxEmptySpace: 131.0px (49.904762dp)\n" +
- "\tworkspaceTopPadding: 18.0px (6.857143dp)\n" +
- "\tworkspaceBottomPadding: 39.0px (14.857142dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 158.0px (60.190475dp)\n" +
- "\toverviewActionsTopMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewRowSpacing: 74.0px (28.190475dp)\n" +
- "\toverviewGridSideMargin: 168.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1307.0px (497.90475dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.79432625px (0.30260047dp)\n" +
- "\tgetCellLayoutHeight(): 1269.0px (483.42856dp)\n" +
- "\tgetCellLayoutWidth(): 1051.0px (400.38095dp)\n")
- }
-
- @Test
- fun twoPanelLandscape() {
- initializeVarsForTwoPanel(isLandscape = true)
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2208.0px (841.1429dp)\n" +
- "\theightPx: 1840.0px (700.9524dp)\n" +
- "\tavailableWidthPx: 2208.0px (841.1429dp)\n" +
- "\tavailableHeightPx: 1730.0px (659.0476dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 110.0px (41.904762dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(80.0, 102.0)dp\n" +
- "\tcellWidthPx: 210.0px (80.0dp)\n" +
- "\tcellHeightPx: 267.0px (101.71429dp)\n" +
- "\tgetCellSize().x: 210.0px (80.0dp)\n" +
- "\tgetCellSize().y: 267.0px (101.71429dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 52.0px (19.809525dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 52.0px (19.809525dp)\n" +
- "\tcellLayoutPaddingPx.left: 26.0px (9.904762dp)\n" +
- "\tcellLayoutPaddingPx.top: 18.0px (6.857143dp)\n" +
- "\tcellLayoutPaddingPx.right: 26.0px (9.904762dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 26.0px (9.904762dp)\n" +
- "\ticonSizePx: 157.0px (59.809525dp)\n" +
- "\ticonTextSizePx: 36.0px (13.714286dp)\n" +
- "\ticonDrawablePaddingPx: 17.0px (6.4761906dp)\n" +
- "\tfolderCellWidthPx: 210.0px (80.0dp)\n" +
- "\tfolderCellHeightPx: 247.0px (94.09524dp)\n" +
- "\tfolderChildIconSizePx: 158.0px (60.190475dp)\n" +
- "\tfolderChildTextSizePx: 37.0px (14.095238dp)\n" +
- "\tfolderChildDrawablePaddingPx: 13.0px (4.952381dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 42.0px (16.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsShiftRange: 1730.0px (659.0476dp)\n" +
- "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsIconSizePx: 157.0px (59.809525dp)\n" +
- "\tallAppsIconTextSizePx: 37.0px (14.095238dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 210.0px (80.0dp)\n" +
- "\tallAppsBorderSpacePxX: 52.0px (19.809525dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 137.0px (52.190475dp)\n" +
- "\tallAppsLeftRightMargin: 207.0px (78.85714dp)\n" +
- "\thotseatBarSizePx: 417.0px (158.85715dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 177.0px (67.42857dp)\n" +
- "\thotseatBarBottomSpacePx: 53.0px (20.190475dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 74.0px (28.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 197.0px (75.04762dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 43.0px (16.380953dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 370.0px (140.95238dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 370.0px (140.95238dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 105.0px (40.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1467.0px (558.8571dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 158.0px (60.190475dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 79.0px (30.095238dp)\n" +
- "\tworkspacePadding.left: 53.0px (20.190475dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 53.0px (20.190475dp)\n" +
- "\tworkspacePadding.bottom: 461.0px (175.61905dp)\n" +
- "\ticonScale: 0.99864316px (0.3804355dp)\n" +
- "\tcellScaleToFit : 0.99864316px (0.3804355dp)\n" +
- "\textraSpace: 57.0px (21.714285dp)\n" +
- "\tunscaled extraSpace: 57.077446px (21.74379dp)\n" +
- "\tmaxEmptySpace: 131.0px (49.904762dp)\n" +
- "\tworkspaceTopPadding: 18.0px (6.857143dp)\n" +
- "\tworkspaceBottomPadding: 39.0px (14.857142dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 158.0px (60.190475dp)\n" +
- "\toverviewActionsTopMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewRowSpacing: 74.0px (28.190475dp)\n" +
- "\toverviewGridSideMargin: 168.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1307.0px (497.90475dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.79432625px (0.30260047dp)\n" +
- "\tgetCellLayoutHeight(): 1269.0px (483.42856dp)\n" +
- "\tgetCellLayoutWidth(): 1051.0px (400.38095dp)\n")
- }
-
- @Test
- fun twoPanelPortrait3Button() {
- initializeVarsForTwoPanel(isGestureMode = false)
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1840.0px (700.9524dp)\n" +
- "\theightPx: 2208.0px (841.1429dp)\n" +
- "\tavailableWidthPx: 1840.0px (700.9524dp)\n" +
- "\tavailableHeightPx: 2098.0px (799.2381dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 110.0px (41.904762dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(68.0, 116.0)dp\n" +
- "\tcellWidthPx: 178.0px (67.809525dp)\n" +
- "\tcellHeightPx: 304.0px (115.809525dp)\n" +
- "\tgetCellSize().x: 178.0px (67.809525dp)\n" +
- "\tgetCellSize().y: 304.0px (115.809525dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 52.0px (19.809525dp)\n" +
- "\tcellLayoutPaddingPx.left: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 21.0px (8.0dp)\n" +
- "\ticonSizePx: 136.0px (51.809525dp)\n" +
- "\ticonTextSizePx: 31.0px (11.809524dp)\n" +
- "\ticonDrawablePaddingPx: 17.0px (6.4761906dp)\n" +
- "\tfolderCellWidthPx: 210.0px (80.0dp)\n" +
- "\tfolderCellHeightPx: 247.0px (94.09524dp)\n" +
- "\tfolderChildIconSizePx: 158.0px (60.190475dp)\n" +
- "\tfolderChildTextSizePx: 37.0px (14.095238dp)\n" +
- "\tfolderChildDrawablePaddingPx: 13.0px (4.952381dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 42.0px (16.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsShiftRange: 2098.0px (799.2381dp)\n" +
- "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsIconSizePx: 136.0px (51.809525dp)\n" +
- "\tallAppsIconTextSizePx: 31.0px (11.809524dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tallAppsCellHeightPx: 345.0px (131.42857dp)\n" +
- "\tallAppsCellWidthPx: 178.0px (67.809525dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 73.0px (27.809525dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 126.0px (48.0dp)\n" +
- "\tallAppsLeftRightMargin: 155.0px (59.04762dp)\n" +
- "\thotseatBarSizePx: 459.0px (174.85715dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 153.0px (58.285713dp)\n" +
- "\thotseatBarBottomSpacePx: 95.0px (36.190475dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 660.0px (251.42857dp)\n" +
- "\thotseatQsbSpace: 95.0px (36.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 219.0px (83.42857dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 87.0px (33.142857dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 78.0px (29.714285dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 660.0px (251.42857dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 57.0px (21.714285dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1236.0px (470.85715dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 158.0px (60.190475dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 58.0px (22.095238dp)\n" +
- "\tworkspacePadding.left: 37.0px (14.095238dp)\n" +
- "\tworkspacePadding.top: 68.0px (25.904762dp)\n" +
- "\tworkspacePadding.right: 37.0px (14.095238dp)\n" +
- "\tworkspacePadding.bottom: 615.0px (234.28572dp)\n" +
- "\ticonScale: 0.9978308px (0.38012603dp)\n" +
- "\tcellScaleToFit : 0.9978308px (0.38012603dp)\n" +
- "\textraSpace: 235.0px (89.52381dp)\n" +
- "\tunscaled extraSpace: 235.51086px (89.71842dp)\n" +
- "\tmaxEmptySpace: 236.0px (89.90476dp)\n" +
- "\tworkspaceTopPadding: 89.0px (33.904762dp)\n" +
- "\tworkspaceBottomPadding: 146.0px (55.61905dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 158.0px (60.190475dp)\n" +
- "\toverviewActionsTopMarginPx: 63.0px (24.0dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewRowSpacing: 74.0px (28.190475dp)\n" +
- "\toverviewGridSideMargin: 168.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 168.0px (64.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 467.0px (177.90475dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1578.0px (601.1429dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.785159px (0.29910818dp)\n" +
- "\tgetCellLayoutHeight(): 1415.0px (539.0476dp)\n" +
- "\tgetCellLayoutWidth(): 883.0px (336.38095dp)\n")
- }
-
- @Test
- fun twoPanelPortrait() {
- initializeVarsForTwoPanel()
- val dp = newDP()
- dp.isTaskbarPresentInApps = true
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1840.0px (700.9524dp)\n" +
- "\theightPx: 2208.0px (841.1429dp)\n" +
- "\tavailableWidthPx: 1840.0px (700.9524dp)\n" +
- "\tavailableHeightPx: 2098.0px (799.2381dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 110.0px (41.904762dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(68.0, 116.0)dp\n" +
- "\tcellWidthPx: 178.0px (67.809525dp)\n" +
- "\tcellHeightPx: 304.0px (115.809525dp)\n" +
- "\tgetCellSize().x: 178.0px (67.809525dp)\n" +
- "\tgetCellSize().y: 304.0px (115.809525dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 52.0px (19.809525dp)\n" +
- "\tcellLayoutPaddingPx.left: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 21.0px (8.0dp)\n" +
- "\ticonSizePx: 136.0px (51.809525dp)\n" +
- "\ticonTextSizePx: 31.0px (11.809524dp)\n" +
- "\ticonDrawablePaddingPx: 17.0px (6.4761906dp)\n" +
- "\tfolderCellWidthPx: 210.0px (80.0dp)\n" +
- "\tfolderCellHeightPx: 247.0px (94.09524dp)\n" +
- "\tfolderChildIconSizePx: 158.0px (60.190475dp)\n" +
- "\tfolderChildTextSizePx: 37.0px (14.095238dp)\n" +
- "\tfolderChildDrawablePaddingPx: 13.0px (4.952381dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 42.0px (16.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsShiftRange: 2098.0px (799.2381dp)\n" +
- "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsIconSizePx: 136.0px (51.809525dp)\n" +
- "\tallAppsIconTextSizePx: 31.0px (11.809524dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tallAppsCellHeightPx: 345.0px (131.42857dp)\n" +
- "\tallAppsCellWidthPx: 178.0px (67.809525dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 73.0px (27.809525dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 126.0px (48.0dp)\n" +
- "\tallAppsLeftRightMargin: 155.0px (59.04762dp)\n" +
- "\thotseatBarSizePx: 459.0px (174.85715dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 153.0px (58.285713dp)\n" +
- "\thotseatBarBottomSpacePx: 95.0px (36.190475dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 95.0px (36.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 219.0px (83.42857dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 87.0px (33.142857dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 302.0px (115.04762dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 302.0px (115.04762dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 84.0px (32.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1236.0px (470.85715dp)\n" +
- "\tisTaskbarPresent:true\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarSize: 158.0px (60.190475dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 58.0px (22.095238dp)\n" +
- "\tworkspacePadding.left: 37.0px (14.095238dp)\n" +
- "\tworkspacePadding.top: 68.0px (25.904762dp)\n" +
- "\tworkspacePadding.right: 37.0px (14.095238dp)\n" +
- "\tworkspacePadding.bottom: 615.0px (234.28572dp)\n" +
- "\ticonScale: 0.9978308px (0.38012603dp)\n" +
- "\tcellScaleToFit : 0.9978308px (0.38012603dp)\n" +
- "\textraSpace: 235.0px (89.52381dp)\n" +
- "\tunscaled extraSpace: 235.51086px (89.71842dp)\n" +
- "\tmaxEmptySpace: 236.0px (89.90476dp)\n" +
- "\tworkspaceTopPadding: 89.0px (33.904762dp)\n" +
- "\tworkspaceBottomPadding: 146.0px (55.61905dp)\n" +
- "\toverviewTaskMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 158.0px (60.190475dp)\n" +
- "\toverviewActionsTopMarginPx: 63.0px (24.0dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewRowSpacing: 74.0px (28.190475dp)\n" +
- "\toverviewGridSideMargin: 168.0px (64.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 168.0px (64.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 467.0px (177.90475dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1578.0px (601.1429dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.785159px (0.29910818dp)\n" +
- "\tgetCellLayoutHeight(): 1415.0px (539.0476dp)\n" +
- "\tgetCellLayoutWidth(): 883.0px (336.38095dp)\n")
- }
-
- @Test
- fun phoneVerticalBar3Button() {
- initializeVarsForPhone(isVerticalBar = true, isGestureMode = false)
- val dp = newDP()
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2400.0px (914.2857dp)\n" +
- "\theightPx: 1080.0px (411.42856dp)\n" +
- "\tavailableWidthPx: 2156.0px (821.3333dp)\n" +
- "\tavailableHeightPx: 1006.0px (383.2381dp)\n" +
- "\tmInsets.left: 118.0px (44.95238dp)\n" +
- "\tmInsets.top: 74.0px (28.190475dp)\n" +
- "\tmInsets.right: 126.0px (48.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(80.0, 104.0)dp\n" +
- "\tcellWidthPx: 153.0px (58.285713dp)\n" +
- "\tcellHeightPx: 160.0px (60.95238dp)\n" +
- "\tgetCellSize().x: 461.0px (175.61905dp)\n" +
- "\tgetCellSize().y: 193.0px (73.52381dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 40.0px (15.238095dp)\n" +
- "\ticonSizePx: 142.0px (54.095238dp)\n" +
- "\ticonTextSizePx: 0.0px (0.0dp)\n" +
- "\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
- "\tfolderCellWidthPx: 175.0px (66.666664dp)\n" +
- "\tfolderCellHeightPx: 205.0px (78.09524dp)\n" +
- "\tfolderChildIconSizePx: 131.0px (49.904762dp)\n" +
- "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
- "\tfolderChildDrawablePaddingPx: 9.0px (3.4285715dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 42.0px (16.0dp)\n" +
- "\tbottomSheetTopPadding: 114.0px (43.42857dp)\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsIconSizePx: 158.0px (60.190475dp)\n" +
- "\tallAppsIconTextSizePx: 37.0px (14.095238dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 329.0px (125.333336dp)\n" +
- "\tallAppsCellWidthPx: 200.0px (76.190475dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 4\n" +
- "\tallAppsLeftRightPadding: 0.0px (0.0dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 247.0px (94.09524dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 160.0px (60.95238dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 63.0px (24.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 42.0px (16.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 95.0px (36.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 65.0px (24.761906dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 48.0px (18.285715dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 42.0px (16.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 189.0px (72.0dp)\n" +
- "\tnumShownHotseatIcons: 4\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1525.0px (580.9524dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.left: 10.0px (3.8095238dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 194.0px (73.90476dp)\n" +
- "\tworkspacePadding.bottom: 0.0px (0.0dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 166.0px (63.238094dp)\n" +
- "\tunscaled extraSpace: 166.0px (63.238094dp)\n" +
- "\tmaxEmptySpace: 184.0px (70.09524dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 42.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 168.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 42.0px (16.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 16.0px (6.095238dp)\n" +
- "\tdropTargetBarSizePx: 95.0px (36.190475dp)\n" +
- "\tdropTargetBarBottomMarginPx: 16.0px (6.095238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 983.0px (374.4762dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.777336px (0.296128dp)\n" +
- "\tgetCellLayoutHeight(): 1006.0px (383.2381dp)\n" +
- "\tgetCellLayoutWidth(): 1952.0px (743.619dp)\n")
- }
-
- @Test
- fun phoneVerticalBar() {
- initializeVarsForPhone(isVerticalBar = true)
- val dp = newDP()
-
- assertThat(dump(dp)).isEqualTo("DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2400.0px (914.2857dp)\n" +
- "\theightPx: 1080.0px (411.42856dp)\n" +
- "\tavailableWidthPx: 2282.0px (869.3333dp)\n" +
- "\tavailableHeightPx: 943.0px (359.2381dp)\n" +
- "\tmInsets.left: 118.0px (44.95238dp)\n" +
- "\tmInsets.top: 74.0px (28.190475dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 63.0px (24.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(80.0, 104.0)dp\n" +
- "\tcellWidthPx: 153.0px (58.285713dp)\n" +
- "\tcellHeightPx: 160.0px (60.95238dp)\n" +
- "\tgetCellSize().x: 493.0px (187.80952dp)\n" +
- "\tgetCellSize().y: 180.0px (68.57143dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 40.0px (15.238095dp)\n" +
- "\ticonSizePx: 142.0px (54.095238dp)\n" +
- "\ticonTextSizePx: 0.0px (0.0dp)\n" +
- "\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
- "\tfolderCellWidthPx: 159.0px (60.57143dp)\n" +
- "\tfolderCellHeightPx: 187.0px (71.2381dp)\n" +
- "\tfolderChildIconSizePx: 119.0px (45.333332dp)\n" +
- "\tfolderChildTextSizePx: 31.0px (11.809524dp)\n" +
- "\tfolderChildDrawablePaddingPx: 8.0px (3.047619dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Horizontal: 42.0px (16.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx Vertical: 42.0px (16.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 42.0px (16.0dp)\n" +
- "\tbottomSheetTopPadding: 114.0px (43.42857dp)\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsIconSizePx: 158.0px (60.190475dp)\n" +
- "\tallAppsIconTextSizePx: 37.0px (14.095238dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 329.0px (125.333336dp)\n" +
- "\tallAppsCellWidthPx: 200.0px (76.190475dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 4\n" +
- "\tallAppsLeftRightPadding: 0.0px (0.0dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 247.0px (94.09524dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 160.0px (60.95238dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 63.0px (24.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 42.0px (16.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 95.0px (36.190475dp)\n" +
- "\thotseatQsbHeight: 165.0px (62.857143dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 65.0px (24.761906dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 111.0px (42.285713dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 42.0px (16.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 63.0px (24.0dp)\n" +
- "\tnumShownHotseatIcons: 4\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1621.0px (617.5238dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.left: 10.0px (3.8095238dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 194.0px (73.90476dp)\n" +
- "\tworkspacePadding.bottom: 0.0px (0.0dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 103.0px (39.238094dp)\n" +
- "\tunscaled extraSpace: 103.0px (39.238094dp)\n" +
- "\tmaxEmptySpace: 131.0px (49.904762dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 42.0px (16.0dp)\n" +
- "\toverviewTaskIconSizePx: 126.0px (48.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 116.0px (44.190475dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 168.0px (64.0dp)\n" +
- "\toverviewActionsTopMarginPx: 32.0px (12.190476dp)\n" +
- "\toverviewActionsHeight: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 95.0px (36.190475dp)\n" +
- "\toverviewPageSpacing: 42.0px (16.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 16.0px (6.095238dp)\n" +
- "\tdropTargetBarSizePx: 95.0px (36.190475dp)\n" +
- "\tdropTargetBarBottomMarginPx: 16.0px (6.095238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 927.0px (353.14285dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76988333px (0.2932889dp)\n" +
- "\tgetCellLayoutHeight(): 943.0px (359.2381dp)\n" +
- "\tgetCellLayoutWidth(): 2078.0px (791.619dp)\n")
- }
-}
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index c822578..9c240f0 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -19,7 +19,7 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
+import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
index 4e49716..ed5526f 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -26,12 +26,12 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.KeyguardManager;
import androidx.test.filters.SmallTest;
import com.android.launcher3.util.LooperExecutor;
import com.android.quickstep.util.GroupTask;
-import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.wm.shell.util.GroupedRecentTaskInfo;
import org.junit.Before;
@@ -56,8 +56,8 @@
public void setup() {
MockitoAnnotations.initMocks(this);
LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
- KeyguardManagerCompat mockKeyguardManagerCompat = mock(KeyguardManagerCompat.class);
- mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManagerCompat,
+ KeyguardManager mockKeyguardManager = mock(KeyguardManager.class);
+ mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManager,
mockSystemUiProxy);
}
@@ -70,7 +70,7 @@
@Test
public void loadTasksInBackground_onlyKeys_noValidTaskDescription() {
- GroupedRecentTaskInfo recentTaskInfos = new GroupedRecentTaskInfo(
+ GroupedRecentTaskInfo recentTaskInfos = GroupedRecentTaskInfo.forSplitTasks(
new ActivityManager.RecentTaskInfo(), new ActivityManager.RecentTaskInfo(), null);
when(mockSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
.thenReturn(new ArrayList<>(Collections.singletonList(recentTaskInfos)));
@@ -90,8 +90,8 @@
task1.taskDescription = new ActivityManager.TaskDescription(taskDescription);
ActivityManager.RecentTaskInfo task2 = new ActivityManager.RecentTaskInfo();
task2.taskDescription = new ActivityManager.TaskDescription();
- GroupedRecentTaskInfo recentTaskInfos = new GroupedRecentTaskInfo(
- task1, task2, null);
+ GroupedRecentTaskInfo recentTaskInfos = GroupedRecentTaskInfo.forSplitTasks(task1, task2,
+ null);
when(mockSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
.thenReturn(new ArrayList<>(Collections.singletonList(recentTaskInfos)));
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index d43aafa..190b002 100644
--- a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -34,6 +34,7 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.LauncherModelHelper;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.ReflectionHelpers;
import com.android.launcher3.util.RotationUtils;
import com.android.launcher3.util.WindowBounds;
@@ -164,6 +165,7 @@
WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
doReturn(cdi).when(wmProxy).getDisplayInfo(any());
doReturn(wm).when(wmProxy).getRealBounds(any(), any());
+ doReturn(NavigationMode.NO_BUTTON).when(wmProxy).getNavigationMode(any());
ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache =
new ArrayMap<>();
diff --git a/res/layout/all_apps_personal_work_tabs.xml b/res/layout/all_apps_personal_work_tabs.xml
index 11143fb..d15b906 100644
--- a/res/layout/all_apps_personal_work_tabs.xml
+++ b/res/layout/all_apps_personal_work_tabs.xml
@@ -20,6 +20,8 @@
android:layout_width="match_parent"
android:layout_height="@dimen/all_apps_header_pill_height"
android:layout_gravity="center_horizontal"
+ android:paddingTop="@dimen/all_apps_tabs_vertical_padding"
+ android:paddingBottom="@dimen/all_apps_tabs_vertical_padding"
android:orientation="horizontal"
style="@style/TextHeadline">
@@ -28,7 +30,6 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/all_apps_tabs_button_horizontal_padding"
- android:layout_marginVertical="@dimen/all_apps_tabs_vertical_padding"
android:layout_weight="1"
android:background="@drawable/all_apps_tabs_background"
android:text="@string/all_apps_personal_tab"
@@ -41,7 +42,6 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/all_apps_tabs_button_horizontal_padding"
- android:layout_marginVertical="@dimen/all_apps_tabs_vertical_padding"
android:layout_weight="1"
android:background="@drawable/all_apps_tabs_background"
android:text="@string/all_apps_work_tab"
diff --git a/res/layout/search_results_rv_layout.xml b/res/layout/search_results_rv_layout.xml
index 567cb5f..9127521 100644
--- a/res/layout/search_results_rv_layout.xml
+++ b/res/layout/search_results_rv_layout.xml
@@ -18,7 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_results_list_view"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:focusable="true" />
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 87bf33d..4dee6e7 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -34,7 +34,8 @@
android:clipChildren="false"
android:orientation="horizontal"
android:paddingLeft="12dp"
- android:paddingRight="12dp" >
+ android:paddingRight="12dp"
+ android:alpha="0">
<com.android.launcher3.folder.FolderNameEditText
android:id="@+id/folder_name"
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index d2fa5fa..81b28ba 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -26,6 +26,7 @@
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp"
android:background="@drawable/work_apps_toggle_background"
+ android:forceHasOverlappingRendering="false"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_corp_off"
android:layout_marginBottom="@dimen/work_fab_margin_bottom"
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 812d249..c64e9b2 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -71,7 +71,7 @@
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"ବ୍ୟକ୍ତିଗତ ଆପ୍ ତାଲିକା"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"କାର୍ଯ୍ୟକାରୀ ଆପ୍ ତାଲିକା"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"ବାହାର କରନ୍ତୁ"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ଆପ୍ ସୂଚନା"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ଆପ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ"</string>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index 072b92d..e718d9c 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -18,4 +18,11 @@
<!-- The duration of the PagedView page snap animation -->
<integer name="config_pageSnapAnimationDuration">550</integer>
+ <!-- The duration of the Widget picker opening and closing animation -->
+ <integer name="config_bottomSheetOpenDuration">500</integer>
+ <integer name="config_bottomSheetCloseDuration">500</integer>
+
+ <!-- The duration of the AllApps opening and closing animation -->
+ <integer name="config_allAppsOpenDuration">@integer/config_bottomSheetOpenDuration</integer>
+ <integer name="config_allAppsCloseDuration">@integer/config_bottomSheetCloseDuration</integer>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index d4c08d0..d3f5033 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -193,4 +193,15 @@
<dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
<dimen name="swipe_back_window_max_delta_y">160dp</dimen>
<dimen name="swipe_back_window_corner_radius">40dp</dimen>
+
+ <!-- The duration of the bottom sheet opening and closing animation -->
+ <integer name="config_bottomSheetOpenDuration">267</integer>
+ <integer name="config_bottomSheetCloseDuration">267</integer>
+
+ <!-- The duration of the AllApps opening and closing animation -->
+ <integer name="config_allAppsOpenDuration">600</integer>
+ <integer name="config_allAppsCloseDuration">300</integer>
+
+ <!-- The max scale for the wallpaper when it's zoomed in -->
+ <item name="config_wallpaperMaxScale" format="float" type="dimen">0</item>
</resources>
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 21dbc5f..5ee6fce 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -109,10 +109,6 @@
| TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE | TYPE_WIDGETS_EDUCATION_DIALOG
| TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS | TYPE_OPTIONS_POPUP_DIALOG;
- // Usually we show the back button when a floating view is open. Instead, hide for these types.
- public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
- | TYPE_SNACKBAR | TYPE_WIDGET_RESIZE_FRAME | TYPE_LISTENER;
-
public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_LISTENER
& ~TYPE_ALL_APPS_EDU;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 1febd68..4cad919 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.icons.GraphicsUtils.getShapePath;
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
@@ -52,6 +53,7 @@
import java.io.PrintWriter;
import java.util.List;
+import java.util.Locale;
@SuppressLint("NewApi")
public class DeviceProfile {
@@ -180,11 +182,19 @@
private final int hotseatQsbShadowHeight;
public int hotseatBorderSpace;
+ // Bottom sheets
+ public int bottomSheetTopPadding;
+ public int bottomSheetOpenDuration;
+ public int bottomSheetCloseDuration;
+ public float bottomSheetWorkspaceScale;
+ public float bottomSheetDepth;
+
// All apps
public Point allAppsBorderSpacePx;
public int allAppsShiftRange;
public int allAppsTopPadding;
- public int bottomSheetTopPadding;
+ public int allAppsOpenDuration;
+ public int allAppsCloseDuration;
public int allAppsCellHeightPx;
public int allAppsCellWidthPx;
public int allAppsIconSizePx;
@@ -315,6 +325,21 @@
bottomSheetTopPadding = mInsets.top // statusbar height
+ res.getDimensionPixelSize(R.dimen.bottom_sheet_extra_top_padding)
+ (isTablet ? 0 : edgeMarginPx); // phones need edgeMarginPx additional padding
+ bottomSheetOpenDuration = res.getInteger(R.integer.config_bottomSheetOpenDuration);
+ bottomSheetCloseDuration = res.getInteger(R.integer.config_bottomSheetCloseDuration);
+ if (isTablet) {
+ bottomSheetWorkspaceScale = workspaceContentScale;
+ // The goal is to set wallpaper to zoom at workspaceContentScale when in AllApps.
+ // When depth is 0, wallpaper zoom is set to maxWallpaperScale.
+ // When depth is 1, wallpaper zoom is set to 1.
+ // For depth to achieve zoom set to maxWallpaperScale * workspaceContentScale:
+ float maxWallpaperScale = res.getFloat(R.dimen.config_wallpaperMaxScale);
+ bottomSheetDepth = Utilities.mapToRange(maxWallpaperScale * workspaceContentScale,
+ maxWallpaperScale, 1f, 0f, 1f, LINEAR);
+ } else {
+ bottomSheetWorkspaceScale = 1f;
+ bottomSheetDepth = 0f;
+ }
folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
folderContentPaddingLeftRight =
@@ -473,6 +498,8 @@
allAppsShiftRange =
res.getDimensionPixelSize(R.dimen.all_apps_starting_vertical_translate);
}
+ allAppsOpenDuration = res.getInteger(R.integer.config_allAppsOpenDuration);
+ allAppsCloseDuration = res.getInteger(R.integer.config_allAppsCloseDuration);
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
R.dimen.drag_flingToDeleteMinVelocity);
@@ -1354,6 +1381,10 @@
return "\t" + name + ": " + value + "px (" + dpiFromPx(value, mMetrics.densityDpi) + "dp)";
}
+ private String dpPointFToString(String name, PointF value) {
+ return String.format(Locale.ENGLISH, "\t%s: PointF(%.1f, %.1f)dp", name, value.x, value.y);
+ }
+
/** Dumps various DeviceProfile variables to the specified writer. */
public void dump(Context context, String prefix, PrintWriter writer) {
writer.println(prefix + "DeviceProfile:");
@@ -1389,7 +1420,7 @@
writer.println(prefix + "\tinv.numSearchContainerColumns: "
+ inv.numSearchContainerColumns);
- writer.println(prefix + "\tminCellSize: " + inv.minCellSize[mTypeIndex] + "dp");
+ writer.println(prefix + dpPointFToString("minCellSize", inv.minCellSize[mTypeIndex]));
writer.println(prefix + pxToDpStr("cellWidthPx", cellWidthPx));
writer.println(prefix + pxToDpStr("cellHeightPx", cellHeightPx));
@@ -1429,9 +1460,15 @@
writer.println(prefix + pxToDpStr("folderTopPadding", folderContentPaddingTop));
writer.println(prefix + pxToDpStr("bottomSheetTopPadding", bottomSheetTopPadding));
+ writer.println(prefix + "\tbottomSheetOpenDuration: " + bottomSheetOpenDuration);
+ writer.println(prefix + "\tbottomSheetCloseDuration: " + bottomSheetCloseDuration);
+ writer.println(prefix + "\tbottomSheetWorkspaceScale: " + bottomSheetWorkspaceScale);
+ writer.println(prefix + "\tbottomSheetDepth: " + bottomSheetDepth);
writer.println(prefix + pxToDpStr("allAppsShiftRange", allAppsShiftRange));
writer.println(prefix + pxToDpStr("allAppsTopPadding", allAppsTopPadding));
+ writer.println(prefix + "\tallAppsOpenDuration: " + allAppsOpenDuration);
+ writer.println(prefix + "\tallAppsCloseDuration: " + allAppsCloseDuration);
writer.println(prefix + pxToDpStr("allAppsIconSizePx", allAppsIconSizePx));
writer.println(prefix + pxToDpStr("allAppsIconTextSizePx", allAppsIconTextSizePx));
writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
@@ -1669,7 +1706,7 @@
mTransposeLayoutWithOrientation = !mInfo.isTablet(mWindowBounds);
}
if (mIsGestureMode == null) {
- mIsGestureMode = DisplayController.getNavigationMode(mContext).hasGestures;
+ mIsGestureMode = mInfo.navigationMode.hasGestures;
}
if (mDotRendererCache == null) {
mDotRendererCache = new SparseArray<>();
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index 4629ca7..11f2020 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3;
-import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
+import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.SHOW;
import android.content.Context;
import android.text.TextUtils;
@@ -33,8 +33,6 @@
* Note: AppCompatEditText doesn't fully support #displayCompletions and #onCommitCompletion
*/
public class ExtendedEditText extends EditText {
-
- private boolean mShowImeAfterFirstLayout;
private boolean mForceDisableSuggestions = false;
/**
@@ -85,28 +83,21 @@
return false;
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (mShowImeAfterFirstLayout) {
- // soft input only shows one frame after the layout of the EditText happens,
- post(() -> {
- showSoftInput();
- mShowImeAfterFirstLayout = false;
- });
- }
- }
-
-
public void showKeyboard() {
- mShowImeAfterFirstLayout = !showSoftInput();
+ onKeyboardShown();
+ showSoftInput();
}
public void hideKeyboard() {
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken());
+ ActivityContext.lookupContext(getContext()).hideKeyboard();
clearFocus();
}
+ protected void onKeyboardShown() {
+ ActivityContext.lookupContext(getContext()).getStatsLogManager()
+ .keyboardStateManager().setKeyboardState(SHOW);
+ }
+
private boolean showSoftInput() {
return requestFocus() &&
getContext().getSystemService(InputMethodManager.class)
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4a52d3e..ce95b15 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -42,6 +42,7 @@
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.logging.StatsLogManager.EventEnum;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
@@ -194,8 +195,6 @@
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.util.UiThreadHelper;
-import com.android.launcher3.util.ViewCapture;
import com.android.launcher3.util.ViewOnDrawExecutor;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.FloatingIconView;
@@ -393,7 +392,6 @@
private LauncherState mPrevLauncherState;
private StringCache mStringCache;
- private ViewCapture mViewCapture;
@Override
@TargetApi(Build.VERSION_CODES.S)
@@ -1125,6 +1123,7 @@
.log(getAllAppsEntryEvent().get());
}
}
+ updateDisallowBack();
}
/**
@@ -1488,23 +1487,11 @@
public void onAttachedToWindow() {
super.onAttachedToWindow();
mOverlayManager.onAttachedToWindow();
- if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
- View root = getDragLayer().getRootView();
- if (mViewCapture != null) {
- mViewCapture.detach();
- }
- mViewCapture = new ViewCapture(getWindow());
- mViewCapture.attach();
- }
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (mViewCapture != null) {
- mViewCapture.detach();
- mViewCapture = null;
- }
mOverlayManager.onDetachedFromWindow();
closeContextMenu();
}
@@ -1667,16 +1654,6 @@
}
}
- /**
- * Hides the keyboard if visible
- */
- public void hideKeyboard() {
- final View v = getWindow().peekDecorView();
- if (v != null && v.getWindowToken() != null) {
- UiThreadHelper.hideKeyboardAsync(this, v.getWindowToken());
- }
- }
-
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
@@ -2985,7 +2962,6 @@
*/
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
- SafeCloseable viewDump = mViewCapture == null ? null : mViewCapture.beginDump(writer, fd);
super.dump(prefix, fd, writer, args);
if (args.length > 0 && TextUtils.equals(args[0], "--all")) {
@@ -3026,10 +3002,6 @@
mPopupDataProvider.dump(prefix, writer);
mDeviceProfile.dump(this, prefix, writer);
- if (viewDump != null) {
- viewDump.close();
- }
-
try {
FileLog.flushAll(writer);
} catch (Exception e) {
@@ -3152,7 +3124,18 @@
public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) { }
- public void onDragLayerHierarchyChanged() { }
+ public void onDragLayerHierarchyChanged() {
+ updateDisallowBack();
+ }
+
+ private void updateDisallowBack() {
+ LauncherRootView rv = getRootView();
+ if (rv != null) {
+ boolean disableBack = getStateManager().getState() == NORMAL
+ && AbstractFloatingView.getTopOpenView(this) == null;
+ rv.setDisallowBackGesture(disableBack);
+ }
+ }
@Override
public void returnToHomescreen() {
@@ -3252,12 +3235,10 @@
* @param progress Transition progress from 0 to 1; where 0 => home and 1 => widgets.
*/
public void onWidgetsTransition(float progress) {
- if (mDeviceProfile.isTablet) {
- float scale =
- Utilities.comp(Utilities.comp(mDeviceProfile.workspaceContentScale) * progress);
- WORKSPACE_WIDGET_SCALE.set(getWorkspace(), scale);
- HOTSEAT_WIDGET_SCALE.set(getHotseat(), scale);
- }
+ float scale = Utilities.mapToRange(progress, 0f, 1f, 1f,
+ mDeviceProfile.bottomSheetWorkspaceScale, EMPHASIZED);
+ WORKSPACE_WIDGET_SCALE.set(getWorkspace(), scale);
+ HOTSEAT_WIDGET_SCALE.set(getHotseat(), scale);
}
private static class NonConfigInstance {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index c3b5392..31a7d18 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -71,17 +71,14 @@
public static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = BaseState.getFlag(2);
// Flag to indicate that workspace should draw page background
public static final int FLAG_WORKSPACE_HAS_BACKGROUNDS = BaseState.getFlag(3);
- // True if the back button should be hidden when in this state (assuming no floating views are
- // open, launcher has window focus, etc).
- public static final int FLAG_HIDE_BACK_BUTTON = BaseState.getFlag(4);
// Flag to indicate if the state would have scrim over sysui region: statu sbar and nav bar
- public static final int FLAG_HAS_SYS_UI_SCRIM = BaseState.getFlag(5);
+ public static final int FLAG_HAS_SYS_UI_SCRIM = BaseState.getFlag(4);
// Flag to inticate that all popups should be closed when this state is enabled.
- public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(6);
- public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
+ public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(5);
+ public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(6);
// Flag indicating that hotseat and its contents are not accessible.
- public static final int FLAG_HOTSEAT_INACCESSIBLE = BaseState.getFlag(8);
+ public static final int FLAG_HOTSEAT_INACCESSIBLE = BaseState.getFlag(7);
public static final float NO_OFFSET = 0;
@@ -110,8 +107,7 @@
*/
public static final LauncherState NORMAL = new LauncherState(NORMAL_STATE_ORDINAL,
LAUNCHER_STATE_HOME,
- FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
- FLAG_HAS_SYS_UI_SCRIM) {
+ FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HAS_SYS_UI_SCRIM) {
@Override
public int getTransitionDuration(Context context, boolean isToState) {
// Arbitrary duration, when going to NORMAL we use the state we're coming from instead.
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 73be5be..68c54c7 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -259,8 +259,13 @@
abortScrollerAnimation(true);
}
+ protected void onScrollerAnimationAborted() {
+ // No-Op
+ }
+
private void abortScrollerAnimation(boolean resetNextPage) {
mScroller.abortAnimation();
+ onScrollerAnimationAborted();
// We need to clean up the next page here to avoid computeScrollHelper from
// updating current page on the pass.
if (resetNextPage) {
@@ -555,11 +560,11 @@
if (mAllowOverScroll) {
if (newPos < mMinScroll && oldPos >= mMinScroll) {
mEdgeGlowLeft.onAbsorb((int) mScroller.getCurrVelocity());
- mScroller.abortAnimation();
+ abortScrollerAnimation(false);
onEdgeAbsorbingScroll();
} else if (newPos > mMaxScroll && oldPos <= mMaxScroll) {
mEdgeGlowRight.onAbsorb((int) mScroller.getCurrVelocity());
- mScroller.abortAnimation();
+ abortScrollerAnimation(false);
onEdgeAbsorbingScroll();
}
}
@@ -569,7 +574,7 @@
int finalPos = mOrientationHandler.getPrimaryValue(mScroller.getFinalX(),
mScroller.getFinalY());
if (newPos == finalPos && mEdgeGlowLeft.isFinished() && mEdgeGlowRight.isFinished()) {
- mScroller.abortAnimation();
+ abortScrollerAnimation(false);
}
invalidate();
diff --git a/src/com/android/launcher3/PendingAddItemInfo.java b/src/com/android/launcher3/PendingAddItemInfo.java
index be994ee..b7a22fc 100644
--- a/src/com/android/launcher3/PendingAddItemInfo.java
+++ b/src/com/android/launcher3/PendingAddItemInfo.java
@@ -18,6 +18,7 @@
import android.content.ComponentName;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.model.data.ItemInfo;
@@ -43,6 +44,7 @@
/**
* Returns shallow copy of the object.
*/
+ @NonNull
@Override
public ItemInfo makeShallowCopy() {
PendingAddItemInfo itemInfo = new PendingAddItemInfo();
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index e33e44e..aa9cfd1 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.SEARCH;
+
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -34,7 +36,6 @@
import com.android.launcher3.views.AppLauncher;
import java.util.ArrayList;
-import java.util.Objects;
/**
* All apps container view with search support for use in a dragging activity.
@@ -44,6 +45,11 @@
public class ActivityAllAppsContainerView<T extends Context & AppLauncher
& DeviceProfileListenable> extends BaseAllAppsContainerView<T> {
+ private static final long DEFAULT_SEARCH_TRANSITION_DURATION_MS = 300;
+
+ // Used to animate Search results out and A-Z apps in, or vice-versa.
+ private final SearchTransitionController mSearchTransitionController;
+
protected SearchUiManager mSearchUiManager;
/**
* View that defines the search box. Result is rendered inside the recycler view defined in the
@@ -52,6 +58,7 @@
private View mSearchContainer;
/** {@code true} when rendered view is in search state instead of the scroll state. */
private boolean mIsSearching;
+ private boolean mRebindAdaptersAfterSearchAnimation;
public ActivityAllAppsContainerView(Context context) {
this(context, null);
@@ -63,6 +70,8 @@
public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+
+ mSearchTransitionController = new SearchTransitionController(this);
}
public SearchUiManager getSearchUiManager() {
@@ -73,19 +82,10 @@
return mSearchContainer;
}
- /** Updates all apps container with the latest search query. */
- public void setLastSearchQuery(String query) {
- mIsSearching = true;
- rebindAdapters();
- mHeader.setCollapsed(true);
- }
-
/** Invoke when the current search session is finished. */
public void onClearSearchResult() {
- mIsSearching = false;
- mHeader.setCollapsed(false);
+ animateToSearchState(false);
rebindAdapters();
- mHeader.reset(false);
}
/**
@@ -93,12 +93,42 @@
*/
public void setSearchResults(ArrayList<AdapterItem> results) {
if (getSearchResultList().setSearchResults(results)) {
- for (int i = 0; i < mAH.size(); i++) {
- if (mAH.get(i).mRecyclerView != null) {
- mAH.get(i).mRecyclerView.onSearchResultsChanged();
- }
- }
+ getSearchRecyclerView().onSearchResultsChanged();
}
+ if (results != null) {
+ animateToSearchState(true);
+ }
+ }
+
+ private void animateToSearchState(boolean goingToSearch) {
+ animateToSearchState(goingToSearch, DEFAULT_SEARCH_TRANSITION_DURATION_MS);
+ }
+
+ private void animateToSearchState(boolean goingToSearch, long durationMs) {
+ if (!mSearchTransitionController.isRunning() && goingToSearch == isSearching()) {
+ return;
+ }
+ if (goingToSearch) {
+ // Fade out the button to pause work apps.
+ mWorkManager.onActivePageChanged(SEARCH);
+ }
+ mSearchTransitionController.animateToSearchState(goingToSearch, durationMs,
+ /* onEndRunnable = */ () -> {
+ mIsSearching = goingToSearch;
+ updateSearchResultsVisibility();
+ int previousPage = getCurrentPage();
+ if (mRebindAdaptersAfterSearchAnimation) {
+ rebindAdapters(false);
+ mRebindAdaptersAfterSearchAnimation = false;
+ }
+ if (!goingToSearch) {
+ setSearchResults(null);
+ if (mViewPager != null) {
+ mViewPager.setCurrentPage(previousPage);
+ }
+ onActivePageChanged(previousPage);
+ }
+ });
}
@Override
@@ -121,6 +151,8 @@
super.reset(animate);
// Reset the search bar after transitioning home.
mSearchUiManager.resetSearch();
+ // Animate to A-Z with 0 time to reset the animation with proper state management.
+ animateToSearchState(false, 0);
}
@Override
@@ -157,21 +189,30 @@
}
@Override
+ public void onActivePageChanged(int currentActivePage) {
+ if (mSearchTransitionController.isRunning()) {
+ // Will be called at the end of the animation.
+ return;
+ }
+ super.onActivePageChanged(currentActivePage);
+ }
+
+ @Override
protected void rebindAdapters(boolean force) {
+ if (mSearchTransitionController.isRunning()) {
+ mRebindAdaptersAfterSearchAnimation = true;
+ return;
+ }
super.rebindAdapters(force);
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
- || getMainAdapterProvider().getDecorator() == null) {
+ || getMainAdapterProvider().getDecorator() == null
+ || getSearchRecyclerView() == null) {
return;
}
RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
- mAH.stream()
- .map(adapterHolder -> adapterHolder.mRecyclerView)
- .filter(Objects::nonNull)
- .forEach(v -> {
- v.removeItemDecoration(decoration); // Remove in case it is already added.
- v.addItemDecoration(decoration);
- });
+ getSearchRecyclerView().removeItemDecoration(decoration); // In case it is already added.
+ getSearchRecyclerView().addItemDecoration(decoration);
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 31e3890..21a7dfb 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END;
import static com.android.launcher3.util.LogConfig.SEARCH_LOGGING;
-import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
import android.content.Context;
import android.graphics.Canvas;
@@ -162,8 +161,7 @@
requestFocus();
mgr.logger().sendToInteractionJankMonitor(
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
+ ActivityContext.lookupContext(getContext()).hideKeyboard();
break;
case SCROLL_STATE_IDLE:
mgr.logger().sendToInteractionJankMonitor(
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index ecc9d7e..22e8bcf 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -42,7 +42,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.util.MultiAdditivePropertyFactory;
+import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.views.ScrimView;
@@ -141,9 +141,9 @@
private ScrimView mScrimView;
- private final MultiAdditivePropertyFactory<View>
- mAppsViewTranslationYPropertyFactory = new MultiAdditivePropertyFactory<>(
- "appsViewTranslationY", View.TRANSLATION_Y);
+ private final MultiPropertyFactory<View>
+ mAppsViewTranslationYPropertyFactory = new MultiPropertyFactory<>(
+ "appsViewTranslationY", View.TRANSLATION_Y, Float::sum);
private MultiValueAlpha mAppsViewAlpha;
private boolean mIsTablet;
@@ -227,7 +227,7 @@
@Override
public void setStateWithAnimation(LauncherState toState,
StateAnimationConfig config, PendingAnimation builder) {
- if (NORMAL.equals(toState) && mLauncher.isInState(ALL_APPS)) {
+ if (mLauncher.isInState(ALL_APPS) && !ALL_APPS.equals(toState)) {
builder.addEndListener(success -> {
// Reset pull back progress and alpha after switching states.
ALL_APPS_PULL_BACK_TRANSLATION.set(this, 0f);
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index 6990e57..42f8b0c 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -127,6 +127,11 @@
public boolean isContentSame(AdapterItem other) {
return itemInfo == null && other.itemInfo == null;
}
+
+ /** Sets the alpha of the decorator for this item. Returns true if successful. */
+ public boolean setDecorationFillAlpha(int alpha) {
+ return false;
+ }
}
protected final T mActivityContext;
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index f3c5dd6..d8d3fa3 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
-import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -107,12 +106,13 @@
updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY());
}
};
- private final WorkProfileManager mWorkManager;
+
+ protected final WorkProfileManager mWorkManager;
private final Paint mNavBarScrimPaint;
private int mNavBarScrimHeight = 0;
- private AllAppsPagedView mViewPager;
+ protected AllAppsPagedView mViewPager;
private SearchRecyclerView mSearchRecyclerView;
protected FloatingHeaderView mHeader;
@@ -349,7 +349,7 @@
* The container for A-Z apps (the ViewPager for main+work tabs, or main RV). This is currently
* hidden while searching.
**/
- private View getAppsRecyclerViewContainer() {
+ protected View getAppsRecyclerViewContainer() {
return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
}
@@ -491,6 +491,7 @@
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
+ mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
if (mUsingTabs) {
mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
@@ -503,8 +504,7 @@
mActivityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
}
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
+ mActivityContext.hideKeyboard();
});
findViewById(R.id.tab_work)
.setOnClickListener((View view) -> {
@@ -512,8 +512,7 @@
mActivityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
}
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
+ mActivityContext.hideKeyboard();
});
setDeviceManagementResources();
onActivePageChanged(mViewPager.getNextPage());
@@ -525,9 +524,10 @@
mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
+ mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
}
- private void updateSearchResultsVisibility() {
+ protected void updateSearchResultsVisibility() {
if (isSearching()) {
getSearchRecyclerView().setVisibility(VISIBLE);
getAppsRecyclerViewContainer().setVisibility(GONE);
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index c5bdb69..8ec2aeb 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -42,6 +42,7 @@
import com.android.systemui.plugins.PluginListener;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Map;
public class FloatingHeaderView extends LinearLayout implements
@@ -82,8 +83,8 @@
protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
// These two values are necessary to ensure that the header protection is drawn correctly.
- private final int mHeaderTopAdjustment;
- private final int mHeaderBottomAdjustment;
+ private final int mTabsAdditionalPaddingTop;
+ private final int mTabsAdditionalPaddingBottom;
private boolean mHeaderProtectionSupported;
protected ViewGroup mTabLayout;
@@ -91,7 +92,6 @@
private AllAppsRecyclerView mWorkRV;
private SearchRecyclerView mSearchRV;
private AllAppsRecyclerView mCurrentRV;
- public boolean mHeaderCollapsed;
protected int mSnappedScrolledY;
private int mTranslationY;
@@ -100,7 +100,12 @@
protected boolean mTabsHidden;
protected int mMaxTranslation;
- private boolean mCollapsed = false;
+ // Whether the header has been scrolled off-screen.
+ private boolean mHeaderCollapsed;
+ // Whether floating rows like predicted apps are hidden.
+ private boolean mFloatingRowsCollapsed;
+ // Total height of all current floating rows. Collapsed rows == 0 height.
+ private int mFloatingRowsHeight;
// This is initialized once during inflation and stays constant after that. Fixed views
// cannot be added or removed dynamically.
@@ -117,9 +122,9 @@
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- mHeaderTopAdjustment = context.getResources()
+ mTabsAdditionalPaddingTop = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_top_adjustment);
- mHeaderBottomAdjustment = context.getResources()
+ mTabsAdditionalPaddingBottom = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_bottom_adjustment);
mHeaderProtectionSupported = context.getResources().getBoolean(
R.bool.config_header_protection_supported);
@@ -148,6 +153,7 @@
}
mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
mAllRows = mFixedRows;
+ updateFloatingRowsHeight();
}
@Override
@@ -179,6 +185,7 @@
count++;
}
}
+ updateFloatingRowsHeight();
}
@Override
@@ -195,7 +202,7 @@
int oldMaxHeight = mMaxTranslation;
updateExpectedHeight();
- if (mMaxTranslation != oldMaxHeight || mCollapsed) {
+ if (mMaxTranslation != oldMaxHeight || mFloatingRowsCollapsed) {
BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
if (parent != null) {
parent.setupHeader();
@@ -258,20 +265,19 @@
}
private void updateExpectedHeight() {
+ updateFloatingRowsHeight();
mMaxTranslation = 0;
- if (mCollapsed) {
+ if (mFloatingRowsCollapsed) {
return;
}
- for (FloatingHeaderRow row : mAllRows) {
- mMaxTranslation += row.getExpectedHeight();
- }
+ mMaxTranslation += mFloatingRowsHeight;
if (!mTabsHidden) {
- mMaxTranslation += mHeaderBottomAdjustment;
+ mMaxTranslation += mTabsAdditionalPaddingBottom;
}
}
public int getMaxTranslation() {
- if (mMaxTranslation == 0 && mTabsHidden) {
+ if (mMaxTranslation == 0 && (mTabsHidden || mFloatingRowsCollapsed)) {
return getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_bottom_padding);
} else if (mMaxTranslation > 0 && mTabsHidden) {
return mMaxTranslation + getPaddingTop();
@@ -312,7 +318,7 @@
int uncappedTranslationY = mTranslationY;
mTranslationY = Math.max(mTranslationY, -mMaxTranslation);
- if (mCollapsed || uncappedTranslationY < mTranslationY - getPaddingTop()) {
+ if (mFloatingRowsCollapsed || uncappedTranslationY < mTranslationY - getPaddingTop()) {
// we hide it completely if already capped (for opening search anim)
for (FloatingHeaderRow row : mAllRows) {
row.setVerticalScroll(0, true /* isScrolledOut */);
@@ -325,11 +331,11 @@
mTabLayout.setTranslationY(mTranslationY);
- int clipTop = getPaddingTop() - mHeaderTopAdjustment;
+ int clipTop = getPaddingTop() - mTabsAdditionalPaddingTop;
if (mTabsHidden) {
- clipTop += getPaddingBottom() - mHeaderBottomAdjustment;
+ clipTop += getPaddingBottom() - mTabsAdditionalPaddingBottom;
}
- mRVClip.top = mTabsHidden ? clipTop : 0;
+ mRVClip.top = mTabsHidden || mFloatingRowsCollapsed ? clipTop : 0;
mHeaderClip.top = clipTop;
// clipping on a draw might cause additional redraw
setClipBounds(mHeaderClip);
@@ -347,10 +353,12 @@
/**
* Hides all the floating rows
*/
- public void setCollapsed(boolean collapse) {
- if (mCollapsed == collapse) return;
+ public void setFloatingRowsCollapsed(boolean collapsed) {
+ if (mFloatingRowsCollapsed == collapsed) {
+ return;
+ }
- mCollapsed = collapse;
+ mFloatingRowsCollapsed = collapsed;
onHeightUpdated();
}
@@ -376,6 +384,30 @@
return !mHeaderCollapsed;
}
+ /** Returns true if personal/work tabs are currently in use. */
+ public boolean usingTabs() {
+ return !mTabsHidden;
+ }
+
+ ViewGroup getTabLayout() {
+ return mTabLayout;
+ }
+
+ /** Calculates the combined height of any floating rows (e.g. predicted apps, app divider). */
+ private void updateFloatingRowsHeight() {
+ mFloatingRowsHeight =
+ Arrays.stream(mAllRows).mapToInt(FloatingHeaderRow::getExpectedHeight).sum();
+ }
+
+ /** Gets the combined height of any floating rows (e.g. predicted apps, app divider). */
+ int getFloatingRowsHeight() {
+ return mFloatingRowsHeight;
+ }
+
+ int getTabsAdditionalPaddingBottom() {
+ return mTabsAdditionalPaddingBottom;
+ }
+
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mTranslationY = (Integer) animation.getAnimatedValue();
@@ -447,9 +479,10 @@
// we only want to show protection when work tab is available and header is either
// collapsed or animating to/from collapsed state
- if (mTabsHidden || !mHeaderCollapsed) {
+ if (mTabsHidden || mFloatingRowsCollapsed || !mHeaderCollapsed) {
return 0;
}
- return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
+ return Math.max(0,
+ getTabLayout().getBottom() - getPaddingTop() + getPaddingBottom() + mTranslationY);
}
}
diff --git a/src/com/android/launcher3/allapps/SearchRecyclerView.java b/src/com/android/launcher3/allapps/SearchRecyclerView.java
index 482bd29..9d1dfc0 100644
--- a/src/com/android/launcher3/allapps/SearchRecyclerView.java
+++ b/src/com/android/launcher3/allapps/SearchRecyclerView.java
@@ -17,12 +17,17 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.core.util.Consumer;
import com.android.launcher3.views.RecyclerViewFastScroller;
/** A RecyclerView for AllApps Search results. */
public class SearchRecyclerView extends AllAppsRecyclerView {
- private static final String TAG = "SearchRecyclerView";
+
+ private Consumer<View> mChildAttachedConsumer;
public SearchRecyclerView(Context context) {
this(context, null);
@@ -41,6 +46,11 @@
super(context, attrs, defStyleAttr, defStyleRes);
}
+ /** This will be called just before a new child is attached to the window. */
+ public void setChildAttachedConsumer(Consumer<View> childAttachedConsumer) {
+ mChildAttachedConsumer = childAttachedConsumer;
+ }
+
@Override
protected void updatePoolSize() {
RecycledViewPool pool = getRecycledViewPool();
@@ -57,4 +67,12 @@
public RecyclerViewFastScroller getScrollbar() {
return null;
}
+
+ @Override
+ public void onChildAttachedToWindow(@NonNull View child) {
+ if (mChildAttachedConsumer != null) {
+ mChildAttachedConsumer.accept(child);
+ }
+ super.onChildAttachedToWindow(child);
+ }
}
diff --git a/src/com/android/launcher3/allapps/SearchTransitionController.java b/src/com/android/launcher3/allapps/SearchTransitionController.java
new file mode 100644
index 0000000..03529af
--- /dev/null
+++ b/src/com/android/launcher3/allapps/SearchTransitionController.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2022 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.allapps;
+
+import static android.view.View.VISIBLE;
+
+import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
+
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
+
+import android.animation.ObjectAnimator;
+import android.graphics.drawable.Drawable;
+import android.util.FloatProperty;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+
+/** Coordinates the transition between Search and A-Z in All Apps. */
+public class SearchTransitionController {
+
+ // Interpolator when the user taps the QSB while already in All Apps.
+ private static final Interpolator DEFAULT_INTERPOLATOR_WITHIN_ALL_APPS = DEACCEL_1_7;
+ // Interpolator when the user taps the QSB from home screen, so transition to all apps is
+ // happening simultaneously.
+ private static final Interpolator DEFAULT_INTERPOLATOR_TRANSITIONING_TO_ALL_APPS = LINEAR;
+
+ /**
+ * These values represent points on the [0, 1] animation progress spectrum. They are used to
+ * animate items in the {@link SearchRecyclerView}.
+ */
+ private static final float TOP_CONTENT_FADE_PROGRESS_START = 0.133f;
+ private static final float CONTENT_FADE_PROGRESS_DURATION = 0.083f;
+ private static final float TOP_BACKGROUND_FADE_PROGRESS_START = 0.633f;
+ private static final float BACKGROUND_FADE_PROGRESS_DURATION = 0.15f;
+ private static final float CONTENT_STAGGER = 0.01f; // Progress before next item starts fading.
+
+ private static final FloatProperty<SearchTransitionController> SEARCH_TO_AZ_PROGRESS =
+ new FloatProperty<SearchTransitionController>("searchToAzProgress") {
+ @Override
+ public Float get(SearchTransitionController controller) {
+ return controller.getSearchToAzProgress();
+ }
+
+ @Override
+ public void setValue(SearchTransitionController controller, float progress) {
+ controller.setSearchToAzProgress(progress);
+ }
+ };
+
+ private final ActivityAllAppsContainerView<?> mAllAppsContainerView;
+
+ private ObjectAnimator mSearchToAzAnimator = null;
+ private float mSearchToAzProgress = 1f;
+
+ public SearchTransitionController(ActivityAllAppsContainerView<?> allAppsContainerView) {
+ mAllAppsContainerView = allAppsContainerView;
+ }
+
+ /** Returns true if a transition animation is currently in progress. */
+ public boolean isRunning() {
+ return mSearchToAzAnimator != null;
+ }
+
+ /**
+ * Starts the transition to or from search state. If a transition is already in progress, the
+ * animation will start from that point with the new duration, and the previous onEndRunnable
+ * will not be called.
+ *
+ * @param goingToSearch true if will be showing search results, otherwise will be showing a-z
+ * @param duration time in ms for the animation to run
+ * @param onEndRunnable will be called when the animation finishes, unless another animation is
+ * scheduled in the meantime
+ */
+ public void animateToSearchState(boolean goingToSearch, long duration, Runnable onEndRunnable) {
+ float targetProgress = goingToSearch ? 0 : 1;
+
+ if (mSearchToAzAnimator != null) {
+ mSearchToAzAnimator.cancel();
+ }
+
+ mSearchToAzAnimator = ObjectAnimator.ofFloat(this, SEARCH_TO_AZ_PROGRESS, targetProgress);
+ boolean inAllApps = Launcher.getLauncher(
+ mAllAppsContainerView.getContext()).getStateManager().isInStableState(
+ LauncherState.ALL_APPS);
+ mSearchToAzAnimator.setDuration(duration).setInterpolator(
+ inAllApps ? DEFAULT_INTERPOLATOR_WITHIN_ALL_APPS
+ : DEFAULT_INTERPOLATOR_TRANSITIONING_TO_ALL_APPS);
+ mSearchToAzAnimator.addListener(forEndCallback(() -> mSearchToAzAnimator = null));
+ if (!goingToSearch) {
+ mSearchToAzAnimator.addListener(forSuccessCallback(() -> {
+ mAllAppsContainerView.getFloatingHeaderView().setFloatingRowsCollapsed(false);
+ mAllAppsContainerView.getFloatingHeaderView().reset(false /* animate */);
+ mAllAppsContainerView.getAppsRecyclerViewContainer().setTranslationY(0);
+ }));
+ }
+ mSearchToAzAnimator.addListener(forSuccessCallback(onEndRunnable));
+
+ mAllAppsContainerView.getFloatingHeaderView().setFloatingRowsCollapsed(true);
+ mAllAppsContainerView.getAppsRecyclerViewContainer().setVisibility(VISIBLE);
+ getSearchRecyclerView().setVisibility(VISIBLE);
+ getSearchRecyclerView().setChildAttachedConsumer(this::onSearchChildAttached);
+ mSearchToAzAnimator.start();
+ }
+
+ private SearchRecyclerView getSearchRecyclerView() {
+ return mAllAppsContainerView.getSearchRecyclerView();
+ }
+
+ private void setSearchToAzProgress(float searchToAzProgress) {
+ mSearchToAzProgress = searchToAzProgress;
+ int searchHeight = updateSearchRecyclerViewProgress();
+
+ FloatingHeaderView headerView = mAllAppsContainerView.getFloatingHeaderView();
+
+ // Add predictions + app divider height to account for predicted apps which will now be in
+ // the Search RV instead of the floating header view. Note `getFloatingRowsHeight` returns 0
+ // when predictions are not shown.
+ int appsTranslationY = searchHeight + headerView.getFloatingRowsHeight();
+
+ if (headerView.usingTabs()) {
+ // Move tabs below the search results, and fade them out in 20% of the animation.
+ headerView.setTranslationY(searchHeight);
+ headerView.setAlpha(clampToProgress(searchToAzProgress, 0.8f, 1f));
+
+ // Account for the additional padding added for the tabs.
+ appsTranslationY -=
+ headerView.getPaddingTop() - headerView.getTabsAdditionalPaddingBottom();
+ }
+
+ View appsContainer = mAllAppsContainerView.getAppsRecyclerViewContainer();
+ appsContainer.setTranslationY(appsTranslationY);
+ // Fade apps out with tabs (in 20% of the total animation).
+ appsContainer.setAlpha(clampToProgress(searchToAzProgress, 0.8f, 1f));
+ }
+
+ /**
+ * Updates the children views of SearchRecyclerView based on the current animation progress.
+ *
+ * @return the total height of animating views (excluding any app icons).
+ */
+ private int updateSearchRecyclerViewProgress() {
+ int numSearchResultsAnimated = 0;
+ int totalHeight = 0;
+ int appRowHeight = 0;
+ Integer top = null;
+ SearchRecyclerView searchRecyclerView = getSearchRecyclerView();
+ for (int i = 0; i < searchRecyclerView.getChildCount(); i++) {
+ View searchResultView = searchRecyclerView.getChildAt(i);
+ if (searchResultView == null) {
+ continue;
+ }
+
+ if (top == null) {
+ top = searchResultView.getTop();
+ }
+
+ if (searchResultView instanceof BubbleTextView) {
+ // The first app icon will set appRowHeight, which will also contribute to
+ // totalHeight. Additional app icons should remove the appRowHeight to remain in
+ // the same row as the first app.
+ searchResultView.setY(top + totalHeight - appRowHeight);
+ if (appRowHeight == 0) {
+ appRowHeight = searchResultView.getHeight();
+ totalHeight += appRowHeight;
+ }
+ // Don't scale/fade app row.
+ continue;
+ }
+
+ // Adjust content alpha based on start progress and stagger.
+ float startContentFadeProgress = Math.max(0,
+ TOP_CONTENT_FADE_PROGRESS_START - CONTENT_STAGGER * numSearchResultsAnimated);
+ float endContentFadeProgress = Math.min(1,
+ startContentFadeProgress + CONTENT_FADE_PROGRESS_DURATION);
+ searchResultView.setAlpha(1 - clampToProgress(mSearchToAzProgress,
+ startContentFadeProgress, endContentFadeProgress));
+
+ // Adjust background (or decorator) alpha based on start progress and stagger.
+ float startBackgroundFadeProgress = Math.max(0,
+ TOP_BACKGROUND_FADE_PROGRESS_START
+ - CONTENT_STAGGER * numSearchResultsAnimated);
+ float endBackgroundFadeProgress = Math.min(1,
+ startBackgroundFadeProgress + BACKGROUND_FADE_PROGRESS_DURATION);
+ float backgroundAlpha = 1 - clampToProgress(mSearchToAzProgress,
+ startBackgroundFadeProgress, endBackgroundFadeProgress);
+ int adapterPosition = searchRecyclerView.getChildAdapterPosition(searchResultView);
+ boolean decoratorFilled =
+ adapterPosition != NO_POSITION
+ && searchRecyclerView.getApps().getAdapterItems().get(adapterPosition)
+ .setDecorationFillAlpha((int) (255 * backgroundAlpha));
+ if (!decoratorFilled) {
+ // Try to adjust background alpha instead (e.g. for Search Edu card).
+ Drawable background = searchResultView.getBackground();
+ if (background != null) {
+ background.setAlpha((int) (255 * backgroundAlpha));
+ }
+ }
+
+ float scaleY = 1 - mSearchToAzProgress;
+ int scaledHeight = (int) (searchResultView.getHeight() * scaleY);
+ searchResultView.setScaleY(scaleY);
+ searchResultView.setY(top + totalHeight);
+
+ numSearchResultsAnimated++;
+ totalHeight += scaledHeight;
+ }
+
+ return totalHeight - appRowHeight;
+ }
+
+ /** Called just before a child is attached to the SearchRecyclerView. */
+ private void onSearchChildAttached(View child) {
+ // Avoid allocating hardware layers for alpha changes.
+ child.forceHasOverlappingRendering(false);
+ if (mSearchToAzProgress > 0) {
+ // Before the child is rendered, apply the animation including it to avoid flicker.
+ updateSearchRecyclerViewProgress();
+ } else {
+ // Apply default states without processing the full layout.
+ child.setAlpha(1);
+ child.setScaleY(1);
+ child.setTranslationY(0);
+ int adapterPosition = getSearchRecyclerView().getChildAdapterPosition(child);
+ if (adapterPosition != NO_POSITION) {
+ getSearchRecyclerView().getApps().getAdapterItems().get(adapterPosition)
+ .setDecorationFillAlpha(255);
+ }
+ if (child.getBackground() != null) {
+ child.getBackground().setAlpha(255);
+ }
+ }
+ }
+
+ private float getSearchToAzProgress() {
+ return mSearchToAzProgress;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index fedc91f..a589448 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -170,12 +170,14 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- if (Utilities.ATLEAST_R && isEnabled()) {
+ if (!Utilities.ATLEAST_R) {
+ return insets;
+ }
+ if (insets.isVisible(WindowInsets.Type.ime())) {
+ Insets keyboardInsets = insets.getInsets(WindowInsets.Type.ime());
+ setTranslationY(mInsets.bottom - keyboardInsets.bottom);
+ } else {
setTranslationY(0);
- if (insets.isVisible(WindowInsets.Type.ime())) {
- Insets keyboardInsets = insets.getInsets(WindowInsets.Type.ime());
- setTranslationY(mInsets.bottom - keyboardInsets.bottom);
- }
}
return insets;
}
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 52d8f63..78c305b 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -168,14 +168,11 @@
public void onSearchResult(String query, ArrayList<AdapterItem> items) {
if (items != null) {
mAppsView.setSearchResults(items);
- mAppsView.setLastSearchQuery(query);
}
}
@Override
public void clearSearchResult() {
- mAppsView.setSearchResults(null);
-
// Clear the search query
mSearchQueryBuilder.clear();
mSearchQueryBuilder.clearSpans();
diff --git a/src/com/android/launcher3/anim/AnimationSuccessListener.java b/src/com/android/launcher3/anim/AnimationSuccessListener.java
index a312070..6196df2 100644
--- a/src/com/android/launcher3/anim/AnimationSuccessListener.java
+++ b/src/com/android/launcher3/anim/AnimationSuccessListener.java
@@ -19,6 +19,8 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import androidx.annotation.CallSuper;
+
/**
* Extension of {@link AnimatorListenerAdapter} for listening for non-cancelled animations
*/
@@ -27,6 +29,7 @@
protected boolean mCancelled = false;
@Override
+ @CallSuper
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 12b4223..d900c90 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -83,6 +83,7 @@
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
}
+ public static final Interpolator OVERSHOOT_0_85 = new OvershootInterpolator(0.85f);
public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index ff40712..0e36dc0 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -65,12 +65,12 @@
*/
public static final BooleanFlag ENABLE_INPUT_CONSUMER_REASON_LOGGING = getDebugFlag(
"ENABLE_INPUT_CONSUMER_REASON_LOGGING",
- false,
+ true,
"Log the reason why an Input Consumer was selected for a gesture.");
public static final BooleanFlag ENABLE_GESTURE_ERROR_DETECTION = getDebugFlag(
"ENABLE_GESTURE_ERROR_DETECTION",
- false,
+ true,
"Analyze gesture events and log detected errors");
// When enabled the promise icon is visible in all apps while installation an app.
@@ -274,10 +274,6 @@
"USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", false,
"Use local overrides for search request timeout");
- public static final BooleanFlag USE_APP_SEARCH_FOR_WEB = getDebugFlag(
- "USE_APP_SEARCH_FOR_WEB", false,
- "Use app search to request zero state web suggestions");
-
public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(
"CONTINUOUS_VIEW_TREE_CAPTURE", false, "Capture View tree every frame");
@@ -285,6 +281,19 @@
"FOLDABLE_WORKSPACE_REORDER", true,
"In foldables, when reordering the icons and widgets, is now going to use both sides");
+ public static final BooleanFlag SHOW_SEARCH_EDUCARD_QSB = new DeviceFlag(
+ "SHOW_SEARCH_EDUCARD_QSB", false, "Shows Search Educard for QSB entry in OneSearch.");
+
+ public static final BooleanFlag ENABLE_IME_LATENCY_LOGGER = getDebugFlag(
+ "ENABLE_IME_LATENCY_LOGGER", false,
+ "Enable option to log the keyboard latency for both atomic and controlled keyboard "
+ + "animations on an EditText");
+
+ // Change of wallpaper depth in widget picker is disabled for tests as it causes flakiness on
+ // very slow cuttlefish devices.
+ public static final BooleanFlag ENABLE_WIDGET_PICKER_DEPTH = new DeviceFlag(
+ "ENABLE_WIDGET_PICKER_DEPTH", true, "Enable changing depth in widget picker.");
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index f027b33..7457f30 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -16,24 +16,16 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.annotation.Nullable;
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -41,8 +33,6 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
-import java.nio.ByteBuffer;
-
/**
* A utility class to generate preview bitmap for dragging.
*/
@@ -57,9 +47,6 @@
public final int blurSizeOutline;
- private OutlineGeneratorCallback mOutlineGeneratorCallback;
- public Bitmap generatedDragOutline;
-
public DragPreviewProvider(View view) {
this(view, view.getContext());
}
@@ -129,15 +116,6 @@
return null;
}
- public final void generateDragOutline(Bitmap preview) {
- if (FeatureFlags.IS_STUDIO_BUILD && mOutlineGeneratorCallback != null) {
- throw new RuntimeException("Drag outline generated twice");
- }
-
- mOutlineGeneratorCallback = new OutlineGeneratorCallback(preview);
- UI_HELPER_EXECUTOR.post(mOutlineGeneratorCallback);
- }
-
protected static Rect getDrawableBounds(Drawable d) {
Rect bounds = new Rect();
d.copyBounds(bounds);
@@ -184,92 +162,4 @@
protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) {
return preview.copy(Bitmap.Config.ALPHA_8, true);
}
-
- private class OutlineGeneratorCallback implements Runnable {
-
- private final Bitmap mPreviewSnapshot;
- private final Context mContext;
- private final boolean mIsIcon;
-
- OutlineGeneratorCallback(Bitmap preview) {
- mPreviewSnapshot = preview;
- mContext = mView.getContext();
- mIsIcon = mView instanceof BubbleTextView;
- }
-
- @Override
- public void run() {
- Bitmap preview = convertPreviewToAlphaBitmap(mPreviewSnapshot);
- if (mIsIcon) {
- int size = ActivityContext.lookupContext(mContext).getDeviceProfile().iconSizePx;
- preview = Bitmap.createScaledBitmap(preview, size, size, false);
- }
- //else case covers AppWidgetHost (doesn't drag/drop across different device profiles)
-
- // We start by removing most of the alpha channel so as to ignore shadows, and
- // other types of partial transparency when defining the shape of the object
- byte[] pixels = new byte[preview.getWidth() * preview.getHeight()];
- ByteBuffer buffer = ByteBuffer.wrap(pixels);
- buffer.rewind();
- preview.copyPixelsToBuffer(buffer);
-
- for (int i = 0; i < pixels.length; i++) {
- if ((pixels[i] & 0xFF) < 188) {
- pixels[i] = 0;
- }
- }
-
- buffer.rewind();
- preview.copyPixelsFromBuffer(buffer);
-
- final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- Canvas canvas = new Canvas();
-
- // calculate the outer blur first
- paint.setMaskFilter(new BlurMaskFilter(blurSizeOutline, BlurMaskFilter.Blur.OUTER));
- int[] outerBlurOffset = new int[2];
- Bitmap thickOuterBlur = preview.extractAlpha(paint, outerBlurOffset);
-
- paint.setMaskFilter(new BlurMaskFilter(
- mContext.getResources().getDimension(R.dimen.blur_size_thin_outline),
- BlurMaskFilter.Blur.OUTER));
- int[] brightOutlineOffset = new int[2];
- Bitmap brightOutline = preview.extractAlpha(paint, brightOutlineOffset);
-
- // calculate the inner blur
- canvas.setBitmap(preview);
- canvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
- paint.setMaskFilter(new BlurMaskFilter(blurSizeOutline, BlurMaskFilter.Blur.NORMAL));
- int[] thickInnerBlurOffset = new int[2];
- Bitmap thickInnerBlur = preview.extractAlpha(paint, thickInnerBlurOffset);
-
- // mask out the inner blur
- paint.setMaskFilter(null);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
- canvas.setBitmap(thickInnerBlur);
- canvas.drawBitmap(preview, -thickInnerBlurOffset[0],
- -thickInnerBlurOffset[1], paint);
- canvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(), paint);
- canvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1], paint);
-
- // draw the inner and outer blur
- paint.setXfermode(null);
- canvas.setBitmap(preview);
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
- canvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
- paint);
- canvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1], paint);
-
- // draw the bright outline
- canvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1], paint);
-
- // cleanup
- canvas.setBitmap(null);
- brightOutline.recycle();
- thickOuterBlur.recycle();
- thickInnerBlur.recycle();
-
- generatedDragOutline = preview;
- }
- }
}
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
index 4890ba6..d5a79dd 100644
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
@@ -16,7 +16,7 @@
package com.android.launcher3.icons;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
import android.content.ComponentName;
import android.content.Context;
@@ -100,7 +100,7 @@
* Launcher specific checks
*/
public static Drawable getIcon(Context context, ShortcutInfo shortcutInfo, int density) {
- if (GO_DISABLE_WIDGETS) {
+ if (GO_DISABLE_SHORTCUTS) {
return null;
}
try {
diff --git a/src/com/android/launcher3/logging/KeyboardStateManager.java b/src/com/android/launcher3/logging/KeyboardStateManager.java
new file mode 100644
index 0000000..3103af1
--- /dev/null
+++ b/src/com/android/launcher3/logging/KeyboardStateManager.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 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 static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.NO_IME_ACTION;
+
+import android.os.SystemClock;
+
+/**
+ * Class to maintain keyboard states.
+ */
+public class KeyboardStateManager {
+ private long mUpdatedTime;
+
+ public enum KeyboardState {
+ NO_IME_ACTION,
+ SHOW,
+ HIDE,
+ }
+
+ private KeyboardState mKeyboardState;
+
+ public KeyboardStateManager() {
+ mKeyboardState = NO_IME_ACTION;
+ }
+
+ /**
+ * Returns time when keyboard state was updated.
+ */
+ public long getLastUpdatedTime() {
+ return mUpdatedTime;
+ }
+
+ /**
+ * Returns current keyboard state.
+ */
+ public KeyboardState getKeyboardState() {
+ return mKeyboardState;
+ }
+
+ /**
+ * Setter method to set keyboard state.
+ */
+ public void setKeyboardState(KeyboardState keyboardState) {
+ mUpdatedTime = SystemClock.elapsedRealtime();
+ mKeyboardState = keyboardState;
+ }
+}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index c4ec4e3..32237e2 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -56,6 +56,7 @@
private InstanceId mInstanceId;
protected @Nullable ActivityContext mActivityContext = null;
+ private KeyboardStateManager mKeyboardStateManager;
/**
* Returns event enum based on the two state transition information when swipe
@@ -592,6 +593,12 @@
@UiEvent(doc = "User tapped on Share app system shortcut.")
LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP(1075),
+
+ @UiEvent(doc = "User has invoked split to right half from an app icon menu")
+ LAUNCHER_APP_ICON_MENU_SPLIT_RIGHT_BOTTOM(1199),
+
+ @UiEvent(doc = "User has invoked split to left half from an app icon menu")
+ LAUNCHER_APP_ICON_MENU_SPLIT_LEFT_TOP(1200)
;
// ADD MORE
@@ -816,6 +823,16 @@
return logger;
}
+ /**
+ * Returns a singleton KeyboardStateManager.
+ */
+ public KeyboardStateManager keyboardStateManager() {
+ if (mKeyboardStateManager == null) {
+ mKeyboardStateManager = new KeyboardStateManager();
+ }
+ return mKeyboardStateManager;
+ }
+
protected StatsLogger createLogger() {
return new StatsLogger() {
};
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index de23c4b..ffb0f2f 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -17,7 +17,7 @@
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
import static com.android.launcher3.shortcuts.ShortcutRequest.PINNED;
import static java.util.stream.Collectors.groupingBy;
@@ -286,7 +286,7 @@
* shortcuts and unpinning any extra shortcuts.
*/
public synchronized void updateShortcutPinnedState(Context context, UserHandle user) {
- if (GO_DISABLE_WIDGETS) {
+ if (GO_DISABLE_SHORTCUTS) {
return;
}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index c25929a..341372e 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -31,6 +31,7 @@
import android.util.ArrayMap;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.InvariantDeviceProfile;
@@ -47,6 +48,7 @@
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -776,17 +778,6 @@
values.put(LauncherSettings.Favorites.SPANY, spanY);
}
- /**
- * This method should return an id that should be the same for two folders containing the
- * same elements.
- */
- private String getFolderMigrationId() {
- return mFolderItems.keySet().stream()
- .map(intentString -> mFolderItems.get(intentString).size() + intentString)
- .sorted()
- .collect(Collectors.joining(","));
- }
-
/** This id is not used in the DB is only used while doing the migration and it identifies
* an entry on each workspace. For example two calculator icons would have the same
* migration id even thought they have different database ids.
@@ -797,9 +788,47 @@
return getFolderMigrationId();
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
return mProvider;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ final String intentStr = cleanIntentString(mIntent);
+ try {
+ Intent i = Intent.parseUri(intentStr, 0);
+ return Objects.requireNonNull(i.getComponent()).toString();
+ } catch (Exception e) {
+ return intentStr;
+ }
default:
- return mIntent;
+ return cleanIntentString(mIntent);
}
}
+
+ /**
+ * This method should return an id that should be the same for two folders containing the
+ * same elements.
+ */
+ @NonNull
+ private String getFolderMigrationId() {
+ return mFolderItems.keySet().stream()
+ .map(intentString -> mFolderItems.get(intentString).size()
+ + cleanIntentString(intentString))
+ .sorted()
+ .collect(Collectors.joining(","));
+ }
+
+ /**
+ * This is needed because sourceBounds can change and make the id of two equal items
+ * different.
+ */
+ @NonNull
+ private String cleanIntentString(@NonNull String intentStr) {
+ try {
+ Intent i = Intent.parseUri(intentStr, 0);
+ i.setSourceBounds(null);
+ return i.toURI();
+ } catch (URISyntaxException e) {
+ Log.e(TAG, "Unable to parse Intent string", e);
+ return intentStr;
+ }
+
+ }
}
}
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index 229bb2d..69f9b53 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -288,6 +288,7 @@
}
@Override
+ @Nullable
public Intent getIntent() {
return intent;
}
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 24e7dd3..34972e7 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -29,6 +29,7 @@
import android.os.UserManager;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.LauncherSettings;
@@ -65,6 +66,7 @@
}
@Override
+ @Nullable
public Intent getIntent() {
return intent;
}
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index 8386adb..524b769 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -26,6 +26,7 @@
import android.os.Process;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
@@ -154,7 +155,7 @@
}
@Override
- public void onAddToDatabase(ContentWriter writer) {
+ public void onAddToDatabase(@NonNull ContentWriter writer) {
super.onAddToDatabase(writer);
writer.put(LauncherSettings.Favorites.TITLE, title)
.put(LauncherSettings.Favorites.OPTIONS, options);
@@ -206,8 +207,9 @@
return String.format("%s; labelState=%s", super.dumpProperties(), getLabelState());
}
+ @NonNull
@Override
- public LauncherAtom.ItemInfo buildProto(FolderInfo fInfo) {
+ public LauncherAtom.ItemInfo buildProto(@Nullable FolderInfo fInfo) {
FolderIcon.Builder folderIcon = FolderIcon.newBuilder()
.setCardinality(contents.size());
if (LabelState.SUGGESTED.equals(getLabelState())) {
@@ -261,6 +263,7 @@
: LabelState.SUGGESTED;
}
+ @NonNull
@Override
public ItemInfo makeShallowCopy() {
FolderInfo folderInfo = new FolderInfo();
@@ -272,6 +275,7 @@
/**
* Returns {@link LauncherAtom.FolderIcon} wrapped as {@link LauncherAtom.ItemInfo} for logging.
*/
+ @NonNull
@Override
public LauncherAtom.ItemInfo buildProto() {
return buildProto(null);
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 1e8e3ca..466f63f 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -42,6 +42,7 @@
import android.os.Process;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
@@ -141,30 +142,34 @@
/**
* Title of the item
*/
+ @Nullable
public CharSequence title;
/**
* Content description of the item.
*/
+ @Nullable
public CharSequence contentDescription;
/**
* When the instance is created using {@link #copyFrom}, this field is used to keep track of
* original {@link ComponentName}.
*/
+ @Nullable
private ComponentName mComponentName;
+ @NonNull
public UserHandle user;
public ItemInfo() {
user = Process.myUserHandle();
}
- protected ItemInfo(ItemInfo info) {
+ protected ItemInfo(@NonNull final ItemInfo info) {
copyFrom(info);
}
- public void copyFrom(ItemInfo info) {
+ public void copyFrom(@NonNull final ItemInfo info) {
id = info.id;
title = info.title;
cellX = info.cellX;
@@ -182,6 +187,7 @@
mComponentName = info.getTargetComponent();
}
+ @Nullable
public Intent getIntent() {
return null;
}
@@ -209,7 +215,7 @@
: null;
}
- public void writeToValues(ContentWriter writer) {
+ public void writeToValues(@NonNull final ContentWriter writer) {
writer.put(LauncherSettings.Favorites.ITEM_TYPE, itemType)
.put(LauncherSettings.Favorites.CONTAINER, container)
.put(LauncherSettings.Favorites.SCREEN, screenId)
@@ -220,7 +226,7 @@
.put(LauncherSettings.Favorites.RANK, rank);
}
- public void readFromValues(ContentValues values) {
+ public void readFromValues(@NonNull final ContentValues values) {
itemType = values.getAsInteger(LauncherSettings.Favorites.ITEM_TYPE);
container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
screenId = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
@@ -234,7 +240,7 @@
/**
* Write the fields of this item to the DB
*/
- public void onAddToDatabase(ContentWriter writer) {
+ public void onAddToDatabase(@NonNull final ContentWriter writer) {
if (Workspace.EXTRA_EMPTY_SCREEN_IDS.contains(screenId)) {
// We should never persist an item on the extra empty screen.
throw new RuntimeException("Screen id should not be extra empty screen: " + screenId);
@@ -245,10 +251,12 @@
}
@Override
+ @NonNull
public final String toString() {
return getClass().getSimpleName() + "(" + dumpProperties() + ")";
}
+ @NonNull
protected String dumpProperties() {
return "id=" + id
+ " type=" + LauncherSettings.Favorites.itemTypeToString(itemType)
@@ -288,14 +296,17 @@
/**
* Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
*/
+ @NonNull
public LauncherAtom.ItemInfo buildProto() {
return buildProto(null);
}
/**
* Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
+ * @param fInfo
*/
- public LauncherAtom.ItemInfo buildProto(FolderInfo fInfo) {
+ @NonNull
+ public LauncherAtom.ItemInfo buildProto(@Nullable final FolderInfo fInfo) {
LauncherAtom.ItemInfo.Builder itemBuilder = getDefaultItemInfoBuilder();
Optional<ComponentName> nullableComponent = Optional.ofNullable(getTargetComponent());
switch (itemType) {
@@ -373,6 +384,7 @@
return itemBuilder.build();
}
+ @NonNull
protected LauncherAtom.ItemInfo.Builder getDefaultItemInfoBuilder() {
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(!Process.myUserHandle().equals(user));
@@ -383,6 +395,7 @@
/**
* Returns {@link ContainerInfo} used when logging this item.
*/
+ @NonNull
public ContainerInfo getContainerInfo() {
switch (container) {
case CONTAINER_HOTSEAT:
@@ -447,6 +460,7 @@
* Returns non-AOSP container wrapped by {@link ExtendedContainers} object. Should be overridden
* by build variants.
*/
+ @NonNull
protected ExtendedContainers getExtendedContainer() {
return ExtendedContainers.getDefaultInstance();
}
@@ -454,6 +468,7 @@
/**
* Returns shallow copy of the object.
*/
+ @NonNull
public ItemInfo makeShallowCopy() {
ItemInfo itemInfo = new ItemInfo();
itemInfo.copyFrom(this);
@@ -463,7 +478,8 @@
/**
* Sets the title of the item and writes to DB model if needed.
*/
- public void setTitle(CharSequence title, ModelWriter modelWriter) {
+ public void setTitle(@Nullable final CharSequence title,
+ @Nullable final ModelWriter modelWriter) {
this.title = title;
}
}
diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
index e57a895..1fbe04f 100644
--- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
@@ -29,6 +29,7 @@
import android.content.res.Resources;
import android.os.Process;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.Launcher;
@@ -191,7 +192,7 @@
}
@Override
- public void onAddToDatabase(ContentWriter writer) {
+ public void onAddToDatabase(@NonNull ContentWriter writer) {
super.onAddToDatabase(writer);
writer.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId)
.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString())
@@ -283,8 +284,9 @@
}
}
+ @NonNull
@Override
- public LauncherAtom.ItemInfo buildProto(FolderInfo folderInfo) {
+ public LauncherAtom.ItemInfo buildProto(@Nullable FolderInfo folderInfo) {
LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
return info.toBuilder()
.setWidget(info.getWidget().toBuilder().setWidgetFeatures(widgetFeatures))
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index e879313..04042ea 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -24,6 +24,7 @@
import android.os.Process;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
@@ -70,7 +71,7 @@
}
@Override
- public void copyFrom(com.android.launcher3.model.data.ItemInfo info) {
+ public void copyFrom(@NonNull com.android.launcher3.model.data.ItemInfo info) {
super.copyFrom(info);
SearchActionItemInfo itemInfo = (SearchActionItemInfo) info;
this.mFallbackPackageName = itemInfo.mFallbackPackageName;
@@ -91,6 +92,7 @@
}
@Override
+ @Nullable
public Intent getIntent() {
return mIntent;
}
@@ -131,8 +133,9 @@
return new SearchActionItemInfo(this);
}
+ @NonNull
@Override
- public ItemInfo buildProto(FolderInfo fInfo) {
+ public ItemInfo buildProto(@Nullable FolderInfo fInfo) {
SearchActionItem.Builder itemBuilder = SearchActionItem.newBuilder()
.setPackageName(mFallbackPackageName);
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 2b3da33..1f16474 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -24,6 +24,7 @@
import android.text.TextUtils;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -130,7 +131,7 @@
}
@Override
- public void onAddToDatabase(ContentWriter writer) {
+ public void onAddToDatabase(@NonNull ContentWriter writer) {
super.onAddToDatabase(writer);
writer.put(Favorites.TITLE, title)
.put(Favorites.INTENT, getIntent())
@@ -147,6 +148,7 @@
}
@Override
+ @Nullable
public Intent getIntent() {
return intent;
}
diff --git a/src/com/android/launcher3/shortcuts/ShortcutRequest.java b/src/com/android/launcher3/shortcuts/ShortcutRequest.java
index 5291ce4..07d3292 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutRequest.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutRequest.java
@@ -16,7 +16,7 @@
package com.android.launcher3.shortcuts;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
import android.content.ComponentName;
import android.content.Context;
@@ -46,7 +46,7 @@
| ShortcutQuery.FLAG_MATCH_MANIFEST;
public static final int PINNED = ShortcutQuery.FLAG_MATCH_PINNED;
- private final ShortcutQuery mQuery = GO_DISABLE_WIDGETS ? null : new ShortcutQuery();
+ private final ShortcutQuery mQuery = GO_DISABLE_SHORTCUTS ? null : new ShortcutQuery();
private final Context mContext;
private final UserHandle mUserHandle;
@@ -73,7 +73,7 @@
* @return A list of ShortcutInfo's associated with the given package.
*/
public ShortcutRequest forPackage(String packageName, @Nullable List<String> shortcutIds) {
- if (!GO_DISABLE_WIDGETS && packageName != null) {
+ if (!GO_DISABLE_SHORTCUTS && packageName != null) {
mQuery.setPackage(packageName);
mQuery.setShortcutIds(shortcutIds);
}
@@ -81,7 +81,7 @@
}
public ShortcutRequest withContainer(@Nullable ComponentName activity) {
- if (!GO_DISABLE_WIDGETS) {
+ if (!GO_DISABLE_SHORTCUTS) {
if (activity == null) {
mFailed = true;
} else {
@@ -92,7 +92,7 @@
}
public QueryResult query(int flags) {
- if (GO_DISABLE_WIDGETS || mFailed) {
+ if (GO_DISABLE_SHORTCUTS || mFailed) {
return QueryResult.DEFAULT;
}
mQuery.setQueryFlags(flags);
@@ -108,7 +108,7 @@
public static class QueryResult extends ArrayList<ShortcutInfo> {
- static final QueryResult DEFAULT = new QueryResult(GO_DISABLE_WIDGETS);
+ static final QueryResult DEFAULT = new QueryResult(GO_DISABLE_SHORTCUTS);
private final boolean mWasSuccess;
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index c44e1e1..54e8e5b 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -345,6 +345,7 @@
@Override
public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
onStateTransitionFailed(state);
}
};
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index fd8b2e5..c408904 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -21,17 +21,19 @@
import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
import static com.android.launcher3.Utilities.dpiFromPx;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Handler;
+import android.os.Message;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.UiThreadHelper;
/**
* Utility class to manage launcher rotation
@@ -39,8 +41,6 @@
public class RotationHelper implements OnSharedPreferenceChangeListener,
DisplayController.DisplayInfoChangeListener {
- private static final String TAG = "RotationHelper";
-
public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
/**
@@ -60,6 +60,7 @@
private BaseActivity mActivity;
private SharedPreferences mSharedPrefs = null;
+ private final Handler mRequestOrientationHandler;
private boolean mIgnoreAutoRotateSettings;
private boolean mForceAllowRotationForTesting;
@@ -89,6 +90,8 @@
public RotationHelper(BaseActivity activity) {
mActivity = activity;
+ mRequestOrientationHandler =
+ new Handler(UI_HELPER_EXECUTOR.getLooper(), this::setOrientationAsync);
}
private void setIgnoreAutoRotateSettings(boolean ignoreAutoRotateSettings) {
@@ -202,10 +205,15 @@
}
if (activityFlags != mLastActivityFlags) {
mLastActivityFlags = activityFlags;
- UiThreadHelper.setOrientationAsync(mActivity, activityFlags);
+ mRequestOrientationHandler.sendEmptyMessage(activityFlags);
}
}
+ private boolean setOrientationAsync(Message msg) {
+ mActivity.setRequestedOrientation(msg.what);
+ return true;
+ }
+
/**
* @return how many factors {@param newRotation} is rotated 90 degrees clockwise.
* E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise...
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index b63715c..3286afb 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -31,8 +31,7 @@
private static final int STATE_FLAGS = FLAG_MULTI_PAGE
| FLAG_WORKSPACE_INACCESSIBLE | FLAG_DISABLE_RESTORE
- | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_WORKSPACE_HAS_BACKGROUNDS
- | FLAG_HIDE_BACK_BUTTON;
+ | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_WORKSPACE_HAS_BACKGROUNDS;
public SpringLoadedState(int id) {
super(id, LAUNCHER_STATE_HOME, STATE_FLAGS);
diff --git a/src/com/android/launcher3/testing/shared/ResourceUtils.java b/src/com/android/launcher3/testing/shared/ResourceUtils.java
index 551aeaf..d0ae258 100644
--- a/src/com/android/launcher3/testing/shared/ResourceUtils.java
+++ b/src/com/android/launcher3/testing/shared/ResourceUtils.java
@@ -36,6 +36,8 @@
public static final String STATUS_BAR_HEIGHT_LANDSCAPE = "status_bar_height_landscape";
public static final String STATUS_BAR_HEIGHT_PORTRAIT = "status_bar_height_portrait";
+ public static final String NAV_BAR_INTERACTION_MODE_RES_NAME = "config_navBarInteractionMode";
+
public static int getNavbarSize(String resName, Resources res) {
return getDimenByName(resName, res, DEFAULT_NAVBAR_VALUE);
}
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index 73f994f..1421ece 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -27,7 +27,6 @@
import android.view.View.OnLongClickListener;
import com.android.launcher3.CellLayout;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DropTarget;
import com.android.launcher3.Launcher;
import com.android.launcher3.dragndrop.DragController;
@@ -118,10 +117,7 @@
}
});
- DeviceProfile grid = launcher.getDeviceProfile();
- DragOptions options = new DragOptions();
- options.intrinsicIconScaleFactor = (float) grid.allAppsIconSizePx / grid.iconSizePx;
- launcher.getWorkspace().beginDragShared(v, launcher.getAppsView(), options);
+ launcher.getWorkspace().beginDragShared(v, launcher.getAppsView(), new DragOptions());
return false;
}
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 9ac1c0e..9afca4f 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -376,6 +376,19 @@
return isRtl ? 1 : -1;
}
+ @Override
+ public void setSecondaryTaskMenuPosition(SplitBounds splitBounds, View taskView,
+ DeviceProfile deviceProfile, View primarySnaphotView, View taskMenuView) {
+ float topLeftTaskPlusDividerPercent = splitBounds.appsStackedVertically
+ ? (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent)
+ : (splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent);
+ FrameLayout.LayoutParams snapshotParams =
+ (FrameLayout.LayoutParams) primarySnaphotView.getLayoutParams();
+ float additionalOffset = (taskView.getHeight() - snapshotParams.topMargin)
+ * topLeftTaskPlusDividerPercent;
+ taskMenuView.setY(taskMenuView.getY() + additionalOffset);
+ }
+
/* -------------------- */
@Override
@@ -440,7 +453,7 @@
public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
int splitInstructionsWidth, int threeButtonNavShift) {
out.setPivotX(0);
- out.setPivotY(0);
+ out.setPivotY(splitInstructionsHeight);
out.setRotation(getDegreesRotated());
int distanceToEdge = out.getResources().getDimensionPixelSize(
R.dimen.split_instructions_bottom_margin_phone_landscape);
@@ -448,8 +461,8 @@
int insetCorrectionX = dp.getInsets().left;
// Center the view in case of unbalanced insets on top or bottom of screen
int insetCorrectionY = (dp.getInsets().bottom - dp.getInsets().top) / 2;
- out.setTranslationX(splitInstructionsHeight + distanceToEdge - insetCorrectionX);
- out.setTranslationY(((splitInstructionsHeight - splitInstructionsWidth) / 2f)
+ out.setTranslationX(distanceToEdge - insetCorrectionX);
+ out.setTranslationY(((-splitInstructionsHeight - splitInstructionsWidth) / 2f)
+ insetCorrectionY);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) out.getLayoutParams();
// Setting gravity to LEFT instead of the lint-recommended START because we always want this
@@ -492,8 +505,8 @@
int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
int dividerBar = splitBoundsConfig.appsStackedVertically
- ? splitBoundsConfig.visualDividerBounds.height()
- : splitBoundsConfig.visualDividerBounds.width();
+ ? (int) (splitBoundsConfig.dividerHeightPercent * parentHeight)
+ : (int) (splitBoundsConfig.dividerWidthPercent * parentWidth);
int primarySnapshotHeight;
int primarySnapshotWidth;
int secondarySnapshotHeight;
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 1a8d355..cbcb700 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -231,6 +231,14 @@
int getTaskDragDisplacementFactor(boolean isRtl);
/**
+ * Calls the corresponding {@link View#setX(float)} or {@link View#setY(float)}
+ * on {@param taskMenuView} by taking the space needed by {@param primarySnapshotView} into
+ * account.
+ * This is expected to only be called for secondary (bottom/right) tasks.
+ */
+ void setSecondaryTaskMenuPosition(SplitBounds splitBounds, View taskView,
+ DeviceProfile deviceProfile, View primarySnaphotView, View taskMenuView);
+ /**
* Maps the velocity from the coordinate plane of the foreground app to that
* of Launcher's (which now will always be portrait)
*/
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index dd9f642..bc1b634 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -27,7 +27,7 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
-import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
@@ -316,6 +316,26 @@
}
@Override
+ public void setSecondaryTaskMenuPosition(SplitBounds splitBounds, View taskView,
+ DeviceProfile deviceProfile, View primarySnaphotView, View taskMenuView) {
+ float topLeftTaskPlusDividerPercent = splitBounds.appsStackedVertically
+ ? (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent)
+ : (splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent);
+ FrameLayout.LayoutParams snapshotParams =
+ (FrameLayout.LayoutParams) primarySnaphotView.getLayoutParams();
+ float additionalOffset;
+ if (deviceProfile.isLandscape) {
+ additionalOffset = (taskView.getWidth() - snapshotParams.leftMargin)
+ * topLeftTaskPlusDividerPercent;
+ taskMenuView.setX(taskMenuView.getX() + additionalOffset);
+ } else {
+ additionalOffset = (taskView.getHeight() - snapshotParams.topMargin)
+ * topLeftTaskPlusDividerPercent;
+ taskMenuView.setY(taskMenuView.getY() + additionalOffset);
+ }
+ }
+
+ @Override
public Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile,
View[] thumbnailViews, int desiredTaskId, View banner) {
@@ -500,7 +520,7 @@
public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
int splitInstructionsWidth, int threeButtonNavShift) {
out.setPivotX(0);
- out.setPivotY(0);
+ out.setPivotY(splitInstructionsHeight);
out.setRotation(getDegreesRotated());
int distanceToEdge;
if ((DisplayController.getNavigationMode(out.getContext()) == THREE_BUTTONS)
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index 387e980..55bb5e8 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -190,7 +190,7 @@
public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
int splitInstructionsWidth, int threeButtonNavShift) {
out.setPivotX(0);
- out.setPivotY(0);
+ out.setPivotY(splitInstructionsHeight);
out.setRotation(getDegreesRotated());
int distanceToEdge = out.getResources().getDimensionPixelSize(
R.dimen.split_instructions_bottom_margin_phone_landscape);
@@ -198,9 +198,8 @@
int insetCorrectionX = dp.getInsets().right;
// Center the view in case of unbalanced insets on top or bottom of screen
int insetCorrectionY = (dp.getInsets().bottom - dp.getInsets().top) / 2;
- out.setTranslationX(splitInstructionsWidth - splitInstructionsHeight - distanceToEdge
- + insetCorrectionX);
- out.setTranslationY(((splitInstructionsHeight + splitInstructionsWidth) / 2f)
+ out.setTranslationX(splitInstructionsWidth - distanceToEdge + insetCorrectionX);
+ out.setTranslationY(((-splitInstructionsHeight + splitInstructionsWidth) / 2f)
+ insetCorrectionY);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) out.getLayoutParams();
// Setting gravity to RIGHT instead of the lint-recommended END because we always want this
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 94f9f25..e57c88d 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -19,11 +19,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.Utilities.dpiFromPx;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_2_BUTTON;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_3_BUTTON;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
@@ -46,9 +42,7 @@
import androidx.annotation.AnyThread;
import androidx.annotation.UiThread;
-import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.Utilities;
-import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;
@@ -56,6 +50,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -81,7 +76,6 @@
| CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS | CHANGE_NAVIGATION_MODE;
private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
- private static final String NAV_BAR_INTERACTION_MODE_RES_NAME = "config_navBarInteractionMode";
private static final String TARGET_OVERLAY_PACKAGE = "android";
private final Context mContext;
@@ -294,7 +288,7 @@
// Used for testing
public Info(Context displayInfoContext,
WindowManagerProxy wmProxy,
- ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
+ Map<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
normalizedDisplayInfo = displayInfo.normalize();
rotation = displayInfo.rotation;
@@ -305,7 +299,7 @@
fontScale = config.fontScale;
densityDpi = config.densityDpi;
mScreenSizeDp = new PortraitSize(config.screenHeightDp, config.screenWidthDp);
- navigationMode = parseNavigationMode(displayInfoContext);
+ navigationMode = wmProxy.getNavigationMode(displayInfoContext);
mPerDisplayBounds.putAll(perDisplayBoundsCache);
WindowBounds[] cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
@@ -405,35 +399,4 @@
}
}
- public enum NavigationMode {
- THREE_BUTTONS(false, 0, LAUNCHER_NAVIGATION_MODE_3_BUTTON),
- TWO_BUTTONS(true, 1, LAUNCHER_NAVIGATION_MODE_2_BUTTON),
- NO_BUTTON(true, 2, LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON);
-
- public final boolean hasGestures;
- public final int resValue;
- public final LauncherEvent launcherEvent;
-
- NavigationMode(boolean hasGestures, int resValue, LauncherEvent launcherEvent) {
- this.hasGestures = hasGestures;
- this.resValue = resValue;
- this.launcherEvent = launcherEvent;
- }
- }
-
- private static NavigationMode parseNavigationMode(Context context) {
- int modeInt = ResourceUtils.getIntegerByName(NAV_BAR_INTERACTION_MODE_RES_NAME,
- context.getResources(), INVALID_RESOURCE_HANDLE);
-
- if (modeInt == INVALID_RESOURCE_HANDLE) {
- Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
- } else {
- for (NavigationMode m : NavigationMode.values()) {
- if (m.resValue == modeInt) {
- return m;
- }
- }
- }
- return Utilities.ATLEAST_S ? NavigationMode.NO_BUTTON : NavigationMode.THREE_BUTTONS;
- }
}
diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java
index 6bc26e7..ee1d1ff 100644
--- a/src/com/android/launcher3/util/LogConfig.java
+++ b/src/com/android/launcher3/util/LogConfig.java
@@ -40,4 +40,14 @@
* When turned on, we enable suggest related logging.
*/
public static final String SEARCH_LOGGING = "SearchLogging";
+
+ /**
+ * When turned on, we enable IME related latency related logging.
+ */
+ public static final String IME_LATENCY_LOGGING = "ImeLatencyLogging";
+
+ /**
+ * When turned on, we enable web suggest appSearch related logging.
+ */
+ public static final String WEB_APP_SEARCH_LOGGING = "WebAppSearchLogging";
}
diff --git a/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java b/src/com/android/launcher3/util/MultiPropertyFactory.java
similarity index 70%
rename from src/com/android/launcher3/util/MultiAdditivePropertyFactory.java
rename to src/com/android/launcher3/util/MultiPropertyFactory.java
index 50f7027..e7a7785 100644
--- a/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java
+++ b/src/com/android/launcher3/util/MultiPropertyFactory.java
@@ -20,7 +20,6 @@
import android.util.FloatProperty;
import android.util.Log;
import android.util.Property;
-import android.view.View;
/**
* Allows to combine multiple values set by several sources.
@@ -30,43 +29,55 @@
* time.
*
* This class behaves similarly to [MultiValueAlpha], but is meant to be more abstract and reusable.
- * It sets the addition of all values.
+ * It aggregate all values using the provided [aggregator].
*
* @param <T> Type where to apply the property.
*/
-public class MultiAdditivePropertyFactory<T extends View> {
+public class MultiPropertyFactory<T> {
private static final boolean DEBUG = false;
- private static final String TAG = "MultiAdditivePropertyFactory";
+ private static final String TAG = "MultiPropertyFactory";
private final String mName;
- private final ArrayMap<Integer, MultiAdditiveProperty> mProperties =
- new ArrayMap<>();
+ private final ArrayMap<Integer, MultiProperty> mProperties = new ArrayMap<>();
// This is an optimization for cases when set is called repeatedly with the same setterIndex.
private float mAggregationOfOthers = 0f;
private Integer mLastIndexSet = -1;
- private final Property<View, Float> mProperty;
+ private final Property<T, Float> mProperty;
+ private final FloatBiFunction mAggregator;
- public MultiAdditivePropertyFactory(String name, Property<View, Float> property) {
+ /**
+ * Represents a function that accepts two float and produces a float.
+ */
+ public interface FloatBiFunction {
+ /**
+ * Applies this function to the given arguments.
+ */
+ float apply(float a, float b);
+ }
+
+ public MultiPropertyFactory(String name, Property<T, Float> property,
+ FloatBiFunction aggregator) {
mName = name;
mProperty = property;
+ mAggregator = aggregator;
}
/** Returns the [MultiFloatProperty] associated with [inx], creating it if not present. */
- public MultiAdditiveProperty get(Integer index) {
+ public MultiProperty get(Integer index) {
return mProperties.computeIfAbsent(index,
- (k) -> new MultiAdditiveProperty(index, mName + "_" + index));
+ (k) -> new MultiProperty(index, mName + "_" + index));
}
/**
* Each [setValue] will be aggregated with the other properties values created by the
* corresponding factory.
*/
- class MultiAdditiveProperty extends FloatProperty<T> {
+ class MultiProperty extends FloatProperty<T> {
private final int mInx;
private float mValue = 0f;
- MultiAdditiveProperty(int inx, String name) {
+ MultiProperty(int inx, String name) {
super(name);
mInx = inx;
}
@@ -77,12 +88,13 @@
mAggregationOfOthers = 0f;
mProperties.forEach((key, property) -> {
if (key != mInx) {
- mAggregationOfOthers += property.mValue;
+ mAggregationOfOthers =
+ mAggregator.apply(mAggregationOfOthers, property.mValue);
}
});
mLastIndexSet = mInx;
}
- float lastAggregatedValue = mAggregationOfOthers + newValue;
+ float lastAggregatedValue = mAggregator.apply(mAggregationOfOthers, newValue);
mValue = newValue;
apply(obj, lastAggregatedValue);
@@ -94,13 +106,13 @@
}
@Override
- public Float get(T view) {
+ public Float get(T object) {
// The scale of the view should match mLastAggregatedValue. Still, if it has been
// changed without using this property, it can differ. As this get method is usually
// used to set the starting point on an animation, this would result in some jumps
// when the view scale is different than the last aggregated value. To stay on the
// safe side, let's return the real view scale.
- return mProperty.get(view);
+ return mProperty.get(object);
}
@Override
@@ -109,7 +121,7 @@
}
}
- protected void apply(View view, float value) {
- mProperty.set(view, value);
+ protected void apply(T object, float value) {
+ mProperty.set(object, value);
}
}
diff --git a/src/com/android/launcher3/util/NavigationMode.java b/src/com/android/launcher3/util/NavigationMode.java
new file mode 100644
index 0000000..37dd41c
--- /dev/null
+++ b/src/com/android/launcher3/util/NavigationMode.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.util;
+
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_2_BUTTON;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_3_BUTTON;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON;
+
+import com.android.launcher3.logging.StatsLogManager;
+
+/**
+ * Navigation mode used in the device.
+ */
+public enum NavigationMode {
+ THREE_BUTTONS(false, 0, LAUNCHER_NAVIGATION_MODE_3_BUTTON),
+ TWO_BUTTONS(true, 1, LAUNCHER_NAVIGATION_MODE_2_BUTTON),
+ NO_BUTTON(true, 2, LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON);
+
+ public final boolean hasGestures;
+ public final int resValue;
+ public final StatsLogManager.LauncherEvent launcherEvent;
+
+ NavigationMode(boolean hasGestures, int resValue, StatsLogManager.LauncherEvent launcherEvent) {
+ this.hasGestures = hasGestures;
+ this.resValue = resValue;
+ this.launcherEvent = launcherEvent;
+ }
+}
diff --git a/src/com/android/launcher3/util/PendingSplitSelectInfo.java b/src/com/android/launcher3/util/PendingSplitSelectInfo.java
index ed02465..58c3be5 100644
--- a/src/com/android/launcher3/util/PendingSplitSelectInfo.java
+++ b/src/com/android/launcher3/util/PendingSplitSelectInfo.java
@@ -16,6 +16,7 @@
package com.android.launcher3.util;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
/**
@@ -28,10 +29,13 @@
private final int mStagedTaskId;
private final int mStagePosition;
+ private final StatsLogManager.EventEnum mSource;
- public PendingSplitSelectInfo(int stagedTaskId, int stagePosition) {
+ public PendingSplitSelectInfo(int stagedTaskId, int stagePosition,
+ StatsLogManager.EventEnum source) {
this.mStagedTaskId = stagedTaskId;
this.mStagePosition = stagePosition;
+ this.mSource = source;
}
public int getStagedTaskId() {
@@ -41,4 +45,8 @@
public @StagePosition int getStagePosition() {
return mStagePosition;
}
+
+ public StatsLogManager.EventEnum getSource() {
+ return mSource;
+ }
}
diff --git a/src/com/android/launcher3/util/ShortcutUtil.java b/src/com/android/launcher3/util/ShortcutUtil.java
index 91cf835..79cafa0 100644
--- a/src/com/android/launcher3/util/ShortcutUtil.java
+++ b/src/com/android/launcher3/util/ShortcutUtil.java
@@ -34,7 +34,7 @@
* Returns true when we should show depp shortcuts in shortcut menu for the item.
*/
public static boolean supportsDeepShortcuts(ItemInfo info) {
- return isActive(info) && isApp(info) && !WidgetsModel.GO_DISABLE_WIDGETS;
+ return isActive(info) && isApp(info) && !WidgetsModel.GO_DISABLE_SHORTCUTS;
}
/**
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index f14d985..88e1b22 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -16,12 +16,17 @@
package com.android.launcher3.util;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_ICON_MENU_SPLIT_LEFT_TOP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_ICON_MENU_SPLIT_RIGHT_BOTTOM;
+
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.graphics.Rect;
import androidx.annotation.IntDef;
+import com.android.launcher3.logging.StatsLogManager;
+
import java.lang.annotation.Retention;
public final class SplitConfigurationOptions {
@@ -170,4 +175,10 @@
@StageType
public int stageType = STAGE_TYPE_UNDEFINED;
}
+
+ public static StatsLogManager.EventEnum getLogEventForPosition(@StagePosition int position) {
+ return position == STAGE_POSITION_TOP_OR_LEFT
+ ? LAUNCHER_APP_ICON_MENU_SPLIT_LEFT_TOP
+ : LAUNCHER_APP_ICON_MENU_SPLIT_RIGHT_BOTTOM;
+ }
}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
deleted file mode 100644
index 7e6711f..0000000
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2017 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.util;
-
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.util.Log;
-import android.view.View;
-import android.view.WindowInsets;
-import android.view.WindowInsetsController;
-import android.view.inputmethod.InputMethodManager;
-
-import com.android.launcher3.Utilities;
-import com.android.launcher3.views.ActivityContext;
-
-/**
- * Utility class for offloading some class from UI thread
- */
-public class UiThreadHelper {
-
- private static final MainThreadInitializedObject<Handler> HANDLER =
- new MainThreadInitializedObject<>(
- c -> new Handler(UI_HELPER_EXECUTOR.getLooper(), new UiCallbacks(c)));
-
- private static final int MSG_HIDE_KEYBOARD = 1;
- private static final int MSG_SET_ORIENTATION = 2;
- private static final int MSG_RUN_COMMAND = 3;
- private static final String STATS_LOGGER_KEY = "STATS_LOGGER_KEY";
-
- @SuppressLint("NewApi")
- public static void hideKeyboardAsync(ActivityContext activityContext, IBinder token) {
- View root = activityContext.getDragLayer();
-
- if (Utilities.ATLEAST_R) {
- Preconditions.assertUIThread();
- // Hide keyboard with WindowInsetsController if could. In case
- // hideSoftInputFromWindow may get ignored by input connection being finished
- // when the screen is off.
- //
- // In addition, inside IMF, the keyboards are closed asynchronously that launcher no
- // longer need to post to the message queue.
- final WindowInsetsController wic = root.getWindowInsetsController();
- WindowInsets insets = root.getRootWindowInsets();
- boolean isImeShown = insets != null && insets.isVisible(WindowInsets.Type.ime());
- if (wic != null && isImeShown) {
- // this method cannot be called cross threads
- wic.hide(WindowInsets.Type.ime());
- activityContext.getStatsLogManager().logger()
- .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
- return;
- }
- }
- // Since the launcher context cannot be accessed directly from callback, adding secondary
- // message to log keyboard close event asynchronously.
- Bundle mHideKeyboardLoggerMsg = new Bundle();
- mHideKeyboardLoggerMsg.putParcelable(
- STATS_LOGGER_KEY,
- Message.obtain(
- HANDLER.get(root.getContext()),
- () -> activityContext
- .getStatsLogManager()
- .logger()
- .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
- )
- );
-
- Message mHideKeyboardMsg = Message.obtain(HANDLER.get(root.getContext()), MSG_HIDE_KEYBOARD,
- token);
- mHideKeyboardMsg.setData(mHideKeyboardLoggerMsg);
- mHideKeyboardMsg.sendToTarget();
- }
-
- public static void setOrientationAsync(Activity activity, int orientation) {
- Message.obtain(HANDLER.get(activity), MSG_SET_ORIENTATION, orientation, 0, activity)
- .sendToTarget();
- }
-
- public static void setBackButtonAlphaAsync(Context context, AsyncCommand command, float alpha,
- boolean animate) {
- runAsyncCommand(context, command, Float.floatToIntBits(alpha), animate ? 1 : 0);
- }
-
- public static void runAsyncCommand(Context context, AsyncCommand command, int arg1, int arg2) {
- Message.obtain(HANDLER.get(context), MSG_RUN_COMMAND, arg1, arg2, command).sendToTarget();
- }
-
- private static class UiCallbacks implements Handler.Callback {
-
- private final Context mContext;
- private final InputMethodManager mIMM;
-
- UiCallbacks(Context context) {
- mContext = context;
- mIMM = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- }
-
- @Override
- public boolean handleMessage(Message message) {
- switch (message.what) {
- case MSG_HIDE_KEYBOARD:
- if (mIMM.hideSoftInputFromWindow((IBinder) message.obj, 0)) {
- // log keyboard close event only when keyboard is actually closed
- ((Message) message.getData().getParcelable(STATS_LOGGER_KEY))
- .sendToTarget();
- }
- return true;
- case MSG_SET_ORIENTATION:
- ((Activity) message.obj).setRequestedOrientation(message.arg1);
- return true;
- case MSG_RUN_COMMAND:
- ((AsyncCommand) message.obj).execute(mContext, message.arg1, message.arg2);
- return true;
- }
- return false;
- }
- }
-
- public interface AsyncCommand {
- void execute(Context proxy, int arg1, int arg2);
- }
-}
diff --git a/src/com/android/launcher3/util/ViewCapture.java b/src/com/android/launcher3/util/ViewCapture.java
deleted file mode 100644
index e368ac3..0000000
--- a/src/com/android/launcher3/util/ViewCapture.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2022 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.util;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
-import static java.util.stream.Collectors.toList;
-
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Trace;
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Base64OutputStream;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver.OnDrawListener;
-import android.view.Window;
-
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-
-import com.android.launcher3.view.ViewCaptureData.ExportedData;
-import com.android.launcher3.view.ViewCaptureData.FrameData;
-import com.android.launcher3.view.ViewCaptureData.ViewNode;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.concurrent.Future;
-import java.util.zip.GZIPOutputStream;
-
-/**
- * Utility class for capturing view data every frame
- */
-public class ViewCapture implements OnDrawListener {
-
- private static final String TAG = "ViewCapture";
-
- // Number of frames to keep in memory
- private static final int MEMORY_SIZE = 2000;
- // Initial size of the reference pool. This is at least be 5 * total number of views in
- // Launcher. This allows the first free frames avoid object allocation during view capture.
- private static final int INIT_POOL_SIZE = 300;
-
- private final Window mWindow;
- private final View mRoot;
- private final Resources mResources;
-
- private final Handler mHandler;
- private final ViewRef mViewRef = new ViewRef();
-
- private int mFrameIndexBg = -1;
- private final long[] mFrameTimesBg = new long[MEMORY_SIZE];
- private final ViewPropertyRef[] mNodesBg = new ViewPropertyRef[MEMORY_SIZE];
-
- // Pool used for capturing view tree on the UI thread.
- private ViewRef mPool = new ViewRef();
-
- /**
- * @param window the window for the capture data
- */
- public ViewCapture(Window window) {
- mWindow = window;
- mRoot = mWindow.getDecorView();
- mResources = mRoot.getResources();
- mHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::captureViewPropertiesBg);
- }
-
- /**
- * Attaches the ViewCapture to the root
- */
- public void attach() {
- mHandler.post(this::initPool);
- }
-
- /**
- * Removes a previously attached ViewCapture from the root
- */
- public void detach() {
- mHandler.post(() -> MAIN_EXECUTOR.execute(
- () -> mRoot.getViewTreeObserver().removeOnDrawListener(this)));
- }
-
- @Override
- public void onDraw() {
- Trace.beginSection("view_capture");
- captureViewTree(mRoot, mViewRef);
- Message m = Message.obtain(mHandler);
- m.obj = mViewRef.next;
- mHandler.sendMessage(m);
- Trace.endSection();
- }
-
- /**
- * Captures the View property on the background thread, and transfer all the ViewRef objects
- * back to the pool
- */
- @WorkerThread
- private boolean captureViewPropertiesBg(Message msg) {
- ViewRef start = (ViewRef) msg.obj;
- long time = msg.getWhen();
- if (start == null) {
- return false;
- }
- mFrameIndexBg++;
- if (mFrameIndexBg >= MEMORY_SIZE) {
- mFrameIndexBg = 0;
- }
- mFrameTimesBg[mFrameIndexBg] = time;
-
- ViewPropertyRef recycle = mNodesBg[mFrameIndexBg];
-
- ViewPropertyRef result = null;
- ViewPropertyRef resultEnd = null;
-
- ViewRef current = start;
- ViewRef last = start;
- while (current != null) {
- ViewPropertyRef propertyRef = recycle;
- if (propertyRef == null) {
- propertyRef = new ViewPropertyRef();
- } else {
- recycle = recycle.next;
- propertyRef.next = null;
- }
-
- propertyRef.transfer(current);
- last = current;
- current = current.next;
-
- if (result == null) {
- result = propertyRef;
- resultEnd = result;
- } else {
- resultEnd.next = propertyRef;
- resultEnd = propertyRef;
- }
- }
- mNodesBg[mFrameIndexBg] = result;
- ViewRef end = last;
- MAIN_EXECUTOR.execute(() -> addToPool(start, end));
- return true;
- }
-
- @UiThread
- private void addToPool(ViewRef start, ViewRef end) {
- end.next = mPool;
- mPool = start;
- }
-
- @WorkerThread
- private void initPool() {
- ViewRef start = new ViewRef();
- ViewRef current = start;
-
- for (int i = 0; i < INIT_POOL_SIZE; i++) {
- current.next = new ViewRef();
- current = current.next;
- }
-
- ViewRef end = current;
- MAIN_EXECUTOR.execute(() -> {
- addToPool(start, end);
- if (mRoot.isAttachedToWindow()) {
- mRoot.getViewTreeObserver().addOnDrawListener(this);
- }
- });
- }
-
- private String getName() {
- String title = mWindow.getAttributes().getTitle().toString();
- return TextUtils.isEmpty(title) ? mWindow.toString() : title;
- }
-
- /**
- * Starts the dump process which is completed on closing the returned object.
- */
- public SafeCloseable beginDump(PrintWriter writer, FileDescriptor out) {
- Future<ExportedData> task = UI_HELPER_EXECUTOR.submit(this::dumpToProto);
-
- return () -> {
- writer.println();
- writer.println(" ContinuousViewCapture:");
- writer.println(" window " + getName() + ":");
- writer.println(" pkg:" + mRoot.getContext().getPackageName());
- writer.print(" data:");
- writer.flush();
-
- try (OutputStream os = new FileOutputStream(out)) {
- ExportedData data = task.get();
- OutputStream encodedOS = new GZIPOutputStream(new Base64OutputStream(os,
- Base64.NO_CLOSE | Base64.NO_PADDING | Base64.NO_WRAP));
- data.writeTo(encodedOS);
- encodedOS.close();
- os.flush();
- } catch (Exception e) {
- Log.e(TAG, "Error capturing proto", e);
- }
- writer.println();
- writer.println("--end--");
- };
- }
-
- @WorkerThread
- private ExportedData dumpToProto() {
- ExportedData.Builder dataBuilder = ExportedData.newBuilder();
- Resources res = mResources;
- ArrayList<Class> classList = new ArrayList<>();
-
- int size = (mNodesBg[MEMORY_SIZE - 1] == null) ? mFrameIndexBg + 1 : MEMORY_SIZE;
- for (int i = size - 1; i >= 0; i--) {
- int index = (MEMORY_SIZE + mFrameIndexBg - i) % MEMORY_SIZE;
- ViewNode.Builder nodeBuilder = ViewNode.newBuilder();
- mNodesBg[index].toProto(res, classList, nodeBuilder);
- dataBuilder.addFrameData(FrameData.newBuilder()
- .setNode(nodeBuilder)
- .setTimestamp(mFrameTimesBg[index]));
- }
- return dataBuilder
- .addAllClassname(classList.stream().map(Class::getName).collect(toList()))
- .build();
- }
-
- private ViewRef captureViewTree(View view, ViewRef start) {
- ViewRef ref;
- if (mPool != null) {
- ref = mPool;
- mPool = mPool.next;
- ref.next = null;
- } else {
- ref = new ViewRef();
- }
- ref.view = view;
- start.next = ref;
- if (view instanceof ViewGroup) {
- ViewRef result = ref;
- ViewGroup parent = (ViewGroup) view;
- int childCount = ref.childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- result = captureViewTree(parent.getChildAt(i), result);
- }
- return result;
- } else {
- ref.childCount = 0;
- return ref;
- }
- }
-
- private static class ViewPropertyRef {
- // We store reference in memory to avoid generating and storing too many strings
- public Class clazz;
- public int hashCode;
- public int childCount = 0;
-
- public int id;
- public int left, top, right, bottom;
- public int scrollX, scrollY;
-
- public float translateX, translateY;
- public float scaleX, scaleY;
- public float alpha;
- public float elevation;
-
- public int visibility;
- public boolean willNotDraw;
- public boolean clipChildren;
-
- public ViewPropertyRef next;
-
- public void transfer(ViewRef viewRef) {
- childCount = viewRef.childCount;
-
- View view = viewRef.view;
- viewRef.view = null;
-
- clazz = view.getClass();
- hashCode = view.hashCode();
- id = view.getId();
- left = view.getLeft();
- top = view.getTop();
- right = view.getRight();
- bottom = view.getBottom();
- scrollX = view.getScrollX();
- scrollY = view.getScrollY();
-
- translateX = view.getTranslationX();
- translateY = view.getTranslationY();
- scaleX = view.getScaleX();
- scaleY = view.getScaleY();
- alpha = view.getAlpha();
-
- visibility = view.getVisibility();
- willNotDraw = view.willNotDraw();
- elevation = view.getElevation();
- }
-
- /**
- * Converts the data to the proto representation and returns the next property ref
- * at the end of the iteration.
- * @return
- */
- public ViewPropertyRef toProto(Resources res, ArrayList<Class> classList,
- ViewNode.Builder outBuilder) {
- String resolvedId;
- if (id >= 0) {
- try {
- resolvedId = res.getResourceTypeName(id) + '/' + res.getResourceEntryName(id);
- } catch (Resources.NotFoundException e) {
- resolvedId = "id/" + "0x" + Integer.toHexString(id).toUpperCase();
- }
- } else {
- resolvedId = "NO_ID";
- }
- int classnameIndex = classList.indexOf(clazz);
- if (classnameIndex < 0) {
- classnameIndex = classList.size();
- classList.add(clazz);
- }
- outBuilder
- .setClassnameIndex(classnameIndex)
- .setHashcode(hashCode)
- .setId(resolvedId)
- .setLeft(left)
- .setTop(top)
- .setWidth(right - left)
- .setHeight(bottom - top)
- .setTranslationX(translateX)
- .setTranslationY(translateY)
- .setScaleX(scaleX)
- .setScaleY(scaleY)
- .setAlpha(alpha)
- .setVisibility(visibility)
- .setWillNotDraw(willNotDraw)
- .setElevation(elevation)
- .setClipChildren(clipChildren);
-
- ViewPropertyRef result = next;
- for (int i = 0; (i < childCount) && (result != null); i++) {
- ViewNode.Builder childBuilder = ViewNode.newBuilder();
- result = result.toProto(res, classList, childBuilder);
- outBuilder.addChildren(childBuilder);
- }
- return result;
- }
- }
-
- private static class ViewRef {
- public View view;
- public int childCount = 0;
- public ViewRef next;
- }
-}
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 582ff8d..fb2ae73 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -17,14 +17,15 @@
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.testing.shared.ResourceUtils.NAVBAR_HEIGHT;
import static com.android.launcher3.testing.shared.ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE;
import static com.android.launcher3.testing.shared.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
+import static com.android.launcher3.testing.shared.ResourceUtils.NAV_BAR_INTERACTION_MODE_RES_NAME;
import static com.android.launcher3.testing.shared.ResourceUtils.STATUS_BAR_HEIGHT;
import static com.android.launcher3.testing.shared.ResourceUtils.STATUS_BAR_HEIGHT_LANDSCAPE;
import static com.android.launcher3.testing.shared.ResourceUtils.STATUS_BAR_HEIGHT_PORTRAIT;
-import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import static com.android.launcher3.util.RotationUtils.deltaRotation;
import static com.android.launcher3.util.RotationUtils.rotateRect;
@@ -40,6 +41,7 @@
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.util.ArrayMap;
+import android.util.Log;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.Surface;
@@ -48,9 +50,10 @@
import android.view.WindowMetrics;
import com.android.launcher3.R;
-import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.Utilities;
+import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.util.WindowBounds;
@@ -59,6 +62,7 @@
*/
public class WindowManagerProxy implements ResourceBasedOverride {
+ private static final String TAG = "WindowManagerProxy";
public static final int MIN_TABLET_WIDTH = 600;
public static final MainThreadInitializedObject<WindowManagerProxy> INSTANCE =
@@ -343,4 +347,24 @@
return displayInfoContext.getSystemService(DisplayManager.class).getDisplay(
DEFAULT_DISPLAY);
}
+
+ /**
+ * Returns the current navigation mode from resource.
+ */
+ public NavigationMode getNavigationMode(Context context) {
+ int modeInt = ResourceUtils.getIntegerByName(NAV_BAR_INTERACTION_MODE_RES_NAME,
+ context.getResources(), INVALID_RESOURCE_HANDLE);
+
+ if (modeInt == INVALID_RESOURCE_HANDLE) {
+ Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+ } else {
+ for (NavigationMode m : NavigationMode.values()) {
+ if (m.resValue == modeInt) {
+ return m;
+ }
+ }
+ }
+ return Utilities.ATLEAST_S ? NavigationMode.NO_BUTTON :
+ NavigationMode.THREE_BUTTONS;
+ }
}
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index e2dc34f..dd5b22e 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -15,16 +15,26 @@
*/
package com.android.launcher3.views;
+import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.HIDE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Rect;
+import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.AccessibilityDelegate;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
+import android.view.inputmethod.InputMethodManager;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.dot.DotInfo;
@@ -36,6 +46,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.ViewCache;
/**
@@ -202,4 +213,47 @@
ActivityAllAppsContainerView<?> appsView) {
return null;
}
+
+ /**
+ * Hides the keyboard if it is visible
+ */
+ default void hideKeyboard() {
+ View root = getDragLayer();
+ if (root == null) {
+ return;
+ }
+ if (Utilities.ATLEAST_R) {
+ Preconditions.assertUIThread();
+ // Hide keyboard with WindowInsetsController if could. In case
+ // hideSoftInputFromWindow may get ignored by input connection being finished
+ // when the screen is off.
+ //
+ // In addition, inside IMF, the keyboards are closed asynchronously that launcher no
+ // longer need to post to the message queue.
+ final WindowInsetsController wic = root.getWindowInsetsController();
+ WindowInsets insets = root.getRootWindowInsets();
+ boolean isImeShown = insets != null && insets.isVisible(WindowInsets.Type.ime());
+ if (wic != null && isImeShown) {
+ StatsLogManager slm = getStatsLogManager();
+ slm.keyboardStateManager().setKeyboardState(HIDE);
+
+ // this method cannot be called cross threads
+ wic.hide(WindowInsets.Type.ime());
+ slm.logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
+ return;
+ }
+ }
+
+ InputMethodManager imm = root.getContext().getSystemService(InputMethodManager.class);
+ IBinder token = root.getWindowToken();
+ if (imm != null && token != null) {
+ UI_HELPER_EXECUTOR.execute(() -> {
+ if (imm.hideSoftInputFromWindow(token, 0)) {
+ // log keyboard close event only when keyboard is actually closed
+ MAIN_EXECUTOR.execute(() ->
+ getStatsLogManager().logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED));
+ }
+ });
+ }
+ }
}
diff --git a/src/com/android/launcher3/views/AppLauncher.java b/src/com/android/launcher3/views/AppLauncher.java
index 19e66ab..dc07e45 100644
--- a/src/com/android/launcher3/views/AppLauncher.java
+++ b/src/com/android/launcher3/views/AppLauncher.java
@@ -16,7 +16,7 @@
package com.android.launcher3.views;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
@@ -190,7 +190,7 @@
*/
default void startShortcut(String packageName, String id, Rect sourceBounds,
Bundle startActivityOptions, UserHandle user) {
- if (GO_DISABLE_WIDGETS) {
+ if (GO_DISABLE_SHORTCUTS) {
return;
}
try {
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index 6e6512d..40e4ce1 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -20,8 +20,6 @@
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
-import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
-
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -313,7 +311,7 @@
}
private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) {
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken());
+ ActivityContext.lookupContext(getContext()).hideKeyboard();
mIsDragging = true;
if (mCanThumbDetach) {
mIsThumbDetached = true;
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 5cffd48..2ac1e94 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -26,6 +28,7 @@
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowInsets;
+import android.view.animation.Interpolator;
import android.widget.Toast;
import androidx.annotation.GuardedBy;
@@ -246,6 +249,12 @@
return true;
}
+ @Override
+ protected Interpolator getIdleInterpolator() {
+ return mActivityContext.getDeviceProfile().isTablet
+ ? EMPHASIZED : super.getIdleInterpolator();
+ }
+
//
// Drag related handling methods that implement {@link DragSource} interface.
//
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
index 5ce8fcf..3e80699 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
@@ -323,6 +323,7 @@
if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
// First, we clear any previously cached content from existing widgets
mCachedRemoteViews.clear();
+ mDeferredViews.clear();
// Then we proceed to cache the content from the widgets
for (int i = 0; i < mViews.size(); i++) {
final int appWidgetId = mViews.keyAt(i);
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index 470a800..ccf4b2e 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -19,6 +19,9 @@
import android.content.Context;
import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.logger.LauncherAtom;
@@ -66,8 +69,9 @@
return WidgetSizes.getWidgetSizeOptions(context, componentName, spanX, spanY);
}
+ @NonNull
@Override
- public LauncherAtom.ItemInfo buildProto(FolderInfo folderInfo) {
+ public LauncherAtom.ItemInfo buildProto(@Nullable FolderInfo folderInfo) {
LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
return info.toBuilder()
.addItemAttributes(LauncherAppWidgetInfo.getAttribute(sourceContainer))
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 0d9198f..da8e25c 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -85,7 +85,6 @@
implements ProviderChangedListener, OnActivePageChangedListener,
WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener {
- private static final long DEFAULT_OPEN_DURATION = 267;
private static final long FADE_IN_DURATION = 150;
private static final long EDUCATION_TIP_DELAY_MS = 200;
private static final long EDUCATION_DIALOG_DELAY_MS = 500;
@@ -582,7 +581,7 @@
mOpenCloseAnimator.setValues(
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
mOpenCloseAnimator
- .setDuration(DEFAULT_OPEN_DURATION)
+ .setDuration(mActivityContext.getDeviceProfile().bottomSheetOpenDuration)
.setInterpolator(AnimationUtils.loadInterpolator(
getContext(), android.R.interpolator.linear_out_slow_in));
mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
@@ -603,7 +602,7 @@
@Override
protected void handleClose(boolean animate) {
- handleClose(animate, DEFAULT_OPEN_DURATION);
+ handleClose(animate, mActivityContext.getDeviceProfile().bottomSheetCloseDuration);
}
@Override
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 702f343..13ad7a4 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -62,6 +62,8 @@
// True is the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = false;
+ // True is the shortcut support is disabled.
+ public static final boolean GO_DISABLE_SHORTCUTS = false;
public static final boolean GO_DISABLE_NOTIFICATION_DOTS = false;
private static final String TAG = "WidgetsModel";
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 9daea94..a581f91 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -42,9 +42,9 @@
@Override
public <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) {
- return !context.getDeviceProfile().isTablet && isToState
- ? 600
- : isToState ? 500 : 300;
+ return isToState
+ ? context.getDeviceProfile().allAppsOpenDuration
+ : context.getDeviceProfile().allAppsCloseDuration;
}
@Override
diff --git a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java b/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
new file mode 100644
index 0000000..8ce932d
--- /dev/null
+++ b/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 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.celllayout;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.ContentWriter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+public class FavoriteItemsTransaction {
+ private ArrayList<ItemInfo> mItemsToSubmit;
+ private Context mContext;
+ private ContentResolver mResolver;
+ public AbstractLauncherUiTest mTest;
+
+ public FavoriteItemsTransaction(Context context, AbstractLauncherUiTest test) {
+ mItemsToSubmit = new ArrayList<>();
+ mContext = context;
+ mResolver = mContext.getContentResolver();
+ mTest = test;
+ }
+
+ public FavoriteItemsTransaction addItem(ItemInfo itemInfo) {
+ this.mItemsToSubmit.add(itemInfo);
+ return this;
+ }
+
+ public FavoriteItemsTransaction removeLast() {
+ this.mItemsToSubmit.remove(this.mItemsToSubmit.size() - 1);
+ return this;
+ }
+
+ /**
+ * Commits all the ItemInfo into the database of Favorites
+ **/
+ public void commit() throws ExecutionException, InterruptedException {
+ List<ContentValues> values = new ArrayList<>();
+ for (ItemInfo item : this.mItemsToSubmit) {
+ ContentWriter writer = new ContentWriter(mContext);
+ item.onAddToDatabase(writer);
+ writer.put(LauncherSettings.Favorites._ID, item.id);
+ values.add(writer.getValues(mContext));
+ }
+ // Submit the icons to the database in the model thread to prevent race conditions
+ MODEL_EXECUTOR.submit(() -> mResolver.bulkInsert(LauncherSettings.Favorites.CONTENT_URI,
+ values.toArray(new ContentValues[0]))).get();
+ // Reload the state of the Launcher
+ MAIN_EXECUTOR.submit(() -> LauncherAppState.getInstance(
+ mContext).getModel().forceReload()).get();
+ }
+}
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index 93fbf97..2846cae 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -47,6 +47,7 @@
import org.junit.runner.RunWith;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
@SmallTest
@@ -58,7 +59,7 @@
private static final String TAG = ReorderWidgets.class.getSimpleName();
- TestWorkspaceBuilder mBoardBuilder;
+ TestWorkspaceBuilder mWorkspaceBuilder;
private View getViewAt(int cellX, int cellY) {
return getFromLauncher(l -> l.getWorkspace().getScreenWithId(
@@ -76,7 +77,7 @@
@Before
public void setup() throws Throwable {
- mBoardBuilder = new TestWorkspaceBuilder(this);
+ mWorkspaceBuilder = new TestWorkspaceBuilder(this, mTargetContext);
TaplTestsLauncher3.initialize(this);
clearHomescreen();
}
@@ -87,7 +88,7 @@
private boolean validateBoard(CellLayoutBoard board) {
boolean match = true;
Point cellDimensions = getCellDimensions();
- for (CellLayoutBoard.WidgetRect widgetRect: board.getWidgets()) {
+ for (CellLayoutBoard.WidgetRect widgetRect : board.getWidgets()) {
if (widgetRect.shouldIgnore()) {
continue;
}
@@ -108,10 +109,13 @@
return match;
}
- private void runTestCase(ReorderTestCase testCase) {
+ private void runTestCase(ReorderTestCase testCase)
+ throws ExecutionException, InterruptedException {
Point mainWidgetCellPos = testCase.mStart.getMain();
- mBoardBuilder.buildBoard(testCase.mStart);
+ FavoriteItemsTransaction transaction =
+ new FavoriteItemsTransaction(mTargetContext, this);
+ mWorkspaceBuilder.buildFromBoard(testCase.mStart, transaction).commit();
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x,
mainWidgetCellPos.y);
@@ -132,7 +136,8 @@
*
* @param testCaseMap map containing all the tests per grid size (Point)
*/
- private void runTestCaseMap(Map<Point, ReorderTestCase> testCaseMap, String testName) {
+ private void runTestCaseMap(Map<Point, ReorderTestCase> testCaseMap, String testName)
+ throws ExecutionException, InterruptedException {
Point iconGridDimensions = mLauncher.getWorkspace().getIconGridDimensions();
Log.d(TAG, "Running test " + testName + " for grid " + iconGridDimensions);
Assume.assumeTrue(
@@ -143,26 +148,26 @@
@ScreenRecord // b/242323136
@Test
- public void simpleReorder() {
+ public void simpleReorder() throws ExecutionException, InterruptedException {
runTestCaseMap(SimpleReorderCase.TEST_BY_GRID_SIZE,
SimpleReorderCase.class.getSimpleName());
}
@ScreenRecord // b/242323136
@Test
- public void pushTest() {
+ public void pushTest() throws ExecutionException, InterruptedException {
runTestCaseMap(PushReorderCase.TEST_BY_GRID_SIZE, PushReorderCase.class.getSimpleName());
}
@ScreenRecord // b/242323136
@Test
- public void fullReorder() {
+ public void fullReorder() throws ExecutionException, InterruptedException {
runTestCaseMap(FullReorderCase.TEST_BY_GRID_SIZE, FullReorderCase.class.getSimpleName());
}
@ScreenRecord // b/242323136
@Test
- public void moveOutReorder() {
+ public void moveOutReorder() throws ExecutionException, InterruptedException {
runTestCaseMap(MoveOutReorderCase.TEST_BY_GRID_SIZE,
MoveOutReorderCase.class.getSimpleName());
}
diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
index 10e399d..16448af 100644
--- a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
+++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
@@ -15,9 +15,12 @@
*/
package com.android.launcher3.celllayout;
+import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
@@ -25,8 +28,10 @@
import androidx.test.core.app.ApplicationProvider;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.AppInfo;
+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.ui.AbstractLauncherUiTest;
@@ -35,6 +40,7 @@
public class TestWorkspaceBuilder {
+ private static final String TAG = "CellLayoutBoardBuilder";
private static final ComponentName APP_COMPONENT_NAME = new ComponentName(
"com.google.android.calculator", "com.android.calculator2.Calculator");
@@ -42,69 +48,118 @@
private UserHandle mMyUser;
- public TestWorkspaceBuilder(AbstractLauncherUiTest test) {
+ private Context mContext;
+ private ContentResolver mResolver;
+
+ public TestWorkspaceBuilder(AbstractLauncherUiTest test, Context context) {
mTest = test;
mMyUser = Process.myUserHandle();
+ mContext = context;
+ mResolver = mContext.getContentResolver();
}
- private static final String TAG = "CellLayoutBoardBuilder";
-
/**
* Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
*/
- private void fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect) {
+ private FavoriteItemsTransaction fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect,
+ FavoriteItemsTransaction transaction) {
int initX = widgetRect.getCellX();
int initY = widgetRect.getCellY();
for (int x = initX; x < initX + widgetRect.getSpanX(); x++) {
for (int y = initY; y < initY + widgetRect.getSpanY(); y++) {
try {
// this widgets are filling, we don't care if we can't place them
- addWidgetInCell(
+ ItemInfo item = createWidgetInCell(
new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE,
new Rect(x, y, x, y))
);
+ transaction.addItem(item);
} catch (Exception e) {
Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
}
}
}
+ return transaction;
}
- private void addWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) {
+ private int getID() {
+ return LauncherSettings.Settings.call(
+ mResolver, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
+ .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ }
+
+ private AppInfo getApp() {
+ return new AppInfo(APP_COMPONENT_NAME, "test icon", mMyUser,
+ AppInfo.makeLaunchIntent(APP_COMPONENT_NAME));
+ }
+
+ private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect,
+ FavoriteItemsTransaction transaction) {
+ if (widgetRect.mType == 'x') {
+ fillWithWidgets(widgetRect, transaction);
+ } else {
+ transaction.addItem(createWidgetInCell(widgetRect));
+ }
+ }
+
+ /**
+ * Builds the given board into the transaction
+ */
+ public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board,
+ FavoriteItemsTransaction transaction) {
+ board.getWidgets().forEach(
+ (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction));
+ board.getIcons().forEach((iconPoint) ->
+ transaction.addItem(createIconInCell(iconPoint))
+ );
+ return transaction;
+ }
+
+ /**
+ * Fills the hotseat row with apps instead of suggestions, for this to work the workspace should
+ * be clean otherwise this doesn't overrides the existing icons.
+ */
+ public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) {
+ int hotseatCount = InvariantDeviceProfile.INSTANCE.get(mContext).numShownHotseatIcons;
+ for (int i = 0; i < hotseatCount; i++) {
+ transaction.addItem(getHotseatValues(i));
+ }
+ return transaction;
+ }
+
+ private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) {
LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false);
LauncherAppWidgetInfo item = createWidgetInfo(info,
ApplicationProvider.getApplicationContext(), true);
-
+ item.id = getID();
item.cellX = widgetRect.getCellX();
item.cellY = widgetRect.getCellY();
item.spanX = widgetRect.getSpanX();
item.spanY = widgetRect.getSpanY();
- mTest.addItemToScreen(item);
+ item.screenId = FIRST_SCREEN_ID;
+ return item;
}
- private void addIconInCell(CellLayoutBoard.IconPoint iconPoint) {
- AppInfo appInfo = new AppInfo(APP_COMPONENT_NAME, "test icon", mMyUser,
- AppInfo.makeLaunchIntent(APP_COMPONENT_NAME));
-
- appInfo.cellX = iconPoint.getCoord().x;
- appInfo.cellY = iconPoint.getCoord().y;
- appInfo.minSpanY = appInfo.minSpanX = appInfo.spanX = appInfo.spanY = 1;
- appInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
- appInfo.componentName = APP_COMPONENT_NAME;
-
- mTest.addItemToScreen(new WorkspaceItemInfo(appInfo));
+ private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint) {
+ WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
+ item.id = getID();
+ item.screenId = FIRST_SCREEN_ID;
+ item.cellX = iconPoint.getCoord().x;
+ item.cellY = iconPoint.getCoord().y;
+ item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
+ item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+ return item;
}
- private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect) {
- if (widgetRect.mType == 'x') {
- fillWithWidgets(widgetRect);
- } else {
- addWidgetInCell(widgetRect);
- }
- }
-
- public void buildBoard(CellLayoutBoard board) {
- board.getWidgets().forEach(this::addCorrespondingWidgetRect);
- board.getIcons().forEach(this::addIconInCell);
+ private ItemInfo getHotseatValues(int x) {
+ WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
+ item.id = getID();
+ item.cellX = x;
+ item.cellY = 0;
+ item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
+ item.rank = x;
+ item.screenId = x;
+ item.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+ return item;
}
}
diff --git a/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java
index 94e55cf..a98882c 100644
--- a/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java
+++ b/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java
@@ -31,13 +31,13 @@
+ "xxxxx\n"
+ "222mm\n"
+ "222mm\n"
- + "ad111\n"
- + "bc111";
+ + "ii111\n"
+ + "ii111";
private static final Point MOVE_TO_5x5 = new Point(0, 4);
private static final String END_BOARD_STR_5x5 = ""
+ "xxxxx\n"
- + "222ad\n"
- + "222bc\n"
+ + "222ii\n"
+ + "222ii\n"
+ "mm111\n"
+ "mm111";
private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5,
@@ -50,13 +50,13 @@
+ "xxxxxx\n"
+ "2222mm\n"
+ "2222mm\n"
- + "ad1111\n"
- + "bc1111";
+ + "ii1111\n"
+ + "ii1111";
private static final Point MOVE_TO_6x5 = new Point(0, 4);
private static final String END_BOARD_STR_6x5 = ""
+ "xxxxxx\n"
- + "2222ad\n"
- + "2222bc\n"
+ + "2222ii\n"
+ + "2222ii\n"
+ "mm1111\n"
+ "mm1111";
private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5,
@@ -68,13 +68,13 @@
private static final String START_BOARD_STR_4x4 = ""
+ "xxxx\n"
+ "22mm\n"
- + "admm\n"
- + "bc11";
+ + "iimm\n"
+ + "ii11";
private static final Point MOVE_TO_4x4 = new Point(0, 3);
private static final String END_BOARD_STR_4x4 = ""
+ "xxxx\n"
- + "22ad\n"
- + "mmbc\n"
+ + "22ii\n"
+ + "mmii\n"
+ "mm11";
private static final ReorderTestCase TEST_CASE_4x4 = new ReorderTestCase(START_BOARD_STR_4x4,
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 5baa7d2..be49974 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -214,9 +214,9 @@
// Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there.
executeOnLauncher(launcher -> assertFalse("Initial workspace state is scrollable",
isWorkspaceScrollable(launcher)));
- workspace.verifyWorkspaceAppIconIsGone(
- "Chrome app was found on empty workspace", "Chrome");
-
+ assertEquals("Initial workspace doesn't have the correct page", workspace.pagesPerScreen(),
+ workspace.getPageCount());
+ workspace.verifyWorkspaceAppIconIsGone("Chrome app was found on empty workspace", "Chrome");
workspace.ensureWorkspaceIsScrollable();
executeOnLauncher(
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index 5761abd..302bd2f 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
+
import android.util.Log;
import android.view.View;
@@ -48,6 +49,7 @@
private int mProfileUserId;
private boolean mWorkProfileSetupSuccessful;
+ private final String TAG = "WorkProfileTest";
@Before
@Override
@@ -56,18 +58,17 @@
String output =
mDevice.executeShellCommand(
"pm create-user --profileOf 0 --managed TestProfile");
- Log.d("b/203817455", "pm create-user; output: " + output);
-
- if (output.startsWith("Success")){
- assertTrue("Failed to create work profile", output.startsWith("Success"));
- mWorkProfileSetupSuccessful = true;
- } else {
- return; // no need to setup launcher since all tests will skip.
- }
+ // b/203817455
+ updateWorkProfileSetupSuccessful("pm create-user", output);
String[] tokens = output.split("\\s+");
mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]);
- mDevice.executeShellCommand("am start-user " + mProfileUserId);
+ output = mDevice.executeShellCommand("am start-user " + mProfileUserId);
+ updateWorkProfileSetupSuccessful("am start-user", output);
+
+ if (!mWorkProfileSetupSuccessful) {
+ return; // no need to setup launcher since all tests will skip.
+ }
mDevice.pressHome();
waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
@@ -107,6 +108,7 @@
@Test
public void workTabExists() {
assumeTrue(mWorkProfileSetupSuccessful);
+ waitForWorkTabSetup();
waitForLauncherCondition("Personal tab is missing",
launcher -> launcher.getAppsView().isPersonalTabVisible(),
LauncherInstrumentation.WAIT_TIME_MS);
@@ -134,7 +136,11 @@
LauncherInstrumentation.WAIT_TIME_MS);
//start work profile toggle OFF test
- executeOnLauncher(l -> l.getAppsView().getWorkManager().getWorkModeSwitch().performClick());
+ executeOnLauncher(l -> {
+ // Ensure updates are not deferred so notification happens when apps pause.
+ l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST);
+ l.getAppsView().getWorkManager().getWorkModeSwitch().performClick();
+ });
waitForLauncherCondition("Work profile toggle OFF failed", launcher -> {
manager.reset(); // pulls current state from system
@@ -183,4 +189,14 @@
}
}, LauncherInstrumentation.WAIT_TIME_MS);
}
+
+ private void updateWorkProfileSetupSuccessful(String cli, String output) {
+ Log.d(TAG, "updateWorkProfileSetupSuccessful, cli=" + cli + " " + "output=" + output);
+ if (output.startsWith("Success")) {
+ assertTrue(output, output.startsWith("Success"));
+ mWorkProfileSetupSuccessful = true;
+ } else {
+ mWorkProfileSetupSuccessful = false;
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt
similarity index 75%
rename from tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt
rename to tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt
index 309d055..a4f189c 100644
--- a/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt
+++ b/tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt
@@ -16,26 +16,32 @@
package com.android.launcher3.util
-import android.view.View
+import android.util.FloatProperty
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
-/** Unit tests for [MultiAdditivePropertyFactory] */
+/** Unit tests for [MultiPropertyFactory] */
@SmallTest
@RunWith(AndroidJUnit4::class)
-class MultiAdditivePropertyTest {
+class MultiPropertyFactoryTest {
private val received = mutableListOf<Float>()
- private val factory =
- object : MultiAdditivePropertyFactory<View?>("Test", View.TRANSLATION_X) {
- override fun apply(obj: View?, value: Float) {
- received.add(value)
- }
+ private val receiveProperty: FloatProperty<Any> = object : FloatProperty<Any>("receive") {
+ override fun setValue(obj: Any?, value: Float) {
+ received.add(value)
}
+ override fun get(o: Any): Float {
+ return 0f
+ }
+ }
+
+ private val factory = MultiPropertyFactory("depth_property", receiveProperty) {
+ x: Float, y: Float -> x + y
+ }
private val p1 = factory.get(1)
private val p2 = factory.get(2)
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
index 5f92199..c365708 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
@@ -15,12 +15,21 @@
*/
package com.android.launcher3.tapl;
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
/**
* Operations on home screen qsb.
*/
public class HomeQsb {
private final LauncherInstrumentation mLauncher;
+ private static final String ASSISTANT_APP_PACKAGE = "com.google.android.googlequicksearchbox";
+ private static final String ASSISTANT_ICON_RES_ID = "mic_icon";
+
HomeQsb(LauncherInstrumentation launcher) {
mLauncher = launcher;
@@ -28,6 +37,35 @@
}
/**
+ * Launch assistant app by tapping mic icon on qsb.
+ */
+ @NonNull
+ public LaunchedAppState launchAssistant() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to click assistant mic icon button");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ UiObject2 assistantIcon = mLauncher.waitForLauncherObject(ASSISTANT_ICON_RES_ID);
+
+ LauncherInstrumentation.log("HomeQsb.launchAssistant before click "
+ + assistantIcon.getVisibleCenter() + " in "
+ + mLauncher.getVisibleBounds(assistantIcon));
+
+ mLauncher.clickLauncherObject(assistantIcon);
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ // assert Assistant App Launched
+ BySelector selector = By.pkg(ASSISTANT_APP_PACKAGE);
+ mLauncher.assertTrue(
+ "assistant app didn't start: (" + selector + ")",
+ mLauncher.getDevice().wait(Until.hasObject(selector),
+ LauncherInstrumentation.WAIT_TIME_MS)
+ );
+ return new LaunchedAppState(mLauncher);
+ }
+ }
+ }
+
+ /**
* Show search result page from tapping qsb.
*/
public SearchResultFromQsb showSearchResult() {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 1fb8cc7..80bc402 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -68,7 +68,6 @@
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.testing.shared.TestInformationRequest;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.systemui.shared.system.ContextUtils;
import com.android.systemui.shared.system.QuickStepContract;
import org.junit.Assert;
@@ -263,7 +262,7 @@
SystemClock.sleep(5000);
} else {
try {
- final int userId = ContextUtils.getUserId(getContext());
+ final int userId = getContext().getUserId();
final String launcherPidCommand = "pidof " + pi.packageName;
final String initialPid = mDevice.executeShellCommand(launcherPidCommand)
.replaceAll("\\s", "");
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index efbdb23..5fab7eb 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -192,6 +192,12 @@
}
}
+ /** Returns the number of pages. */
+ public int getPageCount() {
+ final UiObject2 workspace = verifyActiveContainer();
+ return workspace.getChildCount();
+ }
+
/**
* Returns the number of pages that are visible on the screen simultaneously.
*/