Merge "Update the NORMAL->ALL_APPS transition when tapping on QSB on phones." into tm-dev
diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java
index c287446..e717937 100644
--- a/go/quickstep/src/com/android/launcher3/AppSharing.java
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -39,6 +39,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.views.ActivityContext;
import java.io.File;
@@ -191,9 +192,14 @@
}
private void showCannotShareToast(Context context) {
+ ActivityContext activityContext = ActivityContext.lookupContext(context);
+ String blockedByMessage = activityContext.getStringCache() != null
+ ? activityContext.getStringCache().disabledByAdminMessage
+ : context.getString(R.string.blocked_by_policy);
+
CharSequence text = (mSharingEnabledForUser)
? context.getText(R.string.toast_p2p_app_not_shareable)
- : context.getText(R.string.blocked_by_policy);
+ : blockedByMessage;
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 5c66944..9f3be69 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -62,6 +62,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.Utilities;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
import com.android.launcher3.logger.LauncherAtom.FolderContainer;
@@ -116,7 +117,8 @@
@AnyThread
private void sendEvent(AppTarget target, LauncherAtom.ItemInfo locationInfo, int eventId,
int targetPredictor) {
- if (target != null) {
+ // TODO: remove the running test check when b/231648228 is fixed.
+ if (target != null && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(getContainer(locationInfo))
.build();
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 349dd0a..cbdbdb9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
@@ -51,6 +52,7 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.PaintDrawable;
import android.inputmethodservice.InputMethodService;
+import android.os.Handler;
import android.util.Property;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -158,6 +160,7 @@
private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
this::onComputeInsetsForSeparateWindow;
+ private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
@@ -297,6 +300,8 @@
navButtonsLayoutParams.setMarginEnd(navButtonsLayoutParams.getMarginStart());
navButtonsLayoutParams.gravity = Gravity.CENTER;
mNavButtonContainer.requestLayout();
+
+ mHomeButton.setOnLongClickListener(null);
}
// Animate taskbar background when either..
@@ -388,8 +393,7 @@
|| (flags & FLAG_KEYGUARD_VISIBLE) != 0,
VIEW_TRANSLATE_X, navButtonSize * (isRtl ? -2 : 2), 0));
-
- // home and recents buttons
+ // home button
mHomeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home);
mHomeButtonAlpha = new MultiValueAlpha(mHomeButton, NUM_ALPHA_CHANNELS);
@@ -399,8 +403,21 @@
ALPHA_INDEX_KEYGUARD_OR_DISABLE),
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
(flags & FLAG_DISABLE_HOME) == 0));
+
+ // Recents button
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
navContainer, navButtonController, R.id.recent_apps);
+ mHitboxExtender.init(recentsButton, mNavButtonsView, mContext.getDeviceProfile(),
+ () -> {
+ float[] recentsCoords = new float[2];
+ getDescendantCoordRelativeToAncestor(recentsButton, mNavButtonsView,
+ recentsCoords, false);
+ return recentsCoords;
+ }, new Handler());
+ recentsButton.setOnClickListener(v -> {
+ navButtonController.onButtonClick(BUTTON_RECENTS);
+ mHitboxExtender.onRecentsButtonClicked();
+ });
mPropertyHolders.add(new StatePropertyHolder(recentsButton,
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
&& !mContext.isNavBarKidsModeActive()));
@@ -504,6 +521,9 @@
View button = mAllButtons.get(i);
if (button.getVisibility() == View.VISIBLE) {
parent.getDescendantRectRelativeToSelf(button, mTempRect);
+ if (mHitboxExtender.extendedHitboxEnabled()) {
+ mTempRect.bottom += mContext.mDeviceProfile.getTaskbarOffsetY();
+ }
outRegion.op(mTempRect, Op.UNION);
}
}
@@ -733,6 +753,17 @@
return str.toString();
}
+ public TouchController getTouchController() {
+ return mHitboxExtender;
+ }
+
+ /**
+ * @param alignment 0 -> Taskbar, 1 -> Workspace
+ */
+ public void updateTaskbarAlignment(float alignment) {
+ mHitboxExtender.onAnimationProgressToOverview(alignment);
+ }
+
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
@Override
public void onVisibilityChanged(boolean isVisible) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java b/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java
new file mode 100644
index 0000000..4651570
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java
@@ -0,0 +1,134 @@
+/*
+ * 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.taskbar;
+
+import android.graphics.Rect;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.TouchDelegate;
+import android.view.View;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.util.TouchController;
+
+import java.util.function.Supplier;
+
+/**
+ * Extends the Recents touch area during the taskbar to overview animation
+ * to give user some error room when trying to quickly double tap recents button since it moves.
+ *
+ * Listens for icon alignment as our indication for the animation.
+ */
+public class RecentsHitboxExtender implements TouchController {
+
+ private static final int RECENTS_HITBOX_TIMEOUT_MS = 500;
+
+ private View mRecentsButton;
+ private View mRecentsParent;
+ private DeviceProfile mDeviceProfile;
+ private Supplier<float[]> mParentCoordSupplier;
+ private TouchDelegate mRecentsTouchDelegate;
+ /**
+ * Will be true while the animation from taskbar to overview is occurring.
+ * Lifecycle of this variable slightly extends past the animation by
+ * {@link #RECENTS_HITBOX_TIMEOUT_MS}, so can use this variable as a proxy for if
+ * the current hitbox is extended or not.
+ */
+ private boolean mAnimatingFromTaskbarToOverview;
+ private float mLastIconAlignment;
+ private final Rect mRecentsHitBox = new Rect();
+ private boolean mRecentsButtonClicked;
+ private Handler mHandler;
+ private final Runnable mRecentsHitboxResetRunnable = this::reset;
+
+ public void init(View recentsButton, View recentsParent, DeviceProfile deviceProfile,
+ Supplier<float[]> parentCoordSupplier, Handler handler) {
+ mRecentsButton = recentsButton;
+ mRecentsParent = recentsParent;
+ mDeviceProfile = deviceProfile;
+ mParentCoordSupplier = parentCoordSupplier;
+ mHandler = handler;
+ }
+
+ public void onRecentsButtonClicked() {
+ mRecentsButtonClicked = true;
+ }
+
+ /**
+ * @param progress 0 -> Taskbar, 1 -> Overview
+ */
+ public void onAnimationProgressToOverview(float progress) {
+ if (progress == 1 || progress == 0) {
+ // Done w/ animation
+ mLastIconAlignment = progress;
+ if (mAnimatingFromTaskbarToOverview) {
+ if (progress == 1) {
+ // Finished animation to workspace, remove the touch delegate shortly
+ mHandler.postDelayed(mRecentsHitboxResetRunnable, RECENTS_HITBOX_TIMEOUT_MS);
+ return;
+ } else {
+ // Went back to taskbar, reset immediately
+ mHandler.removeCallbacks(mRecentsHitboxResetRunnable);
+ reset();
+ }
+ }
+ }
+
+ if (mAnimatingFromTaskbarToOverview) {
+ return;
+ }
+
+ if (progress > 0 && mLastIconAlignment == 0 && mRecentsButtonClicked) {
+ // Starting animation, previously we were showing taskbar
+ mAnimatingFromTaskbarToOverview = true;
+ float[] recentsCoords = mParentCoordSupplier.get();
+ int x = (int) recentsCoords[0];
+ int y = (int) (recentsCoords[1]);
+ // Extend hitbox vertically by the offset amount from mDeviceProfile.getTaskbarOffsetY()
+ mRecentsHitBox.set(x, y,
+ x + mRecentsButton.getWidth(),
+ y + mRecentsButton.getHeight() + mDeviceProfile.getTaskbarOffsetY()
+ );
+ mRecentsTouchDelegate = new TouchDelegate(mRecentsHitBox, mRecentsButton);
+ mRecentsParent.setTouchDelegate(mRecentsTouchDelegate);
+ }
+ }
+
+ private void reset() {
+ mAnimatingFromTaskbarToOverview = false;
+ mRecentsButton.setTouchDelegate(null);
+ mRecentsHitBox.setEmpty();
+ mRecentsButtonClicked = false;
+ }
+
+ /**
+ * @return {@code true} if the bounds for recents touches are currently extended
+ */
+ public boolean extendedHitboxEnabled() {
+ return mAnimatingFromTaskbarToOverview;
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return mRecentsTouchDelegate.onTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ return mRecentsHitBox.contains((int)ev.getX(), (int)ev.getY());
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 3e2695c..99c59a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -182,7 +182,8 @@
*/
public TouchController[] getTouchControllers() {
return new TouchController[]{mActivity.getDragController(),
- mControllers.taskbarForceVisibleImmersiveController};
+ mControllers.taskbarForceVisibleImmersiveController,
+ mControllers.navbarButtonsViewController.getTouchController()};
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 138fb99..052c695 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -372,6 +372,7 @@
// If we're already animating to the value, just leave it be instead of restarting it.
if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) {
+ mIconAlignmentForLauncherState.finishAnimation();
animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
.setDuration(duration));
}
@@ -427,6 +428,7 @@
// Switch taskbar and hotseat in last frame
setTaskbarViewVisible(alignment < 1);
+ mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment);
}
private float getCurrentIconAlignmentRatioBetweenAppAndHome() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 5f62749..699ce97 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -66,9 +66,9 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
RecentsView recentsView = launcher.getOverviewPanel();
- float workspacePageHeight = launcher.getDeviceProfile().getCellLayoutHeight();
+ float workspacePageWidth = launcher.getDeviceProfile().getWorkspaceWidth();
recentsView.getTaskSize(sTempRect);
- float scale = (float) sTempRect.height() / workspacePageHeight;
+ float scale = (float) sTempRect.width() / workspacePageWidth;
float parallaxFactor = 0.5f;
return new ScaleAndTranslation(scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 2ca59eb..53dc9dd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -27,6 +27,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
import static com.android.launcher3.logging.StatsLogManager.getLauncherAtomEvent;
@@ -451,9 +452,11 @@
.withSrcState(LAUNCHER_STATE_HOME)
.withDstState(targetState.statsLogOrdinal)
.log(getLauncherAtomEvent(mStartState.statsLogOrdinal, targetState.statsLogOrdinal,
- targetState.ordinal > mStartState.ordinal
- ? LAUNCHER_UNKNOWN_SWIPEUP
- : LAUNCHER_UNKNOWN_SWIPEDOWN));
+ targetState == QUICK_SWITCH
+ ? LAUNCHER_QUICKSWITCH_RIGHT
+ : targetState.ordinal > mStartState.ordinal
+ ? LAUNCHER_UNKNOWN_SWIPEUP
+ : LAUNCHER_UNKNOWN_SWIPEDOWN));
mLauncher.getStateManager().goToState(targetState, false, forEndCallback(this::clearState));
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 1504c12..dbee9c1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -261,7 +261,7 @@
@Override
protected void onReachedFinalState(LauncherState toState) {
- super.onReinitToState(toState);
+ super.onReachedFinalState(toState);
if (toState == ALL_APPS) {
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_OPEN_ALL_APPS);
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 5acce89..f60b225 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.PagedView.INVALID_PAGE;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -66,6 +67,7 @@
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
@@ -926,7 +928,13 @@
mLogDirectionUpOrLeft = velocity.x < 0;
}
mDownPos = downPos;
- handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
+ Runnable handleNormalGestureEndCallback = () ->
+ handleNormalGestureEnd(endVelocity, isFling, velocity, /* isCancel= */ false);
+ if (mRecentsView != null) {
+ mRecentsView.runOnPageScrollsInitialized(handleNormalGestureEndCallback);
+ } else {
+ handleNormalGestureEndCallback.run();
+ }
}
private void endRunningWindowAnim(boolean cancel) {
@@ -1130,6 +1138,13 @@
} else if (endTarget == RECENTS) {
if (mRecentsView != null) {
int nearestPage = mRecentsView.getDestinationPage();
+ if (nearestPage == INVALID_PAGE) {
+ // Allow the snap to invalid page to catch future error cases.
+ Log.e(TAG,
+ "RecentsView destination page is invalid",
+ new IllegalStateException());
+ }
+
boolean isScrolling = false;
if (mRecentsView.getNextPage() != nearestPage) {
// We shouldn't really scroll to the next page when swiping up to recents.
@@ -1162,6 +1177,11 @@
}
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
+ if (mDp == null || !mDp.isGestureMode || mDownPos == null) {
+ // We probably never received an animation controller, skip logging.
+ return;
+ }
+
StatsLogManager.EventEnum event;
switch (endTarget) {
case HOME:
@@ -1185,11 +1205,6 @@
logger.withItemInfo(targetTask.getItemInfo());
}
- DeviceProfile dp = mDp;
- if (dp == null || mDownPos == null) {
- // We probably never received an animation controller, skip logging.
- return;
- }
int pageIndex = endTarget == LAST_TASK || mRecentsView == null
? LOG_NO_OP_PAGE_INDEX
: mRecentsView.getNextPage();
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 48127c0..6745246 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -84,6 +84,8 @@
private STATE_TYPE mTargetState;
+ @Nullable private Runnable mOnInitBackgroundStateUICallback = null;
+
protected BaseActivityInterface(boolean rotationSupportedByActivity,
STATE_TYPE overviewState, STATE_TYPE backgroundState) {
this.rotationSupportedByActivity = rotationSupportedByActivity;
@@ -408,6 +410,21 @@
return null;
}
+ protected void runOnInitBackgroundStateUI(Runnable callback) {
+ mOnInitBackgroundStateUICallback = callback;
+ ACTIVITY_TYPE activity = getCreatedActivity();
+ if (activity != null && activity.getStateManager().getState() == mBackgroundState) {
+ onInitBackgroundStateUI();
+ }
+ }
+
+ private void onInitBackgroundStateUI() {
+ if (mOnInitBackgroundStateUICallback != null) {
+ mOnInitBackgroundStateUICallback.run();
+ mOnInitBackgroundStateUICallback = null;
+ }
+ }
+
public interface AnimationFactory {
void createActivityInterface(long transitionLength);
@@ -447,13 +464,14 @@
mStartState = mActivity.getStateManager().getState();
}
- protected ACTIVITY_TYPE initUI() {
+ protected ACTIVITY_TYPE initBackgroundStateUI() {
STATE_TYPE resetState = mStartState;
if (mStartState.shouldDisableRestore()) {
resetState = mActivity.getStateManager().getRestState();
}
mActivity.getStateManager().setRestState(resetState);
mActivity.getStateManager().goToState(mBackgroundState, false);
+ onInitBackgroundStateUI();
return mActivity;
}
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index 7feec2c..ba61574 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -89,7 +89,7 @@
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback);
- factory.initUI();
+ factory.initBackgroundStateUI();
return factory;
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 10a3a2e..c13b95f 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -135,7 +135,7 @@
}
};
- BaseQuickstepLauncher launcher = factory.initUI();
+ BaseQuickstepLauncher launcher = factory.initBackgroundStateUI();
// Since all apps is not visible, we can safely reset the scroll position.
// This ensures then the next swipe up to all-apps starts from scroll 0.
launcher.getAppsView().reset(false /* animate */);
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 42f9eb6..dffdc5a 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -217,7 +217,8 @@
@Override
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
- interactionHandler.onGestureEnded(0, new PointF(), new PointF());
+ activityInterface.runOnInitBackgroundStateUI(() ->
+ interactionHandler.onGestureEnded(0, new PointF(), new PointF()));
cmd.removeListener(this);
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index ef81449..528fb97 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -66,6 +66,12 @@
mDeviceProfile.overviewPageSpacing);
return response;
}
+
+ case TestProtocol.REQUEST_HAS_TIS: {
+ response.putBoolean(
+ TestProtocol.REQUEST_HAS_TIS, true);
+ return response;
+ }
}
return super.call(method, arg, extras);
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 2565674..54f457d 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -192,6 +192,10 @@
RemoteAnimationTargetCompat.wrap(nonAppTargets) /* nonApps */);
return;
}
+ } else if (nonAppTargets != null && nonAppTargets.length > 0) {
+ TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
+ RemoteAnimationTargetCompat.wrap(nonAppTargets) /* nonApps */,
+ true /*shown*/, dividerAnimator -> dividerAnimator.start());
}
if (mController != null) {
if (mLastAppearedTaskTarget == null
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 3803f03..300f085 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -256,7 +256,7 @@
private BaseIconFactory getIconFactory() {
if (mIconFactory == null) {
mIconFactory = new BaseIconFactory(mContext,
- DisplayController.INSTANCE.get(mContext).getInfo().getDensityDpi(),
+ DisplayController.INSTANCE.get(mContext).getInfo().densityDpi,
mContext.getResources().getDimensionPixelSize(R.dimen.taskbar_icon_size));
}
return mIconFactory;
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index f53491b..3ef1332 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -46,6 +46,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.TaskShortcutFactory.SplitSelectSystemShortcut;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.OverviewActionsView;
@@ -314,9 +315,14 @@
}
protected void showBlockedByPolicyMessage() {
+ ActivityContext activityContext = ActivityContext.lookupContext(
+ mThumbnailView.getContext());
+ String message = activityContext.getStringCache() != null
+ ? activityContext.getStringCache().disabledByAdminMessage
+ : mThumbnailView.getContext().getString(R.string.blocked_by_policy);
Toast.makeText(
mThumbnailView.getContext(),
- R.string.blocked_by_policy,
+ message,
Toast.LENGTH_LONG).show();
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 10c56c9..85ef6cb 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -130,7 +130,7 @@
if (IS_VERBOSE) {
Log.d(TAG, String.format("\nwriteSnapshot(%d):\n%s", instanceId.getId(), info));
}
- if (!Utilities.ATLEAST_R) {
+ if (!Utilities.ATLEAST_R || Utilities.IS_RUNNING_IN_TEST_HARNESS) {
return;
}
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_SNAPSHOT,
@@ -415,6 +415,10 @@
consumer.consume(event, atomInfo);
}
+ // TODO: remove this when b/231648228 is fixed.
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return;
+ }
SysUiStatsLog.write(
SysUiStatsLog.LAUNCHER_EVENT,
SysUiStatsLog.LAUNCHER_UICHANGED__ACTION__DEFAULT_ACTION /* deprecated */,
@@ -510,6 +514,9 @@
}
private static int getCardinality(LauncherAtom.ItemInfo info) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return 0;
+ }
switch (info.getContainerInfo().getContainerCase()) {
case PREDICTED_HOTSEAT_CONTAINER:
return info.getContainerInfo().getPredictedHotseatContainer().getCardinality();
@@ -625,6 +632,9 @@
}
private static int getHierarchy(LauncherAtom.ItemInfo info) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return 0;
+ }
if (info.getContainerInfo().getContainerCase() == FOLDER) {
return info.getContainerInfo().getFolder().getParentContainerCase().getNumber()
+ FOLDER_HIERARCHY_OFFSET;
@@ -665,6 +675,9 @@
}
private static int getSearchAttributes(LauncherAtom.ItemInfo info) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return 0;
+ }
ContainerInfo containerInfo = info.getContainerInfo();
if (containerInfo.getContainerCase() == EXTENDED_CONTAINERS
&& containerInfo.getExtendedContainers().getContainerCase()
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index d4c5b8f..b634518 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -946,7 +946,7 @@
mHasVisibleTaskData.delete(i);
}
if (child instanceof GroupedTaskView) {
- mGroupedTaskViewPool.recycle((GroupedTaskView)taskView);
+ mGroupedTaskViewPool.recycle((GroupedTaskView) taskView);
} else {
mTaskViewPool.recycle(taskView);
}
@@ -1855,17 +1855,18 @@
if (!mActivity.getDeviceProfile().isTablet) {
return super.getDestinationPage(scaledScroll);
}
-
- final int childCount = getChildCount();
- if (mPageScrolls == null || childCount != mPageScrolls.length) {
- return -1;
+ if (!pageScrollsInitialized()) {
+ Log.e(TAG,
+ "Cannot get destination page: RecentsView not properly initialized",
+ new IllegalStateException());
+ return INVALID_PAGE;
}
// When in tablet with variable task width, return the page which scroll is closest to
// screenStart instead of page nearest to center of screen.
int minDistanceFromScreenStart = Integer.MAX_VALUE;
- int minDistanceFromScreenStartIndex = -1;
- for (int i = 0; i < childCount; ++i) {
+ int minDistanceFromScreenStartIndex = INVALID_PAGE;
+ for (int i = 0; i < getChildCount(); ++i) {
int distanceFromScreenStart = Math.abs(mPageScrolls[i] - scaledScroll);
if (distanceFromScreenStart < minDistanceFromScreenStart) {
minDistanceFromScreenStart = distanceFromScreenStart;
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
new file mode 100644
index 0000000..929bff3
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
@@ -0,0 +1,125 @@
+package com.android.launcher3.taskbar;
+
+import static android.view.MotionEvent.ACTION_DOWN;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.DeviceProfile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Supplier;
+
+@RunWith(AndroidJUnit4.class)
+public class RecentsHitboxExtenderTest {
+
+ private static final int TASKBAR_OFFSET_Y = 35;
+ private static final int BUTTON_WIDTH = 10;
+ private static final int BUTTON_HEIGHT = 10;
+
+ private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
+ @Mock
+ View mMockRecentsButton;
+ @Mock
+ View mMockRecentsParent;
+ @Mock
+ DeviceProfile mMockDeviceProfile;
+ @Mock
+ Handler mMockHandler;
+ Context mContext;
+
+ float[] mRecentsCoords = new float[]{0,0};
+ private final Supplier<float[]> mSupplier = () -> mRecentsCoords;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = instrumentation.getContext();
+ mHitboxExtender.init(mMockRecentsButton, mMockRecentsParent, mMockDeviceProfile, mSupplier,
+ mMockHandler);
+ when(mMockDeviceProfile.getTaskbarOffsetY()).thenReturn(TASKBAR_OFFSET_Y);
+ when(mMockRecentsButton.getContext()).thenReturn(mContext);
+ when(mMockRecentsButton.getWidth()).thenReturn(BUTTON_WIDTH);
+ when(mMockRecentsButton.getHeight()).thenReturn(BUTTON_HEIGHT);
+ }
+
+ @Test
+ public void noRecentsButtonClick_notActive() {
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertFalse(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void recentsButtonClick_active() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void homeToTaskbar_notActive() {
+ mHitboxExtender.onAnimationProgressToOverview(1);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertFalse(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void animationEndReset() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ mHitboxExtender.onAnimationProgressToOverview(1);
+ verify(mMockHandler, times(1)).postDelayed(any(), anyLong());
+ }
+
+ @Test
+ public void motionWithinHitbox() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ // Center width, past height but w/in offset bounds
+ MotionEvent motionEvent = getMotionEvent(ACTION_DOWN,
+ BUTTON_WIDTH / 2, BUTTON_HEIGHT + TASKBAR_OFFSET_Y / 2);
+ assertTrue(mHitboxExtender.onControllerInterceptTouchEvent(motionEvent));
+ }
+
+ @Test
+ public void motionOutsideHitbox() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ // Center width, past height and offset
+ MotionEvent motionEvent = getMotionEvent(ACTION_DOWN,
+ BUTTON_WIDTH / 2, BUTTON_HEIGHT + TASKBAR_OFFSET_Y * 2);
+ assertFalse(mHitboxExtender.onControllerInterceptTouchEvent(motionEvent));
+ }
+
+ private MotionEvent getMotionEvent(int action, int x, int y) {
+ return MotionEvent.obtain(0, 0, action, x, y, 0);
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 4d38822..4bf247c 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -52,6 +52,8 @@
public class TaplTestsQuickstep extends AbstractQuickStepTest {
private static final String APP_NAME = "LauncherTestApp";
+ private static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
@Before
public void setUp() throws Exception {
@@ -73,7 +75,7 @@
public static void startTestApps() throws Exception {
startAppFast(getAppPackageName());
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ startAppFast(CALCULATOR_APP_PACKAGE);
startTestActivity(2);
}
@@ -207,7 +209,7 @@
@NavigationModeSwitch
@PortraitLandscape
public void testBackground() throws Exception {
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ startAppFast(CALCULATOR_APP_PACKAGE);
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
assertNotNull("Background.switchToOverview() returned null",
@@ -302,7 +304,7 @@
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ startAppFast(CALCULATOR_APP_PACKAGE);
mLauncher.pressBack();
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
diff --git a/res/color-night-v31/all_apps_button_color_2.xml b/res/color-night-v31/all_apps_button_color_2.xml
index 30b972f..e400543 100644
--- a/res/color-night-v31/all_apps_button_color_2.xml
+++ b/res/color-night-v31/all_apps_button_color_2.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="98" />
</selector>
diff --git a/res/color-night-v31/folder_background_dark.xml b/res/color-night-v31/folder_background_dark.xml
index d607395..696e8ea 100644
--- a/res/color-night-v31/folder_background_dark.xml
+++ b/res/color-night-v31/folder_background_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral2_50"
+ android:color="@android:color/system_neutral2_500"
android:lStar="35" />
</selector>
diff --git a/res/color-night-v31/folder_preview_dark.xml b/res/color-night-v31/folder_preview_dark.xml
index a5bd636..bdd48a2 100644
--- a/res/color-night-v31/folder_preview_dark.xml
+++ b/res/color-night-v31/folder_preview_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral2_50"
+ android:color="@android:color/system_neutral2_500"
android:lStar="30" />
</selector>
diff --git a/res/color-v31/all_apps_button_bg_color.xml b/res/color-v31/all_apps_button_bg_color.xml
index 3ad38bc..8959020 100644
--- a/res/color-v31/all_apps_button_bg_color.xml
+++ b/res/color-v31/all_apps_button_bg_color.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral1_50"
+ android:color="@android:color/system_neutral1_500"
android:lStar="98" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_1.xml b/res/color-v31/all_apps_button_color_1.xml
index 2d0895e..71c7d8d 100644
--- a/res/color-v31/all_apps_button_color_1.xml
+++ b/res/color-v31/all_apps_button_color_1.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent1_50"
+ android:color="@android:color/system_accent1_500"
android:lStar="40" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_2.xml b/res/color-v31/all_apps_button_color_2.xml
index 7674b43..608c8a9 100644
--- a/res/color-v31/all_apps_button_color_2.xml
+++ b/res/color-v31/all_apps_button_color_2.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="48" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_3.xml b/res/color-v31/all_apps_button_color_3.xml
index 17cb54f..dbb97b1 100644
--- a/res/color-v31/all_apps_button_color_3.xml
+++ b/res/color-v31/all_apps_button_color_3.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent1_50"
+ android:color="@android:color/system_accent1_500"
android:lStar="35" />
</selector>
diff --git a/res/color-v31/all_apps_button_color_4.xml b/res/color-v31/all_apps_button_color_4.xml
index a6150f1..d02528f6 100644
--- a/res/color-v31/all_apps_button_color_4.xml
+++ b/res/color-v31/all_apps_button_color_4.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent3_50"
+ android:color="@android:color/system_accent3_500"
android:lStar="48" />
</selector>
diff --git a/res/color-v31/folder_background_light.xml b/res/color-v31/folder_background_light.xml
index e3c7e7d..eb2fdd7 100644
--- a/res/color-v31/folder_background_light.xml
+++ b/res/color-v31/folder_background_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral1_50"
+ android:color="@android:color/system_neutral1_500"
android:lStar="98" />
</selector>
diff --git a/res/color-v31/folder_preview_light.xml b/res/color-v31/folder_preview_light.xml
index fe30c87..ed1205e 100644
--- a/res/color-v31/folder_preview_light.xml
+++ b/res/color-v31/folder_preview_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="80" />
</selector>
diff --git a/res/drawable/rounded_action_button.xml b/res/drawable/rounded_action_button.xml
index b9942c0..81e94f7 100644
--- a/res/drawable/rounded_action_button.xml
+++ b/res/drawable/rounded_action_button.xml
@@ -18,10 +18,11 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurfaceVariant" />
<corners android:radius="@dimen/rounded_button_radius" />
<stroke
android:width="1dp"
- android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+ android:color="?androidprv:attr/colorSurfaceVariant" />
<padding
android:left="@dimen/rounded_button_padding"
android:right="@dimen/rounded_button_padding" />
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index 0f6fc6c..feebfe1 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -22,7 +22,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
- android:importantForAccessibility="no"
+ android:importantForAccessibility="noHideDescendants"
android:layout_marginVertical="8dp">
<!-- The image of the widget. This view does not support padding. Any placement adjustment
should be done using margins. Width & height are set at runtime after scaling the
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 8f0eae7..3cdc2e8 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -21,7 +21,10 @@
android:layout_height="wrap_content"
android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
android:orientation="horizontal"
- launcher:appIconSize="48dp">
+ android:importantForAccessibility="yes"
+ android:focusable="true"
+ launcher:appIconSize="48dp"
+ android:descendantFocusability="afterDescendants">
<ImageView
android:id="@+id/app_icon"
@@ -32,14 +35,11 @@
tools:src="@drawable/ic_corp"/>
<LinearLayout
- android:id="@+id/app_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
- android:orientation="vertical"
- android:focusable="true"
- android:descendantFocusability="afterDescendants">
+ android:orientation="vertical">
<TextView
android:id="@+id/app_title"
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index 73200de..f3b3053 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -16,9 +16,9 @@
<com.android.launcher3.allapps.WorkEduCard xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
+ android:layout_marginTop="@dimen/work_edu_card_margin"
+ android:layout_marginBottom="@dimen/work_edu_card_bottom_margin"
android:gravity="center">
-
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -36,30 +36,29 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/work_card_margin"
- android:layout_marginRight="@dimen/work_card_margin"
+ android:layout_marginEnd="@dimen/work_card_margin"
android:text="@string/work_profile_edu_work_apps"
+ android:textDirection="locale"
android:textSize="18sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/padded_rounded_button_height"
- android:orientation="horizontal"
- >
+ android:orientation="horizontal">
<FrameLayout
android:layout_width="@dimen/rounded_button_width"
android:layout_height="@dimen/rounded_button_width"
+ android:layout_alignParentEnd="true"
android:background="@drawable/rounded_action_button"
- android:padding="@dimen/rounded_button_padding"
- android:layout_alignParentRight="true">
+ android:padding="@dimen/rounded_button_padding">
<ImageButton
+ android:id="@+id/action_btn"
android:layout_width="@dimen/x_icon_size"
android:layout_height="@dimen/x_icon_size"
- android:id="@+id/action_btn"
- android:src="@drawable/ic_remove_no_shadow"
android:layout_gravity="center"
- android:padding="@dimen/x_icon_padding" />
+ android:padding="@dimen/x_icon_padding"
+ android:src="@drawable/ic_remove_no_shadow" />
</FrameLayout>
</RelativeLayout>
-
</RelativeLayout>
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index c536d77..d2fa5fa 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -21,14 +21,14 @@
android:layout_width="wrap_content"
android:gravity="center"
android:includeFontPadding="false"
+ android:textDirection="locale"
android:drawableTint="@color/all_apps_tab_text"
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp"
android:background="@drawable/work_apps_toggle_background"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_corp_off"
- android:layout_marginBottom="@dimen/work_fab_margin"
- android:layout_marginEnd="@dimen/work_fab_margin"
+ android:layout_marginBottom="@dimen/work_fab_margin_bottom"
android:paddingLeft="@dimen/work_mode_fab_padding"
android:paddingRight="@dimen/work_mode_fab_padding"
android:text="@string/work_apps_pause_btn_text" />
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index e85969b..dd3e08b 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -306,17 +306,6 @@
if not specified -->
<attr name="allAppsBorderSpaceTwoPanelLandscapeVertical" format="float" />
- <!-- alignment of hotseat to the grid.
- Not applicable for 3 button mode when taskbar is enabled -->
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpan" format="integer" />
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpanLandscape" format="integer" />
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
- <!-- defaults to numColumns, if not specified -->
- <attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
-
<!-- defaults to borderSpaceDps, if not specified -->
<attr name="hotseatBorderSpace" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7d8914e..098c694 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -129,6 +129,7 @@
<dimen name="all_apps_height_extra">6dp</dimen>
<dimen name="all_apps_bottom_sheet_horizontal_padding">0dp</dimen>
<dimen name="all_apps_paged_view_top_padding">40dp</dimen>
+ <dimen name="all_apps_personal_work_tabs_vertical_margin">16dp</dimen>
<!-- The size of corner radius of the arrow in the arrow toast. -->
<dimen name="arrow_toast_corner_radius">2dp</dimen>
@@ -148,10 +149,12 @@
<dimen name="work_card_padding_horizontal">10dp</dimen>
<dimen name="work_card_button_height">52dp</dimen>
<dimen name="work_fab_margin">16dp</dimen>
+ <dimen name="work_fab_margin_bottom">20dp</dimen>
<dimen name="work_mode_fab_padding">16dp</dimen>
<dimen name="work_profile_footer_padding">20dp</dimen>
<dimen name="work_edu_card_margin">16dp</dimen>
<dimen name="work_edu_card_radius">16dp</dimen>
+ <dimen name="work_edu_card_bottom_margin">26dp</dimen>
<dimen name="work_card_margin">24dp</dimen>
<!-- (x) icon button inside work edu card -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ffa1e3f..ee5e024 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -428,7 +428,7 @@
<string name="work_apps_paused_edu_accept">Got it</string>
<!-- button string shown pause work profile -->
- <string name="work_apps_pause_btn_text">Turn off work apps</string>
+ <string name="work_apps_pause_btn_text">Pause work apps</string>
<!-- button string shown enable work profile -->
<string name="work_apps_enable_btn_text">Turn on work apps</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 864bb58..2109510 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -76,7 +76,7 @@
</style>
<style name="LauncherTheme.DarkMainColor" parent="@style/LauncherTheme">
- <item name="disabledIconAlpha">.254</item>
+ <item name="disabledIconAlpha">.54</item>
</style>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 258da80..07ce598 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -176,7 +176,6 @@
launcher:allAppsBorderSpaceHorizontal="8"
launcher:allAppsBorderSpaceVertical="16"
launcher:allAppsBorderSpaceLandscape="16"
- launcher:hotseatColumnSpanLandscape="4"
launcher:hotseatBorderSpace="58"
launcher:hotseatBorderSpaceLandscape="50.4"
launcher:canBeDefault="true" />
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 561f9b9..31f1da8 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -158,7 +158,6 @@
public final int numShownHotseatIcons;
public int hotseatCellHeightPx;
private final int hotseatExtraVerticalSize;
- private final boolean areNavButtonsInline;
// In portrait: size = height, in landscape: size = width
public int hotseatBarSizePx;
public int hotseatBarTopPaddingPx;
@@ -359,7 +358,7 @@
// We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
// might be inline in either orientations, to keep hotseat size consistent across rotation.
- areNavButtonsInline = isTaskbarPresent && !isGestureMode;
+ boolean areNavButtonsInline = isTaskbarPresent && !isGestureMode;
if (areNavButtonsInline && canQsbInline) {
numShownHotseatIcons = inv.numShrunkenHotseatIcons;
} else {
@@ -374,14 +373,15 @@
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
if (isQsbInline) {
hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
+ qsbWidth = calculateQsbWidth();
} else {
hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
: res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+ qsbWidth = 0;
}
-
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
R.dimen.spring_loaded_hotseat_top_margin);
hotseatBarSidePaddingEndPx =
@@ -390,7 +390,9 @@
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
- updateHotseatIconSize(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
+ hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
+ updateHotseatIconSize(
+ pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
qsbBottomMarginOriginalPx = isScalableGrid
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
@@ -481,10 +483,6 @@
cellLayoutPadding);
updateWorkspacePadding();
- // Hotseat and QSB width depends on updated cellSize and workspace padding
- hotseatBorderSpace = calculateHotseatBorderSpace();
- qsbWidth = calculateQsbWidth();
-
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
R.dimen.drag_flingToDeleteMinVelocity);
@@ -495,26 +493,14 @@
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
- /**
- * QSB width is always calculated because when in 3 button nav the width doesn't follow the
- * width of the hotseat.
- */
private int calculateQsbWidth() {
- if (isQsbInline) {
- int columns = getPanelCount() * inv.numColumns;
- return getIconToIconWidthForColumns(columns)
- - iconSizePx * numShownHotseatIcons
- - hotseatBorderSpace * numShownHotseatIcons;
- } else {
- int columns = inv.hotseatColumnSpan[mTypeIndex];
- return getIconToIconWidthForColumns(columns);
- }
- }
+ int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
- private int getIconToIconWidthForColumns(int columns) {
- return columns * getCellSize().x
- + (columns - 1) * cellLayoutBorderSpacePx.x
- - (getCellSize().x - iconSizePx); // left and right cell space
+ return cellWidthPx * columns
+ + cellLayoutBorderSpacePx.x * (columns - 1)
+ - (cellWidthPx - iconSizePx) // left and right cell space
+ - iconSizePx * numShownHotseatIcons
+ - hotseatBorderSpace * numShownHotseatIcons;
}
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
@@ -665,10 +651,11 @@
updateIconSize(1f, res);
updateWorkspacePadding();
+ Point workspacePadding = getTotalWorkspacePadding();
// Check to see if the icons fit within the available height.
float usedHeight = getCellLayoutHeightSpecification();
- final int maxHeight = getCellLayoutHeight();
+ final int maxHeight = getWorkspaceHeight(workspacePadding);
float extraHeight = Math.max(0, maxHeight - usedHeight);
float scaleY = maxHeight / usedHeight;
boolean shouldScale = scaleY < 1f;
@@ -701,7 +688,7 @@
}
private int getCellLayoutWidthSpecification() {
- int numColumns = getPanelCount() * inv.numColumns;
+ int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
return (cellWidthPx * numColumns) + (cellLayoutBorderSpacePx.x * (numColumns - 1))
+ cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
@@ -754,6 +741,13 @@
// All apps
updateAllAppsIconSize(scale, res);
+ // Hotseat
+ hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
+ if (isQsbInline) {
+ qsbWidth = calculateQsbWidth();
+ } else {
+ qsbWidth = 0;
+ }
updateHotseatIconSize(iconSizePx);
// Folder icon
@@ -761,23 +755,6 @@
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
}
- /**
- * Hotseat width spans a certain number of columns on scalable grids.
- * This method calculates the space between the icons to achieve that width.
- */
- private int calculateHotseatBorderSpace() {
- if (!isScalableGrid) return 0;
- //TODO(http://b/228998082) remove this when 3 button spaces are fixed
- if (areNavButtonsInline) {
- return pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
- } else {
- int columns = inv.hotseatColumnSpan[mTypeIndex];
- float hotseatWidthPx = getIconToIconWidthForColumns(columns);
- float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
- return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
- }
- }
-
/**
* Updates the iconSize for allApps* variants.
@@ -901,18 +878,16 @@
result = new Point();
}
- result.x = calculateCellWidth(getShortcutAndWidgetContainerWidth(),
- cellLayoutBorderSpacePx.x, inv.numColumns);
- result.y = calculateCellHeight(getShortcutAndWidgetContainerHeight(),
- cellLayoutBorderSpacePx.y, inv.numRows);
- return result;
- }
+ // Since we are only concerned with the overall padding, layout direction does
+ // not matter.
+ Point padding = getTotalWorkspacePadding();
- /**
- * Gets the number of panels within the workspace.
- */
- public int getPanelCount() {
- return isTwoPanels ? 2 : 1;
+ int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+ int screenWidthPx = getWorkspaceWidth(padding);
+ result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacePx.x, numColumns);
+ int screenHeightPx = getWorkspaceHeight(padding);
+ result.y = calculateCellHeight(screenHeightPx, cellLayoutBorderSpacePx.y, inv.numRows);
+ return result;
}
/**
@@ -933,7 +908,7 @@
/**
* Gets the scaled top of the workspace in px for the spring-loaded edit state.
*/
- public float getCellLayoutSpringLoadShrunkTop() {
+ public float getWorkspaceSpringLoadShrunkTop() {
workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
+ dropTargetBarBottomMarginPx;
return workspaceSpringLoadShrunkTop;
@@ -942,7 +917,7 @@
/**
* Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
*/
- private float getCellLayoutSpringLoadShrunkBottom() {
+ private float getWorkspaceSpringLoadShrunkBottom() {
int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
workspaceSpringLoadShrunkBottom =
heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
@@ -961,8 +936,9 @@
* Gets the scale of the workspace for the spring-loaded edit state.
*/
public float getWorkspaceSpringLoadScale() {
- float scale = (getCellLayoutSpringLoadShrunkBottom() - getCellLayoutSpringLoadShrunkTop())
- / getCellLayoutHeight();
+ float cellLayoutHeight = availableHeightPx - workspacePadding.top - workspacePadding.bottom;
+ float scale = (getWorkspaceSpringLoadShrunkBottom() - getWorkspaceSpringLoadShrunkTop())
+ / cellLayoutHeight;
scale = Math.min(scale, 1f);
// Reduce scale if next pages would not be visible after scaling the workspace
@@ -976,55 +952,19 @@
return scale;
}
- /**
- * Gets the width of the Workspace, aka a scrollable page of the homescreen.
- */
public int getWorkspaceWidth() {
- return availableWidthPx;
+ return getWorkspaceWidth(getTotalWorkspacePadding());
}
- /**
- * Gets the height of the Workspace, aka a scrollable page of the homescreen.
- */
- public int getWorkspaceHeight() {
- return availableHeightPx;
+ public int getWorkspaceWidth(Point workspacePadding) {
+ int cellLayoutTotalPadding =
+ (isTwoPanels ? 2 : 1) * (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
+ return availableWidthPx - workspacePadding.x - cellLayoutTotalPadding;
}
- /**
- * Gets the width of a single Cell Layout, aka a single panel within a Workspace.
- *
- * <p>This is the width of a Workspace, less its horizontal padding. Note that two-panel
- * layouts have two Cell Layouts per workspace.
- */
- public int getCellLayoutWidth() {
- return (getWorkspaceWidth() - getTotalWorkspacePadding().x) / getPanelCount();
- }
-
- /**
- * Gets the height of a single Cell Layout, aka a single panel within a Workspace.
- *
- * <p>This is the height of a Workspace, less its vertical padding.
- */
- public int getCellLayoutHeight() {
- return getWorkspaceHeight() - getTotalWorkspacePadding().y;
- }
-
- /**
- * Gets the width of the container holding the shortcuts and widgets.
- *
- * <p>This is the width of one Cell Layout less its horizontal padding.
- */
- public int getShortcutAndWidgetContainerWidth() {
- return getCellLayoutWidth() - (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
- }
-
- /**
- * Gets the height of the container holding the shortcuts and widgets.
- *
- * <p>This is the height of one Cell Layout less its vertical padding.
- */
- public int getShortcutAndWidgetContainerHeight() {
- return getCellLayoutHeight() - (cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom);
+ private int getWorkspaceHeight(Point workspacePadding) {
+ return availableHeightPx - workspacePadding.y - (cellLayoutPaddingPx.top
+ + cellLayoutPaddingPx.bottom);
}
public Point getTotalWorkspacePadding() {
@@ -1130,13 +1070,6 @@
mHotseatPadding.left -= diff;
mHotseatPadding.right += diff;
}
- } else if (isScalableGrid) {
- int sideSpacing = (availableWidthPx - qsbWidth) / 2;
- mHotseatPadding.set(sideSpacing,
- hotseatBarTopPaddingPx,
- sideSpacing,
- hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
- + mInsets.bottom);
} else {
// We want the edges of the hotseat to line up with the edges of the workspace, but the
// icons in the hotseat are a different size, and so don't line up perfectly. To account
@@ -1373,7 +1306,6 @@
writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
- writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
writer.println(prefix + pxToDpStr("hotseatBarTopPaddingPx", hotseatBarTopPaddingPx));
writer.println(prefix + pxToDpStr("hotseatBarBottomPaddingPx", hotseatBarBottomPaddingPx));
@@ -1452,7 +1384,7 @@
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
Configuration config = new Configuration(c.getResources().getConfiguration());
config.orientation = orientation;
- config.densityDpi = info.getDensityDpi();
+ config.densityDpi = info.densityDpi;
config.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
return c.createConfigurationContext(config);
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 76106fc..a9db5ce 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -173,9 +173,17 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int qsbWidth = mActivity.getDeviceProfile().qsbWidth;
+ int width;
+ if (mActivity.getDeviceProfile().isQsbInline) {
+ width = mActivity.getDeviceProfile().qsbWidth;
+ } else {
+ MarginLayoutParams qsbParams = (MarginLayoutParams) mQsb.getLayoutParams();
+ width = getShortcutsAndWidgets().getMeasuredWidth()
+ - qsbParams.getMarginStart()
+ - qsbParams.getMarginEnd();
+ }
- mQsb.measure(MeasureSpec.makeMeasureSpec(qsbWidth, MeasureSpec.EXACTLY),
+ mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 0373eef..1f92079 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -127,7 +127,6 @@
public PointF[] borderSpaces;
public float folderBorderSpace;
public float[] hotseatBorderSpaces;
- public int[] hotseatColumnSpan;
public float[] horizontalMargin;
@@ -359,7 +358,6 @@
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
- hotseatColumnSpan = displayOption.hotseatColumnSpan;
numAllAppsColumns = closestProfile.numAllAppsColumns;
numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY
@@ -400,8 +398,7 @@
// We need to ensure that there is enough extra space in the wallpaper
// for the intended parallax effects
float parallaxFactor =
- dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.getDensityDpi())
- < 720
+ dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
? 2
: wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
defaultWallpaperSize.x =
@@ -590,8 +587,8 @@
}
}
- float width = dpiFromPx(minWidthPx, displayInfo.getDensityDpi());
- float height = dpiFromPx(minHeightPx, displayInfo.getDensityDpi());
+ float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
+ float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
// Sort the profiles based on the closeness to the device size
Collections.sort(points, (a, b) ->
@@ -824,9 +821,7 @@
private float folderBorderSpace;
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
private final float[] horizontalMargin = new float[COUNT_SIZES];
- //TODO(http://b/228998082) remove this when 3 button spaces are fixed
private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
- private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
private final float[] iconSizes = new float[COUNT_SIZES];
private final float[] textSizes = new float[COUNT_SIZES];
@@ -1052,17 +1047,6 @@
R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelPortrait,
hotseatBorderSpaces[INDEX_DEFAULT]);
- hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpan, grid.numColumns);
- hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpanLandscape, grid.numColumns);
- hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpanTwoPanelLandscape,
- grid.numColumns);
- hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
- R.styleable.ProfileDisplayOption_hotseatColumnSpanTwoPanelPortrait,
- grid.numColumns);
-
a.recycle();
}
@@ -1121,7 +1105,6 @@
minCellSize[i].y += p.minCellSize[i].y;
horizontalMargin[i] += p.horizontalMargin[i];
hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
- hotseatColumnSpan[i] = p.hotseatColumnSpan[i];
allAppsCellSize[i].x += p.allAppsCellSize[i].x;
allAppsCellSize[i].y += p.allAppsCellSize[i].y;
allAppsIconSizes[i] += p.allAppsIconSizes[i];
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 2ad1d47..ad87451 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1279,13 +1279,16 @@
* @param info The data structure describing the shortcut.
*/
View createShortcut(WorkspaceItemInfo info) {
- return createShortcut((ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
+ // This can be called before PagedView#pageScrollsInitialized returns true, so use the
+ // first page, which we always assume to be present.
+ return createShortcut((ViewGroup) mWorkspace.getChildAt(0), info);
}
/**
* Creates a view representing a shortcut inflated from the specified resource.
*
- * @param parent The group the shortcut belongs to.
+ * @param parent The group the shortcut belongs to. This is not necessarily the group where
+ * the shortcut should be added.
* @param info The data structure describing the shortcut.
* @return A View inflated from layoutResId.
*/
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4501159..597bc8d 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.config.FeatureFlags.ENABLE_THEMED_ICONS;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -97,7 +99,8 @@
modelChangeReceiver.register(mContext, Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
- Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED,
+ ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
if (FeatureFlags.IS_STUDIO_BUILD) {
modelChangeReceiver.register(mContext, Context.RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index ee6f51e..5c5c101 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -51,6 +53,7 @@
import com.android.launcher3.model.PackageIncrementalDownloadUpdatedTask;
import com.android.launcher3.model.PackageInstallStateChangedTask;
import com.android.launcher3.model.PackageUpdatedTask;
+import com.android.launcher3.model.ReloadStringCacheTask;
import com.android.launcher3.model.ShortcutsChangedTask;
import com.android.launcher3.model.UserLockStateChangedTask;
import com.android.launcher3.model.data.AppInfo;
@@ -278,6 +281,8 @@
user, Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)));
}
}
+ } else if (ACTION_DEVICE_POLICY_RESOURCE_UPDATED.equals(action)) {
+ enqueueModelUpdateTask(new ReloadStringCacheTask(mModelDelegate));
} else if (IS_STUDIO_BUILD && ACTION_FORCE_ROLOAD.equals(action)) {
for (Callbacks cb : getCallbacks()) {
if (cb instanceof Launcher) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 0a1d25c..95a8a2a 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -129,7 +129,10 @@
private boolean mAllowEasyFling;
protected PagedOrientationHandler mOrientationHandler = PagedOrientationHandler.PORTRAIT;
- protected int[] mPageScrolls;
+ private final ArrayList<Runnable> mOnPageScrollsInitializedCallbacks = new ArrayList<>();
+
+ // We should always check pageScrollsInitialized() is true when using mPageScrolls.
+ @Nullable protected int[] mPageScrolls = null;
private boolean mIsBeingDragged;
// The amount of movement to begin scrolling
@@ -684,14 +687,37 @@
setMeasuredDimension(widthSize, heightSize);
}
+ /** Returns true iff this PagedView's scroll amounts are initialized to each page index. */
+ protected boolean pageScrollsInitialized() {
+ return mPageScrolls != null && mPageScrolls.length == getChildCount();
+ }
+
+ /**
+ * Queues the given callback to be run once {@code mPageScrolls} has been initialized.
+ */
+ public void runOnPageScrollsInitialized(Runnable callback) {
+ mOnPageScrollsInitializedCallbacks.add(callback);
+ if (pageScrollsInitialized()) {
+ onPageScrollsInitialized();
+ }
+ }
+
+ private void onPageScrollsInitialized() {
+ for (Runnable callback : mOnPageScrollsInitializedCallbacks) {
+ callback.run();
+ }
+ mOnPageScrollsInitializedCallbacks.clear();
+ }
+
@SuppressLint("DrawAllocation")
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mIsLayoutValid = true;
final int childCount = getChildCount();
+ int[] pageScrolls = mPageScrolls;
boolean pageScrollChanged = false;
- if (mPageScrolls == null || childCount != mPageScrolls.length) {
- mPageScrolls = new int[childCount];
+ if (!pageScrollsInitialized()) {
+ pageScrolls = new int[childCount];
pageScrollChanged = true;
}
@@ -701,10 +727,8 @@
if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
- boolean isScrollChanged = getPageScrolls(mPageScrolls, true, SIMPLE_SCROLL_LOGIC);
- if (isScrollChanged) {
- pageScrollChanged = true;
- }
+ pageScrollChanged |= getPageScrolls(pageScrolls, true, SIMPLE_SCROLL_LOGIC);
+ mPageScrolls = pageScrolls;
final LayoutTransition transition = getLayoutTransition();
// If the transition is running defer updating max scroll, as some empty pages could
@@ -738,6 +762,7 @@
if (mScroller.isFinished() && pageScrollChanged) {
setCurrentPage(getNextPage());
}
+ onPageScrollsInitialized();
}
/**
@@ -849,8 +874,10 @@
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
- mCurrentPage = validateNewPage(mCurrentPage);
- mCurrentScrollOverPage = mCurrentPage;
+ runOnPageScrollsInitialized(() -> {
+ mCurrentPage = validateNewPage(mCurrentPage);
+ mCurrentScrollOverPage = mCurrentPage;
+ });
dispatchPageCountChanged();
}
@@ -1153,7 +1180,7 @@
}
public int getScrollForPage(int index) {
- if (mPageScrolls == null || index >= mPageScrolls.length || index < 0) {
+ if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
return mPageScrolls[index];
@@ -1163,7 +1190,7 @@
// While layout transitions are occurring, a child's position may stray from its baseline
// position. This method returns the magnitude of this stray at any given time.
public int getLayoutTransitionOffsetForPage(int index) {
- if (mPageScrolls == null || index >= mPageScrolls.length || index < 0) {
+ if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
View child = getChildAt(index);
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 58df50c..33d2f2b 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -118,7 +118,7 @@
List<AdapterItem> items = mApps.getAdapterItems();
adapterPosition = Math.max(adapterPosition, items.size() - 1);
int extraRows = 0;
- for (int i = 0; i <= adapterPosition; i++) {
+ for (int i = 0; i <= adapterPosition && i < items.size(); i++) {
if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) {
extraRows++;
}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 4390b51..72ca5a7 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -142,7 +142,7 @@
mWorkManager = new WorkProfileManager(
mActivityContext.getSystemService(UserManager.class),
this,
- Utilities.getPrefs(mActivityContext));
+ Utilities.getPrefs(mActivityContext), mActivityContext.getDeviceProfile());
mAH = Arrays.asList(null, null);
mAH.set(AdapterHolder.MAIN, new AdapterHolder(false /* isWork */));
mAH.set(AdapterHolder.WORK, new AdapterHolder(true /* isWork */));
@@ -437,8 +437,12 @@
if (showTabs == mUsingTabs && !force) {
return;
}
+
+ // replaceRVcontainer() needs to use both mUsingTabs value to remove the old view AND
+ // showTabs value to create new view. Hence the mUsingTabs new value assignment MUST happen
+ // after this call.
+ replaceRVContainer(showTabs);
mUsingTabs = showTabs;
- replaceRVContainer(mUsingTabs);
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index c5b02dd..dc9f18c 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -32,6 +32,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
@@ -73,15 +74,17 @@
private final Predicate<ItemInfo> mMatcher;
private WorkModeSwitch mWorkModeSwitch;
+ private final DeviceProfile mDeviceProfile;
@WorkProfileState
private int mCurrentState;
public WorkProfileManager(UserManager userManager, BaseAllAppsContainerView<?> allApps,
- SharedPreferences preferences) {
+ SharedPreferences preferences, DeviceProfile deviceProfile) {
mUserManager = userManager;
mAllApps = allApps;
+ mDeviceProfile = deviceProfile;
mAdapterProvider = new WorkAdapterProvider(allApps.mActivityContext, preferences);
mMatcher = mAllApps.mPersonalMatcher.negate();
}
@@ -141,8 +144,11 @@
mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate(
R.layout.work_mode_fab, mAllApps, false);
}
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) mWorkModeSwitch.getLayoutParams();
int workFabMarginBottom =
- mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.work_fab_margin);
+ mWorkModeSwitch.getResources().getDimensionPixelSize(
+ R.dimen.work_fab_margin_bottom);
if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
workFabMarginBottom <<= 1; // Double margin to add space above search bar.
workFabMarginBottom +=
@@ -151,8 +157,11 @@
if (!mAllApps.mActivityContext.getDeviceProfile().isGestureMode){
workFabMarginBottom += mAllApps.mActivityContext.getDeviceProfile().getInsets().bottom;
}
- ((ViewGroup.MarginLayoutParams) mWorkModeSwitch.getLayoutParams()).bottomMargin =
- workFabMarginBottom;
+ lp.bottomMargin = workFabMarginBottom;
+ int totalScreenWidth = mDeviceProfile.widthPx;
+ int personalWorkTabWidth =
+ mAllApps.mActivityContext.getAppsView().getActiveRecyclerView().getTabWidth();
+ lp.rightMargin = lp.leftMargin = (totalScreenWidth - personalWorkTabWidth) / 2;
if (mWorkModeSwitch.getParent() != mAllApps) {
mAllApps.addView(mWorkModeSwitch);
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 7dd7494..c38cf9a 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -161,14 +161,18 @@
String.format("upperBound (%f) must be greater than lowerBound (%f)",
upperBound, lowerBound));
}
- return t -> clampToProgress(t, lowerBound, upperBound);
+ return t -> clampToProgress(interpolator, t, lowerBound, upperBound);
}
/**
* Returns the progress value's progress between the lower and upper bounds. That is, the
* progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
+ *
+ * Between lowerBound and upperBound, the progress value will be interpolated using the provided
+ * interpolator.
*/
- public static float clampToProgress(float progress, float lowerBound, float upperBound) {
+ public static float clampToProgress(
+ Interpolator interpolator, float progress, float lowerBound, float upperBound) {
if (upperBound < lowerBound) {
throw new IllegalArgumentException(
String.format("upperBound (%f) must be greater than lowerBound (%f)",
@@ -184,7 +188,15 @@
if (progress > upperBound) {
return 1;
}
- return (progress - lowerBound) / (upperBound - lowerBound);
+ return interpolator.getInterpolation((progress - lowerBound) / (upperBound - lowerBound));
+ }
+
+ /**
+ * Returns the progress value's progress between the lower and upper bounds. That is, the
+ * progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
+ */
+ public static float clampToProgress(float progress, float lowerBound, float upperBound) {
+ return clampToProgress(Interpolators.LINEAR, progress, lowerBound, upperBound);
}
/**
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 626e15c..54edb33 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -261,6 +261,10 @@
public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
"ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
+ public static final BooleanFlag ENABLE_SHOW_KEYBOARD_IN_ALL_APPS = getDebugFlag(
+ "ENABLE_SHOW_KEYBOARD_IN_ALL_APPS", false,
+ "Enable option to show keyboard when going to all-apps");
+
public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(
"USE_LOCAL_ICON_OVERRIDES", true,
"Use inbuilt monochrome icons if app doesn't provide one");
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 2b621bd..5021644 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.folder;
+import android.annotation.SuppressLint;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Process;
@@ -22,11 +24,15 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -94,6 +100,7 @@
/**
* Generate and rank the suggested Folder names.
*/
+ @WorkerThread
public void getSuggestedFolderName(Context context,
ArrayList<WorkspaceItemInfo> workspaceItemInfos,
FolderNameInfos nameInfos) {
@@ -107,8 +114,7 @@
Set<UserHandle> users = workspaceItemInfos.stream().map(w -> w.user)
.collect(Collectors.toSet());
if (users.size() == 1 && !users.contains(Process.myUserHandle())) {
- String workFolderName = context.getString(R.string.work_folder_name);
- setAsLastSuggestion(nameInfos, workFolderName);
+ setAsLastSuggestion(nameInfos, getWorkFolderName(context));
}
// If all the icons are from same package (e.g., main icon, shortcut, shortcut)
@@ -130,6 +136,17 @@
}
}
+ @WorkerThread
+ @SuppressLint("NewApi")
+ private String getWorkFolderName(Context context) {
+ if (!Utilities.ATLEAST_T) {
+ return context.getString(R.string.work_folder_name);
+ }
+ return context.getSystemService(DevicePolicyManager.class).getResources()
+ .getString(StringCache.WORK_FOLDER_NAME, () ->
+ context.getString(R.string.work_folder_name));
+ }
+
private Optional<AppInfo> getAppInfoByPackageName(String packageName) {
if (mAppInfos == null || mAppInfos.isEmpty()) {
return Optional.empty();
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index a11bd4f..d5bcb0c 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -83,6 +83,7 @@
import com.android.launcher3.uioverrides.PredictedAppIconInflater;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
@@ -129,7 +130,7 @@
super(base, UserCache.INSTANCE, InstallSessionHelper.INSTANCE,
LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
CustomWidgetManager.INSTANCE, PluginManagerWrapper.INSTANCE,
- WindowManagerProxy.INSTANCE);
+ WindowManagerProxy.INSTANCE, DisplayController.INSTANCE);
mIdp = idp;
mObjectMap.put(InvariantDeviceProfile.INSTANCE, idp);
mObjectMap.put(LauncherAppState.INSTANCE,
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index e36d4cf..ef9250c 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -216,14 +216,15 @@
return false;
}
+ // Sort the items by the reading order.
+ Collections.sort(mHotseatDiff);
+ Collections.sort(mWorkspaceDiff);
+
// Migrate hotseat
HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader,
mDestReader, mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff);
hotseatSolution.find();
- // Sort the items by the reading order.
- Collections.sort(mWorkspaceDiff);
-
// Migrate workspace.
// First we create a collection of the screens
List<Integer> screens = new ArrayList<>();
diff --git a/src/com/android/launcher3/model/ReloadStringCacheTask.java b/src/com/android/launcher3/model/ReloadStringCacheTask.java
new file mode 100644
index 0000000..f4d4298
--- /dev/null
+++ b/src/com/android/launcher3/model/ReloadStringCacheTask.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.model;
+
+import com.android.launcher3.LauncherAppState;
+
+/**
+ * Handles updates due to changes in Device Policy Management resources triggered by
+ * {@link android.app.admin.DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED}.
+ */
+public class ReloadStringCacheTask extends BaseModelUpdateTask {
+ private ModelDelegate mModelDelegate;
+
+ public ReloadStringCacheTask(ModelDelegate modelDelegate) {
+ mModelDelegate = modelDelegate;
+ }
+
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+ synchronized (dataModel) {
+ mModelDelegate.loadStringCache(dataModel.stringCache);
+ StringCache cloneSC = dataModel.stringCache.clone();
+ scheduleCallbackTask(c -> c.bindStringCache(cloneSC));
+ }
+ }
+}
diff --git a/src/com/android/launcher3/model/StringCache.java b/src/com/android/launcher3/model/StringCache.java
index 663a463..9859ddc 100644
--- a/src/com/android/launcher3/model/StringCache.java
+++ b/src/com/android/launcher3/model/StringCache.java
@@ -35,6 +35,11 @@
private static final String PREFIX = "Launcher.";
/**
+ * Work folder name.
+ */
+ public static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
+
+ /**
* User on-boarding title for work profile apps.
*/
private static final String WORK_PROFILE_EDU = PREFIX + "WORK_PROFILE_EDU";
@@ -91,11 +96,6 @@
PREFIX + "ALL_APPS_PERSONAL_TAB_ACCESSIBILITY";
/**
- * Work folder name.
- */
- private static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
-
- /**
* Label on widget tab to indicate work app widgets.
*/
private static final String WIDGETS_WORK_TAB = PREFIX + "WIDGETS_WORK_TAB";
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index a205ab5..15cdc20 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -51,7 +51,7 @@
return super.getWorkspaceScaleAndTranslation(launcher);
}
- float shrunkTop = grid.getCellLayoutSpringLoadShrunkTop();
+ float shrunkTop = grid.getWorkspaceSpringLoadShrunkTop();
float scale = grid.getWorkspaceSpringLoadScale();
float halfHeight = ws.getHeight() / 2;
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index a6b481a..242d2d4 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -198,6 +198,12 @@
return new Point(cellRect.centerX(), cellRect.centerY());
});
+ case TestProtocol.REQUEST_HAS_TIS: {
+ response.putBoolean(
+ TestProtocol.REQUEST_HAS_TIS, false);
+ return response;
+ }
+
default:
return null;
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index e8fd2ff..3a030a8 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -110,6 +110,7 @@
public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT =
"get-activities-created-count";
public static final String REQUEST_GET_ACTIVITIES = "get-activities";
+ public static final String REQUEST_HAS_TIS = "has-touch-interaction-service";
public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size";
public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center";
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index a125fbe..09b8228 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
@@ -330,9 +331,6 @@
Math.min(progress, 1) - endProgress) * durationMultiplier;
}
}
- if (targetState != mStartState) {
- logReachedState(targetState);
- }
mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState));
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(startProgress, endProgress);
@@ -361,6 +359,8 @@
boolean shouldGoToTargetState = mGoingBetweenStates || (mToState != targetState);
if (shouldGoToTargetState) {
goToTargetState(targetState);
+ } else {
+ logReachedState(mToState);
}
}
@@ -368,13 +368,19 @@
if (!mLauncher.isInState(targetState)) {
// If we're already in the target state, don't jump to it at the end of the animation in
// case the user started interacting with it before the animation finished.
- mLauncher.getStateManager().goToState(targetState, false /* animated */);
+ mLauncher.getStateManager().goToState(targetState, false /* animated */,
+ forEndCallback(() -> logReachedState(targetState)));
+ } else {
+ logReachedState(targetState);
}
mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
1f).setDuration(0).start();
}
private void logReachedState(LauncherState targetState) {
+ if (mStartState == targetState) {
+ return;
+ }
// Transition complete. log the action
mLauncher.getStatsLogManager().logger()
.withSrcState(mStartState.statsLogOrdinal)
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 7c73be5..777da23 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -290,7 +290,7 @@
// Configuration property
public final float fontScale;
- private final int densityDpi;
+ public final int densityDpi;
public final NavigationMode navigationMode;
private final PortraitSize mScreenSizeDp;
@@ -357,10 +357,6 @@
public float smallestSizeDp(WindowBounds bounds) {
return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
}
-
- public int getDensityDpi() {
- return densityDpi;
- }
}
/**
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index b0e2ec1..48df04f 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -95,7 +95,7 @@
mTitle = findViewById(R.id.app_title);
mSubtitle = findViewById(R.id.app_subtitle);
mExpandToggle = findViewById(R.id.toggle);
- findViewById(R.id.app_container).setAccessibilityDelegate(new AccessibilityDelegate() {
+ setAccessibilityDelegate(new AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
index 6d0fcb6..f91f1c4 100644
--- a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -64,7 +64,6 @@
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(false)
- whenever(info.getDensityDpi()).thenReturn(560)
inv = newScalableInvariantDeviceProfile()
}
@@ -78,7 +77,6 @@
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
inv = newScalableInvariantDeviceProfile()
}
@@ -109,7 +107,6 @@
PointF(16f, 16f)
).toTypedArray()
hotseatBorderSpaces = FloatArray(4) { 16f }
- hotseatColumnSpan = IntArray(4) { 4 }
iconSize = FloatArray(4) { 56f }
allAppsIconSize = FloatArray(4) { 56f }
iconTextSize = FloatArray(4) { 14f }
diff --git a/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
deleted file mode 100644
index 63abc7d..0000000
--- a/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
+++ /dev/null
@@ -1,258 +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
-
-import android.graphics.PointF
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.launcher3.util.WindowBounds
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers
-import org.mockito.Mockito.`when` as whenever
-
-/**
- * Test for [DeviceProfile] grid dimensions.
- *
- * This includes workspace, cell layout, shortcut and widget container, cell sizes, etc.
- */
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class DeviceProfileGridDimensionsTest : DeviceProfileBaseTest() {
-
- @Test
- fun getWorkspaceWidth_twoPanelLandscapeScalable4By4GridTablet_workspaceWidthIsFullPage() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceWidth = availableWidth
- assertThat(dp.workspaceWidth).isEqualTo(expectedWorkspaceWidth)
- }
-
- @Test
- fun getWorkspaceHeight_twoPanelLandscapeScalable4By4GridTablet_workspaceHeightIsFullPage() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceHeight = availableHeight
- assertThat(dp.workspaceHeight).isEqualTo(expectedWorkspaceHeight)
- }
-
- @Test
- fun getCellLayoutWidth_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceWidth = availableWidth
- val expectedCellLayoutWidth =
- (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
- dp.panelCount
- assertThat(dp.cellLayoutWidth).isEqualTo(expectedCellLayoutWidth)
- }
-
- @Test
- fun getCellLayoutHeight_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelHeight() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceHeight = availableHeight
- val expectedCellLayoutHeight =
- expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
- assertThat(dp.cellLayoutHeight).isEqualTo(expectedCellLayoutHeight)
- }
-
- @Test
- fun getShortcutAndWidgetContainerWidth_twoPanelLandscapeScalable4By4GridTablet_equalsIconsPlusBorderSpacesWidth() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceWidth = availableWidth
- val expectedCellLayoutWidth =
- (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
- dp.panelCount
- val expectedShortcutAndWidgetContainerWidth = expectedCellLayoutWidth -
- (dp.cellLayoutPaddingPx.left + dp.cellLayoutPaddingPx.right)
- assertThat(dp.shortcutAndWidgetContainerWidth).isEqualTo(expectedShortcutAndWidgetContainerWidth)
- }
-
- @Test
- fun getShortcutAndWidgetContainerHeight_twoPanelLandscapeScalable4By4GridTablet_equalsIconsPlusBorderSpacesHeight() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceHeight = availableHeight
- val expectedCellLayoutHeight =
- expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
- val expectedShortcutAndWidgetContainerHeight = expectedCellLayoutHeight -
- (dp.cellLayoutPaddingPx.top + dp.cellLayoutPaddingPx.bottom)
- assertThat(dp.shortcutAndWidgetContainerHeight).isEqualTo(
- expectedShortcutAndWidgetContainerHeight)
- }
-
- @Test
- fun getCellSize_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- val expectedWorkspaceWidth = availableWidth
- val expectedCellLayoutWidth =
- (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
- dp.panelCount
- val expectedShortcutAndWidgetContainerWidth =
- expectedCellLayoutWidth -
- (dp.cellLayoutPaddingPx.left + dp.cellLayoutPaddingPx.right)
- assertThat(dp.getCellSize().x).isEqualTo(
- (expectedShortcutAndWidgetContainerWidth -
- ((inv!!.numColumns - 1) * dp.cellLayoutBorderSpacePx.x)) / inv!!.numColumns)
- val expectedWorkspaceHeight = availableHeight
- val expectedCellLayoutHeight =
- expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
- val expectedShortcutAndWidgetContainerHeight = expectedCellLayoutHeight -
- (dp.cellLayoutPaddingPx.top + dp.cellLayoutPaddingPx.bottom)
- assertThat(dp.getCellSize().y).isEqualTo(
- (expectedShortcutAndWidgetContainerHeight -
- ((inv!!.numRows - 1) * dp.cellLayoutBorderSpacePx.y)) / inv!!.numRows)
- }
-
- @Test
- fun getPanelCount_twoPanelLandscapeScalable4By4GridTablet_equalsTwoPanels() {
- val tabletWidth = 2560
- val tabletHeight = 1600
- val availableWidth = 2560
- val availableHeight = 1500
- windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
- useTwoPanels = true
- whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
- whenever(info.getDensityDpi()).thenReturn(320)
- inv = getScalable4By4InvariantDeviceProfile()
-
- val dp = newDP()
-
- assertThat(dp.panelCount).isEqualTo(2)
- }
-
- fun getScalable4By4InvariantDeviceProfile(): InvariantDeviceProfile {
- return InvariantDeviceProfile().apply {
- isScalable = true
- numColumns = 4
- numRows = 4
- numShownHotseatIcons = 4
- numDatabaseHotseatIcons = 6
- numShrunkenHotseatIcons = 5
- horizontalMargin = FloatArray(4) { 22f }
- borderSpaces = listOf(
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f)
- ).toTypedArray()
- allAppsBorderSpaces = listOf(
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f),
- PointF(16f, 16f)
- ).toTypedArray()
- hotseatBorderSpaces = FloatArray(4) { 16f }
- hotseatColumnSpan = IntArray(4) { 4 }
- iconSize = FloatArray(4) { 56f }
- allAppsIconSize = FloatArray(4) { 56f }
- iconTextSize = FloatArray(4) { 14f }
- allAppsIconTextSize = FloatArray(4) { 14f }
- minCellSize = listOf(
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f)
- ).toTypedArray()
- allAppsCellSize = listOf(
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f),
- PointF(64f, 83f)
- ).toTypedArray()
- inlineQsb = booleanArrayOf(
- false,
- false,
- false,
- false
- )
- }
- }
-}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/HotseatShownIconsTest.kt b/tests/src/com/android/launcher3/HotseatSizeTest.kt
similarity index 97%
rename from tests/src/com/android/launcher3/HotseatShownIconsTest.kt
rename to tests/src/com/android/launcher3/HotseatSizeTest.kt
index 593239d..a44939f 100644
--- a/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
+++ b/tests/src/com/android/launcher3/HotseatSizeTest.kt
@@ -23,13 +23,15 @@
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.`when` as whenever
/**
* Test for [DeviceProfile]
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
-class HotseatShownIconsTest : DeviceProfileBaseTest() {
+class HotseatSizeTest : DeviceProfileBaseTest() {
@Test
fun hotseat_size_is_normal_for_handhelds() {
diff --git a/tests/src/com/android/launcher3/InlineQsbTest.kt b/tests/src/com/android/launcher3/InlineQsbTest.kt
index 905c1e1..e00dca8 100644
--- a/tests/src/com/android/launcher3/InlineQsbTest.kt
+++ b/tests/src/com/android/launcher3/InlineQsbTest.kt
@@ -29,16 +29,17 @@
class InlineQsbTest : DeviceProfileBaseTest() {
@Test
- fun qsb_is_not_inline_for_phones() {
+ fun qsbWidth_is_match_parent_for_phones() {
initializeVarsForPhone()
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
- fun qsb_is_inline_for_tablet_portrait() {
+ fun qsbWidth_is_match_parent_for_tablet_portrait() {
initializeVarsForTablet()
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
@@ -61,10 +62,11 @@
)
assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
- fun qsb_is_inline_for_tablet_landscape() {
+ fun qsbWidth_has_size_for_tablet_landscape() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
@@ -73,17 +75,16 @@
false,
false
)
- numColumns = 6
- numRows = 5
- numShownHotseatIcons = 6
}
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
+ assertThat(dp.qsbWidth).isGreaterThan(0)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
}
}
@@ -91,13 +92,14 @@
* This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
*/
@Test
- fun qsb_is_not_inline_for_tablet_landscape_without_inline() {
+ fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
initializeVarsForTablet(isLandscape = true)
useTwoPanels = true
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
}
}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
index 8d275cc..3623513 100644
--- a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
+++ b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
@@ -135,7 +135,7 @@
resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
}
return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
- info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
+ info.densityDpi, info.cutout, code, grids, resourceOverrides);
}
public static DeviceEmulationData getDevice(String deviceCode) throws Exception {
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
new file mode 100644
index 0000000..5f92199
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
@@ -0,0 +1,45 @@
+/*
+ * 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.tapl;
+
+/**
+ * Operations on home screen qsb.
+ */
+public class HomeQsb {
+
+ private final LauncherInstrumentation mLauncher;
+
+ HomeQsb(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ mLauncher.waitForLauncherObject("search_container_hotseat");
+ }
+
+ /**
+ * Show search result page from tapping qsb.
+ */
+ public SearchResultFromQsb showSearchResult() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to open search result page");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ mLauncher.clickLauncherObject(
+ mLauncher.waitForLauncherObject("search_container_hotseat"));
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
+ "clicked qsb to open search result page")) {
+ return new SearchResultFromQsb(mLauncher);
+ }
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 45a0196..39cd4ff 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -33,7 +33,7 @@
/**
* Ancestor for AppIcon and AppMenuItem.
*/
-abstract class Launchable {
+public abstract class Launchable {
protected static final int DEFAULT_DRAG_STEPS = 10;
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index afb4f8d..2b3583e 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1499,9 +1499,14 @@
0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
}
+ private boolean hasTIS() {
+ return getTestInfo(TestProtocol.REQUEST_HAS_TIS).getBoolean(TestProtocol.REQUEST_HAS_TIS);
+ }
+
+
public void sendPointer(long downTime, long currentTime, int action, Point point,
GestureScope gestureScope) {
- final boolean notLauncher3 = !isLauncher3();
+ final boolean hasTIS = hasTIS();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
@@ -1509,12 +1514,12 @@
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
}
- if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) {
+ if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
}
break;
case MotionEvent.ACTION_UP:
- if (notLauncher3 && gestureScope != GestureScope.INSIDE
+ if (hasTIS && gestureScope != GestureScope.INSIDE
&& gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
&& (gestureScope == GestureScope.OUTSIDE_WITH_PILFER
|| gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) {
@@ -1528,7 +1533,7 @@
|| gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL);
}
- if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) {
+ if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
expectEvent(TestProtocol.SEQUENCE_TIS,
gestureScope == GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
|| gestureScope == GestureScope.OUTSIDE_WITH_KEYCODE
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
new file mode 100644
index 0000000..82652c7
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -0,0 +1,50 @@
+/*
+ * 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.tapl;
+
+import android.widget.TextView;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on search result page opened from home screen qsb.
+ */
+public class SearchResultFromQsb {
+ // The input resource id in the search box.
+ private static final String INPUT_RES = "input";
+ private final LauncherInstrumentation mLauncher;
+
+ SearchResultFromQsb(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ mLauncher.waitForLauncherObject("search_container_all_apps");
+ }
+
+ /** Set the input to the search input edit text and update search results. */
+ public void searchForInput(String input) {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to search for result with an input");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ mLauncher.waitForLauncherObject(INPUT_RES).setText(input);
+ }
+ }
+
+ /** Find the app from search results with app name. */
+ public Launchable findAppIcon(String appName) {
+ UiObject2 icon = mLauncher.waitForLauncherObject(By.clazz(TextView.class).text(appName));
+ return new AllAppsAppIcon(mLauncher, icon);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index b0b42ba..954af3d 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -112,6 +112,18 @@
}
/**
+ * Returns the home qsb.
+ *
+ * The qsb must already be visible when calling this method.
+ */
+ public HomeQsb getQsb() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get the home qsb")) {
+ return new HomeQsb(mLauncher);
+ }
+ }
+
+ /**
* Returns an icon for the app, if currently visible.
*
* @param appName name of the app