Merge branch 'ub-launcher3-edmonton' into pi-dev

am: bf29023212

Change-Id: I6ef016a92f772bf74b85c7eec84110269adf83ea
This commit is contained in:
Jon
2018-05-31 15:22:09 -07:00
committed by android-build-merger
46 changed files with 537 additions and 258 deletions
+5
View File
@@ -112,6 +112,11 @@
public <init>(...); public <init>(...);
} }
# UserEventDispatcherExtension
-keep class com.android.quickstep.logging.UserEventDispatcherExtension {
public <init>(...);
}
-keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** { -keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** {
*; *;
} }
+2
View File
@@ -110,6 +110,8 @@ enum ControlType {
QUICK_SCRUB_BUTTON = 12; QUICK_SCRUB_BUTTON = 12;
CLEAR_ALL_BUTTON = 13; CLEAR_ALL_BUTTON = 13;
CANCEL_TARGET = 14; CANCEL_TARGET = 14;
TASK_PREVIEW = 15;
SPLIT_SCREEN_TARGET = 16;
} }
enum TipType { enum TipType {
@@ -24,6 +24,7 @@
android:id="@+id/overview_panel_container" android:id="@+id/overview_panel_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipChildren="false"
> >
<include layout="@layout/overview_clear_all_button"/> <include layout="@layout/overview_clear_all_button"/>
@@ -33,6 +34,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"
android:outlineProvider="none"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:theme="@style/HomeScreenElementTheme" android:theme="@style/HomeScreenElementTheme"
> >
+2
View File
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipChildren="false"
android:visibility="invisible" android:visibility="invisible"
> >
<include layout="@layout/overview_clear_all_button"/> <include layout="@layout/overview_clear_all_button"/>
@@ -28,6 +29,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"
android:outlineProvider="none"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:accessibilityPaneTitle="@string/accessibility_recent_apps" android:accessibilityPaneTitle="@string/accessibility_recent_apps"
android:theme="@style/HomeScreenElementTheme" android:theme="@style/HomeScreenElementTheme"
+1 -1
View File
@@ -18,5 +18,5 @@
<string name="overview_callbacks_class" translatable="false"></string> <string name="overview_callbacks_class" translatable="false"></string>
<string name="user_event_dispatcher_class" translatable="false">com.google.quickstep.logging.UserEventDispatcherExtension</string> <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
</resources> </resources>
@@ -50,6 +50,7 @@ import android.graphics.Matrix;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.CancellationSignal;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
@@ -105,6 +106,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
private static final int APP_LAUNCH_ALPHA_DURATION = 50; private static final int APP_LAUNCH_ALPHA_DURATION = 50;
public static final int RECENTS_LAUNCH_DURATION = 336; public static final int RECENTS_LAUNCH_DURATION = 336;
public static final int RECENTS_QUICKSCRUB_LAUNCH_DURATION = 300;
private static final int LAUNCHER_RESUME_START_DELAY = 100; private static final int LAUNCHER_RESUME_START_DELAY = 100;
private static final int CLOSING_TRANSITION_DURATION_MS = 250; private static final int CLOSING_TRANSITION_DURATION_MS = 250;
@@ -236,8 +238,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
return bounds; return bounds;
} }
public void setRemoteAnimationProvider(RemoteAnimationProvider animationProvider) { public void setRemoteAnimationProvider(final RemoteAnimationProvider animationProvider,
CancellationSignal cancellationSignal) {
mRemoteAnimationProvider = animationProvider; mRemoteAnimationProvider = animationProvider;
cancellationSignal.setOnCancelListener(() -> {
if (animationProvider == mRemoteAnimationProvider) {
mRemoteAnimationProvider = null;
}
});
} }
/** /**
@@ -253,15 +261,21 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
RecentsView recentsView = mLauncher.getOverviewPanel(); RecentsView recentsView = mLauncher.getOverviewPanel();
boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING); boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING);
boolean skipLauncherChanges = !launcherClosing; boolean skipLauncherChanges = !launcherClosing;
boolean isLaunchingFromQuickscrub =
recentsView.getQuickScrubController().isWaitingForTaskLaunch();
TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets); TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
if (taskView == null) { if (taskView == null) {
return false; return false;
} }
int duration = isLaunchingFromQuickscrub
? RECENTS_QUICKSCRUB_LAUNCH_DURATION
: RECENTS_LAUNCH_DURATION;
ClipAnimationHelper helper = new ClipAnimationHelper(); ClipAnimationHelper helper = new ClipAnimationHelper();
target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper) target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper)
.setDuration(RECENTS_LAUNCH_DURATION)); .setDuration(duration));
Animator childStateAnimation = null; Animator childStateAnimation = null;
// Found a visible recents task that matches the opening app, lets launch the app from there // Found a visible recents task that matches the opening app, lets launch the app from there
@@ -270,7 +284,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
if (launcherClosing) { if (launcherClosing) {
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper); launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper);
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
launcherAnim.setDuration(RECENTS_LAUNCH_DURATION); launcherAnim.setDuration(duration);
// Make sure recents gets fixed up by resetting task alphas and scales, etc. // Make sure recents gets fixed up by resetting task alphas and scales, etc.
windowAnimEndListener = new AnimatorListenerAdapter() { windowAnimEndListener = new AnimatorListenerAdapter() {
@@ -282,11 +296,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
}; };
} else { } else {
AnimatorPlaybackController controller = AnimatorPlaybackController controller =
mLauncher.getStateManager() mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration);
.createAnimationToNewWorkspace(NORMAL, RECENTS_LAUNCH_DURATION);
controller.dispatchOnStart(); controller.dispatchOnStart();
childStateAnimation = controller.getTarget(); childStateAnimation = controller.getTarget();
launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION); launcherAnim = controller.getAnimationPlayer().setDuration(duration);
windowAnimEndListener = new AnimatorListenerAdapter() { windowAnimEndListener = new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@@ -581,11 +594,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
float offsetX = (scaledWindowWidth - iconWidth) / 2; float offsetX = (scaledWindowWidth - iconWidth) / 2;
float offsetY = (scaledWindowHeight - iconHeight) / 2; float offsetY = (scaledWindowHeight - iconHeight) / 2;
if (mLauncher.isInMultiWindowModeCompat()) { mFloatingView.getLocationOnScreen(floatingViewBounds);
mFloatingView.getLocationOnScreen(floatingViewBounds);
} else {
mFloatingView.getLocationInWindow(floatingViewBounds);
}
float transX0 = floatingViewBounds[0] - offsetX; float transX0 = floatingViewBounds[0] - offsetX;
float transY0 = floatingViewBounds[1] - offsetY; float transY0 = floatingViewBounds[1] - offsetY;
matrix.postTranslate(transX0, transY0); matrix.postTranslate(transX0, transY0);
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler; import android.os.Handler;
import com.android.launcher3.states.InternalStateHandler; import com.android.launcher3.states.InternalStateHandler;
@@ -48,10 +49,11 @@ public class LauncherInitListener extends InternalStateHandler implements Activi
// Set a one-time animation provider. After the first call, this will get cleared. // Set a one-time animation provider. After the first call, this will get cleared.
// TODO: Probably also check the intended target id. // TODO: Probably also check the intended target id.
CancellationSignal cancellationSignal = new CancellationSignal();
appTransitionManager.setRemoteAnimationProvider((targets) -> { appTransitionManager.setRemoteAnimationProvider((targets) -> {
// On the first call clear the reference. // On the first call clear the reference.
appTransitionManager.setRemoteAnimationProvider(null); cancellationSignal.cancel();
RemoteAnimationProvider provider = mRemoteAnimationProvider; RemoteAnimationProvider provider = mRemoteAnimationProvider;
mRemoteAnimationProvider = null; mRemoteAnimationProvider = null;
@@ -59,7 +61,7 @@ public class LauncherInitListener extends InternalStateHandler implements Activi
return provider.createWindowAnimation(targets); return provider.createWindowAnimation(targets);
} }
return null; return null;
}); }, cancellationSignal);
} }
OverviewCallbacks.get(launcher).onInitOverviewTransition(); OverviewCallbacks.get(launcher).onInitOverviewTransition();
return mOnInitListener.test(launcher, alreadyOnHome); return mOnInitListener.test(launcher, alreadyOnHome);
@@ -34,7 +34,7 @@ public class FastOverviewState extends OverviewState {
/** /**
* Vertical transition of the task previews relative to the full container. * Vertical transition of the task previews relative to the full container.
*/ */
public static final float OVERVIEW_TRANSLATION_FACTOR = 0.5f; public static final float OVERVIEW_TRANSLATION_FACTOR = 0.4f;
private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION
| FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY; | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY;
@@ -76,4 +76,10 @@ public class FastOverviewState extends OverviewState {
return Math.min(Math.min(dp.availableHeightPx / usedHeight, return Math.min(Math.min(dp.availableHeightPx / usedHeight,
dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP); dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP);
} }
@Override
public void onStateDisabled(Launcher launcher) {
super.onStateDisabled(launcher);
launcher.<RecentsView>getOverviewPanel().getQuickScrubController().cancelActiveQuickscrub();
}
} }
@@ -76,15 +76,16 @@ public class RecentsViewStateController implements StateHandler {
} }
PropertySetter setter = config.getPropertySetter(builder); PropertySetter setter = config.getPropertySetter(builder);
float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher); float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR); Interpolator scaleAndTransYInterpolator = builder.getInterpolator(
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0], scaleInterpolator); ANIM_OVERVIEW_SCALE, LINEAR);
Interpolator transYInterpolator = scaleInterpolator;
if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) { if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
transYInterpolator = Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0, scaleAndTransYInterpolator = Interpolators.clampToProgress(
QUICK_SCRUB_TRANSLATION_Y_FACTOR); QUICK_SCRUB_START_INTERPOLATOR, 0, QUICK_SCRUB_TRANSLATION_Y_FACTOR);
} }
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0],
scaleAndTransYInterpolator);
setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1], setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
transYInterpolator); scaleAndTransYInterpolator);
setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0, setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
@@ -25,14 +25,19 @@ import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN; import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN; import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.CancellationSignal;
import android.util.Base64; import android.util.Base64;
import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppTransitionManagerImpl;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager; import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -41,6 +46,8 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.TouchController; import com.android.launcher3.util.TouchController;
import com.android.quickstep.OverviewInteractionState; import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel; import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -179,6 +186,23 @@ public class UiFactory {
} }
} }
public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
CancellationSignal cancellationSignal) {
LauncherAppTransitionManagerImpl appTransitionManager =
(LauncherAppTransitionManagerImpl) launcher.getAppTransitionManager();
appTransitionManager.setRemoteAnimationProvider((targets) -> {
// On the first call clear the reference.
cancellationSignal.cancel();
ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(targets));
AnimatorSet anim = new AnimatorSet();
anim.play(fadeAnimation);
return anim;
}, cancellationSignal);
}
public static boolean dumpActivity(Activity activity, PrintWriter writer) { public static boolean dumpActivity(Activity activity, PrintWriter writer) {
if (!Utilities.IS_DEBUG_DEVICE) { if (!Utilities.IS_DEBUG_DEVICE) {
return false; return false;
@@ -46,6 +46,7 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -82,7 +83,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo, void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo,
boolean activityVisible); boolean activityVisible);
float getTranslationYForQuickScrub(T activity); float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context);
void executeOnWindowAvailable(T activity, Runnable action); void executeOnWindowAvailable(T activity, Runnable action);
@@ -151,10 +153,15 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
} }
@Override @Override
public float getTranslationYForQuickScrub(Launcher activity) { public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
LauncherRecentsView recentsView = activity.getOverviewPanel(); Context context) {
return recentsView.computeTranslationYForFactor( // The padding calculations are exactly same as that of RecentsView.setInsets
FastOverviewState.OVERVIEW_TRANSLATION_FACTOR); int topMargin = context.getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top;
int paddingBottom = dp.availableHeightPx + dp.getInsets().top - targetRect.rect.bottom;
return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop);
} }
@Override @Override
@@ -380,7 +387,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
} }
@Override @Override
public float getTranslationYForQuickScrub(RecentsActivity activity) { public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context) {
return 0; return 0;
} }
@@ -46,9 +46,9 @@ public class AnimatedFloat {
mUpdateCallback = updateCallback; mUpdateCallback = updateCallback;
} }
public ObjectAnimator animateToValue(float v) { public ObjectAnimator animateToValue(float start, float end) {
cancelAnimation(); cancelAnimation();
mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, v); mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end);
mValueAnimator.addListener(new AnimatorListenerAdapter() { mValueAnimator.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animator) { public void onAnimationEnd(Animator animator) {
@@ -63,6 +63,16 @@ public class DeferredTouchConsumer implements TouchConsumer {
mTarget.onQuickScrubProgress(progress); mTarget.onQuickScrubProgress(progress);
} }
@Override
public void onQuickStep(MotionEvent ev) {
mTarget.onQuickStep(ev);
}
@Override
public void onCommand(int command) {
mTarget.onCommand(command);
}
@Override @Override
public void preProcessMotionEvent(MotionEvent ev) { public void preProcessMotionEvent(MotionEvent ev) {
mVelocityTracker.addMovement(ev); mVelocityTracker.addMovement(ev);
@@ -92,6 +102,11 @@ public class DeferredTouchConsumer implements TouchConsumer {
return target == null ? true : target.deferNextEventToMainThread(); return target == null ? true : target.deferNextEventToMainThread();
} }
@Override
public void onShowOverviewFromAltTab() {
mTarget.onShowOverviewFromAltTab();
}
public interface DeferredTouchProvider { public interface DeferredTouchProvider {
TouchConsumer createTouchConsumer(VelocityTracker tracker); TouchConsumer createTouchConsumer(VelocityTracker tracker);
@@ -55,6 +55,8 @@ public class MotionEventQueue {
ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT); ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_QUICK_STEP = private static final int ACTION_QUICK_STEP =
ACTION_VIRTUAL | (7 << ACTION_POINTER_INDEX_SHIFT); ACTION_VIRTUAL | (7 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_COMMAND =
ACTION_VIRTUAL | (8 << ACTION_POINTER_INDEX_SHIFT);
private final EventArray mEmptyArray = new EventArray(); private final EventArray mEmptyArray = new EventArray();
private final Object mExecutionLock = new Object(); private final Object mExecutionLock = new Object();
@@ -165,6 +167,9 @@ public class MotionEventQueue {
case ACTION_QUICK_STEP: case ACTION_QUICK_STEP:
mConsumer.onQuickStep(event); mConsumer.onQuickStep(event);
break; break;
case ACTION_COMMAND:
mConsumer.onCommand(event.getSource());
break;
default: default:
Log.e(TAG, "Invalid virtual event: " + event.getAction()); Log.e(TAG, "Invalid virtual event: " + event.getAction());
} }
@@ -222,6 +227,12 @@ public class MotionEventQueue {
queueVirtualAction(ACTION_DEFER_INIT, 0); queueVirtualAction(ACTION_DEFER_INIT, 0);
} }
public void onCommand(int command) {
MotionEvent ev = MotionEvent.obtain(0, 0, ACTION_COMMAND, 0, 0, 0);
ev.setSource(command);
queueNoPreProcess(ev);
}
public TouchConsumer getConsumer() { public TouchConsumer getConsumer() {
return mConsumer; return mConsumer;
} }
@@ -37,6 +37,7 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Looper; import android.os.Looper;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.SparseArray;
import android.view.Choreographer; import android.view.Choreographer;
import android.view.Display; import android.view.Display;
import android.view.MotionEvent; import android.view.MotionEvent;
@@ -69,6 +70,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150; private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
private final SparseArray<RecentsAnimationState> mAnimationStates = new SparseArray<>();
private final RunningTaskInfo mRunningTask; private final RunningTaskInfo mRunningTask;
private final RecentsModel mRecentsModel; private final RecentsModel mRecentsModel;
private final Intent mHomeIntent; private final Intent mHomeIntent;
@@ -183,7 +185,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
case ACTION_UP: { case ACTION_UP: {
TraceHelper.endSection("TouchInt"); TraceHelper.endSection("TouchInt");
finishTouchTracking(); finishTouchTracking(ev);
break; break;
} }
} }
@@ -212,8 +214,9 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
private void startTouchTrackingForWindowAnimation(long touchTimeMs) { private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
// Create the shared handler // Create the shared handler
RecentsAnimationState animationState = new RecentsAnimationState();
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler( final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
mRunningTask, this, touchTimeMs, mActivityControlHelper); animationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper);
// Preload the plan // Preload the plan
mRecentsModel.loadTasks(mRunningTask.id, null); mRecentsModel.loadTasks(mRunningTask.id, null);
@@ -237,31 +240,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
public void onHandleAssistData(Bundle bundle) { public void onHandleAssistData(Bundle bundle) {
mRecentsModel.preloadAssistData(mRunningTask.id, bundle); mRecentsModel.preloadAssistData(mRunningTask.id, bundle);
} }
}, }, animationState, null, null);
new RecentsAnimationListener() {
public void onAnimationStart(
RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds) {
if (mInteractionHandler == handler) {
TraceHelper.partitionSection("RecentsController", "Received");
handler.onRecentsAnimationStart(controller,
new RemoteAnimationTargetSet(apps, MODE_CLOSING),
homeContentInsets, minimizedHomeBounds);
} else {
TraceHelper.endSection("RecentsController", "Finishing no handler");
controller.finish(false /* toHome */);
}
}
public void onAnimationCanceled() {
TraceHelper.endSection("RecentsController",
"Cancelled: " + mInteractionHandler);
if (mInteractionHandler == handler) {
handler.onRecentsAnimationCanceled();
}
}
}, null, null);
if (Looper.myLooper() != Looper.getMainLooper()) { if (Looper.myLooper() != Looper.getMainLooper()) {
startActivity.run(); startActivity.run();
@@ -277,12 +256,22 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
} }
} }
@Override
public void onCommand(int command) {
RecentsAnimationState state = mAnimationStates.get(command);
if (state != null) {
state.execute();
}
}
/** /**
* Called when the gesture has ended. Does not correlate to the completion of the interaction as * Called when the gesture has ended. Does not correlate to the completion of the interaction as
* the animation can still be running. * the animation can still be running.
*/ */
private void finishTouchTracking() { private void finishTouchTracking(MotionEvent ev) {
if (mPassedInitialSlop && mInteractionHandler != null) { if (mPassedInitialSlop && mInteractionHandler != null) {
mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
mVelocityTracker.computeCurrentVelocity(1000, mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(this).getScaledMaximumFlingVelocity()); ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
@@ -398,4 +387,55 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
// TODO: Consider also check if the eventQueue is using mainThread of not. // TODO: Consider also check if the eventQueue is using mainThread of not.
return mInteractionHandler != null; return mInteractionHandler != null;
} }
private class RecentsAnimationState implements RecentsAnimationListener {
private final int id;
private RecentsAnimationControllerCompat mController;
private RemoteAnimationTargetSet mTargets;
private Rect mHomeContentInsets;
private Rect mMinimizedHomeBounds;
private boolean mCancelled;
public RecentsAnimationState() {
id = mAnimationStates.size();
mAnimationStates.put(id, this);
}
@Override
public void onAnimationStart(
RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds) {
mController = controller;
mTargets = new RemoteAnimationTargetSet(apps, MODE_CLOSING);
mHomeContentInsets = homeContentInsets;
mMinimizedHomeBounds = minimizedHomeBounds;
mEventQueue.onCommand(id);
}
@Override
public void onAnimationCanceled() {
mCancelled = true;
mEventQueue.onCommand(id);
}
public void execute() {
if (mInteractionHandler == null || mInteractionHandler.id != id) {
if (!mCancelled && mController != null) {
TraceHelper.endSection("RecentsController", "Finishing no handler");
mController.finish(false /* toHome */);
}
} else if (mCancelled) {
TraceHelper.endSection("RecentsController",
"Cancelled: " + mInteractionHandler);
mInteractionHandler.onRecentsAnimationCanceled();
} else {
TraceHelper.partitionSection("RecentsController", "Received");
mInteractionHandler.onRecentsAnimationStart(mController, mTargets,
mHomeContentInsets, mMinimizedHomeBounds);
}
}
}
} }
@@ -40,7 +40,7 @@ import com.android.quickstep.views.TaskView;
public class QuickScrubController implements OnAlarmListener { public class QuickScrubController implements OnAlarmListener {
public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240; public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240;
public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 150; public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 200;
// We want the translation y to finish faster than the rest of the animation. // We want the translation y to finish faster than the rest of the animation.
public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6; public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6;
public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN; public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN;
@@ -132,6 +132,17 @@ public class QuickScrubController implements OnAlarmListener {
} }
} }
public void cancelActiveQuickscrub() {
if (!mInQuickScrub) {
return;
}
Log.d(TAG, "Quickscrub was active, cancelling");
mInQuickScrub = false;
mActivityControlHelper = null;
mOnFinishedTransitionToQuickScrubRunnable = null;
mRecentsView.setNextPageSwitchRunnable(null);
}
/** /**
* Initializes the UI for quick scrub, returns true if success. * Initializes the UI for quick scrub, returns true if success.
*/ */
@@ -145,6 +156,10 @@ public class QuickScrubController implements OnAlarmListener {
return true; return true;
} }
public boolean isWaitingForTaskLaunch() {
return mWaitingForTaskLaunch;
}
/** /**
* Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction. * Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction.
*/ */
@@ -20,6 +20,7 @@ import android.content.Context;
import com.android.launcher3.MainProcessInitializer; import com.android.launcher3.MainProcessInitializer;
import com.android.systemui.shared.system.ThreadedRendererCompat; import com.android.systemui.shared.system.ThreadedRendererCompat;
@SuppressWarnings("unused")
public class QuickstepProcessInitializer extends MainProcessInitializer { public class QuickstepProcessInitializer extends MainProcessInitializer {
public QuickstepProcessInitializer(Context context) { } public QuickstepProcessInitializer(Context context) { }
@@ -20,6 +20,8 @@ import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.UiThreadHelper; import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
/** /**
@@ -27,6 +29,10 @@ import java.util.concurrent.ExecutorService;
*/ */
public class RecentsAnimationWrapper { public class RecentsAnimationWrapper {
// A list of callbacks to run when we receive the recents animation target. There are different
// than the state callbacks as these run on the current worker thread.
private final ArrayList<Runnable> mCallbacks = new ArrayList<>();
public RemoteAnimationTargetSet targetSet; public RemoteAnimationTargetSet targetSet;
private RecentsAnimationControllerCompat mController; private RecentsAnimationControllerCompat mController;
@@ -46,6 +52,21 @@ public class RecentsAnimationWrapper {
if (mInputConsumerEnabled) { if (mInputConsumerEnabled) {
enableInputConsumer(); enableInputConsumer();
} }
if (!mCallbacks.isEmpty()) {
for (Runnable action : new ArrayList<>(mCallbacks)) {
action.run();
}
mCallbacks.clear();
}
}
public synchronized void runOnInit(Runnable action) {
if (targetSet == null) {
mCallbacks.add(action);
} else {
action.run();
}
} }
/** /**
@@ -16,6 +16,8 @@
package com.android.quickstep; package com.android.quickstep;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@@ -35,6 +37,7 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo; import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.InstantAppResolver;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskThumbnailView;
@@ -166,7 +169,8 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
Log.w(TAG, "Failed to notify SysUI of split screen: ", e); Log.w(TAG, "Failed to notify SysUI of split screen: ", e);
return; return;
} }
activity.getUserEventDispatcher().logActionOnControl(TAP,
LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
// Add a device profile change listener to kick off animating the side tasks // Add a device profile change listener to kick off animating the side tasks
// once we enter multiwindow mode and relayout // once we enter multiwindow mode and relayout
activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener); activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
@@ -48,6 +48,8 @@ public interface TouchConsumer extends Consumer<MotionEvent> {
default void onQuickStep(MotionEvent ev) { } default void onQuickStep(MotionEvent ev) { }
default void onCommand(int command) { }
/** /**
* Called on the binder thread to allow the consumer to process the motion event before it is * Called on the binder thread to allow the consumer to process the motion event before it is
* posted on a handler thread. * posted on a handler thread.
@@ -16,6 +16,7 @@
package com.android.quickstep; package com.android.quickstep;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -29,6 +30,7 @@ import android.animation.ObjectAnimator;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
@@ -36,6 +38,7 @@ import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserHandle;
import android.support.annotation.AnyThread; import android.support.annotation.AnyThread;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread; import android.support.annotation.WorkerThread;
@@ -51,6 +54,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher;
@@ -65,11 +69,12 @@ import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.LayoutListener; import com.android.quickstep.ActivityControlHelper.LayoutListener;
import com.android.quickstep.TouchConsumer.InteractionType; import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@@ -167,6 +172,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
// An increasing identifier per single instance of OtherActivityTouchConsumer. Generally one
// instance of OtherActivityTouchConsumer will only have one swipe handle, but sometimes we can
// end up with multiple handlers if we get recents command in the middle of a swipe gesture.
// This is used to match the corresponding activity manager callbacks in
// OtherActivityTouchConsumer
public final int id;
private final Context mContext; private final Context mContext;
private final ActivityControlHelper<T> mActivityControlHelper; private final ActivityControlHelper<T> mActivityControlHelper;
private final ActivityInitListener mActivityInitListener; private final ActivityInitListener mActivityInitListener;
@@ -199,6 +210,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
InputConsumerController.getRecentsAnimationInputConsumer(); InputConsumerController.getRecentsAnimationInputConsumer();
private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper(); private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper();
private final long mTouchTimeMs; private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime; private long mLauncherFrameDrawnTime;
@@ -207,8 +219,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private float mLongSwipeDisplacement = 0; private float mLongSwipeDisplacement = 0;
private LongSwipeHelper mLongSwipeController; private LongSwipeHelper mLongSwipeController;
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, WindowTransformSwipeHandler(int id, RunningTaskInfo runningTaskInfo, Context context,
ActivityControlHelper<T> controller) { long touchTimeMs, ActivityControlHelper<T> controller) {
this.id = id;
mContext = context; mContext = context;
mRunningTaskInfo = runningTaskInfo; mRunningTaskInfo = runningTaskInfo;
mRunningTaskId = runningTaskInfo.id; mRunningTaskId = runningTaskInfo.id;
@@ -453,11 +466,40 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
"Can't change interaction type to " + interactionType); "Can't change interaction type to " + interactionType);
} }
mInteractionType = interactionType; mInteractionType = interactionType;
mRecentsAnimationWrapper.runOnInit(this::shiftAnimationDestinationForQuickscrub);
setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED); setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
// Start the window animation without waiting for launcher. // Start the window animation without waiting for launcher.
animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR); animateToProgress(mCurrentShift.value, 1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR);
}
private void shiftAnimationDestinationForQuickscrub() {
TransformedRect tempRect = new TransformedRect();
mActivityControlHelper
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect);
float offsetY =
mActivityControlHelper.getTranslationYForQuickScrub(tempRect, mDp, mContext);
float scale, offsetX;
Resources res = mContext.getResources();
if (ActivityManagerWrapper.getInstance().getRecentTasks(2, UserHandle.myUserId()).size()
< 2) {
// There are not enough tasks, we don't need to shift
offsetX = 0;
scale = 1;
} else {
offsetX = res.getDimensionPixelSize(R.dimen.recents_page_spacing)
+ tempRect.rect.width();
float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
res.getDimensionPixelSize(R.dimen.recents_page_spacing);
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
scale = TaskView.getCurveScaleForInterpolation(interpolation);
}
mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
} }
@WorkerThread @WorkerThread
@@ -606,11 +648,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private void handleNormalGestureEnd(float endVelocity, boolean isFling) { private void handleNormalGestureEnd(float endVelocity, boolean isFling) {
long duration = MAX_SWIPE_DURATION; long duration = MAX_SWIPE_DURATION;
final float endShift; final float endShift;
final float startShift;
if (!isFling) { if (!isFling) {
endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted ? 1 : 0; endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted ? 1 : 0;
long expectedDuration = Math.abs(Math.round((endShift - mCurrentShift.value) long expectedDuration = Math.abs(Math.round((endShift - mCurrentShift.value)
* MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER)); * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
duration = Math.min(MAX_SWIPE_DURATION, expectedDuration); duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
startShift = mCurrentShift.value;
} else { } else {
endShift = endVelocity < 0 ? 1 : 0; endShift = endVelocity < 0 ? 1 : 0;
float minFlingVelocity = mContext.getResources() float minFlingVelocity = mContext.getResources()
@@ -624,9 +668,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / endVelocity)); long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / endVelocity));
duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration); duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
} }
startShift = Utilities.boundToRange(mCurrentShift.value - endVelocity * SINGLE_FRAME_MS
/ (mTransitionDragLength * 1000), 0, 1);
} }
animateToProgress(endShift, duration, DEACCEL); animateToProgress(startShift, endShift, duration, DEACCEL);
} }
private void doLogGesture(boolean toLauncher) { private void doLogGesture(boolean toLauncher) {
@@ -646,9 +692,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
} }
/** Animates to the given progress, where 0 is the current app and 1 is overview. */ /** Animates to the given progress, where 0 is the current app and 1 is overview. */
private void animateToProgress(float progress, long duration, Interpolator interpolator) { private void animateToProgress(float start, float end, long duration,
mIsGoingToHome = Float.compare(progress, 1) == 0; Interpolator interpolator) {
ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration); mIsGoingToHome = Float.compare(end, 1) == 0;
ObjectAnimator anim = mCurrentShift.animateToValue(start, end).setDuration(duration);
anim.setInterpolator(interpolator); anim.setInterpolator(interpolator);
anim.addListener(new AnimationSuccessListener() { anim.addListener(new AnimationSuccessListener() {
@Override @Override
@@ -658,7 +705,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
: STATE_SCALED_CONTROLLER_APP); : STATE_SCALED_CONTROLLER_APP);
} }
}); });
anim.start(); mRecentsAnimationWrapper.runOnInit(anim::start);
} }
@UiThread @UiThread
@@ -700,6 +747,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mRecentsView.setRunningTaskHidden(false); mRecentsView.setRunningTaskHidden(false);
mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */); mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
mQuickScrubController.cancelActiveQuickscrub();
} }
private void notifyTransitionCancelled() { private void notifyTransitionCancelled() {
@@ -785,30 +833,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
// Inform the last progress in case we skipped before. // Inform the last progress in case we skipped before.
mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress); mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
// Make sure the window follows the first task if it moves, e.g. during quick scrub.
TaskView firstTask = mRecentsView.getPageAt(0);
// The first task may be null if we are swiping up from a task that does not
// appear in the list (i.e. the assistant)
if (firstTask != null) {
int scrollForFirstTask = mRecentsView.getScrollForPage(0);
int scrollForSecondTask = mRecentsView.getChildCount() > 1
? mRecentsView.getScrollForPage(1) : scrollForFirstTask;
float offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask;
TransformedRect tempRect = new TransformedRect();
mActivityControlHelper
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
float interpolation = Math.min(1,
Math.abs(offsetFromFirstTask) / distanceToReachEdge);
mClipAnimationHelper.offsetTarget(
firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask,
mActivityControlHelper.getTranslationYForQuickScrub(mActivity),
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
} }
private void onFinishedTransitionToQuickScrub() { private void onFinishedTransitionToQuickScrub() {
@@ -20,10 +20,8 @@ import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.quickstep.RecentsActivity; import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
@@ -73,21 +71,4 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
// Just use the activity task size for multi-window as well. // Just use the activity task size for multi-window as well.
return false; return false;
} }
@Override
public void addTaskAccessibilityActionsExtra(AccessibilityNodeInfo info) {
info.addAction(
new AccessibilityNodeInfo.AccessibilityAction(
R.string.recents_clear_all,
getContext().getText(R.string.recents_clear_all)));
}
@Override
public boolean performTaskAccessibilityActionExtra(int action) {
if (action == R.string.recents_clear_all) {
dismissAllTasks();
return true;
}
return false;
}
} }
@@ -15,10 +15,9 @@
*/ */
package com.android.quickstep.logging; package com.android.quickstep.logging;
import android.content.Context;
import android.util.Log; import android.util.Log;
import static com.android.launcher3.logging.LoggerUtils.newAction;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET; import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET;
import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE; import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
@@ -27,20 +26,20 @@ import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP; import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.nano.LauncherDumpProto;
import com.android.launcher3.userevent.nano.LauncherLogExtensions;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.systemui.shared.system.LauncherEventUtil;
import com.android.systemui.shared.system.MetricsLoggerCompat; import com.android.systemui.shared.system.MetricsLoggerCompat;
/** /**
* This class handles AOSP MetricsLogger function calls and logging around * This class handles AOSP MetricsLogger function calls and logging around
* quickstep interactions. * quickstep interactions.
*/ */
@SuppressWarnings("unused")
public class UserEventDispatcherExtension extends UserEventDispatcher { public class UserEventDispatcherExtension extends UserEventDispatcher {
private static final String TAG = "UserEventDispatcher"; private static final String TAG = "UserEventDispatcher";
public UserEventDispatcherExtension(Context context) { }
public void logStateChangeAction(int action, int dir, int srcChildTargetType, public void logStateChangeAction(int action, int dir, int srcChildTargetType,
int srcParentContainerType, int dstContainerType, int srcParentContainerType, int dstContainerType,
int pageIndex) { int pageIndex) {
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep.util;
import static com.android.quickstep.util.RemoteAnimationProvider.prepareTargetsForFirstFrame;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
/**
* Animation listener which fades out the closing targets
*/
public class RemoteFadeOutAnimationListener implements AnimatorUpdateListener {
private final RemoteAnimationTargetSet mTarget;
private boolean mFirstFrame = true;
public RemoteFadeOutAnimationListener(RemoteAnimationTargetCompat[] targets) {
mTarget = new RemoteAnimationTargetSet(targets, MODE_CLOSING);
}
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
TransactionCompat t = new TransactionCompat();
if (mFirstFrame) {
prepareTargetsForFirstFrame(mTarget.unfilteredApps, t, MODE_CLOSING);
mFirstFrame = false;
}
float alpha = 1 - valueAnimator.getAnimatedFraction();
for (RemoteAnimationTargetCompat app : mTarget.apps) {
t.setAlpha(app.leash, alpha);
}
t.apply();
}
}
@@ -16,13 +16,11 @@
package com.android.quickstep.views; package com.android.quickstep.views;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button; import android.widget.Button;
public class ClearAllButton extends Button { public class ClearAllButton extends Button {
@@ -37,12 +35,9 @@ public class ClearAllButton extends Button {
} }
@Override @Override
public boolean performAccessibilityAction(int action, Bundle arguments) { public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
final boolean res = super.performAccessibilityAction(action, arguments); super.onInitializeAccessibilityNodeInfo(info);
if (action == ACTION_ACCESSIBILITY_FOCUS) { info.setParent(mRecentsView); // Pretend we are a part of the task carousel.
mRecentsView.revealClearAllButton();
}
return res;
} }
@Override @Override
@@ -39,6 +39,7 @@ import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle; import android.os.UserHandle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@@ -386,7 +387,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private void updateClearAllButtonAlpha() { private void updateClearAllButtonAlpha() {
if (mClearAllButton != null) { if (mClearAllButton != null) {
final float alpha = calculateClearAllButtonAlpha(); final float alpha = calculateClearAllButtonAlpha();
mIsClearAllButtonFullyRevealed = alpha == 1; final boolean revealed = alpha == 1;
if (mIsClearAllButtonFullyRevealed != revealed) {
mIsClearAllButtonFullyRevealed = revealed;
mClearAllButton.setImportantForAccessibility(revealed ?
IMPORTANT_FOR_ACCESSIBILITY_YES :
IMPORTANT_FOR_ACCESSIBILITY_NO);
}
mClearAllButton.setAlpha(alpha * mContentAlpha); mClearAllButton.setAlpha(alpha * mContentAlpha);
} }
} }
@@ -507,6 +514,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
DeviceProfile dp = mActivity.getDeviceProfile(); DeviceProfile dp = mActivity.getDeviceProfile();
getTaskSize(dp, mTempRect); getTaskSize(dp, mTempRect);
// Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub.
mTempRect.top -= mTaskTopMargin; mTempRect.top -= mTaskTopMargin;
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top, setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
dp.availableWidthPx + mInsets.left - mTempRect.right, dp.availableWidthPx + mInsets.left - mTempRect.right,
@@ -1284,8 +1292,31 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
scrollTo(mIsRtl ? 0 : computeMaxScrollX(), 0); scrollTo(mIsRtl ? 0 : computeMaxScrollX(), 0);
} }
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (getChildCount() > 0) {
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
if (!mIsClearAllButtonFullyRevealed && getCurrentPage() == getPageCount() - 1) {
revealClearAllButton();
return true;
}
}
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
if (mIsClearAllButtonFullyRevealed) {
setCurrentPage(getChildCount() - 1);
return true;
}
}
break;
}
}
return super.performAccessibilityAction(action, arguments);
}
@Override @Override
public void addChildrenForAccessibility(ArrayList<View> outChildren) { public void addChildrenForAccessibility(ArrayList<View> outChildren) {
outChildren.add(mClearAllButton);
for (int i = getChildCount() - 1; i >= 0; --i) { for (int i = getChildCount() - 1; i >= 0; --i) {
outChildren.add(getChildAt(i)); outChildren.add(getChildAt(i));
} }
@@ -1295,6 +1326,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info); super.onInitializeAccessibilityNodeInfo(info);
if (getChildCount() > 0) {
info.addAction(mIsClearAllButtonFullyRevealed ?
AccessibilityNodeInfo.ACTION_SCROLL_FORWARD :
AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
info.setScrollable(true);
}
final AccessibilityNodeInfo.CollectionInfo final AccessibilityNodeInfo.CollectionInfo
collectionInfo = AccessibilityNodeInfo.CollectionInfo.obtain( collectionInfo = AccessibilityNodeInfo.CollectionInfo.obtain(
1, getChildCount(), false, 1, getChildCount(), false,
@@ -1306,11 +1344,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public void onInitializeAccessibilityEvent(AccessibilityEvent event) { public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event); super.onInitializeAccessibilityEvent(event);
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { event.setScrollable(getPageCount() > 0);
final int visiblePageNumber = getChildCount() - getCurrentPage() - 1;
event.setFromIndex(visiblePageNumber); if (!mIsClearAllButtonFullyRevealed
event.setToIndex(visiblePageNumber); && event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
event.setItemCount(getChildCount()); final int childCount = getChildCount();
final int[] visibleTasks = getVisibleChildrenRange();
event.setFromIndex(childCount - visibleTasks[1] - 1);
event.setToIndex(childCount - visibleTasks[0] - 1);
event.setItemCount(childCount);
} }
} }
@@ -1325,9 +1367,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return true; return true;
} }
public void addTaskAccessibilityActionsExtra(AccessibilityNodeInfo info) {
}
public boolean performTaskAccessibilityActionExtra(int action) { public boolean performTaskAccessibilityActionExtra(int action) {
return false; return false;
} }
@@ -124,4 +124,9 @@ public class RecentsViewContainer extends InsettableFrameLayout {
return mRecentsView.requestFocus(direction, previouslyFocusedRect) || return mRecentsView.requestFocus(direction, previouslyFocusedRect) ||
super.requestFocus(direction, previouslyFocusedRect); super.requestFocus(direction, previouslyFocusedRect);
} }
@Override
public void addChildrenForAccessibility(ArrayList<View> outChildren) {
outChildren.add(mRecentsView);
}
} }
@@ -28,9 +28,6 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.Path.Direction; import android.graphics.Path.Direction;
import android.graphics.Path.Op; import android.graphics.Path.Op;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
@@ -48,11 +45,6 @@ import com.android.launcher3.views.ScrimView;
*/ */
public class ShelfScrimView extends ScrimView { public class ShelfScrimView extends ScrimView {
private static final int THRESHOLD_ALPHA_DARK = 102;
private static final int THRESHOLD_ALPHA_LIGHT = 46;
private static final int THRESHOLD_ALPHA_SUPER_LIGHT = 128;
private static final int CLEAR_ALL_TASKS = R.string.recents_clear_all;
// In transposed layout, we simply draw a flat color. // In transposed layout, we simply draw a flat color.
private boolean mDrawingFlatColor; private boolean mDrawingFlatColor;
@@ -81,13 +73,7 @@ public class ShelfScrimView extends ScrimView {
mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher); mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher);
mEndAlpha = Color.alpha(mEndScrim); mEndAlpha = Color.alpha(mEndScrim);
if (Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark)) { mThresholdAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha);
mThresholdAlpha = THRESHOLD_ALPHA_DARK;
} else if (Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
mThresholdAlpha = THRESHOLD_ALPHA_SUPER_LIGHT;
} else {
mThresholdAlpha = THRESHOLD_ALPHA_LIGHT;
}
mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius); mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -208,43 +194,4 @@ public class ShelfScrimView extends ScrimView {
mRadius, mRadius, mPaint); mRadius, mRadius, mPaint);
return minTop - mDragHandleSize - top; return minTop - mDragHandleSize - top;
} }
@NonNull
@Override
protected AccessibilityHelper createAccessibilityHelper() {
return new ShelfScrimAccessibilityHelper();
}
protected class ShelfScrimAccessibilityHelper extends AccessibilityHelper {
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId,
AccessibilityNodeInfoCompat node) {
super.onPopulateNodeForVirtualView(virtualViewId, node);
if (mLauncher.isInState(OVERVIEW)) {
final RecentsView overviewPanel = mLauncher.getOverviewPanel();
if (overviewPanel.getChildCount() != 0) {
node.addAction(
new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
CLEAR_ALL_TASKS,
getContext().getText(CLEAR_ALL_TASKS)));
}
}
}
@Override
protected boolean onPerformActionForVirtualView(
int virtualViewId, int action, Bundle arguments) {
if (super.onPerformActionForVirtualView(virtualViewId, action, arguments)) return true;
if (action == CLEAR_ALL_TASKS) {
if (mLauncher.isInState(OVERVIEW)) {
mLauncher.<RecentsView>getOverviewPanel().dismissAllTasks();
}
return true;
}
return false;
}
}
} }
@@ -29,6 +29,7 @@ import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Shader; import android.graphics.Shader;
import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.FloatProperty; import android.util.FloatProperty;
import android.util.Property; import android.util.Property;
@@ -37,8 +38,10 @@ import android.view.View;
import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskOverlayFactory.TaskOverlay; import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task;
@@ -50,6 +53,7 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
public class TaskThumbnailView extends View { public class TaskThumbnailView extends View {
private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256]; private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
private static final LightingColorFilter[] sHighlightFilterCache = new LightingColorFilter[256];
public static final Property<TaskThumbnailView, Float> DIM_ALPHA_MULTIPLIER = public static final Property<TaskThumbnailView, Float> DIM_ALPHA_MULTIPLIER =
new FloatProperty<TaskThumbnailView>("dimAlphaMultiplier") { new FloatProperty<TaskThumbnailView>("dimAlphaMultiplier") {
@@ -68,6 +72,7 @@ public class TaskThumbnailView extends View {
private final BaseActivity mActivity; private final BaseActivity mActivity;
private final TaskOverlay mOverlay; private final TaskOverlay mOverlay;
private final boolean mIsDarkTextTheme;
private final Paint mPaint = new Paint(); private final Paint mPaint = new Paint();
private final Paint mBackgroundPaint = new Paint(); private final Paint mBackgroundPaint = new Paint();
@@ -97,6 +102,7 @@ public class TaskThumbnailView extends View {
mPaint.setFilterBitmap(true); mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE); mBackgroundPaint.setColor(Color.WHITE);
mActivity = BaseActivity.fromContext(context); mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
} }
public void bind() { public void bind() {
@@ -198,7 +204,7 @@ public class TaskThumbnailView extends View {
private void updateThumbnailPaintFilter() { private void updateThumbnailPaintFilter() {
int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255); int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255);
if (mBitmapShader != null) { if (mBitmapShader != null) {
LightingColorFilter filter = getLightingColorFilter(mul); LightingColorFilter filter = getDimmingColorFilter(mul, mIsDarkTextTheme);
mPaint.setColorFilter(filter); mPaint.setColorFilter(filter);
mBackgroundPaint.setColorFilter(filter); mBackgroundPaint.setColorFilter(filter);
} else { } else {
@@ -287,16 +293,25 @@ public class TaskThumbnailView extends View {
updateThumbnailMatrix(); updateThumbnailMatrix();
} }
private static LightingColorFilter getLightingColorFilter(int dimColor) { private static LightingColorFilter getDimmingColorFilter(int intensity, boolean shouldLighten) {
if (dimColor < 0) { intensity = Utilities.boundToRange(intensity, 0, 255);
dimColor = 0; if (intensity == 255) {
} else if (dimColor > 255) { return null;
dimColor = 255;
} }
if (sDimFilterCache[dimColor] == null) { if (shouldLighten) {
sDimFilterCache[dimColor] = if (sHighlightFilterCache[intensity] == null) {
new LightingColorFilter(Color.argb(255, dimColor, dimColor, dimColor), 0); int colorAdd = 255 - intensity;
sHighlightFilterCache[intensity] = new LightingColorFilter(
Color.argb(255, intensity, intensity, intensity),
Color.argb(255, colorAdd, colorAdd, colorAdd));
}
return sHighlightFilterCache[intensity];
} else {
if (sDimFilterCache[intensity] == null) {
sDimFilterCache[intensity] = new LightingColorFilter(
Color.argb(255, intensity, intensity, intensity), 0);
}
return sDimFilterCache[intensity];
} }
return sDimFilterCache[dimColor];
} }
} }
@@ -250,12 +250,12 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f); setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
} }
public float getCurveScaleForInterpolation(float linearInterpolation) { public static float getCurveScaleForInterpolation(float linearInterpolation) {
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation); float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
return getCurveScaleForCurveInterpolation(curveInterpolation); return getCurveScaleForCurveInterpolation(curveInterpolation);
} }
private float getCurveScaleForCurveInterpolation(float curveInterpolation) { private static float getCurveScaleForCurveInterpolation(float curveInterpolation) {
return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR; return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
} }
@@ -321,8 +321,6 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
} }
final RecentsView recentsView = getRecentsView(); final RecentsView recentsView = getRecentsView();
recentsView.addTaskAccessibilityActionsExtra(info);
final AccessibilityNodeInfo.CollectionItemInfo itemInfo = final AccessibilityNodeInfo.CollectionItemInfo itemInfo =
AccessibilityNodeInfo.CollectionItemInfo.obtain( AccessibilityNodeInfo.CollectionItemInfo.obtain(
0, 1, recentsView.getChildCount() - recentsView.indexOfChild(this) - 1, 1, 0, 1, recentsView.getChildCount() - recentsView.indexOfChild(this) - 1, 1,
+1
View File
@@ -22,4 +22,5 @@
android:clipToPadding="false" android:clipToPadding="false"
android:clipChildren="false" android:clipChildren="false"
android:elevation="@dimen/deep_shortcuts_elevation" android:elevation="@dimen/deep_shortcuts_elevation"
android:importantForAccessibility="yes"
android:orientation="vertical" /> android:orientation="vertical" />
+1
View File
@@ -20,6 +20,7 @@
<!-- Attributes used for launcher theme --> <!-- Attributes used for launcher theme -->
<attr name="allAppsScrimColor" format="color" /> <attr name="allAppsScrimColor" format="color" />
<attr name="allAppsInterimScrimAlpha" format="integer" />
<attr name="allAppsNavBarScrimColor" format="color" /> <attr name="allAppsNavBarScrimColor" format="color" />
<attr name="popupColorPrimary" format="color" /> <attr name="popupColorPrimary" format="color" />
<attr name="popupColorSecondary" format="color" /> <attr name="popupColorSecondary" format="color" />
+4
View File
@@ -29,6 +29,7 @@
<style name="BaseLauncherThemeWithCustomAttrs" parent="@style/BaseLauncherTheme"> <style name="BaseLauncherThemeWithCustomAttrs" parent="@style/BaseLauncherTheme">
<item name="allAppsScrimColor">#EAFFFFFF</item> <item name="allAppsScrimColor">#EAFFFFFF</item>
<item name="allAppsInterimScrimAlpha">46</item>
<item name="allAppsNavBarScrimColor">#66FFFFFF</item> <item name="allAppsNavBarScrimColor">#66FFFFFF</item>
<item name="popupColorPrimary">#FFF</item> <item name="popupColorPrimary">#FFF</item>
<item name="popupColorSecondary">#F5F5F5</item> <!-- Gray 100 --> <item name="popupColorSecondary">#F5F5F5</item> <!-- Gray 100 -->
@@ -47,6 +48,7 @@
<style name="LauncherTheme.DarkText" parent="@style/LauncherTheme"> <style name="LauncherTheme.DarkText" parent="@style/LauncherTheme">
<item name="workspaceTextColor">#FF212121</item> <item name="workspaceTextColor">#FF212121</item>
<item name="allAppsInterimScrimAlpha">128</item>
<item name="workspaceShadowColor">@android:color/transparent</item> <item name="workspaceShadowColor">@android:color/transparent</item>
<item name="workspaceAmbientShadowColor">@android:color/transparent</item> <item name="workspaceAmbientShadowColor">@android:color/transparent</item>
<item name="workspaceKeyShadowColor">@android:color/transparent</item> <item name="workspaceKeyShadowColor">@android:color/transparent</item>
@@ -62,6 +64,7 @@
<item name="android:colorControlHighlight">#A0FFFFFF</item> <item name="android:colorControlHighlight">#A0FFFFFF</item>
<item name="android:colorPrimary">#FF212121</item> <item name="android:colorPrimary">#FF212121</item>
<item name="allAppsScrimColor">#EA212121</item> <item name="allAppsScrimColor">#EA212121</item>
<item name="allAppsInterimScrimAlpha">102</item>
<item name="allAppsNavBarScrimColor">#80000000</item> <item name="allAppsNavBarScrimColor">#80000000</item>
<item name="popupColorPrimary">?android:attr/colorPrimary</item> <item name="popupColorPrimary">?android:attr/colorPrimary</item>
<item name="popupColorSecondary">#424242</item> <!-- Gray 800 --> <item name="popupColorSecondary">#424242</item> <!-- Gray 800 -->
@@ -71,6 +74,7 @@
</style> </style>
<style name="LauncherThemeDark.DarKText" parent="@style/LauncherThemeDark"> <style name="LauncherThemeDark.DarKText" parent="@style/LauncherThemeDark">
<item name="allAppsInterimScrimAlpha">25</item>
<item name="workspaceTextColor">#FF212121</item> <item name="workspaceTextColor">#FF212121</item>
<item name="workspaceShadowColor">@android:color/transparent</item> <item name="workspaceShadowColor">@android:color/transparent</item>
<item name="workspaceAmbientShadowColor">@android:color/transparent</item> <item name="workspaceAmbientShadowColor">@android:color/transparent</item>
@@ -17,7 +17,6 @@
package com.android.launcher3; package com.android.launcher3;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE; import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE; import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
@@ -222,7 +221,8 @@ public class LauncherStateManager {
} }
} }
// Cancel the current animation // Cancel the current animation. This will reset mState to mCurrentStableState, so store it.
LauncherState fromState = mState;
mConfig.reset(); mConfig.reset();
if (!animated) { if (!animated) {
@@ -245,10 +245,10 @@ public class LauncherStateManager {
// Since state NORMAL can be reached from multiple states, just assume that the // Since state NORMAL can be reached from multiple states, just assume that the
// transition plays in reverse and use the same duration as previous state. // transition plays in reverse and use the same duration as previous state.
mConfig.duration = state == NORMAL ? mState.transitionDuration : state.transitionDuration; mConfig.duration = state == NORMAL ? fromState.transitionDuration : state.transitionDuration;
AnimatorSetBuilder builder = new AnimatorSetBuilder(); AnimatorSetBuilder builder = new AnimatorSetBuilder();
prepareForAtomicAnimation(mState, state, builder); prepareForAtomicAnimation(fromState, state, builder);
AnimatorSet animation = createAnimationToNewWorkspaceInternal( AnimatorSet animation = createAnimationToNewWorkspaceInternal(
state, builder, onCompleteRunnable); state, builder, onCompleteRunnable);
Runnable runnable = new StartAnimRunnable(animation); Runnable runnable = new StartAnimRunnable(animation);
@@ -347,6 +347,12 @@ public class LauncherStateManager {
} }
} }
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
mState = mCurrentStableState;
}
@Override @Override
public void onAnimationSuccess(Animator animator) { public void onAnimationSuccess(Animator animator) {
// Run any queued runnables // Run any queued runnables
@@ -432,7 +438,6 @@ public class LauncherStateManager {
} }
public void setCurrentUserControlledAnimation(AnimatorPlaybackController controller) { public void setCurrentUserControlledAnimation(AnimatorPlaybackController controller) {
clearCurrentAnimation();
setCurrentAnimation(controller.getTarget()); setCurrentAnimation(controller.getTarget());
mConfig.userControlled = true; mConfig.userControlled = true;
mConfig.playbackController = controller; mConfig.playbackController = controller;
+35
View File
@@ -152,6 +152,8 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
// Similar to the platform implementation of isLayoutValid(); // Similar to the platform implementation of isLayoutValid();
protected boolean mIsLayoutValid; protected boolean mIsLayoutValid;
private int[] mTmpIntPair = new int[2];
public PagedView(Context context) { public PagedView(Context context) {
this(context, null); this(context, null);
} }
@@ -1448,6 +1450,10 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate, protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate,
TimeInterpolator interpolator) { TimeInterpolator interpolator) {
if (mFirstLayout) {
setCurrentPage(whichPage);
return false;
}
if (FeatureFlags.IS_DOGFOOD_BUILD) { if (FeatureFlags.IS_DOGFOOD_BUILD) {
duration *= Settings.System.getFloat(getContext().getContentResolver(), duration *= Settings.System.getFloat(getContext().getContentResolver(),
@@ -1600,4 +1606,33 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
boolean shouldIncludeView(View view); boolean shouldIncludeView(View view);
} }
public int[] getVisibleChildrenRange() {
float visibleLeft = 0;
float visibleRight = visibleLeft + getMeasuredWidth();
float scaleX = getScaleX();
if (scaleX < 1 && scaleX > 0) {
float mid = getMeasuredWidth() / 2;
visibleLeft = mid - ((mid - visibleLeft) / scaleX);
visibleRight = mid + ((visibleRight - mid) / scaleX);
}
int leftChild = -1;
int rightChild = -1;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getPageAt(i);
float left = child.getLeft() + child.getTranslationX() - getScrollX();
if (left <= visibleRight && (left + child.getMeasuredWidth()) >= visibleLeft) {
if (leftChild == -1) {
leftChild = i;
}
rightChild = i;
}
}
mTmpIntPair[0] = leftChild;
mTmpIntPair[1] = rightChild;
return mTmpIntPair;
}
} }
+3 -22
View File
@@ -1381,28 +1381,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
if (mChildrenLayersEnabled) { if (mChildrenLayersEnabled) {
final int screenCount = getChildCount(); final int screenCount = getChildCount();
float visibleLeft = 0; final int[] visibleScreens = getVisibleChildrenRange();
float visibleRight = visibleLeft + getMeasuredWidth(); int leftScreen = visibleScreens[0];
float scaleX = getScaleX(); int rightScreen = visibleScreens[1];
if (scaleX < 1 && scaleX > 0) {
float mid = getMeasuredWidth() / 2;
visibleLeft = mid - ((mid - visibleLeft) / scaleX);
visibleRight = mid + ((visibleRight - mid) / scaleX);
}
int leftScreen = -1;
int rightScreen = -1;
for (int i = 0; i < screenCount; i++) {
final View child = getPageAt(i);
float left = child.getLeft() + child.getTranslationX() - getScrollX();
if (left <= visibleRight && (left + child.getMeasuredWidth()) >= visibleLeft) {
if (leftScreen == -1) {
leftScreen = i;
}
rightScreen = i;
}
}
if (mForceDrawAdjacentPages) { if (mForceDrawAdjacentPages) {
// In overview mode, make sure that the two side pages are visible. // In overview mode, make sure that the two side pages are visible.
leftScreen = Utilities.boundToRange(getCurrentPage() - 1, 0, rightScreen); leftScreen = Utilities.boundToRange(getCurrentPage() - 1, 0, rightScreen);
@@ -466,9 +466,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
*/ */
public void addSpringFromFlingUpdateListener(ValueAnimator animator, float velocity) { public void addSpringFromFlingUpdateListener(ValueAnimator animator, float velocity) {
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
boolean shouldSpring = true;
@Override @Override
public void onAnimationUpdate(ValueAnimator valueAnimator) { public void onAnimationUpdate(ValueAnimator valueAnimator) {
if (valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) { if (shouldSpring
&& valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
int searchViewId = getSearchView().getId(); int searchViewId = getSearchView().getId();
addSpringView(searchViewId); addSpringView(searchViewId);
@@ -481,7 +484,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
} }
}); });
animator.removeUpdateListener(this); shouldSpring = false;
} }
} }
}); });
@@ -159,7 +159,7 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen
postCleanup(); postCleanup();
} }
private void postCleanup() { protected void postCleanup() {
clearReference(); clearReference();
if (mLauncher != null) { if (mLauncher != null) {
// Remove any drag params from the launcher intent since the drag operation is complete. // Remove any drag params from the launcher intent since the drag operation is complete.
@@ -22,14 +22,17 @@ import android.content.pm.LauncherApps.PinItemRequest;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.CancellationSignal;
import android.view.DragEvent; import android.view.DragEvent;
import android.view.View; import android.view.View;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import com.android.launcher3.DragSource; import com.android.launcher3.DragSource;
import com.android.launcher3.ItemInfo; import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.PendingAddItemInfo; import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo; import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -44,11 +47,13 @@ import com.android.launcher3.widget.WidgetAddFlowHandler;
public class PinItemDragListener extends BaseItemDragListener { public class PinItemDragListener extends BaseItemDragListener {
private final PinItemRequest mRequest; private final PinItemRequest mRequest;
private final CancellationSignal mCancelSignal;
public PinItemDragListener(PinItemRequest request, Rect previewRect, public PinItemDragListener(PinItemRequest request, Rect previewRect,
int previewBitmapWidth, int previewViewWidth) { int previewBitmapWidth, int previewViewWidth) {
super(previewRect, previewBitmapWidth, previewViewWidth); super(previewRect, previewBitmapWidth, previewViewWidth);
mRequest = request; mRequest = request;
mCancelSignal = new CancellationSignal();
} }
@Override @Override
@@ -59,6 +64,15 @@ public class PinItemDragListener extends BaseItemDragListener {
return super.onDragStart(event); return super.onDragStart(event);
} }
@Override
public boolean init(Launcher launcher, boolean alreadyOnHome) {
super.init(launcher, alreadyOnHome);
if (!alreadyOnHome) {
UiFactory.useFadeOutAnimationForLauncherStart(launcher, mCancelSignal);
}
return false;
}
@Override @Override
protected PendingItemDragHelper createDragHelper() { protected PendingItemDragHelper createDragHelper() {
final PendingAddItemInfo item; final PendingAddItemInfo item;
@@ -95,6 +109,12 @@ public class PinItemDragListener extends BaseItemDragListener {
targetParent.containerType = LauncherLogProto.ContainerType.PINITEM; targetParent.containerType = LauncherLogProto.ContainerType.PINITEM;
} }
@Override
protected void postCleanup() {
super.postCleanup();
mCancelSignal.cancel();
}
public static RemoteViews getPreview(PinItemRequest request) { public static RemoteViews getPreview(PinItemRequest request) {
Bundle extras = request.getExtras(); Bundle extras = request.getExtras();
if (extras != null && if (extras != null &&
@@ -330,9 +330,9 @@ public class LauncherIcons implements AutoCloseable {
mOldBounds.set(icon.getBounds()); mOldBounds.set(icon.getBounds());
if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) { if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
int offset = Math.max((int)(BLUR_FACTOR * textureWidth), Math.min(left, top)); int offset = Math.max((int) Math.ceil(BLUR_FACTOR * textureWidth), Math.max(left, top));
int size = Math.max(width, height); int size = Math.max(width, height);
icon.setBounds(offset, offset, size, size); icon.setBounds(offset, offset, offset + size, offset + size);
} else { } else {
icon.setBounds(left, top, left+width, top+height); icon.setBounds(left, top, left+width, top+height);
} }
@@ -18,7 +18,6 @@ package com.android.launcher3.keyboard;
import android.graphics.Rect; import android.graphics.Rect;
import android.view.View; import android.view.View;
import android.view.View.OnFocusChangeListener;
import com.android.launcher3.PagedView; import com.android.launcher3.PagedView;
@@ -52,8 +51,8 @@ public class ViewGroupFocusHelper extends FocusIndicatorHelper {
private void computeLocationRelativeToContainer(View child, Rect outRect) { private void computeLocationRelativeToContainer(View child, Rect outRect) {
View parent = (View) child.getParent(); View parent = (View) child.getParent();
outRect.left += child.getLeft(); outRect.left += child.getX();
outRect.top += child.getTop(); outRect.top += child.getY();
if (parent != mContainer) { if (parent != mContainer) {
if (parent instanceof PagedView) { if (parent instanceof PagedView) {
@@ -64,22 +63,4 @@ public class ViewGroupFocusHelper extends FocusIndicatorHelper {
computeLocationRelativeToContainer(parent, outRect); computeLocationRelativeToContainer(parent, outRect);
} }
} }
/**
* Sets the alpha of this FocusIndicatorHelper to 0 when a view with this listener
* receives focus.
*/
public View.OnFocusChangeListener getHideIndicatorOnFocusListener() {
return new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
endCurrentAnimation();
setCurrentView(null);
setAlpha(0);
invalidateDirty();
}
}
};
}
} }
@@ -527,6 +527,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
protected void closeComplete() { protected void closeComplete() {
super.closeComplete(); super.closeComplete();
mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible()); mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible());
mOriginalIcon.forceHideBadge(false);
} }
@Override @Override
@@ -142,6 +142,8 @@ public class ImportDataTask {
// First row of first screen is not empty // First row of first screen is not empty
createEmptyRowOnFirstScreen = c.moveToNext(); createEmptyRowOnFirstScreen = c.moveToNext();
} }
} else {
createEmptyRowOnFirstScreen = false;
} }
ArrayList<ContentProviderOperation> insertOperations = new ArrayList<>(BATCH_INSERT_SIZE); ArrayList<ContentProviderOperation> insertOperations = new ArrayList<>(BATCH_INSERT_SIZE);
@@ -36,7 +36,6 @@ import android.widget.FrameLayout;
import com.android.launcher3.AppWidgetResizeFrame; import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
@@ -68,6 +67,10 @@ public class QsbContainerView extends FrameLayout {
super.setPadding(0, 0, 0, 0); super.setPadding(0, 0, 0, 0);
} }
protected void setPaddingUnchecked(int left, int top, int right, int bottom) {
super.setPadding(left, top, right, bottom);
}
/** /**
* A fragment to display the QSB. * A fragment to display the QSB.
*/ */
@@ -100,7 +103,7 @@ public class QsbContainerView extends FrameLayout {
mWrapper = new FrameLayout(getActivity()); mWrapper = new FrameLayout(getActivity());
// Only add the view when enabled // Only add the view when enabled
if (FeatureFlags.QSB_ON_FIRST_SCREEN) { if (isQsbEnabled()) {
mWrapper.addView(createQsb(mWrapper)); mWrapper.addView(createQsb(mWrapper));
} }
return mWrapper; return mWrapper;
@@ -212,7 +215,7 @@ public class QsbContainerView extends FrameLayout {
private void rebindFragment() { private void rebindFragment() {
// Exit if the embedded qsb is disabled // Exit if the embedded qsb is disabled
if (!FeatureFlags.QSB_ON_FIRST_SCREEN) { if (!isQsbEnabled()) {
return; return;
} }
@@ -221,6 +224,10 @@ public class QsbContainerView extends FrameLayout {
mWrapper.addView(createQsb(mWrapper)); mWrapper.addView(createQsb(mWrapper));
} }
} }
public boolean isQsbEnabled() {
return FeatureFlags.QSB_ON_FIRST_SCREEN;
}
} }
/** /**
@@ -52,6 +52,13 @@ public class Themes {
return value; return value;
} }
public static int getAttrInteger(Context context, int attr) {
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
int value = ta.getInteger(0, 0);
ta.recycle();
return value;
}
/** /**
* Returns the alpha corresponding to the theme attribute {@param attr}, in the range [0, 255]. * Returns the alpha corresponding to the theme attribute {@param attr}, in the range [0, 255].
*/ */
@@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.CancellationSignal;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -51,6 +52,9 @@ public class UiFactory {
public static void onTrimMemory(Launcher launcher, int level) { } public static void onTrimMemory(Launcher launcher, int level) { }
public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
CancellationSignal cancellationSignal) { }
public static boolean dumpActivity(Activity activity, PrintWriter writer) { public static boolean dumpActivity(Activity activity, PrintWriter writer) {
return false; return false;
} }