Merge changes I358a6020,I202ed999 into ub-launcher3-master
* changes:
Inline INDEX_PAUSE_TO_OVERVIEW_ANIM
Allow pause during quick switch for any horizontal displacement
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 258f24a..d15a2d2 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -56,7 +56,7 @@
android:visibility="gone" />
<Space
- android:id="@+id/share_space"
+ android:id="@+id/oav_three_button_space"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 313db8c..c85fe6c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -35,16 +35,13 @@
loading full resolution screenshots. -->
<dimen name="recents_fast_fling_velocity">600dp</dimen>
- <!-- These velocities are in dp / s -->
- <dimen name="quickstep_fling_threshold_velocity">500dp</dimen>
- <dimen name="quickstep_fling_min_velocity">250dp</dimen>
-
<!-- These speeds are in dp / ms -->
<dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
<dimen name="motion_pause_detector_speed_slow">0.15dp</dimen>
<dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
<dimen name="motion_pause_detector_speed_fast">1.4dp</dimen>
<dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen>
+ <dimen name="quickstep_fling_threshold_speed">0.5dp</dimen>
<!-- Launcher app transition -->
<dimen name="content_trans_y">50dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index f3d5434..dddcc86 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -57,6 +57,7 @@
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
+import android.os.Trace;
import android.util.Pair;
import android.view.View;
@@ -137,6 +138,7 @@
// Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f;
+ public static final String TRANSITION_OPEN_LAUNCHER = "transition:OpenLauncher";
protected final BaseQuickstepLauncher mLauncher;
@@ -853,6 +855,21 @@
// is initialized.
if (launcherIsATargetWithMode(appTargets, MODE_OPENING)
|| mLauncher.isForceInvisible()) {
+ if (Trace.isEnabled()) {
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
+ super.onAnimationStart(animation);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
+ }
+ });
+ }
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
@@ -887,6 +904,9 @@
*/
private class AppLaunchAnimationRunner implements WrappedAnimationRunnerImpl {
+ private static final String TRANSITION_LAUNCH_FROM_RECENTS = "transition:LaunchFromRecents";
+ private static final String TRANSITION_LAUNCH_FROM_ICON = "transition:LaunchFromIcon";
+
private final Handler mHandler;
private final View mV;
@@ -909,7 +929,8 @@
boolean launcherClosing =
launcherIsATargetWithMode(appTargets, MODE_CLOSING);
- if (isLaunchingFromRecents(mV, appTargets)) {
+ final boolean launchingFromRecents = isLaunchingFromRecents(mV, appTargets);
+ if (launchingFromRecents) {
composeRecentsLaunchAnimator(anim, mV, appTargets, wallpaperTargets,
launcherClosing);
} else {
@@ -917,6 +938,26 @@
launcherClosing);
}
+ if (Trace.isEnabled()) {
+ final String section =
+ launchingFromRecents
+ ? TRANSITION_LAUNCH_FROM_RECENTS : TRANSITION_LAUNCH_FROM_ICON;
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ Trace.beginAsyncSection(section, 0);
+ super.onAnimationStart(animation);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ Trace.endAsyncSection(section, 0);
+ }
+ });
+ }
+
if (launcherClosing) {
anim.addListener(mForceInvisibleListener);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 591d3ca..c78d474 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -75,6 +75,7 @@
private final float mMotionPauseMinDisplacement;
private boolean mDidTouchStartInNavBar;
+ private boolean mStartedOverview;
private boolean mReachedOverview;
// The last recorded displacement before we reached overview.
private PointF mStartDisplacement = new PointF();
@@ -128,7 +129,7 @@
mMotionPauseDetector.clear();
if (handlingOverviewAnim()) {
- mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
+ mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseDetected);
}
if (mFromState == NORMAL && mToState == HINT_STATE) {
@@ -138,6 +139,7 @@
mFromState.getOverviewScrimAlpha(mLauncher),
mToState.getOverviewScrimAlpha(mLauncher));
}
+ mStartedOverview = false;
mReachedOverview = false;
mOverviewResistYAnim = null;
}
@@ -152,7 +154,7 @@
@Override
public void onDragEnd(float velocity) {
- if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
+ if (mStartedOverview) {
goToOverviewOrHomeOnDragEnd(velocity);
} else {
super.onDragEnd(velocity);
@@ -185,7 +187,7 @@
}
}
- private void onMotionPauseChanged(boolean isPaused) {
+ private void onMotionPauseDetected() {
if (mCurrentAnimation == null) {
return;
}
@@ -199,6 +201,7 @@
maybeSwipeInteractionToOverviewComplete();
});
});
+ mStartedOverview = true;
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
}
@@ -219,7 +222,7 @@
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NoButtonNavbarToOverviewTouchController");
}
- if (mMotionPauseDetector.isPaused()) {
+ if (mStartedOverview) {
if (!mReachedOverview) {
mStartDisplacement.set(xDisplacement, yDisplacement);
mStartY = event.getY();
@@ -234,8 +237,6 @@
* OVERVIEW_MOVEMENT_FACTOR);
}
}
- // Stay in Overview.
- return true;
}
float upDisplacement = -yDisplacement;
@@ -243,13 +244,12 @@
|| upDisplacement < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(event);
- return super.onDrag(yDisplacement, xDisplacement, event);
+ // Stay in Overview.
+ return mStartedOverview || super.onDrag(yDisplacement, xDisplacement, event);
}
private void goToOverviewOrHomeOnDragEnd(float velocity) {
- float velocityDp = dpiFromPx(velocity);
- boolean isFling = Math.abs(velocityDp) > 1;
- boolean goToHomeInsteadOfOverview = isFling;
+ boolean goToHomeInsteadOfOverview = !mMotionPauseDetector.isPaused();
if (goToHomeInsteadOfOverview) {
new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
.animateWithVelocity(velocity);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 34d5f73..a6a3497 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -79,7 +79,7 @@
* the user as possible, also handles swipe up and hold to go to overview and swiping back home.
*/
public class NoButtonQuickSwitchTouchController implements TouchController,
- BothAxesSwipeDetector.Listener, MotionPauseDetector.OnMotionPauseListener {
+ BothAxesSwipeDetector.Listener {
/** The minimum progress of the scale/translationY animation until drag end. */
private static final float Y_ANIM_MIN_PROGRESS = 0.25f;
@@ -167,7 +167,7 @@
if (start) {
mStartState = mLauncher.getStateManager().getState();
- mMotionPauseDetector.setOnMotionPauseListener(this);
+ mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseDetected);
// We have detected horizontal drag start, now allow swipe up as well.
mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT | DIRECTION_UP,
@@ -177,8 +177,7 @@
}
}
- @Override
- public void onMotionPauseChanged(boolean isPaused) {
+ private void onMotionPauseDetected() {
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index aaa2720..26ad377 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -19,6 +19,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.QuickstepAppTransitionManagerImpl.TRANSITION_OPEN_LAUNCHER;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
@@ -53,6 +54,7 @@
import android.graphics.Rect;
import android.os.Build;
import android.os.SystemClock;
+import android.os.Trace;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -89,6 +91,7 @@
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
+import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TransformParams;
@@ -201,6 +204,7 @@
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsMotionPaused;
+ private boolean mHasMotionEverBeenPaused;
private boolean mContinuingLastGesture;
@@ -482,13 +486,20 @@
.getHighResLoadingState().setVisible(true);
}
- /**
- * Called when motion pause is detected
- */
- public void onMotionPauseChanged(boolean isPaused) {
- mIsMotionPaused = isPaused;
- maybeUpdateRecentsAttachedState();
- performHapticFeedback();
+ public MotionPauseDetector.OnMotionPauseListener getMotionPauseListener() {
+ return new MotionPauseDetector.OnMotionPauseListener() {
+ @Override
+ public void onMotionPauseDetected() {
+ mHasMotionEverBeenPaused = true;
+ maybeUpdateRecentsAttachedState();
+ performHapticFeedback();
+ }
+
+ @Override
+ public void onMotionPauseChanged(boolean isPaused) {
+ mIsMotionPaused = isPaused;
+ }
+ };
}
public void maybeUpdateRecentsAttachedState() {
@@ -519,7 +530,7 @@
// The window is going away so make sure recents is always visible in this case.
recentsAttachedToAppWindow = true;
} else {
- recentsAttachedToAppWindow = mIsMotionPaused || mIsLikelyToStartNewTask;
+ recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask;
}
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
@@ -742,8 +753,9 @@
@UiThread
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
- .getDimension(R.dimen.quickstep_fling_threshold_velocity);
- boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
+ .getDimension(R.dimen.quickstep_fling_threshold_speed);
+ boolean isFling = mGestureStarted && !mIsMotionPaused
+ && Math.abs(endVelocity) > flingThreshold;
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
@@ -858,7 +870,7 @@
if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
endTarget = HOME;
- } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsMotionPaused) {
+ } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) {
// If swiping at a diagonal, base end target on the faster velocity.
endTarget = NEW_TASK;
} else if (isSwipeUp) {
@@ -878,7 +890,6 @@
@UiThread
private void handleNormalGestureEnd(float endVelocity, boolean isFling, PointF velocity,
boolean isCancel) {
- PointF velocityPxPerMs = new PointF(velocity.x / 1000, velocity.y / 1000);
long duration = MAX_SWIPE_DURATION;
float currentShift = mCurrentShift.value;
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
@@ -893,14 +904,12 @@
startShift = currentShift;
interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
} else {
- startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
+ startShift = Utilities.boundToRange(currentShift - velocity.y
* getSingleFrameMs(mContext) / mTransitionDragLength, 0, mDragLengthFactor);
- float minFlingVelocity = mContext.getResources()
- .getDimension(R.dimen.quickstep_fling_min_velocity);
- if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
+ if (mTransitionDragLength > 0) {
if (endTarget == RECENTS && !mDeviceState.isFullyGesturalNavMode()) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
- startShift, endShift, endShift, endVelocity / 1000,
+ startShift, endShift, endShift, endVelocity,
mTransitionDragLength, mContext);
endShift = overshoot.end;
interpolator = overshoot.interpolator;
@@ -912,7 +921,7 @@
// we want the page's snap velocity to approximately match the velocity at
// which the user flings, so we scale the duration by a value near to the
// derivative of the scroll interpolator at zero, ie. 2.
- long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
+ long baseDuration = Math.round(Math.abs(distanceToTravel / velocity.y));
duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
if (endTarget == RECENTS) {
@@ -952,7 +961,7 @@
mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED);
}
- animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
+ animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocity);
}
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
@@ -1135,6 +1144,7 @@
anim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
+ Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
if (mActivity != null) {
removeLiveTileOverlay();
}
@@ -1149,6 +1159,12 @@
maybeUpdateRecentsAttachedState(false);
mActivityInterface.onSwipeUpToHomeComplete(mDeviceState);
}
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
+ }
});
if (mRecentsAnimationTargets != null) {
mRecentsAnimationTargets.addReleaseCheck(anim);
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index e4b8ce2..39af0db 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -58,6 +58,12 @@
FeatureFlags.ENABLE_OVERVIEW_SHARE.get());
return response;
}
+
+ case TestProtocol.REQUEST_OVERVIEW_CONTENT_PUSH_ENABLED: {
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ FeatureFlags.ENABLE_OVERVIEW_CONTENT_PUSH.get());
+ return response;
+ }
}
return super.call(method);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 584ff28..5aaea00 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
+import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import static com.android.quickstep.AbsSwipeUpHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
@@ -35,7 +36,6 @@
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
-import android.view.ViewConfiguration;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
@@ -180,12 +180,11 @@
*/
private void finishTouchTracking(MotionEvent ev) {
if (mThresholdCrossed && ev.getAction() == ACTION_UP) {
- mVelocityTracker.computeCurrentVelocity(1000,
- ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
+ mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
float velocityY = mVelocityTracker.getYVelocity();
float flingThreshold = mContext.getResources()
- .getDimension(R.dimen.quickstep_fling_threshold_velocity);
+ .getDimension(R.dimen.quickstep_fling_threshold_speed);
boolean dismissTask;
if (Math.abs(velocityY) > flingThreshold) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index f02e5e6..b1a1133 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -28,6 +28,7 @@
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
+import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import static com.android.quickstep.GestureState.STATE_OVERSCROLL_WINDOW_CREATED;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -52,9 +53,9 @@
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TraceHelper;
-import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.AbsSwipeUpHandler;
import com.android.quickstep.AbsSwipeUpHandler.Factory;
+import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationCallbacks;
@@ -365,7 +366,7 @@
mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs,
mTaskAnimationManager.isRecentsAnimationRunning());
mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
- mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler::onMotionPauseChanged);
+ mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler.getMotionPauseListener());
Intent intent = new Intent(mInteractionHandler.getLaunchIntent());
mInteractionHandler.initWhenReady(intent);
@@ -393,8 +394,7 @@
if (ev.getActionMasked() == ACTION_CANCEL) {
mInteractionHandler.onGestureCancelled();
} else {
- mVelocityTracker.computeCurrentVelocity(1000,
- ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
+ mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
float velocity = mNavBarPosition.isRightEdge()
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
index b9827ff..a8bf333 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -42,18 +42,16 @@
mMotionPauseMinDisplacement = context.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
mMotionPauseDetector = new MotionPauseDetector(context, true /* makePauseHarderToTrigger*/);
- mMotionPauseDetector.setOnMotionPauseListener(isPaused -> {
- if (isPaused) {
- SystemUiProxy.INSTANCE.get(context).stopScreenPinning();
- BaseDraggingActivity launcherActivity = gestureState.getActivityInterface()
- .getCreatedActivity();
- if (launcherActivity != null) {
- launcherActivity.getRootView().performHapticFeedback(
- HapticFeedbackConstants.LONG_PRESS,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- }
- mMotionPauseDetector.clear();
+ mMotionPauseDetector.setOnMotionPauseListener(() -> {
+ SystemUiProxy.INSTANCE.get(context).stopScreenPinning();
+ BaseDraggingActivity launcherActivity = gestureState.getActivityInterface()
+ .getCreatedActivity();
+ if (launcherActivity != null) {
+ launcherActivity.getRootView().performHapticFeedback(
+ HapticFeedbackConstants.LONG_PRESS,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
+ mMotionPauseDetector.clear();
});
}
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 81c4d0c..f897ecc 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -144,7 +144,6 @@
if (mGestureCallback == null || mAssistantGestureActive) {
return;
}
- finalVelocity.set(finalVelocity.x / 1000, finalVelocity.y / 1000);
if (mTouchCameFromNavBar) {
mGestureCallback.onNavBarGestureAttempted(wasFling
? HOME_GESTURE_COMPLETED : OVERVIEW_GESTURE_COMPLETED, finalVelocity);
@@ -182,7 +181,7 @@
mLaunchedAssistant = false;
mSwipeUpTouchTracker.init();
mMotionPauseDetector.clear();
- mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
+ mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseDetected);
break;
case MotionEvent.ACTION_MOVE:
mLastPos.set(event.getX(), event.getY());
@@ -220,7 +219,6 @@
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mMotionPauseDetector.clear();
- mMotionPauseDetector.setOnMotionPauseListener(null);
if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) {
mGestureCallback.onNavBarGestureAttempted(
HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, new PointF());
@@ -252,10 +250,8 @@
return intercepted;
}
- protected void onMotionPauseChanged(boolean isPaused) {
- if (isPaused) {
- VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
- }
+ protected void onMotionPauseDetected() {
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index b862936..d0f6879 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -184,11 +184,15 @@
}
if (mIsPaused != isPaused) {
mIsPaused = isPaused;
+ boolean isFirstDetectedPause = !mHasEverBeenPaused && mIsPaused;
if (mIsPaused) {
AccessibilityManagerCompat.sendPauseDetectedEventToTest(mContext);
mHasEverBeenPaused = true;
}
if (mOnMotionPauseListener != null) {
+ if (isFirstDetectedPause) {
+ mOnMotionPauseListener.onMotionPauseDetected();
+ }
mOnMotionPauseListener.onMotionPauseChanged(mIsPaused);
}
}
@@ -211,7 +215,10 @@
}
public interface OnMotionPauseListener {
- void onMotionPauseChanged(boolean isPaused);
+ /** Called only the first time motion pause is detected. */
+ void onMotionPauseDetected();
+ /** Called every time motion changes from paused to not paused and vice versa. */
+ default void onMotionPauseChanged(boolean isPaused) { }
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
index 29b9558..7bbde30 100644
--- a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
+++ b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
@@ -21,13 +21,14 @@
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import android.content.Context;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
-import android.view.ViewConfiguration;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
/**
@@ -50,7 +51,8 @@
NavBarPosition navBarPosition, Runnable onInterceptTouch,
OnSwipeUpListener onSwipeUp) {
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
- mMinFlingVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
+ mMinFlingVelocity = context.getResources().getDimension(
+ R.dimen.quickstep_fling_threshold_speed);
mNavBarPosition = navBarPosition;
mDisableHorizontalSwipe = disableHorizontalSwipe;
mOnInterceptTouch = onInterceptTouch;
@@ -130,7 +132,7 @@
}
private void onGestureEnd(MotionEvent ev) {
- mVelocityTracker.computeCurrentVelocity(1000);
+ mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
float velocityX = mVelocityTracker.getXVelocity();
float velocityY = mVelocityTracker.getYVelocity();
float velocity = mNavBarPosition.isRightEdge()
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 8f60991..2a6c9e9 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -113,7 +113,7 @@
findViewById(R.id.action_screenshot).setOnClickListener(this);
if (ENABLE_OVERVIEW_SHARE.get()) {
share.setVisibility(VISIBLE);
- findViewById(R.id.share_space).setVisibility(VISIBLE);
+ findViewById(R.id.oav_three_button_space).setVisibility(VISIBLE);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6ae91b6..0362377 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2251,7 +2251,7 @@
public void setRecentsAnimationTargets(RecentsAnimationController recentsAnimationController,
RecentsAnimationTargets recentsAnimationTargets) {
mRecentsAnimationController = recentsAnimationController;
- if (recentsAnimationTargets != null) {
+ if (recentsAnimationTargets != null && recentsAnimationTargets.apps.length > 0) {
mLiveTileTaskViewSimulator.setPreview(
recentsAnimationTargets.apps[recentsAnimationTargets.apps.length - 1]);
mLiveTileParams.setTargetSet(recentsAnimationTargets);
diff --git a/res/layout/search_result_people_item.xml b/res/layout/search_result_people_item.xml
new file mode 100644
index 0000000..a505e4a
--- /dev/null
+++ b/res/layout/search_result_people_item.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 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.
+-->
+<com.android.launcher3.views.SearchResultPeopleView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:gravity="center_vertical"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:orientation="horizontal">
+
+ <View
+ android:id="@+id/icon"
+ android:layout_marginRight="8dp"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+ <TextView
+ android:layout_width="0dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:id="@+id/title"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <ImageButton
+ android:id="@+id/provider_0"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:layout_margin="5dp"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+ <ImageButton
+ android:id="@+id/provider_1"
+ android:layout_margin="5dp"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+ <ImageButton
+ android:id="@+id/provider_2"
+ android:layout_margin="5dp"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+</com.android.launcher3.views.SearchResultPeopleView>
\ No newline at end of file
diff --git a/res/layout/search_result_shortcut.xml b/res/layout/search_result_shortcut.xml
new file mode 100644
index 0000000..c350c97
--- /dev/null
+++ b/res/layout/search_result_shortcut.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 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.
+-->
+<com.android.launcher3.views.SearchResultShortcut xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:padding="@dimen/dynamic_grid_edge_margin">
+
+ <com.android.launcher3.BubbleTextView
+ android:id="@+id/bubble_text"
+ style="@style/BaseIcon"
+ android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
+ android:gravity="start|center_vertical"
+ android:textAlignment="viewStart"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="16sp"
+ android:layout_height="wrap_content"
+ launcher:iconDisplay="hero_app"
+ launcher:layoutHorizontal="true" />
+
+ <View
+ android:id="@+id/icon"
+ android:layout_width="@dimen/deep_shortcut_icon_size"
+ android:layout_height="@dimen/deep_shortcut_icon_size"
+ android:layout_gravity="start|center_vertical"
+ android:background="@drawable/ic_deepshortcut_placeholder" />
+
+</com.android.launcher3.views.SearchResultShortcut>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index fc0a5e1..325b62f 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -59,7 +59,6 @@
<bool name="hotseat_transpose_layout_with_orientation">true</bool>
<!-- Various classes overriden by projects/build flavors. -->
- <string name="app_filter_class" translatable="false"></string>
<string name="user_event_dispatcher_class" translatable="false"></string>
<string name="folder_name_provider_class" translatable="false"></string>
<string name="stats_log_manager_class" translatable="false"></string>
@@ -187,4 +186,6 @@
<string-array name="live_wallpapers_remove_sysui_scrims">
</string-array>
+
+ <string-array name="filtered_components" ></string-array>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ad3e2b7..6ab8150 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -58,6 +58,8 @@
<!-- All Apps -->
<!-- Search bar text in the apps view. [CHAR_LIMIT=50] -->
<string name="all_apps_search_bar_hint">Search apps</string>
+ <!-- Search bar text in the apps view. [CHAR_LIMIT=50] -->
+ <string name="all_apps_on_device_search_bar_hint">Search this phone and more...</string>
<!-- Loading apps text. [CHAR_LIMIT=50] -->
<string name="all_apps_loading_message">Loading apps…</string>
<!-- No-search-results text. [CHAR_LIMIT=50] -->
diff --git a/src/com/android/launcher3/AppFilter.java b/src/com/android/launcher3/AppFilter.java
index 9b6166f..3db456c 100644
--- a/src/com/android/launcher3/AppFilter.java
+++ b/src/com/android/launcher3/AppFilter.java
@@ -3,15 +3,25 @@
import android.content.ComponentName;
import android.content.Context;
-import com.android.launcher3.util.ResourceBasedOverride;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
-public class AppFilter implements ResourceBasedOverride {
+/**
+ * Utility class to filter out components from various lists
+ */
+public class AppFilter {
- public static AppFilter newInstance(Context context) {
- return Overrides.getObject(AppFilter.class, context, R.string.app_filter_class);
+ private final Set<ComponentName> mFilteredComponents;
+
+ public AppFilter(Context context) {
+ mFilteredComponents = Arrays.stream(
+ context.getResources().getStringArray(R.array.filtered_components))
+ .map(ComponentName::unflattenFromString)
+ .collect(Collectors.toSet());
}
public boolean shouldShowApp(ComponentName app) {
- return true;
+ return !mFilteredComponents.contains(app);
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index cacd3fb..2e36bc0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -88,6 +88,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
@@ -466,6 +467,10 @@
mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener(
() -> getStateManager().goToState(NORMAL));
+
+ if (Utilities.ATLEAST_R) {
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+ }
}
protected LauncherOverlayManager getDefaultOverlay() {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index b278e81..bfe327e 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -122,7 +122,7 @@
mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context);
mIconCache = new IconCache(mContext, mInvariantDeviceProfile, iconCacheFileName);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
- mModel = new LauncherModel(context, this, mIconCache, AppFilter.newInstance(mContext));
+ mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext));
}
protected void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 1f51566..5079469 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -67,6 +67,9 @@
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.SpringRelativeLayout;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
+
+import java.util.function.IntConsumer;
/**
* The all apps view container.
@@ -538,34 +541,35 @@
* Handles selection on focused view and returns success
*/
public boolean selectFocusedView(View v) {
- ItemInfo itemInfo = getHighlightedItemInfo();
- if (itemInfo != null) {
- return mLauncher.startActivitySafely(v, itemInfo.getIntent(), itemInfo);
+ ItemInfo headerItem = getHighlightedItemFromHeader();
+ if (headerItem != null) {
+ return mLauncher.startActivitySafely(v, headerItem.getIntent(), headerItem);
}
AdapterItem focusedItem = getActiveRecyclerView().getApps().getFocusedChild();
if (focusedItem instanceof AdapterItemWithPayload) {
- Runnable onSelection = ((AdapterItemWithPayload) focusedItem).getSelectionHandler();
+ IntConsumer onSelection =
+ ((AdapterItemWithPayload) focusedItem).getSelectionHandler();
if (onSelection != null) {
- onSelection.run();
+ onSelection.accept(SearchTargetEvent.QUICK_SELECT);
return true;
}
}
+ if (focusedItem.appInfo != null) {
+ ItemInfo itemInfo = focusedItem.appInfo;
+ return mLauncher.startActivitySafely(v, itemInfo.getIntent(), itemInfo);
+ }
return false;
}
/**
- * Returns the ItemInfo of a view that is in focus, ready to be launched by an IME.
+ * Returns the ItemInfo of a focused view inside {@link FloatingHeaderView}
*/
- public ItemInfo getHighlightedItemInfo() {
+ public ItemInfo getHighlightedItemFromHeader() {
View view = getFloatingHeaderView().getFocusedChild();
if (view != null && view.getTag() instanceof ItemInfo) {
return ((ItemInfo) view.getTag());
}
- if (getActiveRecyclerView().getApps().getFocusedChild() != null) {
- // TODO: when new pipelines are included, getSearchResults
- // should be supported at recycler view level and not apps list level.
- return getActiveRecyclerView().getApps().getFocusedChild().appInfo;
- }
+
return null;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index da161ac..f077173 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -54,8 +55,13 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.HeroSearchResultView;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
import java.util.List;
+import java.util.function.IntConsumer;
/**
* The grid view adapter of all the apps.
@@ -89,6 +95,10 @@
public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 9;
+ public static final int VIEW_TYPE_SEARCH_SHORTCUT = 1 << 10;
+
+ public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11;
+
// Common view type masks
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
@@ -179,7 +189,9 @@
|| viewType == VIEW_TYPE_SEARCH_HERO_APP
|| viewType == VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
|| viewType == VIEW_TYPE_SEARCH_SLICE
- || viewType == VIEW_TYPE_SEARCH_ROW;
+ || viewType == VIEW_TYPE_SEARCH_ROW
+ || viewType == VIEW_TYPE_SEARCH_PEOPLE
+ || viewType == VIEW_TYPE_SEARCH_SHORTCUT;
}
}
@@ -190,18 +202,28 @@
*/
public static class AdapterItemWithPayload<T> extends AdapterItem {
private T mPayload;
- private Runnable mSelectionHandler;
+ private AllAppsSearchPlugin mPlugin;
+ private IntConsumer mSelectionHandler;
- public AdapterItemWithPayload(T payload, int type) {
- mPayload = payload;
- viewType = type;
+ public AllAppsSearchPlugin getPlugin() {
+ return mPlugin;
}
- public void setSelectionHandler(Runnable runnable) {
+ public void setPlugin(AllAppsSearchPlugin plugin) {
+ mPlugin = plugin;
+ }
+
+ public AdapterItemWithPayload(T payload, int type, AllAppsSearchPlugin plugin) {
+ mPayload = payload;
+ viewType = type;
+ mPlugin = plugin;
+ }
+
+ public void setSelectionHandler(IntConsumer runnable) {
mSelectionHandler = runnable;
}
- public Runnable getSelectionHandler() {
+ public IntConsumer getSelectionHandler() {
return mSelectionHandler;
}
@@ -390,10 +412,12 @@
case VIEW_TYPE_ICON:
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
R.layout.all_apps_icon, parent, false);
- icon.setOnClickListener(mOnIconClickListener);
- icon.setOnLongClickListener(mOnIconLongClickListener);
icon.setLongPressTimeoutFactor(1f);
icon.setOnFocusChangeListener(mIconFocusListener);
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ icon.setOnClickListener(mOnIconClickListener);
+ icon.setOnLongClickListener(mOnIconLongClickListener);
+ }
// Ensure the all apps icon height matches the workspace icons in portrait mode.
icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
@@ -413,7 +437,6 @@
case VIEW_TYPE_SEARCH_CORPUS_TITLE:
return new ViewHolder(
mLayoutInflater.inflate(R.layout.search_section_title, parent, false));
-
case VIEW_TYPE_SEARCH_HERO_APP:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.search_result_hero_app, parent, false));
@@ -426,6 +449,12 @@
case VIEW_TYPE_SEARCH_SLICE:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.search_result_slice, parent, false));
+ case VIEW_TYPE_SEARCH_SHORTCUT:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.search_result_shortcut, parent, false));
+ case VIEW_TYPE_SEARCH_PEOPLE:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.search_result_people_item, parent, false));
default:
throw new RuntimeException("Unexpected view type");
}
@@ -435,10 +464,36 @@
public void onBindViewHolder(ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case VIEW_TYPE_ICON:
- AppInfo info = mApps.getAdapterItems().get(position).appInfo;
+ AdapterItem adapterItem = mApps.getAdapterItems().get(position);
+ AppInfo info = adapterItem.appInfo;
BubbleTextView icon = (BubbleTextView) holder.itemView;
icon.reset();
icon.applyFromApplicationInfo(info);
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ break;
+ }
+ //TODO: replace with custom TopHitBubbleTextView with support for both shortcut
+ // and apps
+ if (adapterItem instanceof AdapterItemWithPayload) {
+ AdapterItemWithPayload withPayload = (AdapterItemWithPayload) adapterItem;
+ IntConsumer selectionHandler = type -> {
+ SearchTargetEvent e = new SearchTargetEvent(SearchTarget.ItemType.APP,
+ type);
+ e.bundle = HeroSearchResultView.getAppBundle(info);
+ if (withPayload.getPlugin() != null) {
+ withPayload.getPlugin().notifySearchTargetEvent(e);
+ }
+ };
+ icon.setOnClickListener(view -> {
+ selectionHandler.accept(SearchTargetEvent.SELECT);
+ mOnIconClickListener.onClick(view);
+ });
+ icon.setOnLongClickListener(view -> {
+ selectionHandler.accept(SearchTargetEvent.LONG_PRESS);
+ return mOnIconLongClickListener.onLongClick(view);
+ });
+ withPayload.setSelectionHandler(selectionHandler);
+ }
break;
case VIEW_TYPE_EMPTY_SEARCH:
TextView emptyViewText = (TextView) holder.itemView;
@@ -456,11 +511,22 @@
break;
case VIEW_TYPE_SEARCH_SLICE:
SliceView sliceView = (SliceView) holder.itemView;
- Uri uri = ((AdapterItemWithPayload<Uri>) mApps.getAdapterItems().get(position))
- .getPayload();
+ AdapterItemWithPayload<Uri> item =
+ (AdapterItemWithPayload<Uri>) mApps.getAdapterItems().get(position);
+ sliceView.setOnSliceActionListener((info1, s) -> {
+ if (item.getPlugin() != null) {
+ SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
+ SearchTarget.ItemType.SETTINGS_SLICE,
+ SearchTargetEvent.CHILD_SELECT);
+ searchTargetEvent.bundle = new Bundle();
+ searchTargetEvent.bundle.putParcelable("uri", item.getPayload());
+ item.getPlugin().notifySearchTargetEvent(searchTargetEvent);
+ }
+ });
try {
- LiveData<Slice> liveData = SliceLiveData.fromUri(mLauncher, uri);
+ LiveData<Slice> liveData = SliceLiveData.fromUri(mLauncher, item.getPayload());
liveData.observe(this::getLifecycle, sliceView);
+ sliceView.setTag(liveData);
} catch (Exception ignored) {
}
break;
@@ -468,6 +534,8 @@
case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
case VIEW_TYPE_SEARCH_HERO_APP:
case VIEW_TYPE_SEARCH_ROW:
+ case VIEW_TYPE_SEARCH_SHORTCUT:
+ case VIEW_TYPE_SEARCH_PEOPLE:
PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
payloadResultView.applyAdapterInfo(
(AdapterItemWithPayload) mApps.getAdapterItems().get(position));
@@ -479,6 +547,25 @@
}
@Override
+ public void onViewRecycled(@NonNull ViewHolder holder) {
+ super.onViewRecycled(holder);
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
+ if (holder.itemView instanceof BubbleTextView) {
+ BubbleTextView icon = (BubbleTextView) holder.itemView;
+ icon.setOnClickListener(mOnIconClickListener);
+ icon.setOnLongClickListener(mOnIconLongClickListener);
+ } else if (holder.itemView instanceof SliceView) {
+ SliceView sliceView = (SliceView) holder.itemView;
+ sliceView.setOnSliceActionListener(null);
+ if (sliceView.getTag() instanceof LiveData) {
+ LiveData sliceLiveData = (LiveData) sliceView.getTag();
+ sliceLiveData.removeObservers(this::getLifecycle);
+ }
+ }
+ }
+
+
+ @Override
public boolean onFailedToRecycleView(ViewHolder holder) {
// Always recycle and we will reset the view when it is bound
return true;
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 0268b96..4195a05 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -270,11 +270,7 @@
editText.requestFocus();
}
}
- if (Float.compare(mProgress, 1f) == 0) {
- // Called when home gesture closes all apps container.
- // TODO: should make the controller hide synchronously
- mInsetController.hide();
- }
+ // TODO: should make the controller hide synchronously
}
}
}
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 29e3404..3320189 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -115,11 +115,6 @@
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// selectFocusedView should return SearchTargetEvent that is passed onto onClick
if (Launcher.getLauncher(mLauncher).getAppsView().selectFocusedView(v)) {
- if (mSearchAlgorithm instanceof PluginWrapper) {
- ((PluginWrapper) mSearchAlgorithm).runOnPluginIfConnected(plugin -> {
- plugin.onClick(false, null);
- });
- }
return true;
}
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index d8fca1d..2627149 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -149,6 +149,9 @@
public static final BooleanFlag ENABLE_OVERVIEW_SHARE = getDebugFlag(
"ENABLE_OVERVIEW_SHARE", false, "Show Share button in Overview Actions");
+ public static final BooleanFlag ENABLE_OVERVIEW_CONTENT_PUSH = getDebugFlag(
+ "ENABLE_OVERVIEW_CONTENT_PUSH", false, "Show Content Push button in Overview Actions");
+
public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
"ENABLE_DATABASE_RESTORE", true,
"Enable database restore when new restore session is created");
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index f1606ea..c841b7b 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -17,6 +17,7 @@
package com.android.launcher3.folder;
import static android.text.TextUtils.isEmpty;
+import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -34,8 +35,10 @@
import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Path;
import android.graphics.Rect;
+import android.os.Build;
import android.text.InputType;
import android.text.Selection;
import android.text.TextUtils;
@@ -47,11 +50,16 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Alarm;
import com.android.launcher3.BubbleTextView;
@@ -252,6 +260,13 @@
int measureSpec = MeasureSpec.UNSPECIFIED;
mFooter.measure(measureSpec, measureSpec);
mFooterHeight = mFooter.getMeasuredHeight();
+
+ if (Utilities.ATLEAST_R) {
+ WindowInsetsAnimation.Callback cb = new FolderWindowInsetsAnimationCallback(
+ DISPATCH_MODE_STOP, this);
+
+ setWindowInsetsAnimationCallback(cb);
+ }
}
public boolean onLongClick(View v) {
@@ -373,6 +388,26 @@
return false;
}
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
+ if (Utilities.ATLEAST_R) {
+ this.setTranslationY(0);
+
+ if (windowInsets.isVisible(WindowInsets.Type.ime())) {
+ Insets keyboardInsets = windowInsets.getInsets(WindowInsets.Type.ime());
+ int folderHeightFromBottom = getHeightFromBottom();
+
+ if (keyboardInsets.bottom > folderHeightFromBottom) {
+ // Translate this folder above the keyboard, then add the folder name's padding
+ this.setTranslationY(folderHeightFromBottom - keyboardInsets.bottom
+ - mFolderName.getPaddingBottom());
+ }
+ }
+ }
+
+ return windowInsets;
+ }
+
public FolderIcon getFolderIcon() {
return mFolderIcon;
}
@@ -1646,4 +1681,64 @@
mLauncher.getUserEventDispatcher()
.logLauncherEvent(mInfo.getFolderLabelStateLauncherEvent(fromState, toState));
}
+
+ /** Returns the height of the current folder's bottom edge from the bottom of the screen. */
+ private int getHeightFromBottom() {
+ DragLayer.LayoutParams layoutParams = (DragLayer.LayoutParams) getLayoutParams();
+ int folderBottomPx = layoutParams.y + layoutParams.height;
+ int windowBottomPx = mLauncher.getDeviceProfile().heightPx;
+
+ return windowBottomPx - folderBottomPx;
+ }
+
+ /** Callback that animates a folder sliding up above the ime. */
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ private static class FolderWindowInsetsAnimationCallback
+ extends WindowInsetsAnimation.Callback {
+
+ private final Folder mFolder;
+ float mFolderTranslationStart;
+ float mFolderTranslationEnd;
+
+ FolderWindowInsetsAnimationCallback(int dispatchMode, Folder folder) {
+ super(dispatchMode);
+
+ mFolder = folder;
+ }
+
+ @Override
+ public void onPrepare(@NonNull WindowInsetsAnimation animation) {
+ mFolderTranslationStart = mFolder.getTranslationY();
+ }
+
+ @NonNull
+ @Override
+ public WindowInsetsAnimation.Bounds onStart(
+ @NonNull WindowInsetsAnimation animation,
+ @NonNull WindowInsetsAnimation.Bounds bounds) {
+ mFolderTranslationEnd = mFolder.getTranslationY();
+
+ mFolder.setTranslationY(mFolderTranslationStart);
+
+ return super.onStart(animation, bounds);
+ }
+
+ @NonNull
+ @Override
+ public WindowInsets onProgress(@NonNull WindowInsets windowInsets,
+ @NonNull List<WindowInsetsAnimation> list) {
+ if (list.size() == 0) {
+ mFolder.setTranslationY(0);
+
+ return windowInsets;
+ }
+ float progress = list.get(0).getInterpolatedFraction();
+
+ mFolder.setTranslationY(
+ Utilities.mapRange(progress, mFolderTranslationStart, mFolderTranslationEnd));
+
+ return windowInsets;
+ }
+
+ }
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 0f1432a..cd84c96 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -599,7 +599,10 @@
@Override
public WorkspaceResult call() {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
- loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI);
+ loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
+ LauncherSettings.Favorites.SCREEN + " = 0 or "
+ + LauncherSettings.Favorites.CONTAINER + " = "
+ + LauncherSettings.Favorites.CONTAINER_HOTSEAT);
return new WorkspaceResult(mBgDataModel, null, mWidgetProvidersMap);
}
}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 444c2da..8013557 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -67,8 +67,8 @@
private static final String TAG = "Launcher.IconCache";
- private final Predicate<ItemInfoWithIcon> mIsUsingFallbackIconCheck = w -> w.bitmap != null
- && w.bitmap.isNullOrLowRes() && !isDefaultIcon(w.bitmap, w.user);
+ private final Predicate<ItemInfoWithIcon> mIsUsingFallbackOrNonDefaultIconCheck = w ->
+ w.bitmap != null && (w.bitmap.isNullOrLowRes() || !isDefaultIcon(w.bitmap, w.user));
private final CachingLogic<ComponentWithLabel> mComponentWithLabelCachingLogic;
private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic;
@@ -192,14 +192,14 @@
* Fill in {@param info} with the icon for {@param si}
*/
public void getShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) {
- getShortcutIcon(info, si, true, mIsUsingFallbackIconCheck);
+ getShortcutIcon(info, si, true, mIsUsingFallbackOrNonDefaultIconCheck);
}
/**
* Fill in {@param info} with an unbadged icon for {@param si}
*/
public void getUnbadgedShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) {
- getShortcutIcon(info, si, false, mIsUsingFallbackIconCheck);
+ getShortcutIcon(info, si, false, mIsUsingFallbackOrNonDefaultIconCheck);
}
/**
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index a9e385f..2b4520b 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -127,6 +127,7 @@
private boolean mStopped;
+ private final Set<PackageUserKey> mPendingPackages = new HashSet<>();
private boolean mItemsDeleted = false;
public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,
@@ -294,16 +295,17 @@
}
private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {
- loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI);
+ loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI,
+ null /* selection */);
}
- protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri) {
+ protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri,
+ String selection) {
final Context context = mApp.getContext();
final ContentResolver contentResolver = context.getContentResolver();
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
final boolean isSafeMode = pmHelper.isSafeMode();
final boolean isSdCardReady = Utilities.isBootCompleted();
- final Set<PackageUserKey> pendingPackages = new HashSet<>();
boolean clearDb = false;
try {
@@ -332,6 +334,7 @@
synchronized (mBgDataModel) {
mBgDataModel.clear();
+ mPendingPackages.clear();
final HashMap<PackageUserKey, SessionInfo> installingPkgs =
mSessionHelper.getActiveSessions();
@@ -342,8 +345,8 @@
Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();
final LoaderCursor c = new LoaderCursor(
- contentResolver.query(contentUri, null, null, null, null), contentUri, mApp,
- mUserManagerState);
+ contentResolver.query(contentUri, null, selection, null, null), contentUri,
+ mApp, mUserManagerState);
try {
final int appWidgetIdIndex = c.getColumnIndexOrThrow(
@@ -484,7 +487,7 @@
// SdCard is not ready yet. Package might get available,
// once it is ready.
Log.d(TAG, "Missing pkg, will check later: " + targetPkg);
- pendingPackages.add(new PackageUserKey(targetPkg, c.user));
+ mPendingPackages.add(new PackageUserKey(targetPkg, c.user));
// Add the icon on the workspace anyway.
allowMissingTarget = true;
} else {
@@ -768,20 +771,7 @@
}
// Remove dead items
- if (c.commitDeleted()) {
- // Remove any empty folder
- int[] deletedFolderIds = LauncherSettings.Settings
- .call(contentResolver,
- LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
- .getIntArray(LauncherSettings.Settings.EXTRA_VALUE);
- for (int folderId : deletedFolderIds) {
- mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
- mBgDataModel.folders.remove(folderId);
- mBgDataModel.itemsIdMap.remove(folderId);
- }
-
- mItemsDeleted = true;
- }
+ mItemsDeleted = c.commitDeleted();
// Sort the folder items, update ranks, and make sure all preview items are high res.
FolderGridOrganizer verifier =
@@ -807,13 +797,6 @@
}
c.commitRestoredItems();
- if (!isSdCardReady && !pendingPackages.isEmpty()) {
- context.registerReceiver(
- new SdCardAvailableReceiver(mApp, pendingPackages),
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED),
- null,
- MODEL_EXECUTOR.getHandler());
- }
}
}
@@ -840,14 +823,34 @@
private void sanitizeData() {
Context context = mApp.getContext();
+ ContentResolver contentResolver = context.getContentResolver();
if (mItemsDeleted) {
+ // Remove any empty folder
+ int[] deletedFolderIds = LauncherSettings.Settings
+ .call(contentResolver,
+ LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
+ .getIntArray(LauncherSettings.Settings.EXTRA_VALUE);
+ for (int folderId : deletedFolderIds) {
+ mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
+ mBgDataModel.folders.remove(folderId);
+ mBgDataModel.itemsIdMap.remove(folderId);
+ }
+
// Remove any ghost widgets
- LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.call(contentResolver,
LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);
}
// Update pinned state of model shortcuts
mBgDataModel.updateShortcutPinnedState(context);
+
+ if (!Utilities.isBootCompleted() && !mPendingPackages.isEmpty()) {
+ context.registerReceiver(
+ new SdCardAvailableReceiver(mApp, mPendingPackages),
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED),
+ null,
+ MODEL_EXECUTOR.getHandler());
+ }
}
private List<LauncherActivityInfo> loadAllApps() {
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 30f8fb0..b2d0081 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -96,6 +96,8 @@
public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
public static final String REQUEST_OVERVIEW_SHARE_ENABLED = "overview-share-enabled";
+ public static final String REQUEST_OVERVIEW_CONTENT_PUSH_ENABLED =
+ "overview-content-push-enabled";
public static boolean sDisableSensorRotation;
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
diff --git a/src/com/android/launcher3/util/VelocityUtils.java b/src/com/android/launcher3/util/VelocityUtils.java
new file mode 100644
index 0000000..d5962ed
--- /dev/null
+++ b/src/com/android/launcher3/util/VelocityUtils.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+/**
+ * Contains some constants and functions to standardize velocity usage.
+ */
+public class VelocityUtils {
+
+ /**
+ * Unit to pass to {@link android.view.VelocityTracker#computeCurrentVelocity(int)}.
+ */
+ public static final int PX_PER_MS = 1;
+
+}
diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index 761ef0d..a8e1c6b 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -18,7 +18,9 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Point;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -41,6 +43,9 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.touch.ItemLongClickListener;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
import java.util.List;
@@ -54,6 +59,7 @@
BubbleTextView mBubbleTextView;
View mIconView;
BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2];
+ AllAppsSearchPlugin mPlugin;
public HeroSearchResultView(Context context) {
super(context);
@@ -79,7 +85,10 @@
mBubbleTextView = findViewById(R.id.bubble_text);
- mBubbleTextView.setOnClickListener(launcher.getItemOnClickListener());
+ mBubbleTextView.setOnClickListener(view -> {
+ handleSelection(SearchTargetEvent.SELECT);
+ launcher.getItemOnClickListener().onClick(view);
+ });
mBubbleTextView.setOnLongClickListener(new HeroItemDragHandler(getContext(), this));
setLayoutParams(
new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, grid.allAppsCellHeightPx));
@@ -91,7 +100,18 @@
bubbleTextView.setLayoutParams(
new LinearLayout.LayoutParams(grid.allAppsIconSizePx,
grid.allAppsIconSizePx));
- bubbleTextView.setOnClickListener(launcher.getItemOnClickListener());
+ bubbleTextView.setOnClickListener(view -> {
+ WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag();
+ SearchTargetEvent event = new SearchTargetEvent(
+ SearchTarget.ItemType.APP_HERO,
+ SearchTargetEvent.CHILD_SELECT);
+ event.bundle = getAppBundle(itemInfo);
+ event.bundle.putString("shortcut_id", itemInfo.getDeepShortcutId());
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(event);
+ }
+ launcher.getItemOnClickListener().onClick(view);
+ });
}
}
@@ -110,6 +130,8 @@
mDeepShortcutTextViews[i].applyFromItemInfoWithIcon(shorcutInfos.get(i));
}
}
+ mPlugin = adapterItem.getPlugin();
+ adapterItem.setSelectionHandler(this::handleSelection);
}
@Override
@@ -147,7 +169,38 @@
mLauncher.getWorkspace().beginDragShared(mContainer.mBubbleTextView,
draggableView, mContainer, itemInfo, previewProvider, new DragOptions());
+ SearchTargetEvent event = new SearchTargetEvent(
+ SearchTarget.ItemType.APP_HERO, SearchTargetEvent.LONG_PRESS);
+ event.bundle = getAppBundle(itemInfo);
+ if (mContainer.mPlugin != null) {
+ mContainer.mPlugin.notifySearchTargetEvent(event);
+ }
+
return false;
}
}
+
+ private void handleSelection(int eventType) {
+ ItemInfo itemInfo = (ItemInfo) mBubbleTextView.getTag();
+ if (itemInfo == null) return;
+ Launcher launcher = Launcher.getLauncher(getContext());
+ launcher.startActivitySafely(this, itemInfo.getIntent(), itemInfo);
+
+ SearchTargetEvent event = new SearchTargetEvent(
+ SearchTarget.ItemType.APP_HERO, eventType);
+ event.bundle = getAppBundle(itemInfo);
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(event);
+ }
+ }
+
+ /**
+ * Helper method to generate {@link SearchTargetEvent} bundle from {@link ItemInfo}
+ */
+ public static Bundle getAppBundle(ItemInfo itemInfo) {
+ Bundle b = new Bundle();
+ b.putParcelable(Intent.EXTRA_COMPONENT_NAME, itemInfo.getTargetComponent());
+ b.putParcelable(Intent.EXTRA_USER, itemInfo.user);
+ return b;
+ }
}
diff --git a/src/com/android/launcher3/views/SearchResultPeopleView.java b/src/com/android/launcher3/views/SearchResultPeopleView.java
new file mode 100644
index 0000000..78e9841
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultPeopleView.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2020 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.views;
+
+import static android.content.Intent.URI_ALLOW_UNSAFE;
+import static android.content.Intent.URI_ANDROID_APP_SCHEME;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.util.Themes;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+
+/**
+ * A view representing a single people search result in all apps
+ */
+public class SearchResultPeopleView extends LinearLayout implements
+ AllAppsSearchBarController.PayloadResultHandler<Bundle> {
+
+ private final int mIconSize;
+ private final int mButtonSize;
+ private final PackageManager mPackageManager;
+ private View mIconView;
+ private TextView mTitleView;
+ private ImageButton[] mProviderButtons = new ImageButton[3];
+ private AllAppsSearchPlugin mPlugin;
+ private Uri mContactUri;
+
+
+ public SearchResultPeopleView(Context context) {
+ this(context, null, 0);
+ }
+
+ public SearchResultPeopleView(Context context,
+ @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SearchResultPeopleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
+ mPackageManager = getContext().getPackageManager();
+ mIconSize = deviceProfile.iconSizePx;
+ mButtonSize = (int) (deviceProfile.iconSizePx / 1.5f);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mIconView = findViewById(R.id.icon);
+ mIconView.getLayoutParams().height = mIconSize;
+ mIconView.getLayoutParams().width = mIconSize;
+ mTitleView = findViewById(R.id.title);
+ mProviderButtons[0] = findViewById(R.id.provider_0);
+ mProviderButtons[1] = findViewById(R.id.provider_1);
+ mProviderButtons[2] = findViewById(R.id.provider_2);
+ for (ImageButton button : mProviderButtons) {
+ button.getLayoutParams().width = mButtonSize;
+ button.getLayoutParams().height = mButtonSize;
+ }
+ setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
+ }
+
+ @Override
+ public void applyAdapterInfo(
+ AllAppsGridAdapter.AdapterItemWithPayload<Bundle> adapterItemWithPayload) {
+ Bundle payload = adapterItemWithPayload.getPayload();
+ mPlugin = adapterItemWithPayload.getPlugin();
+ mTitleView.setText(payload.getString("title"));
+ mContactUri = payload.getParcelable("contact_uri");
+ Bitmap icon = payload.getParcelable("icon");
+ if (icon != null) {
+ RoundedBitmapDrawable d = RoundedBitmapDrawableFactory.create(getResources(), icon);
+ float radius = Themes.getDialogCornerRadius(getContext());
+ d.setCornerRadius(radius);
+ d.setBounds(0, 0, mIconSize, mIconSize);
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(),
+ Bitmap.createScaledBitmap(icon, mIconSize, mIconSize, false));
+ mIconView.setBackground(d);
+ }
+
+ ArrayList<Bundle> providers = payload.getParcelableArrayList("providers");
+ for (int i = 0; i < mProviderButtons.length; i++) {
+ ImageButton button = mProviderButtons[i];
+ if (providers != null && i < providers.size()) {
+ try {
+ Bundle provider = providers.get(i);
+ Intent intent = Intent.parseUri(provider.getString("intent_uri_str"),
+ URI_ANDROID_APP_SCHEME | URI_ALLOW_UNSAFE);
+ setupProviderButton(button, provider, intent);
+ String pkg = provider.getString("package_name");
+ UI_HELPER_EXECUTOR.post(() -> {
+ try {
+ ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(
+ pkg, 0);
+ Drawable appIcon = applicationInfo.loadIcon(mPackageManager);
+ button.setImageDrawable(appIcon);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+
+ });
+ } catch (URISyntaxException ex) {
+ button.setVisibility(GONE);
+ }
+ } else {
+ button.setVisibility(GONE);
+ }
+ }
+ adapterItemWithPayload.setSelectionHandler(this::handleSelection);
+ }
+
+ private void setupProviderButton(ImageButton button, Bundle provider, Intent intent) {
+ Launcher launcher = Launcher.getLauncher(getContext());
+ button.setOnClickListener(b -> {
+ launcher.startActivitySafely(b, intent, null);
+ SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
+ SearchTarget.ItemType.PEOPLE,
+ SearchTargetEvent.CHILD_SELECT);
+ searchTargetEvent.bundle = new Bundle();
+ searchTargetEvent.bundle.putParcelable("contact_uri", mContactUri);
+ searchTargetEvent.bundle.putBundle("provider", provider);
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(searchTargetEvent);
+ }
+ });
+ }
+
+
+ private void handleSelection(int eventType) {
+ if (mContactUri != null) {
+ Launcher launcher = Launcher.getLauncher(getContext());
+ launcher.startActivitySafely(this, new Intent(Intent.ACTION_VIEW, mContactUri).setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK), null);
+ SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
+ SearchTarget.ItemType.PEOPLE, eventType);
+ searchTargetEvent.bundle = new Bundle();
+ searchTargetEvent.bundle.putParcelable("contact_uri", mContactUri);
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(searchTargetEvent);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/SearchResultPlayItem.java b/src/com/android/launcher3/views/SearchResultPlayItem.java
index 19a4c5d..8624609 100644
--- a/src/com/android/launcher3/views/SearchResultPlayItem.java
+++ b/src/com/android/launcher3/views/SearchResultPlayItem.java
@@ -38,6 +38,9 @@
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
import java.io.IOException;
import java.net.URL;
@@ -54,6 +57,7 @@
private Button mPreviewButton;
private String mPackageName;
private boolean mIsInstantGame;
+ private AllAppsSearchPlugin mPlugin;
public SearchResultPlayItem(Context context) {
this(context, null, 0);
@@ -84,13 +88,14 @@
ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
iconParams.height = mDeviceProfile.allAppsIconSizePx;
iconParams.width = mDeviceProfile.allAppsIconSizePx;
- setOnClickListener(view -> handleSelection());
+ setOnClickListener(view -> handleSelection(SearchTargetEvent.SELECT));
}
@Override
public void applyAdapterInfo(AdapterItemWithPayload<Bundle> adapterItemWithPayload) {
Bundle bundle = adapterItemWithPayload.getPayload();
+ mPlugin = adapterItemWithPayload.getPlugin();
adapterItemWithPayload.setSelectionHandler(this::handleSelection);
if (bundle.getString("package", "").equals(mPackageName)) {
return;
@@ -129,13 +134,14 @@
}
}
- private void handleSelection() {
+ private void handleSelection(int eventType) {
if (mPackageName == null) return;
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(
"https://play.google.com/store/apps/details?id="
+ mPackageName));
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(i);
+ logSearchEvent(eventType);
}
private void launchInstantGame() {
@@ -150,5 +156,16 @@
intent.putExtra("callerId", getContext().getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
+ logSearchEvent(SearchTargetEvent.CHILD_SELECT);
+ }
+
+ private void logSearchEvent(int eventType) {
+ SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
+ SearchTarget.ItemType.PLAY_RESULTS, eventType);
+ searchTargetEvent.bundle = new Bundle();
+ searchTargetEvent.bundle.putString("package_name", mPackageName);
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(searchTargetEvent);
+ }
}
}
diff --git a/src/com/android/launcher3/views/SearchResultShortcut.java b/src/com/android/launcher3/views/SearchResultShortcut.java
new file mode 100644
index 0000000..307cf34
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultShortcut.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 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.views;
+
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import android.content.Context;
+import android.content.pm.ShortcutInfo;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.touch.ItemClickHandler;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
+
+/**
+ * A view representing a stand alone shortcut search result
+ */
+public class SearchResultShortcut extends FrameLayout implements
+ AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
+
+ private BubbleTextView mBubbleTextView;
+ private View mIconView;
+ private ShortcutInfo mShortcutInfo;
+ private AllAppsSearchPlugin mPlugin;
+
+ public SearchResultShortcut(@NonNull Context context) {
+ super(context);
+ }
+
+ public SearchResultShortcut(@NonNull Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SearchResultShortcut(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ Launcher launcher = Launcher.getLauncher(getContext());
+ DeviceProfile grid = launcher.getDeviceProfile();
+ mIconView = findViewById(R.id.icon);
+ ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
+ iconParams.height = grid.allAppsIconSizePx;
+ iconParams.width = grid.allAppsIconSizePx;
+ mBubbleTextView = findViewById(R.id.bubble_text);
+ setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
+ }
+
+ @Override
+ public void applyAdapterInfo(
+ AllAppsGridAdapter.AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
+ SearchTarget payload = adapterItemWithPayload.getPayload();
+ mPlugin = adapterItemWithPayload.getPlugin();
+ mShortcutInfo = payload.shortcuts.get(0);
+ WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext());
+ mBubbleTextView.applyFromWorkspaceItem(workspaceItemInfo);
+ mIconView.setBackground(mBubbleTextView.getIcon());
+ LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
+ MODEL_EXECUTOR.execute(() -> {
+ launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
+ mBubbleTextView.applyFromWorkspaceItem(workspaceItemInfo);
+ mIconView.setBackground(mBubbleTextView.getIcon());
+ });
+ adapterItemWithPayload.setSelectionHandler(this::handleSelection);
+ }
+
+ private void handleSelection(int eventType) {
+ WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) mBubbleTextView.getTag();
+ ItemClickHandler.onClickAppShortcut(this, itemInfo, Launcher.getLauncher(getContext()));
+
+ SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
+ SearchTarget.ItemType.SHORTCUT, eventType);
+ searchTargetEvent.shortcut = mShortcutInfo;
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(searchTargetEvent);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/SearchSettingsRowView.java b/src/com/android/launcher3/views/SearchSettingsRowView.java
index 08c78ff..93bcee2 100644
--- a/src/com/android/launcher3/views/SearchSettingsRowView.java
+++ b/src/com/android/launcher3/views/SearchSettingsRowView.java
@@ -31,6 +31,9 @@
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
import java.util.ArrayList;
@@ -44,6 +47,7 @@
private TextView mDescriptionView;
private TextView mBreadcrumbsView;
private Intent mIntent;
+ private AllAppsSearchPlugin mPlugin;
public SearchSettingsRowView(@NonNull Context context) {
super(context);
@@ -72,6 +76,7 @@
public void applyAdapterInfo(
AllAppsGridAdapter.AdapterItemWithPayload<Bundle> adapterItemWithPayload) {
Bundle bundle = adapterItemWithPayload.getPayload();
+ mPlugin = adapterItemWithPayload.getPlugin();
mIntent = bundle.getParcelable("intent");
showIfAvailable(mTitleView, bundle.getString("title"));
showIfAvailable(mDescriptionView, bundle.getString("description"));
@@ -79,7 +84,7 @@
//TODO: implement RTL friendly breadcrumbs view
showIfAvailable(mBreadcrumbsView, breadcrumbs != null
? String.join(" > ", breadcrumbs) : null);
- adapterItemWithPayload.setSelectionHandler(() -> onClick(this));
+ adapterItemWithPayload.setSelectionHandler(this::handleSelection);
}
private void showIfAvailable(TextView view, @Nullable String string) {
@@ -93,10 +98,22 @@
@Override
public void onClick(View view) {
+ handleSelection(SearchTargetEvent.SELECT);
+ }
+
+ private void handleSelection(int eventType) {
if (mIntent == null) return;
// TODO: create ItemInfo object and then use it to call startActivityForResult for proper
// WW logging
- Launcher launcher = Launcher.getLauncher(view.getContext());
+ Launcher launcher = Launcher.getLauncher(getContext());
launcher.startActivityForResult(mIntent, 0);
+
+ SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
+ SearchTarget.ItemType.SETTINGS_ROW, eventType);
+ searchTargetEvent.bundle = new Bundle();
+ searchTargetEvent.bundle.putParcelable("intent", mIntent);
+ if (mPlugin != null) {
+ mPlugin.notifySearchTargetEvent(searchTargetEvent);
+ }
}
}
diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
index 9949678..437cf3c 100644
--- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
+++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
@@ -47,7 +47,10 @@
*/
void performSearch(String query, Consumer<List<SearchTarget>> results);
- void onClick(boolean isTouch, SearchTargetEvent event);
+ /**
+ * Send over search target interaction events to Plugin
+ */
+ void notifySearchTargetEvent(SearchTargetEvent event);
/**
* Send signal when user exits all apps.
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
index 913fc0e..c6b8300 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
@@ -31,7 +31,9 @@
DETAIL(2),
ROW(3),
ROW_WITH_BUTTON(4),
- SLICE(5);
+ SLICE(5),
+ SHORTCUT(6),
+ PEOPLE(7);
private final int mId;
ViewType(int id) {
@@ -48,7 +50,9 @@
SETTINGS_ROW(1, "Settings", ViewType.ROW),
SETTINGS_SLICE(2, "Settings", ViewType.SLICE),
APP(3, "", ViewType.TOP_HIT),
- APP_HERO(4, "", ViewType.HERO);
+ APP_HERO(4, "", ViewType.HERO),
+ SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT),
+ PEOPLE(6, "People", ViewType.PEOPLE);
private final int mId;
private final String mTitle;
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
index 00aacd0..ac4bc33 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
@@ -22,18 +22,19 @@
* Event used for the feedback loop to the plugin. (and future aiai)
*/
public class SearchTargetEvent {
+ public static final int SELECT = 0;
+ public static final int QUICK_SELECT = 1;
+ public static final int LONG_PRESS = 2;
+ public static final int CHILD_SELECT = 3;
+
public SearchTarget.ItemType type;
public ShortcutInfo shortcut;
+ public int eventType;
public Bundle bundle;
public float score;
- public SearchTargetEvent(SearchTarget.ItemType itemType,
- ShortcutInfo shortcut,
- Bundle bundle,
- float score) {
+ public SearchTargetEvent(SearchTarget.ItemType itemType, int eventType) {
this.type = itemType;
- this.shortcut = shortcut;
- this.bundle = bundle;
- this.score = score;
+ this.eventType = eventType;
}
}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 34ebbac..b4e45f8 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -234,7 +234,7 @@
WidgetValidityCheck(LauncherAppState app) {
mIdp = app.getInvariantDeviceProfile();
- mAppFilter = AppFilter.newInstance(app.getContext());
+ mAppFilter = new AppFilter(app.getContext());
}
@Override
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 80adf05..22833ec 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1313,6 +1313,11 @@
TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+ boolean overviewContentPushEnabled() {
+ return getTestInfo(TestProtocol.REQUEST_OVERVIEW_CONTENT_PUSH_ENABLED).getBoolean(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
private void disableSensorRotation() {
getTestInfo(TestProtocol.REQUEST_MOCK_SENSOR_ROTATION);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index a30a404..e3e0f42 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -34,6 +34,27 @@
}
/**
+ * Clicks content push button.
+ */
+ @NonNull
+ public Overview clickAndDismissContentPush() {
+ if (mLauncher.overviewContentPushEnabled()) {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to click content push button and exit screenshot ui")) {
+ UiObject2 exo = mLauncher.waitForObjectInContainer(mOverviewActions,
+ "action_content_push");
+ mLauncher.clickLauncherObject(exo);
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "clicked content push button")) {
+ return new Overview(mLauncher);
+ }
+ }
+ }
+ return new Overview(mLauncher);
+ }
+
+ /**
* Clicks screenshot button and closes screenshot ui.
*/
@NonNull