Merge "Inherit TextAppearance.DeviceDefault for the RRO text font" into ub-launcher3-master
diff --git a/Android.mk b/Android.mk
index 628b632..74b96d4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -319,7 +319,7 @@
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_PROGUARD_ENABLED := full
-LOCAL_PACKAGE_NAME := Launcher3QuickStepGoIconRecents
+LOCAL_PACKAGE_NAME := Launcher3GoIconRecents
LOCAL_PRIVILEGED_MODULE := true
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 Launcher3QuickStep
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3
diff --git a/SecondaryDisplayLauncher/res/values-ta/strings.xml b/SecondaryDisplayLauncher/res/values-ta/strings.xml
index 2f1262f..6bb054a 100644
--- a/SecondaryDisplayLauncher/res/values-ta/strings.xml
+++ b/SecondaryDisplayLauncher/res/values-ta/strings.xml
@@ -20,6 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="couldnt_launch" msgid="7873588052226763866">"நடவடிக்கையைத் துவக்க இயலவில்லை"</string>
- <string name="add_app_shortcut" msgid="2756755330707509435">"ஆப்ஸ் குறுக்குவழியைச் சேர்"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ஆப்ஸ் ஷார்ட்கட்டைச் சேர்"</string>
<string name="set_wallpaper" msgid="6475195450505435904">"வால்பேப்பரை அமை"</string>
</resources>
diff --git a/go/quickstep/res/layout/fallback_recents_activity.xml b/go/quickstep/res/layout/fallback_recents_activity.xml
new file mode 100644
index 0000000..653f463
--- /dev/null
+++ b/go/quickstep/res/layout/fallback_recents_activity.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2019 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.quickstep.fallback.GoRecentsActivityRootView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drag_layer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
+
+ <include
+ android:id="@+id/overview_panel"
+ layout="@layout/overview_panel"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:outlineProvider="none"
+ android:theme="@style/HomeScreenElementTheme" />
+</com.android.quickstep.fallback.GoRecentsActivityRootView>
diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml
index 82d5890..6c50950 100644
--- a/go/quickstep/res/layout/icon_recents_root_view.xml
+++ b/go/quickstep/res/layout/icon_recents_root_view.xml
@@ -18,13 +18,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="center">
- <!-- TODO(114136250): Remove this temporary placeholder view for Go recents -->
- <TextView
+ android:orientation="vertical">
+ <androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/recent_task_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="center"
- android:text="Stub!"
- android:textSize="40sp"/>
+ android:scrollbars="none"/>
</com.android.quickstep.views.IconRecentsView>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java b/go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java
index 95d8c4e..96b4ae5 100644
--- a/go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java
+++ b/go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java
@@ -29,18 +29,6 @@
}
@Override
- protected boolean isQuickSwitchInProgress() {
- // Go does not support quick scrub.
- return false;
- }
-
- @Override
- protected ActivityOptions getQuickSwitchActivityOptions() {
- // Go does not support quick scrub.
- return null;
- }
-
- @Override
protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v,
RemoteAnimationTargetCompat[] targets, boolean launcherClosing) {
//TODO: Implement this based off IconRecentsView
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/go/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 6144d69..afc8e47 100644
--- a/go/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -50,11 +50,6 @@
}
@Override
- public void onStateDisabled(Launcher launcher) {
- RecentsModel.INSTANCE.get(launcher).resetAssistCache();
- }
-
- @Override
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
return new PageAlphaProvider(DEACCEL_2) {
@Override
diff --git a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
new file mode 100644
index 0000000..f199643
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.util.Log;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+/**
+ * Provider for the atomic remote window animation from the app to the overview.
+ *
+ * @param <T> activity that contains the overview
+ */
+final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements
+ RemoteAnimationProvider {
+
+ private static final long RECENTS_LAUNCH_DURATION = 250;
+ private static final String TAG = "AppToOverviewAnimationProvider";
+
+ private final ActivityControlHelper<T> mHelper;
+
+ AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) {
+ mHelper = helper;
+ }
+
+ /**
+ * Callback for when the activity is ready/initialized.
+ *
+ * @param activity the activity that is ready
+ * @param wasVisible true if it was visible before
+ */
+ boolean onActivityReady(T activity, Boolean wasVisible) {
+ ActivityControlHelper.AnimationFactory factory =
+ mHelper.prepareRecentsUI(activity, wasVisible,
+ false /* animate activity */, (controller) -> {
+ controller.dispatchOnStart();
+ ValueAnimator anim = controller.getAnimationPlayer()
+ .setDuration(RECENTS_LAUNCH_DURATION);
+ anim.setInterpolator(FAST_OUT_SLOW_IN);
+ anim.start();
+ });
+ factory.onRemoteAnimationReceived(null);
+ factory.createActivityController(RECENTS_LAUNCH_DURATION);
+ return false;
+ }
+
+ /**
+ * Create remote window animation from the currently running app to the overview panel.
+ *
+ * @param targetCompats the target apps
+ * @return animation from app to overview
+ */
+ @Override
+ public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
+ //TODO: Implement the overview to app window animation for Go.
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(ValueAnimator.ofInt(0, 1).setDuration(RECENTS_LAUNCH_DURATION));
+ return anim;
+ }
+
+ /**
+ * Get duration of animation from app to overview.
+ *
+ * @return duration of animation
+ */
+ long getRecentsLaunchDuration() {
+ return RECENTS_LAUNCH_DURATION;
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
new file mode 100644
index 0000000..abb9242
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.graphics.Rect;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.views.IconRecentsView;
+
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+/**
+ * {@link ActivityControlHelper} for recents when the default launcher is different than the
+ * currently running one and apps should interact with the {@link RecentsActivity} as opposed
+ * to the in-launcher one.
+ */
+public final class FallbackActivityControllerHelper extends
+ GoActivityControlHelper<RecentsActivity> {
+
+ public FallbackActivityControllerHelper() { }
+
+ @Override
+ public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible,
+ boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
+ if (activityVisible) {
+ return (transitionLength) -> { };
+ }
+
+ IconRecentsView rv = activity.getOverviewPanel();
+ rv.setAlpha(0);
+
+ return new AnimationFactory() {
+
+ boolean isAnimatingToRecents = false;
+
+ @Override
+ public void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) {
+ isAnimatingToRecents = targets != null && targets.isAnimatingHome();
+ if (!isAnimatingToRecents) {
+ rv.setAlpha(1);
+ }
+ createActivityController(getSwipeUpDestinationAndLength(
+ activity.getDeviceProfile(), activity, new Rect()));
+ }
+
+ @Override
+ public void createActivityController(long transitionLength) {
+ if (!isAnimatingToRecents) {
+ return;
+ }
+
+ ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1);
+ anim.setDuration(transitionLength).setInterpolator(LINEAR);
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.play(anim);
+ callback.accept(AnimatorPlaybackController.wrap(animatorSet, transitionLength));
+ }
+ };
+ }
+
+ @Override
+ public ActivityInitListener createActivityInitListener(
+ BiPredicate<RecentsActivity, Boolean> onInitListener) {
+ return new RecentsActivityTracker(onInitListener);
+ }
+
+ @Nullable
+ @Override
+ public RecentsActivity getCreatedActivity() {
+ return RecentsActivityTracker.getCurrentActivity();
+ }
+
+ @Nullable
+ @Override
+ public IconRecentsView getVisibleRecentsView() {
+ RecentsActivity activity = getCreatedActivity();
+ if (activity != null && activity.hasWindowFocus()) {
+ return activity.getOverviewPanel();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
+ return false;
+ }
+
+ @Override
+ public AlphaProperty getAlphaProperty(RecentsActivity activity) {
+ return activity.getDragLayer().getAlphaProperty(0);
+ }
+
+ @Override
+ public int getContainerType() {
+ return LauncherLogProto.ContainerType.SIDELOADED_LAUNCHER;
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java b/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java
new file mode 100644
index 0000000..7078871
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java
@@ -0,0 +1,59 @@
+package com.android.quickstep;
+
+import android.content.Context;
+import android.graphics.Rect;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+/**
+ * Base activity control helper for Go that stubs out most of the functionality that is not needed
+ * for Go.
+ *
+ * @param <T> activity that contains the overview
+ */
+public abstract class GoActivityControlHelper<T extends BaseDraggingActivity> implements
+ ActivityControlHelper<T> {
+
+ @Override
+ public void onTransitionCancelled(T activity, boolean activityVisible) {
+ // Go transitions to overview are all atomic.
+ }
+
+ @Override
+ public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
+ // TODO Implement outRect depending on where the task should animate to.
+ // Go does not support swipe up gesture.
+ return 0;
+ }
+
+ @Override
+ public void onSwipeUpComplete(T activity) {
+ // Go does not support swipe up gesture.
+ }
+
+ @Override
+ public HomeAnimationFactory prepareHomeUI(T activity) {
+ // Go does not support gestures from app to home.
+ return null;
+ }
+
+ @Override
+ public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
+ // Go does not support gestures to overview.
+ return null;
+ }
+
+ @Override
+ public boolean shouldMinimizeSplitScreen() {
+ // Go does not support split screen.
+ return true;
+ }
+
+ @Override
+ public boolean isInLiveTileMode() {
+ // Go does not support live tiles.
+ return false;
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java
index e1df3ba..76685f3 100644
--- a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -18,81 +18,23 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.graphics.Rect;
-
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListener;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
-import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.IconRecentsView;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
/**
- * {@link ActivityControlHelper} for the in-launcher recents. As Go does not support most gestures
- * from app to overview/home, most of this class is stubbed out.
+ * {@link ActivityControlHelper} for the in-launcher recents.
* TODO: Implement the app to overview animation functionality
*/
-public final class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher>{
-
- @Override
- public LayoutListener createLayoutListener(Launcher activity) {
- // Go does not have draggable task snapshots.
- return null;
- }
-
- @Override
- public void onQuickInteractionStart(Launcher activity, ActivityManager.RunningTaskInfo taskInfo,
- boolean activityVisible, TouchInteractionLog touchInteractionLog) {
- // Go does not have quick interactions.
- }
-
- @Override
- public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
- Context context) {
- // Go does not have quick scrub.
- return 0;
- }
-
- @Override
- public void executeOnWindowAvailable(Launcher activity, Runnable action) {
- // Go does not support live tiles.
- }
-
- @Override
- public void onTransitionCancelled(Launcher activity, boolean activityVisible) {
- LauncherState startState = activity.getStateManager().getRestState();
- activity.getStateManager().goToState(startState, activityVisible);
- }
-
- @Override
- public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context,
- int interactionType, TransformedRect outRect) {
- // TODO Implement outRect depending on where the task should animate to.
- // Go does not support swipe up gesture.
- return 0;
- }
-
- @Override
- public void onSwipeUpComplete(Launcher activity) {
- // Go does not support swipe up gesture.
- }
-
- @Override
- public HomeAnimationFactory prepareHomeUI(Launcher activity) {
- // Go does not support gestures from app to home.
- return null;
- }
+public final class LauncherActivityControllerHelper extends GoActivityControlHelper<Launcher> {
@Override
public AnimationFactory prepareRecentsUI(Launcher activity,
@@ -101,8 +43,7 @@
//TODO: Implement this based off where the recents view needs to be for app => recents anim.
return new AnimationFactory() {
@Override
- public void createActivityController(long transitionLength,
- @TouchConsumer.InteractionType int interactionType) {}
+ public void createActivityController(long transitionLength) {}
@Override
public void onTransitionCancelled() {}
@@ -138,64 +79,29 @@
}
@Override
- public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
+ public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
Launcher launcher = getVisibleLauncher();
if (launcher == null) {
return false;
}
- if (fromRecentsButton) {
- launcher.getUserEventDispatcher().logActionCommand(
- LauncherLogProto.Action.Command.RECENTS_BUTTON,
- getContainerType(),
- LauncherLogProto.ContainerType.TASKSWITCHER);
- }
- launcher.getStateManager().goToState(OVERVIEW);
+ launcher.getUserEventDispatcher().logActionCommand(
+ LauncherLogProto.Action.Command.RECENTS_BUTTON,
+ getContainerType(),
+ LauncherLogProto.ContainerType.TASKSWITCHER);
+ launcher.getStateManager().goToState(OVERVIEW,
+ launcher.getStateManager().shouldAnimateStateChange(), onCompleteCallback);
return true;
}
@Override
- public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
- return homeBounds;
- }
-
- @Override
- public boolean shouldMinimizeSplitScreen() {
- return true;
- }
-
- @Override
- public boolean deferStartingActivity(int downHitTarget) {
- // Go only supports back to overview so we always defer starting activity.
- return true;
- }
-
- @Override
- public boolean supportsLongSwipe(Launcher activity) {
- // Go does not support long swipe from the app.
- return false;
- }
-
- @Override
public AlphaProperty getAlphaProperty(Launcher activity) {
return activity.getDragLayer().getAlphaProperty(DragLayer.ALPHA_INDEX_SWIPE_UP);
}
@Override
- public LongSwipeHelper getLongSwipeController(Launcher activity, int runningTaskId) {
- // Go does not support long swipe from the app.
- return null;
- }
-
- @Override
public int getContainerType() {
final Launcher launcher = getVisibleLauncher();
return launcher != null ? launcher.getStateManager().getState().containerType
: LauncherLogProto.ContainerType.APP;
}
-
- @Override
- public boolean isInLiveTileMode() {
- // Go does not support live tiles.
- return false;
- }
}
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
similarity index 86%
rename from quickstep/src/com/android/quickstep/OverviewCommandHelper.java
rename to go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 5b4f673..d9873fe 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -30,7 +30,7 @@
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
-import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.IconRecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -67,10 +67,14 @@
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
}
- public void onOverviewShown() {
+ public void onOverviewShown(boolean triggeredFromAltTab) {
mMainThreadExecutor.execute(new ShowRecentsCommand());
}
+ public void onOverviewHidden() {
+ mMainThreadExecutor.execute(new HideRecentsCommand());
+ }
+
public void onTip(int actionType, int viewType) {
mMainThreadExecutor.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
@@ -84,6 +88,19 @@
}
}
+ private class HideRecentsCommand extends RecentsActivityCommand {
+
+ @Override
+ protected boolean handleCommand(long elapsedTime) {
+ IconRecentsView recents = (IconRecentsView) mHelper.getVisibleRecentsView();
+ if (recents == null) {
+ return false;
+ }
+ //TODO: Launch last running task or go to home.
+ return true;
+ }
+ }
+
private class RecentsActivityCommand<T extends BaseDraggingActivity> implements Runnable {
protected final ActivityControlHelper<T> mHelper;
@@ -114,7 +131,7 @@
return;
}
- if (mHelper.switchToRecentsIfVisible(true)) {
+ if (mHelper.switchToRecentsIfVisible(null /* onCompleteCallback */)) {
// If successfully switched, then return
return;
}
@@ -127,13 +144,9 @@
}
protected boolean handleCommand(long elapsedTime) {
- // TODO: We need to fix this case with PIP, when an activity first enters PIP, it shows
- // the menu activity which takes window focus, preventing the right condition from
- // being run below
- RecentsView recents = mHelper.getVisibleRecentsView();
+ IconRecentsView recents = mHelper.getVisibleRecentsView();
if (recents != null) {
- // Launch the next task
- recents.showNextTask();
+ //TODO: Launch next task in icon recents.
return true;
} else if (elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
// The user tried to launch back into overview too quickly, either after
diff --git a/go/quickstep/src/com/android/quickstep/RecentsActivity.java b/go/quickstep/src/com/android/quickstep/RecentsActivity.java
new file mode 100644
index 0000000..a186aaa
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import android.app.ActivityOptions;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.fallback.GoRecentsActivityRootView;
+import com.android.quickstep.views.IconRecentsView;
+
+/**
+ * A recents activity that displays recent tasks with an icon and small snapshot.
+ */
+public final class RecentsActivity extends BaseRecentsActivity {
+
+ private GoRecentsActivityRootView mRecentsRootView;
+ private IconRecentsView mIconRecentsView;
+
+ @Override
+ protected void initViews() {
+ setContentView(R.layout.fallback_recents_activity);
+ mRecentsRootView = findViewById(R.id.drag_layer);
+ mIconRecentsView = findViewById(R.id.overview_panel);
+ }
+
+ @Override
+ protected void reapplyUi() {
+ //TODO: Implement this depending on how insets will affect the view.
+ }
+
+ @Override
+ public BaseDragLayer getDragLayer() {
+ return mRecentsRootView;
+ }
+
+ @Override
+ public View getRootView() {
+ return mRecentsRootView;
+ }
+
+ @Override
+ public <T extends View> T getOverviewPanel() {
+ return (T) mIconRecentsView;
+ }
+
+ @Override
+ public ActivityOptions getActivityLaunchOptions(View v) {
+ //TODO: Hook into recents launch animation
+ return null;
+ }
+
+ @Override
+ protected void onStart() {
+ // Set the alpha to 1 before calling super, as it may get set back to 0 due to
+ // onActivityStart callback.
+ mIconRecentsView.setAlpha(0);
+ super.onStart();
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
new file mode 100644
index 0000000..77c3f33
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+
+import com.android.systemui.shared.recents.model.Task;
+
+import java.util.ArrayList;
+
+/**
+ * Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
+ * appropriate {@link Task} from the recents task list.
+ */
+public final class TaskAdapter extends Adapter<TaskHolder> {
+
+ private static final int MAX_TASKS_TO_DISPLAY = 6;
+ private static final String TAG = "TaskAdapter";
+ private final ArrayList<Task> mTaskList;
+
+ public TaskAdapter(@NonNull ArrayList<Task> taskList) {
+ mTaskList = taskList;
+ }
+
+ @Override
+ public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ // TODO: Swap in an actual task view here (view w/ icon, label, etc.)
+ TextView stubView = new TextView(parent.getContext());
+ return new TaskHolder(stubView);
+ }
+
+ @Override
+ public void onBindViewHolder(TaskHolder holder, int position) {
+ holder.bindTask(mTaskList.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return Math.min(mTaskList.size(), MAX_TASKS_TO_DISPLAY);
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/TaskHolder.java b/go/quickstep/src/com/android/quickstep/TaskHolder.java
new file mode 100644
index 0000000..1ea6d76
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/TaskHolder.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
+import com.android.systemui.shared.recents.model.Task;
+
+/**
+ * A recycler view holder that holds the task view and binds {@link Task} content (app title, icon,
+ * etc.) to the view.
+ */
+final class TaskHolder extends ViewHolder {
+
+ // TODO: Implement the actual task view to be held.
+ // For now, we just use a simple text view.
+ private final TextView mStubView;
+
+ public TaskHolder(TextView stubView) {
+ super(stubView);
+ mStubView = stubView;
+ }
+
+ /**
+ * Bind task content to the view. This includes the task icon and title as well as binding
+ * input handlers such as which task to launch/remove.
+ *
+ * @param task the task to bind to the view this
+ */
+ public void bindTask(Task task) {
+ mStubView.setText("Stub task view: " + task.titleDescription);
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
new file mode 100644
index 0000000..2858deb
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
+
+import android.annotation.TargetApi;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.Region;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
+
+/**
+ * Service connected by system-UI for handling touch interaction.
+ */
+@TargetApi(Build.VERSION_CODES.O)
+public class TouchInteractionService extends Service {
+
+ public static final int EDGE_NAV_BAR = 1 << 8;
+
+ private static final String TAG = "TouchInteractionService";
+
+ private final IBinder mMyBinder = new IOverviewProxy.Stub() {
+
+ @Override
+ public void onActiveNavBarRegionChanges(Region region) throws RemoteException { }
+
+ @Override
+ public void onInitialize(Bundle bundle) throws RemoteException {
+ ISystemUiProxy iSystemUiProxy = ISystemUiProxy.Stub
+ .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
+ mRecentsModel.setSystemUiProxy(iSystemUiProxy);
+ }
+
+ @Override
+ public void onOverviewToggle() {
+ mOverviewCommandHelper.onOverviewToggle();
+ }
+
+ @Override
+ public void onOverviewShown(boolean triggeredFromAltTab) {
+ mOverviewCommandHelper.onOverviewShown(triggeredFromAltTab);
+ }
+
+ @Override
+ public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+ if (triggeredFromAltTab && !triggeredFromHomeKey) {
+ // onOverviewShownFromAltTab hides the overview and ends at the target app
+ mOverviewCommandHelper.onOverviewHidden();
+ }
+ }
+
+ @Override
+ public void onTip(int actionType, int viewType) {
+ mOverviewCommandHelper.onTip(actionType, viewType);
+ }
+
+ /** Deprecated methods **/
+ public void onQuickStep(MotionEvent motionEvent) { }
+
+ public void onQuickScrubEnd() { }
+
+ public void onQuickScrubProgress(float progress) { }
+
+ public void onQuickScrubStart() { }
+
+ public void onPreMotionEvent(int downHitTarget) { }
+
+ public void onMotionEvent(MotionEvent ev) { }
+
+ public void onBind(ISystemUiProxy iSystemUiProxy) {
+ mRecentsModel.setSystemUiProxy(iSystemUiProxy);
+ }
+ };
+
+ private static boolean sConnected = false;;
+
+ public static boolean isConnected() {
+ return sConnected;
+ }
+
+ private RecentsModel mRecentsModel;
+ private OverviewComponentObserver mOverviewComponentObserver;
+ private OverviewCommandHelper mOverviewCommandHelper;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mRecentsModel = RecentsModel.INSTANCE.get(this);
+ mOverviewComponentObserver = new OverviewComponentObserver(this);
+ mOverviewCommandHelper = new OverviewCommandHelper(this,
+ mOverviewComponentObserver);
+
+ sConnected = true;
+ }
+
+ @Override
+ public void onDestroy() {
+ mOverviewComponentObserver.onDestroy();
+ sConnected = false;
+ super.onDestroy();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Touch service connected");
+ }
+ return mMyBinder;
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java b/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java
new file mode 100644
index 0000000..d748e89
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.fallback;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.RecentsActivity;
+
+/**
+ * Minimal implementation of {@link BaseDragLayer} for Go's fallback recents activity.
+ */
+public final class GoRecentsActivityRootView extends BaseDragLayer<RecentsActivity> {
+ public GoRecentsActivityRootView(Context context, AttributeSet attrs) {
+ super(context, attrs, 1 /* alphaChannelCount */);
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index e4741e9..15da10c 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -15,14 +15,27 @@
*/
package com.android.quickstep.views;
+import static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL;
+
import android.content.Context;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.ViewDebug;
import android.widget.FrameLayout;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.R;
+import com.android.quickstep.RecentsModel;
+import com.android.quickstep.TaskAdapter;
+import com.android.systemui.shared.recents.model.Task;
+
+import java.util.ArrayList;
+
/**
- * Root view for the icon recents view.
+ * Root view for the icon recents view. Acts as the main interface to the rest of the Launcher code
+ * base.
*/
public final class IconRecentsView extends FrameLayout {
@@ -45,6 +58,11 @@
@Override
public void setValue(IconRecentsView view, float v) {
ALPHA.set(view, v);
+ if (view.getVisibility() != VISIBLE && v > 0) {
+ view.setVisibility(VISIBLE);
+ } else if (view.getVisibility() != GONE && v == 0){
+ view.setVisibility(GONE);
+ }
}
@Override
@@ -58,10 +76,28 @@
* is top aligned and 0.5 is centered vertically.
*/
@ViewDebug.ExportedProperty(category = "launcher")
+
+ // TODO: Write a recents task list observer that creates/updates tasks and signals task adapter.
+ private static final ArrayList<Task> DUMMY_TASK_LIST = new ArrayList<>();
+ private final Context mContext;
+
private float mTranslationYFactor;
+ private TaskAdapter mTaskAdapter;
+ private RecyclerView mTaskRecyclerView;
public IconRecentsView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mContext = context;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mTaskAdapter = new TaskAdapter(DUMMY_TASK_LIST);
+ mTaskRecyclerView = findViewById(R.id.recent_task_recycler_view);
+ mTaskRecyclerView.setAdapter(mTaskAdapter);
+ mTaskRecyclerView.setLayoutManager(
+ new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
}
public void setTranslationYFactor(float translationFactor) {
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 9ccd477..8c58e3e 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml b/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml
new file mode 100644
index 0000000..7b4da83
--- /dev/null
+++ b/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <stroke
+ android:color="@color/chip_hint_foreground_color"
+ android:width="@dimen/chip_hint_border_width"/>
+ <corners android:radius="@dimen/chip_hint_corner_radius"/>
+ <padding
+ android:left="@dimen/chip_hint_outer_padding"
+ android:top="@dimen/chip_hint_outer_padding"
+ android:right="@dimen/chip_hint_outer_padding"
+ android:bottom="@dimen/chip_hint_outer_padding"/>
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
similarity index 100%
rename from quickstep/res/layout/fallback_recents_activity.xml
rename to quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/hint.xml b/quickstep/recents_ui_overrides/res/layout/hint.xml
new file mode 100644
index 0000000..7e2d6af
--- /dev/null
+++ b/quickstep/recents_ui_overrides/res/layout/hint.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.quickstep.hints.HintView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/chip_hint_height"
+ android:layout_gravity="center_horizontal|bottom"
+ android:paddingStart="@dimen/chip_hint_start_padding"
+ android:paddingEnd="@dimen/chip_hint_end_padding"
+ android:background="@drawable/chip_hint_background_light"
+ android:gravity="center"
+ android:layout_marginHorizontal="@dimen/chip_hint_horizontal_margin"
+ android:orientation="horizontal"
+ android:elevation="@dimen/chip_hint_elevation"
+ android:layoutDirection="ltr">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/chip_icon_size"
+ android:layout_height="@dimen/chip_icon_size"
+ android:visibility="gone"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:contentDescription="@null"/>
+
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/chip_text_height"
+ android:paddingTop="@dimen/chip_text_top_padding"
+ android:paddingStart="@dimen/chip_text_start_padding"
+ android:fontFamily="google-sans-medium"
+ android:textAlignment="textStart"
+ android:singleLine="true"
+ android:textColor="@color/chip_hint_foreground_color"
+ android:textSize="@dimen/chip_text_size"
+ android:ellipsize="none"
+ android:includeFontPadding="true"/>
+
+
+</com.android.quickstep.hints.HintView>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/res/layout/hint_container.xml b/quickstep/recents_ui_overrides/res/layout/hint_container.xml
new file mode 100644
index 0000000..336f63e
--- /dev/null
+++ b/quickstep/recents_ui_overrides/res/layout/hint_container.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.quickstep.hints.HintsContainer
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="horizontal"/>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/res/values/colors.xml b/quickstep/recents_ui_overrides/res/values/colors.xml
new file mode 100644
index 0000000..1e8d0cc
--- /dev/null
+++ b/quickstep/recents_ui_overrides/res/values/colors.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="chip_hint_foreground_color">#fff</color>
+</resources>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/res/values/dimens.xml b/quickstep/recents_ui_overrides/res/values/dimens.xml
new file mode 100644
index 0000000..b654d5c
--- /dev/null
+++ b/quickstep/recents_ui_overrides/res/values/dimens.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="chip_hint_border_width">1dp</dimen>
+ <dimen name="chip_hint_corner_radius">20dp</dimen>
+ <dimen name="chip_hint_outer_padding">20dp</dimen>
+ <dimen name="chip_hint_start_padding">10dp</dimen>
+ <dimen name="chip_hint_end_padding">12dp</dimen>
+ <dimen name="chip_hint_horizontal_margin">20dp</dimen>
+ <dimen name="chip_hint_elevation">2dp</dimen>
+ <dimen name="chip_icon_size">16dp</dimen>
+ <dimen name="chip_text_height">26dp</dimen>
+ <dimen name="chip_text_top_padding">4dp</dimen>
+ <dimen name="chip_text_start_padding">10dp</dimen>
+ <dimen name="chip_text_size">14sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 9921455..1042c60 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -19,8 +19,8 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.quickstep.TaskUtils.findTaskViewToLaunch;
-import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator;
+import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
+import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -61,33 +61,16 @@
}
@Override
- protected boolean isQuickSwitchInProgress() {
- return mRecentsView.getQuickScrubController().isQuickSwitch();
- }
-
- @Override
- protected ActivityOptions getQuickSwitchActivityOptions() {
- return ActivityOptions.makeCustomAnimation(mLauncher, R.anim.no_anim,
- R.anim.no_anim);
- }
-
- @Override
protected void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v,
@NonNull RemoteAnimationTargetCompat[] targets, boolean launcherClosing) {
RecentsView recentsView = mLauncher.getOverviewPanel();
boolean skipLauncherChanges = !launcherClosing;
- boolean isLaunchingFromQuickscrub =
- recentsView.getQuickScrubController().isWaitingForTaskLaunch();
TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
- int duration = isLaunchingFromQuickscrub
- ? RECENTS_QUICKSCRUB_LAUNCH_DURATION
- : RECENTS_LAUNCH_DURATION;
-
ClipAnimationHelper helper = new ClipAnimationHelper(mLauncher);
anim.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper)
- .setDuration(duration));
+ .setDuration(RECENTS_LAUNCH_DURATION));
Animator childStateAnimation = null;
// Found a visible recents task that matches the opening app, lets launch the app from there
@@ -96,7 +79,7 @@
if (launcherClosing) {
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper);
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
- launcherAnim.setDuration(duration);
+ launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
// Make sure recents gets fixed up by resetting task alphas and scales, etc.
windowAnimEndListener = new AnimatorListenerAdapter() {
@@ -108,10 +91,11 @@
};
} else {
AnimatorPlaybackController controller =
- mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration);
+ mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL,
+ RECENTS_LAUNCH_DURATION);
controller.dispatchOnStart();
childStateAnimation = controller.getTarget();
- launcherAnim = controller.getAnimationPlayer().setDuration(duration);
+ launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
windowAnimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java
index 8d28f33..963f1fa 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java
@@ -15,10 +15,11 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
+
import android.os.RemoteException;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.quickstep.QuickScrubController;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
@@ -33,7 +34,7 @@
FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
public BackgroundAppState(int id) {
- super(id, QuickScrubController.QUICK_SCRUB_FROM_HOME_START_DURATION, STATE_FLAGS);
+ super(id, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
}
@Override
@@ -51,7 +52,7 @@
@Override
public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
- // Initialize the recents view scale to what it would be when starting swipe up/quickscrub
+ // Initialize the recents view scale to what it would be when starting swipe up
RecentsView recentsView = launcher.getOverviewPanel();
recentsView.getTaskSize(sTempRect);
int appWidth = launcher.getDragLayer().getWidth();
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FastOverviewState.java
deleted file mode 100644
index 1d65a54..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FastOverviewState.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.uioverrides;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Rect;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.quickstep.QuickScrubController;
-import com.android.quickstep.views.RecentsView;
-
-/**
- * Extension of overview state used for QuickScrub
- */
-public class FastOverviewState extends OverviewState {
-
- private static final float MAX_PREVIEW_SCALE_UP = 1.3f;
- /**
- * Vertical transition of the task previews relative to the full container.
- */
- public static final float OVERVIEW_TRANSLATION_FACTOR = 0.4f;
- public static final float OVERVIEW_CENTERED_TRANSLATION_FACTOR = 0.5f;
-
- private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION
- | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY;
-
- public FastOverviewState(int id) {
- super(id, QuickScrubController.QUICK_SCRUB_FROM_HOME_START_DURATION, STATE_FLAGS);
- }
-
- @Override
- public void onStateTransitionEnd(Launcher launcher) {
- super.onStateTransitionEnd(launcher);
- RecentsView recentsView = launcher.getOverviewPanel();
- recentsView.getQuickScrubController().onFinishedTransitionToQuickScrub();
- }
-
- @Override
- public int getVisibleElements(Launcher launcher) {
- return NONE;
- }
-
- @Override
- public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
- RecentsView recentsView = launcher.getOverviewPanel();
- recentsView.getTaskSize(sTempRect);
-
- boolean isQuickSwitch = recentsView.getQuickScrubController().isQuickSwitch();
- float translationYFactor = isQuickSwitch
- ? OVERVIEW_CENTERED_TRANSLATION_FACTOR
- : OVERVIEW_TRANSLATION_FACTOR;
- return new float[] {getOverviewScale(launcher.getDeviceProfile(), sTempRect, launcher,
- isQuickSwitch), translationYFactor};
- }
-
- public static float getOverviewScale(DeviceProfile dp, Rect taskRect, Context context,
- boolean isQuickSwitch) {
- if (dp.isVerticalBarLayout() && !isQuickSwitch) {
- return 1f;
- }
-
- Resources res = context.getResources();
- float usedHeight = taskRect.height() + res.getDimension(R.dimen.task_thumbnail_top_margin);
- float usedWidth = taskRect.width() + 2 * (res.getDimension(R.dimen.recents_page_spacing)
- + res.getDimension(R.dimen.quickscrub_adjacent_visible_width));
- if (isQuickSwitch) {
- usedWidth = taskRect.width();
- return Math.max(dp.availableHeightPx / usedHeight, dp.availableWidthPx / usedWidth);
- }
- return Math.min(Math.min(dp.availableHeightPx / usedHeight,
- dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP);
- }
-
- @Override
- public void onStateDisabled(Launcher launcher) {
- super.onStateDisabled(launcher);
- launcher.<RecentsView>getOverviewPanel().getQuickScrubController().cancelActiveQuickscrub();
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java
index b37c2e0..a41362f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java
@@ -91,5 +91,6 @@
} else {
super.onDragEnd(velocity, fling);
}
+ mMotionPauseDetector.clear();
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java
index de6f7a7..3602508 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
@@ -76,18 +75,13 @@
public void onStateEnabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- AbstractFloatingView.closeAllOpenViews(launcher);
- } else {
- AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
- }
+ AbstractFloatingView.closeAllOpenViews(launcher);
}
@Override
public void onStateDisabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(false);
- RecentsModel.INSTANCE.get(launcher).resetAssistCache();
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
index 51e9495..027fd91 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -120,13 +120,11 @@
*/
public static void onLauncherStateOrResumeChanged(Launcher launcher) {
LauncherState state = launcher.getStateManager().getState();
- if (!OverviewInteractionState.INSTANCE.get(launcher).swipeGestureInitializing()) {
- DeviceProfile profile = launcher.getDeviceProfile();
- boolean visible = (state == NORMAL || state == OVERVIEW) && launcher.isUserActive()
- && !profile.isVerticalBarLayout();
- UiThreadHelper.runAsyncCommand(launcher, SET_SHELF_HEIGHT_CMD,
- visible ? 1 : 0, profile.hotseatBarSizePx);
- }
+ DeviceProfile profile = launcher.getDeviceProfile();
+ boolean visible = (state == NORMAL || state == OVERVIEW) && launcher.isUserActive()
+ && !profile.isVerticalBarLayout();
+ UiThreadHelper.runAsyncCommand(launcher, SET_SHELF_HEIGHT_CMD,
+ visible ? 1 : 0, profile.hotseatBarSizePx);
if (state == NORMAL) {
launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 7d7946d..0b3bd6c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,10 +15,6 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
@@ -26,7 +22,6 @@
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
-import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
@@ -34,7 +29,6 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -56,6 +50,9 @@
if (state.overviewUi) {
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
+ mRecentsView.setHintVisibility(1);
+ } else {
+ mRecentsView.setHintVisibility(0);
}
}
@@ -66,6 +63,7 @@
if (!toState.overviewUi) {
builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals);
+ mRecentsView.setHintVisibility(0);
}
if (toState.overviewUi) {
@@ -77,20 +75,11 @@
updateAnim.setDuration(config.duration);
builder.play(updateAnim);
mRecentsView.updateEmptyMessage();
+ builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1));
}
}
@Override
- Interpolator getScaleAndTransYInterpolator(@NonNull LauncherState toState,
- @NonNull AnimatorSetBuilder builder) {
- if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
- return Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0,
- QUICK_SCRUB_TRANSLATION_Y_FACTOR);
- }
- return super.getScaleAndTransYInterpolator(toState, builder);
- }
-
- @Override
FloatProperty<LauncherRecentsView> getTranslationYFactorProperty() {
return TRANSLATION_Y_FACTOR;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
similarity index 100%
rename from quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
rename to quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
diff --git a/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
similarity index 96%
rename from quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
index e0eeda5..e5747dc 100644
--- a/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -34,7 +33,6 @@
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
@@ -82,7 +80,7 @@
anim.start();
});
factory.onRemoteAnimationReceived(null);
- factory.createActivityController(RECENTS_LAUNCH_DURATION, INTERACTION_NORMAL);
+ factory.createActivityController(RECENTS_LAUNCH_DURATION);
mActivity = activity;
mRecentsView = mActivity.getOverviewPanel();
return false;
@@ -136,9 +134,8 @@
loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
clipHelper.updateSource(homeBounds, runningTaskTarget);
- TransformedRect targetRect = new TransformedRect();
- mHelper.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity,
- INTERACTION_NORMAL, targetRect);
+ Rect targetRect = new Rect();
+ mHelper.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity, targetRect);
clipHelper.updateTargetRect(targetRect);
clipHelper.prepareAnimation(false /* isOpening */);
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java
similarity index 66%
rename from quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java
index aba6060..1ed1353 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java
@@ -15,41 +15,33 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.os.Handler;
-import android.os.Looper;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
-import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
/**
* {@link ActivityControlHelper} for recents when the default launcher is different than the
* currently running one and apps should interact with the {@link RecentsActivity} as opposed
@@ -58,39 +50,7 @@
public final class FallbackActivityControllerHelper implements
ActivityControlHelper<RecentsActivity> {
- private final ComponentName mHomeComponent;
- private final Handler mUiHandler = new Handler(Looper.getMainLooper());
-
- public FallbackActivityControllerHelper(ComponentName homeComponent) {
- mHomeComponent = homeComponent;
- }
-
- @Override
- public void onQuickInteractionStart(RecentsActivity activity, RunningTaskInfo taskInfo,
- boolean activityVisible, TouchInteractionLog touchInteractionLog) {
- QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
- .getQuickScrubController();
-
- // TODO: match user is as well
- boolean startingFromHome = !activityVisible &&
- (taskInfo == null || Objects.equals(taskInfo.topActivity, mHomeComponent));
- controller.onQuickScrubStart(startingFromHome, this, touchInteractionLog);
- if (activityVisible) {
- mUiHandler.postDelayed(controller::onFinishedTransitionToQuickScrub,
- OVERVIEW_TRANSITION_MS);
- }
- }
-
- @Override
- public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
- Context context) {
- return 0;
- }
-
- @Override
- public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) {
- action.run();
- }
+ public FallbackActivityControllerHelper() { }
@Override
public void onTransitionCancelled(RecentsActivity activity, boolean activityVisible) {
@@ -98,15 +58,14 @@
}
@Override
- public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context,
- @InteractionType int interactionType, TransformedRect outRect) {
- LayoutUtils.calculateFallbackTaskSize(context, dp, outRect.rect);
+ public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
+ LayoutUtils.calculateFallbackTaskSize(context, dp, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
return dp.hotseatBarSizePx + hotseatInset;
} else {
- return dp.heightPx - outRect.rect.bottom;
+ return dp.heightPx - outRect.bottom;
}
}
@@ -148,7 +107,7 @@
public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible,
boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
if (activityVisible) {
- return (transitionLength, interactionType) -> { };
+ return (transitionLength) -> { };
}
RecentsView rv = activity.getOverviewPanel();
@@ -165,12 +124,11 @@
rv.setContentAlpha(1);
}
createActivityController(getSwipeUpDestinationAndLength(
- activity.getDeviceProfile(), activity, INTERACTION_NORMAL,
- new TransformedRect()), INTERACTION_NORMAL);
+ activity.getDeviceProfile(), activity, new Rect()));
}
@Override
- public void createActivityController(long transitionLength, int interactionType) {
+ public void createActivityController(long transitionLength) {
if (!isAnimatingToRecents) {
return;
}
@@ -185,26 +143,6 @@
}
@Override
- public LayoutListener createLayoutListener(RecentsActivity activity) {
- // We do not change anything as part of layout changes in fallback activity. Return a
- // default layout listener.
- return new LayoutListener() {
- @Override
- public void open() { }
-
- @Override
- public void setHandler(WindowTransformSwipeHandler handler) { }
-
- @Override
- public void finish() { }
-
- @Override
- public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
- float cornerRadius) { }
- };
- }
-
- @Override
public ActivityInitListener createActivityInitListener(
BiPredicate<RecentsActivity, Boolean> onInitListener) {
return new RecentsActivityTracker(onInitListener);
@@ -227,17 +165,11 @@
}
@Override
- public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
+ public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
return false;
}
@Override
- public boolean deferStartingActivity(int downHitTarget) {
- // Always defer starting the activity when using fallback
- return true;
- }
-
- @Override
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
// TODO: Remove this once b/77875376 is fixed
return target.sourceContainerBounds;
@@ -250,16 +182,6 @@
}
@Override
- public boolean supportsLongSwipe(RecentsActivity activity) {
- return false;
- }
-
- @Override
- public LongSwipeHelper getLongSwipeController(RecentsActivity activity, int runningTaskId) {
- return null;
- }
-
- @Override
public AlphaProperty getAlphaProperty(RecentsActivity activity) {
return activity.getDragLayer().getAlphaProperty(0);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/InputConsumer.java
new file mode 100644
index 0000000..8dfb9ab
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/InputConsumer.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+@TargetApi(Build.VERSION_CODES.O)
+public interface InputConsumer {
+ InputConsumer NO_OP = new InputConsumer() { };
+
+ default boolean isActive() {
+ return false;
+ }
+
+ /**
+ * Called by the event queue when the consumer is about to be switched to a new consumer.
+ */
+ default void onConsumerAboutToBeSwitched() { }
+
+ default void onMotionEvent(MotionEvent ev) { }
+
+ default void onKeyEvent(KeyEvent ev) { }
+
+ default void onInputEvent(InputEvent ev) {
+ if (ev instanceof MotionEvent) {
+ onMotionEvent((MotionEvent) ev);
+ } else {
+ onKeyEvent((KeyEvent) ev);
+ }
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index af25355..ffd3b4b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -19,54 +19,41 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO;
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
-import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
-import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.Region;
+import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.R;
-import com.android.launcher3.TestProtocol;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.SpringObjectAnimator;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.uioverrides.FastOverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
-import com.android.quickstep.TouchConsumer.InteractionType;
+import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.TransformedRect;
-import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -74,70 +61,18 @@
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+
/**
* {@link ActivityControlHelper} for the in-launcher recents.
*/
public final class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
@Override
- public LayoutListener createLayoutListener(Launcher activity) {
- return LauncherLayoutListener.resetAndGet(activity);
- }
-
- @Override
- public void onQuickInteractionStart(Launcher activity, RunningTaskInfo taskInfo,
- boolean activityVisible, TouchInteractionLog touchInteractionLog) {
- LauncherState fromState = activity.getStateManager().getState();
- QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
- .getQuickScrubController();
- boolean isQuickSwitch = controller.isQuickSwitch();
- boolean animate = activityVisible;
- if (isQuickSwitch && fromState == FAST_OVERVIEW && !animate) {
- // We can already be in FAST_OVERVIEW if createActivityController() was called
- // before us. This could happen, for instance, when launcher is slow to load when
- // starting quick switch, causing us to call onQuickScrubStart() on the background
- // thread. In this case, we also hadn't set isQuickSwitch = true before setting
- // FAST_OVERVIEW, so we need to reapply FAST_OVERVIEW to take that into account.
- activity.getStateManager().reapplyState();
- } else {
- activity.getStateManager().goToState(FAST_OVERVIEW, animate);
- }
-
- controller.onQuickScrubStart(activityVisible && !fromState.overviewUi, this,
- touchInteractionLog);
-
- if (!activityVisible) {
- // For the duration of the gesture, lock the screen orientation to ensure that we
- // do not rotate mid-quickscrub
- activity.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK);
- }
- }
-
- @Override
- public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
- Context context) {
- // The padding calculations are exactly same as that of RecentsView.setInsets
- int topMargin = context.getResources()
- .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
- int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top;
- int paddingBottom = dp.heightPx - dp.getInsets().bottom - targetRect.rect.bottom;
-
- return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop);
- }
-
- @Override
- public void executeOnWindowAvailable(Launcher activity, Runnable action) {
- activity.getWorkspace().runOnOverlayHidden(action);
- }
-
- @Override
- public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context,
- @InteractionType int interactionType, TransformedRect outRect) {
- LayoutUtils.calculateLauncherTaskSize(context, dp, outRect.rect);
- if (interactionType == INTERACTION_QUICK_SCRUB) {
- outRect.scale = FastOverviewState.getOverviewScale(dp, outRect.rect, context,
- FeatureFlags.QUICK_SWITCH.get());
- }
+ public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
+ LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -163,17 +98,41 @@
@NonNull
@Override
public HomeAnimationFactory prepareHomeUI(Launcher activity) {
- DeviceProfile dp = activity.getDeviceProfile();
+ final DeviceProfile dp = activity.getDeviceProfile();
+ final RecentsView recentsView = activity.getOverviewPanel();
+ final ComponentName component = recentsView.getRunningTaskView().getTask().key
+ .sourceComponent;
+
+ final View workspaceView = activity.getWorkspace().getFirstMatchForAppClose(component);
+ final FloatingIconView floatingView = workspaceView == null ? null
+ : new FloatingIconView(activity);
+ final Rect iconLocation = new Rect();
+ if (floatingView != null) {
+ floatingView.matchPositionOf(activity, workspaceView, true /* hideOriginal */,
+ iconLocation);
+ }
return new HomeAnimationFactory() {
+ @Nullable
+ @Override
+ public View getFloatingView() {
+ return floatingView;
+ }
+
@NonNull
@Override
public RectF getWindowTargetRect() {
- int halfIconSize = dp.iconSizePx / 2;
- float targetCenterX = dp.availableWidthPx / 2;
- float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
- return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
- targetCenterX + halfIconSize, targetCenterY + halfIconSize);
+ final int halfIconSize = dp.iconSizePx / 2;
+ final float targetCenterX = dp.availableWidthPx / 2f;
+ final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
+
+ if (workspaceView != null) {
+ return new RectF(iconLocation);
+ } else {
+ // Fallback to animate to center of screen.
+ return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
+ targetCenterX + halfIconSize, targetCenterY + halfIconSize);
+ }
}
@NonNull
@@ -208,8 +167,7 @@
// Optimization, hide the all apps view to prevent layout while initializing
activity.getAppsView().getContentView().setVisibility(View.GONE);
- AccessibilityManagerCompat.sendEventToTest(
- activity, TestProtocol.SWITCHED_TO_STATE_MESSAGE);
+ AccessibilityManagerCompat.sendStateEventToTest(activity, fromState.ordinal);
} else {
fromState = startState;
}
@@ -219,10 +177,9 @@
private ShelfAnimState mShelfState;
@Override
- public void createActivityController(long transitionLength,
- @InteractionType int interactionType) {
+ public void createActivityController(long transitionLength) {
createActivityControllerInternal(activity, activityVisible, fromState,
- transitionLength, interactionType, callback);
+ transitionLength, callback);
}
@Override
@@ -268,10 +225,8 @@
private void createActivityControllerInternal(Launcher activity, boolean wasVisible,
LauncherState fromState, long transitionLength,
- @InteractionType int interactionType,
Consumer<AnimatorPlaybackController> callback) {
- LauncherState endState = interactionType == INTERACTION_QUICK_SCRUB
- ? FAST_OVERVIEW : OVERVIEW;
+ LauncherState endState = OVERVIEW;
if (wasVisible && fromState != BACKGROUND_APP) {
// If a translucent app was launched fom launcher, animate launcher states.
DeviceProfile dp = activity.getDeviceProfile();
@@ -293,10 +248,7 @@
endState.getVerticalProgress(activity));
anim.play(shiftAnim);
}
-
- if (interactionType == INTERACTION_NORMAL) {
- playScaleDownAnim(anim, activity, endState);
- }
+ playScaleDownAnim(anim, activity, endState);
anim.setDuration(transitionLength * 2);
activity.getStateManager().setCurrentAnimation(anim);
@@ -390,24 +342,24 @@
}
@Override
- public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
+ public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
Launcher launcher = getVisibleLauncher();
if (launcher == null) {
return false;
}
- if (fromRecentsButton) {
- launcher.getUserEventDispatcher().logActionCommand(
- LauncherLogProto.Action.Command.RECENTS_BUTTON,
- getContainerType(),
- LauncherLogProto.ContainerType.TASKSWITCHER);
- }
- launcher.getStateManager().goToState(OVERVIEW);
+
+ launcher.getUserEventDispatcher().logActionCommand(
+ LauncherLogProto.Action.Command.RECENTS_BUTTON,
+ getContainerType(),
+ LauncherLogProto.ContainerType.TASKSWITCHER);
+ launcher.getStateManager().goToState(OVERVIEW,
+ launcher.getStateManager().shouldAnimateStateChange(), onCompleteCallback);
return true;
}
@Override
- public boolean deferStartingActivity(int downHitTarget) {
- return downHitTarget == HIT_TARGET_BACK || downHitTarget == HIT_TARGET_ROTATION;
+ public boolean deferStartingActivity(Region activeNavBarRegion, MotionEvent ev) {
+ return activeNavBarRegion.contains((int) ev.getX(), (int) ev.getY());
}
@Override
@@ -421,19 +373,6 @@
}
@Override
- public boolean supportsLongSwipe(Launcher activity) {
- return !activity.getDeviceProfile().isVerticalBarLayout();
- }
-
- @Override
- public LongSwipeHelper getLongSwipeController(Launcher activity, int runningTaskId) {
- if (activity.getDeviceProfile().isVerticalBarLayout()) {
- return null;
- }
- return new LongSwipeHelper(activity, runningTaskId);
- }
-
- @Override
public AlphaProperty getAlphaProperty(Launcher activity) {
return activity.getDragLayer().getAlphaProperty(DragLayer.ALPHA_INDEX_SWIPE_UP);
}
diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/MultiStateCallback.java
similarity index 78%
rename from quickstep/src/com/android/quickstep/MultiStateCallback.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/MultiStateCallback.java
index a408f95..9fceab4 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/MultiStateCallback.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.quickstep.WindowTransformSwipeHandler.STATES;
-
import android.util.Log;
import android.util.SparseArray;
@@ -29,17 +27,28 @@
public class MultiStateCallback {
private static final String TAG = "MultiStateCallback";
- private static final boolean DEBUG_STATES = false;
+ public static final boolean DEBUG_STATES = false;
private final SparseArray<Runnable> mCallbacks = new SparseArray<>();
private final SparseArray<Consumer<Boolean>> mStateChangeHandlers = new SparseArray<>();
+ private final String[] mStateNames;
+
+ public MultiStateCallback(String[] stateNames) {
+ mStateNames = DEBUG_STATES ? stateNames : null;
+ }
+
private int mState = 0;
/**
* Adds the provided state flags to the global state and executes any callbacks as a result.
*/
public void setState(int stateFlag) {
+ if (DEBUG_STATES) {
+ Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding "
+ + convertToFlagNames(stateFlag) + " to " + convertToFlagNames(mState));
+ }
+
int oldState = mState;
mState = mState | stateFlag;
@@ -64,6 +73,11 @@
* as a result.
*/
public void clearState(int stateFlag) {
+ if (DEBUG_STATES) {
+ Log.d(TAG, "[" + System.identityHashCode(this) + "] Removing "
+ + convertToFlagNames(stateFlag) + " from " + convertToFlagNames(mState));
+ }
+
int oldState = mState;
mState = mState & ~stateFlag;
notifyStateChangeHandlers(oldState);
@@ -105,24 +119,14 @@
return (mState & stateMask) == stateMask;
}
- private void debugNewState(int stateFlag) {
- if (!DEBUG_STATES) {
- return;
- }
-
- int state = getState();
- StringJoiner currentStateStr = new StringJoiner(", ", "[", "]");
- String stateFlagStr = "Unknown-" + stateFlag;
- for (int i = 0; i < STATES.length; i++) {
- if ((state & (i << i)) != 0) {
- currentStateStr.add(STATES[i]);
- }
- if (stateFlag == (1 << i)) {
- stateFlagStr = STATES[i] + " (" + stateFlag + ")";
+ private String convertToFlagNames(int flags) {
+ StringJoiner joiner = new StringJoiner(", ", "[", " (" + flags + ")]");
+ for (int i = 0; i < mStateNames.length; i++) {
+ if ((flags & (1 << i)) != 0) {
+ joiner.add(mStateNames[i]);
}
}
- Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding " + stateFlagStr + " to "
- + currentStateStr);
+ return joiner.toString();
}
}
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
similarity index 67%
rename from quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
index 84f16cb..67bfeaa 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
@@ -24,6 +24,8 @@
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
+import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi;
@@ -34,8 +36,8 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
-import android.os.Bundle;
-import android.os.SystemClock;
+import android.os.Handler;
+import android.os.Looper;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
@@ -43,102 +45,132 @@
import android.view.ViewConfiguration;
import android.view.WindowManager;
+import androidx.annotation.UiThread;
+
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
+import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.AssistDataReceiver;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.NavigationBarCompat;
-import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
+import java.util.function.Consumer;
/**
- * Touch consumer for handling events originating from an activity other than Launcher
+ * Input consumer for handling events originating from an activity other than Launcher
*/
@TargetApi(Build.VERSION_CODES.P)
-public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer {
+public class OtherActivityInputConsumer extends ContextWrapper implements InputConsumer {
- public static final String DOWN_EVT = "OtherActivityTouchConsumer.DOWN";
- private static final String UP_EVT = "OtherActivityTouchConsumer.UP";
+ public static final String DOWN_EVT = "OtherActivityInputConsumer.DOWN";
+ private static final String UP_EVT = "OtherActivityInputConsumer.UP";
+ private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
private final RecentsModel mRecentsModel;
private final Intent mHomeIntent;
private final ActivityControlHelper mActivityControlHelper;
private final OverviewCallbacks mOverviewCallbacks;
private final TaskOverlayFactory mTaskOverlayFactory;
- private final TouchInteractionLog mTouchInteractionLog;
private final InputConsumerController mInputConsumer;
private final SwipeSharedState mSwipeSharedState;
- private final MotionEventQueue mEventQueue;
+ private final int mDisplayRotation;
+ private final Rect mStableInsets = new Rect();
+
+ private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
private final MotionPauseDetector mMotionPauseDetector;
private VelocityTracker mVelocityTracker;
+ private WindowTransformSwipeHandler mInteractionHandler;
+
private final boolean mIsDeferredDownTarget;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
private int mActivePointerId = INVALID_POINTER_ID;
- private boolean mPassedInitialSlop;
- // Used for non-deferred gestures to determine when to start dragging
- private int mQuickStepDragSlop;
- private float mStartDisplacement;
- private WindowTransformSwipeHandler mInteractionHandler;
- private int mDisplayRotation;
- private Rect mStableInsets = new Rect();
- public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo,
+ private final float mDragSlop;
+ private final float mTouchSlop;
+
+ // Slop used to check when we start moving window.
+ private boolean mPassedDragSlop;
+ // Slop used to determine when we say that the gesture has started.
+ private boolean mPassedTouchSlop;
+
+ // TODO: Start displacement should have both x and y
+ private float mStartDisplacement;
+
+ private Handler mMainThreadHandler;
+ private Runnable mCancelRecentsAnimationRunnable = () -> {
+ ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
+ true /* restoreHomeStackPosition */);
+ };
+
+ public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
- @HitTarget int downHitTarget, OverviewCallbacks overviewCallbacks,
+ boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
TaskOverlayFactory taskOverlayFactory, InputConsumerController inputConsumer,
- TouchInteractionLog touchInteractionLog, MotionEventQueue eventQueue,
+ Consumer<OtherActivityInputConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState) {
super(base);
+ mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
mRecentsModel = recentsModel;
mHomeIntent = homeIntent;
mMotionPauseDetector = new MotionPauseDetector(base);
- mEventQueue = eventQueue;
+ mOnCompleteCallback = onCompleteCallback;
mVelocityTracker = VelocityTracker.obtain();
mActivityControlHelper = activityControl;
- mIsDeferredDownTarget = activityControl.deferStartingActivity(downHitTarget);
+ mIsDeferredDownTarget = isDeferredDownTarget;
mOverviewCallbacks = overviewCallbacks;
mTaskOverlayFactory = taskOverlayFactory;
- mTouchInteractionLog = touchInteractionLog;
- mTouchInteractionLog.setTouchConsumer(this);
mInputConsumer = inputConsumer;
mSwipeSharedState = swipeSharedState;
+
+ Display display = getSystemService(WindowManager.class).getDefaultDisplay();
+ mDisplayRotation = display.getRotation();
+ WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
+
+ mDragSlop = NavigationBarCompat.getQuickStepDragSlopPx();
+ mTouchSlop = NavigationBarCompat.getQuickStepTouchSlopPx();
+ // If active listener isn't null, we are continuing the previous gesture.
+ mPassedTouchSlop = mPassedDragSlop = mSwipeSharedState.getActiveListener() != null;
}
@Override
- public void onShowOverviewFromAltTab() {
- startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis());
- }
-
- @Override
- public void accept(MotionEvent ev) {
+ public void onMotionEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
return;
}
+
+ // Proxy events to recents view
+ if (!isNavBarOnLeft() && !isNavBarOnRight()) {
+ if (mPassedDragSlop && mInteractionHandler != null
+ && !mRecentsViewDispatcher.hasConsumer()) {
+ mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher());
+ }
+ int edgeFlags = ev.getEdgeFlags();
+ ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
+ mRecentsViewDispatcher.dispatchEvent(ev);
+ ev.setEdgeFlags(edgeFlags);
+ }
+
mVelocityTracker.addMovement(ev);
if (ev.getActionMasked() == ACTION_POINTER_UP) {
mVelocityTracker.clear();
mMotionPauseDetector.clear();
}
- mTouchInteractionLog.addMotionEvent(ev);
switch (ev.getActionMasked()) {
case ACTION_DOWN: {
RaceConditionTracker.onEvent(DOWN_EVT, ENTER);
@@ -146,9 +178,6 @@
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
- // If active listener isn't null, we are continuing the previous gesture.
- mPassedInitialSlop = mSwipeSharedState.getActiveListener() != null;
- mQuickStepDragSlop = NavigationBarCompat.getQuickStepDragSlopPx();
// Start the window animation on down to give more time for launcher to draw if the
// user didn't start the gesture over the back button
@@ -156,9 +185,6 @@
startTouchTrackingForWindowAnimation(ev.getEventTime());
}
- Display display = getSystemService(WindowManager.class).getDefaultDisplay();
- mDisplayRotation = display.getRotation();
- WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
break;
}
@@ -182,20 +208,40 @@
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float displacement = getDisplacement(ev);
- if (!mPassedInitialSlop) {
+
+ if (!mPassedDragSlop) {
if (!mIsDeferredDownTarget) {
// Normal gesture, ensure we pass the drag slop before we start tracking
// the gesture
- if (Math.abs(displacement) > mQuickStepDragSlop) {
- mPassedInitialSlop = true;
+ if (Math.abs(displacement) > mDragSlop) {
+ mPassedDragSlop = true;
mStartDisplacement = displacement;
}
}
}
- if (mPassedInitialSlop && mInteractionHandler != null) {
+ if (!mPassedTouchSlop) {
+ if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) >=
+ mTouchSlop) {
+ mPassedTouchSlop = true;
+
+ TOUCH_INTERACTION_LOG.startQuickStep();
+ if (mIsDeferredDownTarget) {
+ // Deferred gesture, start the animation and gesture tracking once
+ // we pass the actual touch slop
+ startTouchTrackingForWindowAnimation(ev.getEventTime());
+ }
+ if (!mPassedDragSlop) {
+ mPassedDragSlop = true;
+ mStartDisplacement = displacement;
+ }
+ notifyGestureStarted();
+ }
+ }
+
+ if (mPassedDragSlop && mInteractionHandler != null) {
// Move
- dispatchMotion(ev, displacement - mStartDisplacement, null);
+ mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
if (FeatureFlags.SWIPE_HOME.get()) {
boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
@@ -220,14 +266,6 @@
}
}
- private void dispatchMotion(MotionEvent ev, float displacement, @Nullable Float velocityX) {
- mInteractionHandler.updateDisplacement(displacement);
- boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
- if (!isLandscape) {
- mInteractionHandler.dispatchMotionEventToRecentsView(ev, velocityX);
- }
- }
-
private void notifyGestureStarted() {
if (mInteractionHandler == null) {
return;
@@ -250,12 +288,12 @@
}
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
- mTouchInteractionLog.startRecentsAnimation();
+ TOUCH_INTERACTION_LOG.startRecentsAnimation();
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
mRunningTask, this, touchTimeMs, mActivityControlHelper,
- listenerSet != null, mInputConsumer, mTouchInteractionLog);
+ listenerSet != null, mInputConsumer);
// Preload the plan
mRecentsModel.getTasks(null);
@@ -264,32 +302,16 @@
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
handler.initWhenReady();
- TraceHelper.beginSection("RecentsController");
-
if (listenerSet != null) {
listenerSet.addListener(handler);
mSwipeSharedState.applyActiveRecentsAnimationState(handler);
} else {
- AssistDataReceiver assistDataReceiver = !mTaskOverlayFactory.needAssist() ? null :
- new AssistDataReceiver() {
- @Override
- public void onHandleAssistData(Bundle bundle) {
- if (mInteractionHandler == null) {
- // Interaction is probably complete
- mRecentsModel.preloadAssistData(mRunningTask.id, bundle);
- } else if (handler == mInteractionHandler) {
- handler.onAssistDataReceived(bundle);
- }
- }
- };
-
RecentsAnimationListenerSet newListenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
newListenerSet.addListener(handler);
BackgroundExecutor.get().submit(
() -> ActivityManagerWrapper.getInstance().startRecentsActivity(
- mHomeIntent, assistDataReceiver, newListenerSet,
- null, null));
+ mHomeIntent, null, newListenerSet, null, null));
}
}
@@ -298,7 +320,7 @@
* the animation can still be running.
*/
private void finishTouchTracking(MotionEvent ev) {
- if (mPassedInitialSlop && mInteractionHandler != null) {
+ if (mPassedDragSlop && mInteractionHandler != null) {
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
@@ -307,8 +329,7 @@
: isNavBarOnLeft() ? -velocityX
: mVelocityTracker.getYVelocity(mActivePointerId);
- dispatchMotion(ev, getDisplacement(ev) - mStartDisplacement, velocityX);
-
+ mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
mInteractionHandler.onGestureEnded(velocity, velocityX);
} else {
// Since we start touch tracking on DOWN, we may reach this state without actually
@@ -316,18 +337,22 @@
onConsumerAboutToBeSwitched();
onInteractionGestureFinished();
- // Also clean up in case the system has handled the UP and canceled the animation before
- // we had a chance to start the recents animation. In such a case, we will not receive
- ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
- true /* restoreHomeStackPosition */);
+ // Cancel the recents animation if SysUI happens to handle UP before we have a chance
+ // to start the recents animation. In addition, workaround for b/126336729 by delaying
+ // the cancel of the animation for a period, in case SysUI is slow to handle UP and we
+ // handle DOWN & UP and move the home stack before SysUI can start the activity
+ mMainThreadHandler.removeCallbacks(mCancelRecentsAnimationRunnable);
+ mMainThreadHandler.postDelayed(mCancelRecentsAnimationRunnable, 100);
}
mVelocityTracker.recycle();
mVelocityTracker = null;
+ mMotionPauseDetector.clear();
}
@Override
public void onConsumerAboutToBeSwitched() {
Preconditions.assertUIThread();
+ mMainThreadHandler.removeCallbacks(mCancelRecentsAnimationRunnable);
if (mInteractionHandler != null) {
// The consumer is being switched while we are active. Set up the shared state to be
// used by the next animation
@@ -348,7 +373,7 @@
Preconditions.assertUIThread();
removeListener();
mInteractionHandler = null;
- mEventQueue.onConsumerInactive(this);
+ mOnCompleteCallback.accept(this);
}
private void removeListener() {
@@ -358,53 +383,6 @@
}
}
- @Override
- public void onQuickScrubStart() {
- if (!mPassedInitialSlop && mIsDeferredDownTarget && mInteractionHandler == null) {
- // If we deferred starting the window animation on touch down, then
- // start tracking now
- startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis());
- mPassedInitialSlop = true;
- }
-
- mTouchInteractionLog.startQuickScrub();
- if (mInteractionHandler != null) {
- mInteractionHandler.onQuickScrubStart();
- }
- notifyGestureStarted();
- }
-
- @Override
- public void onQuickScrubEnd() {
- mTouchInteractionLog.endQuickScrub("onQuickScrubEnd");
- if (mInteractionHandler != null) {
- mInteractionHandler.onQuickScrubEnd();
- }
- }
-
- @Override
- public void onQuickScrubProgress(float progress) {
- mTouchInteractionLog.setQuickScrubProgress(progress);
- if (mInteractionHandler != null) {
- mInteractionHandler.onQuickScrubProgress(progress);
- }
- }
-
- @Override
- public void onQuickStep(MotionEvent ev) {
- mTouchInteractionLog.startQuickStep();
- if (mIsDeferredDownTarget) {
- // Deferred gesture, start the animation and gesture tracking once we pass the actual
- // touch slop
- startTouchTrackingForWindowAnimation(ev.getEventTime());
- }
- if (!mPassedInitialSlop) {
- mPassedInitialSlop = true;
- mStartDisplacement = getDisplacement(ev);
- }
- notifyGestureStarted();
- }
-
private float getDisplacement(MotionEvent ev) {
float eventX = ev.getX();
float eventY = ev.getY();
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
similarity index 71%
copy from quickstep/src/com/android/quickstep/OverviewCommandHelper.java
copy to quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
index 5b4f673..6533c63 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
@@ -18,6 +18,8 @@
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.content.Context;
@@ -31,6 +33,7 @@
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -67,8 +70,12 @@
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
}
- public void onOverviewShown() {
- mMainThreadExecutor.execute(new ShowRecentsCommand());
+ public void onOverviewShown(boolean triggeredFromAltTab) {
+ mMainThreadExecutor.execute(new ShowRecentsCommand(triggeredFromAltTab));
+ }
+
+ public void onOverviewHidden() {
+ mMainThreadExecutor.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
@@ -78,10 +85,58 @@
private class ShowRecentsCommand extends RecentsActivityCommand {
+ private final boolean mTriggeredFromAltTab;
+
+ ShowRecentsCommand(boolean triggeredFromAltTab) {
+ mTriggeredFromAltTab = triggeredFromAltTab;
+ }
+
@Override
protected boolean handleCommand(long elapsedTime) {
+ // TODO: Go to the next page if started from alt-tab.
return mHelper.getVisibleRecentsView() != null;
}
+
+ @Override
+ protected void onTransitionComplete() {
+ if (mTriggeredFromAltTab) {
+ RecentsView rv = (RecentsView) mHelper.getVisibleRecentsView();
+ if (rv == null) {
+ return;
+ }
+
+ // Ensure that recents view has focus so that it receives the followup key inputs
+ TaskView taskView = rv.getNextTaskView();
+ if (taskView == null) {
+ if (rv.getTaskViewCount() > 0) {
+ taskView = (TaskView) rv.getPageAt(0);
+ taskView.requestFocus();
+ } else {
+ rv.requestFocus();
+ }
+ } else {
+ taskView.requestFocus();
+ }
+ }
+ }
+ }
+
+ private class HideRecentsCommand extends RecentsActivityCommand {
+
+ @Override
+ protected boolean handleCommand(long elapsedTime) {
+ RecentsView recents = (RecentsView) mHelper.getVisibleRecentsView();
+ if (recents == null) {
+ return false;
+ }
+ int currentPage = recents.getNextPage();
+ if (currentPage >= 0 && currentPage < recents.getTaskViewCount()) {
+ ((TaskView) recents.getPageAt(currentPage)).launchTask(true);
+ } else {
+ recents.startHome();
+ }
+ return true;
+ }
}
private class RecentsActivityCommand<T extends BaseDraggingActivity> implements Runnable {
@@ -114,7 +169,7 @@
return;
}
- if (mHelper.switchToRecentsIfVisible(true)) {
+ if (mHelper.switchToRecentsIfVisible(this::onTransitionComplete)) {
// If successfully switched, then return
return;
}
@@ -162,7 +217,16 @@
mListener.unregister();
- return mAnimationProvider.createWindowAnimation(targetCompats);
+ AnimatorSet animatorSet = mAnimationProvider.createWindowAnimation(targetCompats);
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onTransitionComplete();
+ }
+ });
+ return animatorSet;
}
+
+ protected void onTransitionComplete() { }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java
new file mode 100644
index 0000000..28c4db4
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+
+import android.graphics.PointF;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.util.CachedEventDispatcher;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+
+/**
+ * Input consumer for handling touch on the recents/Launcher activity.
+ */
+public class OverviewInputConsumer<T extends BaseDraggingActivity>
+ implements InputConsumer {
+
+ private final CachedEventDispatcher mCachedEventDispatcher = new CachedEventDispatcher();
+ private final T mActivity;
+ private final BaseDragLayer mTarget;
+ private final int[] mLocationOnScreen = new int[2];
+ private final PointF mDownPos = new PointF();
+ private final int mTouchSlop;
+
+ private final boolean mStartingInActivityBounds;
+
+ private boolean mTrackingStarted = false;
+ private boolean mInvalidated = false;
+
+ OverviewInputConsumer(T activity, boolean startingInActivityBounds) {
+ mActivity = activity;
+ mTarget = activity.getDragLayer();
+ mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
+ mStartingInActivityBounds = startingInActivityBounds;
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent ev) {
+ if (mInvalidated) {
+ return;
+ }
+ mCachedEventDispatcher.dispatchEvent(ev);
+ int action = ev.getActionMasked();
+ if (action == ACTION_DOWN) {
+ if (mStartingInActivityBounds) {
+ startTouchTracking(ev, false /* updateLocationOffset */,
+ false /* closeActiveWindows */);
+ return;
+ }
+ mTrackingStarted = false;
+ mDownPos.set(ev.getX(), ev.getY());
+ } else if (!mTrackingStarted) {
+ switch (action) {
+ case ACTION_CANCEL:
+ case ACTION_UP:
+ startTouchTracking(ev, true /* updateLocationOffset */,
+ false /* closeActiveWindows */);
+ break;
+ case ACTION_MOVE: {
+ float displacement = mActivity.getDeviceProfile().isLandscape ?
+ ev.getX() - mDownPos.x : ev.getY() - mDownPos.y;
+ if (Math.abs(displacement) >= mTouchSlop) {
+ // Start tracking only when mTouchSlop is crossed.
+ startTouchTracking(ev, true /* updateLocationOffset */,
+ true /* closeActiveWindows */);
+ }
+ }
+ }
+ }
+
+ if (action == ACTION_UP || action == ACTION_CANCEL) {
+ mInvalidated = true;
+
+ // Set an empty consumer to that all the cached events are cleared
+ if (!mCachedEventDispatcher.hasConsumer()) {
+ mCachedEventDispatcher.setConsumer(motionEvent -> { });
+ }
+ }
+ }
+
+ @Override
+ public void onKeyEvent(KeyEvent ev) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ mActivity.dispatchKeyEvent(ev);
+ }
+ }
+
+ private void startTouchTracking(MotionEvent ev, boolean updateLocationOffset,
+ boolean closeActiveWindows) {
+ if (updateLocationOffset) {
+ mTarget.getLocationOnScreen(mLocationOnScreen);
+ }
+
+ if (closeActiveWindows) {
+ OverviewCallbacks.get(mActivity).closeAllWindows();
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+ TOUCH_INTERACTION_LOG.startQuickStep();
+ }
+
+ mTrackingStarted = true;
+ mCachedEventDispatcher.setConsumer(this::sendEvent);
+
+ }
+
+ private void sendEvent(MotionEvent ev) {
+ if (mInvalidated || !mTarget.verifyTouchDispatch(this, ev)) {
+ mInvalidated = true;
+ return;
+ }
+ int flags = ev.getEdgeFlags();
+ ev.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
+ ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
+ if (ev.getAction() == ACTION_DOWN) {
+ mTarget.onInterceptTouchEvent(ev);
+ }
+ mTarget.onTouchEvent(ev);
+ ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
+ ev.setEdgeFlags(flags);
+ }
+
+ public static InputConsumer newInstance(ActivityControlHelper activityHelper,
+ boolean startingInActivityBounds) {
+ BaseDraggingActivity activity = activityHelper.getCreatedActivity();
+ if (activity == null) {
+ return InputConsumer.NO_OP;
+ }
+ return new OverviewInputConsumer(activity, startingInActivityBounds);
+ }
+}
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepProcessInitializer.java
new file mode 100644
index 0000000..befeee0
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.launcher3.BuildConfig;
+import com.android.launcher3.MainProcessInitializer;
+import com.android.systemui.shared.system.ThreadedRendererCompat;
+
+@SuppressWarnings("unused")
+public class QuickstepProcessInitializer extends MainProcessInitializer {
+
+ private static final String TAG = "QuickstepProcessInitializer";
+
+ public QuickstepProcessInitializer(Context context) { }
+
+ @Override
+ protected void init(Context context) {
+ // Workaround for b/120550382, an external app can cause the launcher process to start for
+ // a work profile user which we do not support. Disable the application immediately when we
+ // detect this to be the case.
+ UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if (um.isManagedProfile()) {
+ PackageManager pm = context.getPackageManager();
+ pm.setApplicationEnabledSetting(context.getPackageName(),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
+ Log.w(TAG, "Disabling " + BuildConfig.APPLICATION_ID
+ + ", unable to run in a managed profile");
+ return;
+ }
+
+ super.init(context);
+
+ // Elevate GPU priority for Quickstep and Remote animations.
+ ThreadedRendererCompat.setContextPriority(ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
similarity index 62%
rename from quickstep/src/com/android/quickstep/RecentsActivity.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index b76a1ab..5decc3e 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -15,13 +15,12 @@
*/
package com.android.quickstep;
-import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
-import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
-
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
-import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION;
-import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY;
-import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator;
+import static com.android.launcher3.QuickstepAppTransitionManagerImpl
+ .STATUS_BAR_TRANSITION_DURATION;
+import static com.android.launcher3.QuickstepAppTransitionManagerImpl
+ .STATUS_BAR_TRANSITION_PRE_DELAY;
+import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
@@ -29,23 +28,16 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
-import android.content.Intent;
import android.content.res.Configuration;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.uioverrides.UiFactory;
-import com.android.launcher3.util.SystemUiController;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
@@ -56,46 +48,22 @@
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
/**
- * A simple activity to show the recently launched tasks
+ * A recents activity that shows the recently launched tasks as swipable task cards.
+ * See {@link com.android.quickstep.views.RecentsView}.
*/
-public class RecentsActivity extends BaseDraggingActivity {
+public final class RecentsActivity extends BaseRecentsActivity {
private Handler mUiHandler = new Handler(Looper.getMainLooper());
private RecentsRootView mRecentsRootView;
private FallbackRecentsView mFallbackRecentsView;
- private Configuration mOldConfig;
-
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mOldConfig = new Configuration(getResources().getConfiguration());
- initDeviceProfile();
-
+ protected void initViews() {
setContentView(R.layout.fallback_recents_activity);
mRecentsRootView = findViewById(R.id.drag_layer);
mFallbackRecentsView = findViewById(R.id.overview_panel);
-
mRecentsRootView.setup();
-
- getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
- Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
- RecentsActivityTracker.onRecentsActivityCreate(this);
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- int diff = newConfig.diff(mOldConfig);
- if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
- onHandleConfigChanged();
- }
- mOldConfig.setTo(newConfig);
- super.onConfigurationChanged(newConfig);
}
@Override
@@ -110,16 +78,10 @@
}
}
- private void onHandleConfigChanged() {
- mUserEventDispatcher = null;
- initDeviceProfile();
-
- AbstractFloatingView.closeOpenViews(this, true,
- AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
- dispatchDeviceProfileChanged();
-
+ @Override
+ protected void onHandleConfigChanged() {
+ super.onHandleConfigChanged();
mRecentsRootView.setup();
- reapplyUi();
}
@Override
@@ -127,15 +89,12 @@
mRecentsRootView.dispatchInsets();
}
- private void initDeviceProfile() {
+ @Override
+ protected DeviceProfile createDeviceProfile() {
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
-
- // In case we are reusing IDP, create a copy so that we don't conflict with Launcher
- // activity.
- mDeviceProfile = (mRecentsRootView != null) && isInMultiWindowMode()
+ return (mRecentsRootView != null) && isInMultiWindowMode()
? dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize())
- : dp.copy(this);
- onDeviceProfileInitiated();
+ : super.createDeviceProfile();
}
@Override
@@ -211,55 +170,4 @@
super.onStart();
mFallbackRecentsView.resetTaskVisuals();
}
-
- @Override
- protected void onStop() {
- super.onStop();
-
- // Workaround for b/78520668, explicitly trim memory once UI is hidden
- onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
- }
-
- @Override
- public void onEnterAnimationComplete() {
- super.onEnterAnimationComplete();
- UiFactory.onEnterAnimationComplete(this);
- }
-
- @Override
- public void onTrimMemory(int level) {
- super.onTrimMemory(level);
- UiFactory.onTrimMemory(this, level);
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- RecentsActivityTracker.onRecentsActivityNewIntent(this);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- RecentsActivityTracker.onRecentsActivityDestroy(this);
- }
-
- @Override
- public void onBackPressed() {
- // TODO: Launch the task we came from
- startHome();
- }
-
- public void startHome() {
- startActivity(new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- }
-
- @Override
- public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
- super.dump(prefix, fd, writer, args);
- writer.println(prefix + "Misc:");
- dumpMisc(writer);
- }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
new file mode 100644
index 0000000..f0bc223
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -0,0 +1,179 @@
+/*
+ * 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;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import com.android.launcher3.util.Preconditions;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
+import com.android.systemui.shared.system.InputConsumerController;
+
+import java.util.ArrayList;
+import java.util.function.Supplier;
+
+import androidx.annotation.UiThread;
+
+/**
+ * Wrapper around RecentsAnimationController to help with some synchronization
+ */
+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 SwipeAnimationTargetSet targetSet;
+
+ private boolean mWindowThresholdCrossed = false;
+
+ private final InputConsumerController mInputConsumerController;
+ private final Supplier<InputConsumer> mInputProxySupplier;
+
+ private InputConsumer mInputConsumer;
+ private boolean mTouchInProgress;
+
+ private boolean mFinishPending;
+
+ public RecentsAnimationWrapper(InputConsumerController inputConsumerController,
+ Supplier<InputConsumer> inputProxySupplier) {
+ mInputConsumerController = inputConsumerController;
+ mInputProxySupplier = inputProxySupplier;
+ }
+
+ @UiThread
+ public synchronized void setController(SwipeAnimationTargetSet targetSet) {
+ Preconditions.assertUIThread();
+ this.targetSet = targetSet;
+
+ if (targetSet == null) {
+ return;
+ }
+ targetSet.setWindowThresholdCrossed(mWindowThresholdCrossed);
+
+ 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();
+ }
+ }
+
+ /**
+ * @param onFinishComplete A callback that runs on the main thread after the animation
+ * controller has finished on the background thread.
+ */
+ @UiThread
+ public void finish(boolean toRecents, Runnable onFinishComplete) {
+ Preconditions.assertUIThread();
+ if (!toRecents) {
+ finishAndClear(false, onFinishComplete);
+ } else {
+ if (mTouchInProgress) {
+ mFinishPending = true;
+ // Execute the callback
+ if (onFinishComplete != null) {
+ onFinishComplete.run();
+ }
+ } else {
+ finishAndClear(true, onFinishComplete);
+ }
+ }
+ }
+
+ private void finishAndClear(boolean toRecents, Runnable onFinishComplete) {
+ SwipeAnimationTargetSet controller = targetSet;
+ targetSet = null;
+ if (controller != null) {
+ controller.finishController(toRecents, onFinishComplete);
+ }
+ }
+
+ public void enableInputConsumer() {
+ if (targetSet != null) {
+ targetSet.enableInputConsumer();
+ }
+ }
+
+ /**
+ * Indicates that the gesture has crossed the window boundary threshold and system UI can be
+ * update the represent the window behind
+ */
+ public void setWindowThresholdCrossed(boolean windowThresholdCrossed) {
+ if (mWindowThresholdCrossed != windowThresholdCrossed) {
+ mWindowThresholdCrossed = windowThresholdCrossed;
+ if (targetSet != null) {
+ targetSet.setWindowThresholdCrossed(windowThresholdCrossed);
+ }
+ }
+ }
+
+ public void enableInputProxy() {
+ mInputConsumerController.setInputListener(this::onInputConsumerEvent);
+ }
+
+ private boolean onInputConsumerEvent(InputEvent ev) {
+ if (ev instanceof MotionEvent) {
+ onInputConsumerMotionEvent((MotionEvent) ev);
+ } else if (ev instanceof KeyEvent) {
+ if (mInputConsumer == null) {
+ mInputConsumer = mInputProxySupplier.get();
+ }
+ mInputConsumer.onKeyEvent((KeyEvent) ev);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean onInputConsumerMotionEvent(MotionEvent ev) {
+ int action = ev.getAction();
+ if (action == ACTION_DOWN) {
+ mTouchInProgress = true;
+ if (mInputConsumer == null) {
+ mInputConsumer = mInputProxySupplier.get();
+ }
+ } else if (action == ACTION_CANCEL || action == ACTION_UP) {
+ // Finish any pending actions
+ mTouchInProgress = false;
+ if (mFinishPending) {
+ mFinishPending = false;
+ finishAndClear(true /* toRecents */, null);
+ }
+ }
+ if (mInputConsumer != null) {
+ mInputConsumer.onMotionEvent(ev);
+ }
+
+ return true;
+ }
+
+ public SwipeAnimationTargetSet getController() {
+ return targetSet;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
similarity index 70%
rename from quickstep/src/com/android/quickstep/SwipeSharedState.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
index 15914ba..7c6638a 100644
--- a/quickstep/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
@@ -15,6 +15,9 @@
*/
package com.android.quickstep;
+import android.util.Log;
+
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
@@ -25,23 +28,35 @@
*/
public class SwipeSharedState implements SwipeAnimationListener {
+ private final OverviewComponentObserver mOverviewComponentObserver;
+
private RecentsAnimationListenerSet mRecentsAnimationListener;
private SwipeAnimationTargetSet mLastAnimationTarget;
+
private boolean mLastAnimationCancelled = false;
+ private boolean mLastAnimationRunning = false;
public boolean canGestureBeContinued;
public boolean goingToLauncher;
+ public SwipeSharedState(OverviewComponentObserver overviewComponentObserver) {
+ mOverviewComponentObserver = overviewComponentObserver;
+ }
+
@Override
public final void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
mLastAnimationTarget = targetSet;
+
mLastAnimationCancelled = false;
+ mLastAnimationRunning = true;
}
@Override
public final void onRecentsAnimationCanceled() {
mLastAnimationTarget = null;
+
mLastAnimationCancelled = true;
+ mLastAnimationRunning = false;
}
private void clearListenerState() {
@@ -51,12 +66,31 @@
mRecentsAnimationListener = null;
mLastAnimationTarget = null;
mLastAnimationCancelled = false;
+ mLastAnimationRunning = false;
+ }
+
+ private void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet) {
+ if (mLastAnimationTarget == targetSet) {
+ mLastAnimationRunning = false;
+ }
}
public RecentsAnimationListenerSet newRecentsAnimationListenerSet() {
Preconditions.assertUIThread();
+
+ if (mLastAnimationRunning) {
+ String msg = "New animation started before completing old animation";
+ if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ throw new IllegalArgumentException(msg);
+ } else {
+ Log.e("SwipeSharedState", msg, new Exception());
+ }
+ }
+
clearListenerState();
- mRecentsAnimationListener = new RecentsAnimationListenerSet();
+ mRecentsAnimationListener = new RecentsAnimationListenerSet(mOverviewComponentObserver
+ .getActivityControlHelper().shouldMinimizeSplitScreen(),
+ this::onSwipeAnimationFinished);
mRecentsAnimationListener.addListener(this);
return mRecentsAnimationListener;
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
similarity index 95%
rename from quickstep/src/com/android/quickstep/TaskOverlayFactory.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index cc49d46..d979c99 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -31,8 +31,6 @@
import java.util.ArrayList;
import java.util.List;
-import androidx.annotation.AnyThread;
-
/**
* Factory class to create and add an overlays on the TaskView
*/
@@ -51,11 +49,6 @@
new MainThreadInitializedObject<>(c -> Overrides.getObject(TaskOverlayFactory.class,
c, R.string.task_overlay_factory_class));
- @AnyThread
- public boolean needAssist() {
- return false;
- }
-
public TaskOverlay createOverlay(View thumbnailView) {
return new TaskOverlay();
}
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/TaskSystemShortcut.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
new file mode 100644
index 0000000..4526d67
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
+
+import android.animation.ValueAnimator;
+import android.content.ComponentName;
+import android.graphics.RectF;
+import android.view.View;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Utilities;
+import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
+
+/**
+ * Utility class for helpful methods related to {@link TaskView} objects and their tasks.
+ */
+public final class TaskViewUtils {
+
+ private TaskViewUtils() {}
+
+ /**
+ * Try to find a TaskView that corresponds with the component of the launched view.
+ *
+ * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation.
+ * Otherwise, we will assume we are using a normal app transition, but it's possible that the
+ * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView.
+ */
+ public static TaskView findTaskViewToLaunch(
+ BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) {
+ RecentsView recentsView = activity.getOverviewPanel();
+ if (v instanceof TaskView) {
+ TaskView taskView = (TaskView) v;
+ return recentsView.isTaskViewVisible(taskView) ? taskView : null;
+ }
+
+ // It's possible that the launched view can still be resolved to a visible task view, check
+ // the task id of the opening task and see if we can find a match.
+ if (v.getTag() instanceof ItemInfo) {
+ ItemInfo itemInfo = (ItemInfo) v.getTag();
+ ComponentName componentName = itemInfo.getTargetComponent();
+ int userId = itemInfo.user.getIdentifier();
+ if (componentName != null) {
+ for (int i = 0; i < recentsView.getTaskViewCount(); i++) {
+ TaskView taskView = recentsView.getTaskViewAt(i);
+ if (recentsView.isTaskViewVisible(taskView)) {
+ Task.TaskKey key = taskView.getTask().key;
+ if (componentName.equals(key.getComponent()) && userId == key.userId) {
+ return taskView;
+ }
+ }
+ }
+ }
+ }
+
+ if (targets == null) {
+ return null;
+ }
+ // Resolve the opening task id
+ int openingTaskId = -1;
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == MODE_OPENING) {
+ openingTaskId = target.taskId;
+ break;
+ }
+ }
+
+ // If there is no opening task id, fall back to the normal app icon launch animation
+ if (openingTaskId == -1) {
+ return null;
+ }
+
+ // If the opening task id is not currently visible in overview, then fall back to normal app
+ // icon launch animation
+ TaskView taskView = recentsView.getTaskView(openingTaskId);
+ if (taskView == null || !recentsView.isTaskViewVisible(taskView)) {
+ return null;
+ }
+ return taskView;
+ }
+
+ /**
+ * @return Animator that controls the window of the opening targets for the recents launch
+ * animation.
+ */
+ public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
+ RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) {
+ ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams()
+ .setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(v));
+
+ final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
+ appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
+ appAnimator.addUpdateListener(new MultiValueUpdateListener() {
+
+ // Defer fading out the view until after the app window gets faded in
+ final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR);
+ final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR);
+
+ final RemoteAnimationTargetSet mTargetSet;
+
+ final RectF mThumbnailRect;
+
+ {
+ mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING);
+ inOutHelper.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value);
+
+ inOutHelper.prepareAnimation(true /* isOpening */);
+ inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(),
+ mTargetSet.apps.length == 0 ? null : mTargetSet.apps[0]);
+
+ mThumbnailRect = new RectF(inOutHelper.getTargetRect());
+ mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY());
+ Utilities.scaleRectFAboutCenter(mThumbnailRect, 1 / v.getScaleX());
+ }
+
+ @Override
+ public void onUpdate(float percent) {
+ params.setProgress(1 - percent);
+ RectF taskBounds = inOutHelper.applyTransform(mTargetSet, params);
+ if (!skipViewChanges) {
+ float scale = taskBounds.width() / mThumbnailRect.width();
+ v.setScaleX(scale);
+ v.setScaleY(scale);
+ v.setTranslationX(taskBounds.centerX() - mThumbnailRect.centerX());
+ v.setTranslationY(taskBounds.centerY() - mThumbnailRect.centerY());
+ v.setAlpha(mViewAlpha.value);
+ }
+ }
+ });
+ return appAnimator;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionLog.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionLog.java
similarity index 80%
rename from quickstep/src/com/android/quickstep/TouchInteractionLog.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionLog.java
index 053efbb..4b660d4 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionLog.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionLog.java
@@ -23,7 +23,7 @@
import java.util.LinkedList;
/**
- * Keeps track of debugging logs for a particular quickstep/scrub gesture.
+ * Keeps track of debugging logs for a particular quickstep gesture.
*/
public class TouchInteractionLog {
@@ -42,7 +42,7 @@
getCurrentLog().add("[" + mDateFormat.format(mCalendar.getTime()) + "]");
}
- public void setTouchConsumer(TouchConsumer consumer) {
+ public void setInputConsumer(InputConsumer consumer) {
getCurrentLog().add("tc=" + consumer.getClass().getSimpleName());
}
@@ -54,18 +54,6 @@
getCurrentLog().add("qstStart");
}
- public void startQuickScrub() {
- getCurrentLog().add("qsStart");
- }
-
- public void setQuickScrubProgress(float progress) {
- getCurrentLog().add("qsP=" + progress);
- }
-
- public void endQuickScrub(String reason) {
- getCurrentLog().add("qsEnd=" + reason);
- }
-
public void startRecentsAnimation() {
getCurrentLog().add("raStart");
}
@@ -82,14 +70,6 @@
getCurrentLog().add("raFinish=" + toHome);
}
- public void launchTaskStart() {
- getCurrentLog().add("launchStart");
- }
-
- public void launchTaskEnd(boolean result) {
- getCurrentLog().add("launchEnd=" + result);
- }
-
public void dump(PrintWriter pw) {
pw.println("TouchInteractionLog {");
for (ArrayList<String> gesture : mGestureLogs) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
new file mode 100644
index 0000000..ddf3ad5
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static android.view.MotionEvent.ACTION_DOWN;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_CHANNEL;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
+
+import android.annotation.TargetApi;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.Region;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Choreographer;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.util.UiThreadHelper;
+import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher;
+import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
+import com.android.systemui.shared.system.InputConsumerController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Service connected by system-UI for handling touch interaction.
+ */
+@TargetApi(Build.VERSION_CODES.O)
+public class TouchInteractionService extends Service {
+
+ public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
+ public static final LooperExecutor BACKGROUND_EXECUTOR =
+ new LooperExecutor(UiThreadHelper.getBackgroundLooper());
+
+ public static final TouchInteractionLog TOUCH_INTERACTION_LOG = new TouchInteractionLog();
+
+ public static final int EDGE_NAV_BAR = 1 << 8;
+
+ private static final String TAG = "TouchInteractionService";
+
+ private final IBinder mMyBinder = new IOverviewProxy.Stub() {
+
+ public void onActiveNavBarRegionChanges(Region region) {
+ mActiveNavBarRegion = region;
+ }
+
+ public void onInitialize(Bundle bundle) {
+ mISystemUiProxy = ISystemUiProxy.Stub
+ .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
+ mRecentsModel.setSystemUiProxy(mISystemUiProxy);
+ mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
+
+ disposeEventHandlers();
+ mInputEventReceiver = InputChannelCompat.fromBundle(bundle, KEY_EXTRA_INPUT_CHANNEL,
+ Looper.getMainLooper(), mMainChoreographer,
+ TouchInteractionService.this::onInputEvent);
+ }
+
+ @Override
+ public void onOverviewToggle() {
+ mOverviewCommandHelper.onOverviewToggle();
+ }
+
+ @Override
+ public void onOverviewShown(boolean triggeredFromAltTab) {
+ mOverviewCommandHelper.onOverviewShown(triggeredFromAltTab);
+ }
+
+ @Override
+ public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+ if (triggeredFromAltTab && !triggeredFromHomeKey) {
+ // onOverviewShownFromAltTab hides the overview and ends at the target app
+ mOverviewCommandHelper.onOverviewHidden();
+ }
+ }
+
+ @Override
+ public void onTip(int actionType, int viewType) {
+ mOverviewCommandHelper.onTip(actionType, viewType);
+ }
+
+ /** Deprecated methods **/
+ public void onQuickStep(MotionEvent motionEvent) { }
+
+ public void onQuickScrubEnd() { }
+
+ public void onQuickScrubProgress(float progress) { }
+
+ public void onQuickScrubStart() { }
+
+ public void onPreMotionEvent(int downHitTarget) { }
+
+ public void onMotionEvent(MotionEvent ev) {
+ if (mDeprecatedDispatcher == null) {
+ ev.recycle();
+ } else {
+ mDeprecatedDispatcher.dispatch(ev);
+ }
+ }
+
+ public void onBind(ISystemUiProxy iSystemUiProxy) {
+ mISystemUiProxy = iSystemUiProxy;
+ mRecentsModel.setSystemUiProxy(mISystemUiProxy);
+ mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
+
+ // On Bind is received before onInitialize which will dispose these handlers
+ disposeEventHandlers();
+ Pair<InputEventDispatcher, InputEventReceiver> pair = InputChannelCompat.createPair(
+ "sysui-callbacks", Looper.getMainLooper(), mMainChoreographer,
+ TouchInteractionService.this::onInputEvent);
+ mDeprecatedDispatcher = pair.first;
+ mInputEventReceiver = pair.second;
+
+ }
+ };
+
+ private static boolean sConnected = false;
+
+ public static boolean isConnected() {
+ return sConnected;
+ }
+
+ private ActivityManagerWrapper mAM;
+ private RecentsModel mRecentsModel;
+ private ISystemUiProxy mISystemUiProxy;
+ private OverviewCommandHelper mOverviewCommandHelper;
+ private OverviewComponentObserver mOverviewComponentObserver;
+ private OverviewInteractionState mOverviewInteractionState;
+ private OverviewCallbacks mOverviewCallbacks;
+ private TaskOverlayFactory mTaskOverlayFactory;
+ private InputConsumerController mInputConsumer;
+ private SwipeSharedState mSwipeSharedState;
+
+ private InputConsumer mConsumer = InputConsumer.NO_OP;
+ private Choreographer mMainChoreographer;
+
+ private InputEventReceiver mInputEventReceiver;
+ private Region mActiveNavBarRegion = new Region();
+
+ private InputEventDispatcher mDeprecatedDispatcher;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mAM = ActivityManagerWrapper.getInstance();
+ mRecentsModel = RecentsModel.INSTANCE.get(this);
+ mOverviewComponentObserver = new OverviewComponentObserver(this);
+ mMainChoreographer = Choreographer.getInstance();
+
+ mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver);
+ mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
+ mOverviewCallbacks = OverviewCallbacks.get(this);
+ mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
+ mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver);
+ mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
+ mInputConsumer.registerInputConsumer();
+
+ sConnected = true;
+
+ // Temporarily disable model preload
+ // new ModelPreload().start(this);
+ }
+
+ @Override
+ public void onDestroy() {
+ mInputConsumer.unregisterInputConsumer();
+ mOverviewComponentObserver.onDestroy();
+ disposeEventHandlers();
+ sConnected = false;
+ super.onDestroy();
+ }
+
+ private void disposeEventHandlers() {
+ if (mInputEventReceiver != null) {
+ mInputEventReceiver.dispose();
+ mInputEventReceiver = null;
+ }
+ if (mDeprecatedDispatcher != null) {
+ mDeprecatedDispatcher.dispose();
+ mDeprecatedDispatcher = null;
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.d(TAG, "Touch service connected");
+ return mMyBinder;
+ }
+
+ private void onInputEvent(InputEvent ev) {
+ if (!(ev instanceof MotionEvent)) {
+ Log.e(TAG, "Unknown event " + ev);
+ return;
+ }
+ MotionEvent event = (MotionEvent) ev;
+ if (event.getAction() == ACTION_DOWN) {
+ TOUCH_INTERACTION_LOG.prepareForNewGesture();
+ boolean useSharedState = mConsumer.isActive();
+ mConsumer.onConsumerAboutToBeSwitched();
+ mConsumer = newConsumer(useSharedState, event);
+ TOUCH_INTERACTION_LOG.setInputConsumer(mConsumer);
+ }
+ TOUCH_INTERACTION_LOG.addMotionEvent(event);
+
+ mConsumer.onMotionEvent(event);
+ }
+
+ private InputConsumer newConsumer(boolean useSharedState, MotionEvent event) {
+ RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
+ if (!useSharedState) {
+ mSwipeSharedState.clearAllState();
+ }
+
+ if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher) {
+ return InputConsumer.NO_OP;
+ } else if (mSwipeSharedState.goingToLauncher ||
+ mOverviewComponentObserver.getActivityControlHelper().isResumed()) {
+ return OverviewInputConsumer.newInstance(
+ mOverviewComponentObserver.getActivityControlHelper(), false);
+ } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
+ mOverviewComponentObserver.getActivityControlHelper().isInLiveTileMode()) {
+ return OverviewInputConsumer.newInstance(
+ mOverviewComponentObserver.getActivityControlHelper(), false);
+ } else {
+ ActivityControlHelper activityControl =
+ mOverviewComponentObserver.getActivityControlHelper();
+ boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
+ return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
+ mOverviewComponentObserver.getOverviewIntent(), activityControl,
+ shouldDefer, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer,
+ this::onConsumerInactive, mSwipeSharedState);
+ }
+ }
+
+ /**
+ * To be called by the consumer when it's no longer active.
+ */
+ private void onConsumerInactive(InputConsumer caller) {
+ if (mConsumer == caller) {
+ mConsumer = InputConsumer.NO_OP;
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ TOUCH_INTERACTION_LOG.dump(pw);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
similarity index 70%
rename from quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index bc4e094..4d0136e 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -25,16 +25,14 @@
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+import static com.android.launcher3.config.FeatureFlags.SWIPE_HOME;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
-import static com.android.launcher3.config.FeatureFlags.SWIPE_HOME;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_FROM_APP_START_DURATION;
-import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_FROM_APP_START_DURATION;
-import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
-import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
+import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK;
@@ -50,28 +48,23 @@
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
+import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.Interpolator;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -81,7 +74,6 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -90,110 +82,93 @@
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
-import com.android.quickstep.ActivityControlHelper.LayoutListener;
-import com.android.quickstep.TouchConsumer.InteractionType;
-import com.android.quickstep.TouchInteractionService.OverviewTouchConsumer;
+import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
-import com.android.quickstep.util.TransformedRect;
+import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.recents.utilities.RectFEvaluator;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
@TargetApi(Build.VERSION_CODES.O)
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
- implements SwipeAnimationListener {
+ implements SwipeAnimationListener, OnApplyWindowInsetsListener {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
+ private static final String[] STATE_NAMES = DEBUG_STATES ? new String[19] : null;
+
+ private static int getFlagForIndex(int index, String name) {
+ if (DEBUG_STATES) {
+ STATE_NAMES[index] = name;
+ }
+ return 1 << index;
+ }
+
// Launcher UI related states
- private static final int STATE_LAUNCHER_PRESENT = 1 << 0;
- private static final int STATE_LAUNCHER_STARTED = 1 << 1;
- private static final int STATE_LAUNCHER_DRAWN = 1 << 2;
- private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 3;
+ private static final int STATE_LAUNCHER_PRESENT = getFlagForIndex(0, "STATE_LAUNCHER_PRESENT");
+ private static final int STATE_LAUNCHER_STARTED = getFlagForIndex(1, "STATE_LAUNCHER_STARTED");
+ private static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN");
+ private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE =
+ getFlagForIndex(3, "STATE_ACTIVITY_MULTIPLIER_COMPLETE");
// Internal initialization states
- private static final int STATE_APP_CONTROLLER_RECEIVED = 1 << 4;
+ private static final int STATE_APP_CONTROLLER_RECEIVED =
+ getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
// Interaction finish states
- private static final int STATE_SCALED_CONTROLLER_HOME = 1 << 5;
- private static final int STATE_SCALED_CONTROLLER_RECENTS = 1 << 6;
- private static final int STATE_SCALED_CONTROLLER_LAST_TASK = 1 << 7;
+ private static final int STATE_SCALED_CONTROLLER_HOME =
+ getFlagForIndex(5, "STATE_SCALED_CONTROLLER_HOME");
+ private static final int STATE_SCALED_CONTROLLER_RECENTS =
+ getFlagForIndex(6, "STATE_SCALED_CONTROLLER_RECENTS");
+ private static final int STATE_SCALED_CONTROLLER_LAST_TASK =
+ getFlagForIndex(7, "STATE_SCALED_CONTROLLER_LAST_TASK");
- private static final int STATE_HANDLER_INVALIDATED = 1 << 8;
- private static final int STATE_GESTURE_STARTED_QUICKSTEP = 1 << 9;
- private static final int STATE_GESTURE_STARTED_QUICKSCRUB = 1 << 10;
- private static final int STATE_GESTURE_CANCELLED = 1 << 11;
- private static final int STATE_GESTURE_COMPLETED = 1 << 12;
+ private static final int STATE_HANDLER_INVALIDATED =
+ getFlagForIndex(8, "STATE_HANDLER_INVALIDATED");
+ private static final int STATE_GESTURE_STARTED =
+ getFlagForIndex(9, "STATE_GESTURE_STARTED");
+ private static final int STATE_GESTURE_CANCELLED =
+ getFlagForIndex(10, "STATE_GESTURE_CANCELLED");
+ private static final int STATE_GESTURE_COMPLETED =
+ getFlagForIndex(11, "STATE_GESTURE_COMPLETED");
- // States for quick switch/scrub
- private static final int STATE_CURRENT_TASK_FINISHED = 1 << 13;
- private static final int STATE_QUICK_SCRUB_START = 1 << 14;
- private static final int STATE_QUICK_SCRUB_END = 1 << 15;
+ private static final int STATE_CAPTURE_SCREENSHOT =
+ getFlagForIndex(12, "STATE_CAPTURE_SCREENSHOT");
+ private static final int STATE_SCREENSHOT_CAPTURED =
+ getFlagForIndex(13, "STATE_SCREENSHOT_CAPTURED");
+ private static final int STATE_SCREENSHOT_VIEW_SHOWN =
+ getFlagForIndex(14, "STATE_SCREENSHOT_VIEW_SHOWN");
- private static final int STATE_CAPTURE_SCREENSHOT = 1 << 16;
- private static final int STATE_SCREENSHOT_CAPTURED = 1 << 17;
- private static final int STATE_SCREENSHOT_VIEW_SHOWN = 1 << 18;
-
- private static final int STATE_RESUME_LAST_TASK = 1 << 19;
- private static final int STATE_START_NEW_TASK = 1 << 20;
- private static final int STATE_ASSIST_DATA_RECEIVED = 1 << 21;
-
+ private static final int STATE_RESUME_LAST_TASK =
+ getFlagForIndex(15, "STATE_RESUME_LAST_TASK");
+ private static final int STATE_START_NEW_TASK =
+ getFlagForIndex(16, "STATE_START_NEW_TASK");
+ private static final int STATE_CURRENT_TASK_FINISHED =
+ getFlagForIndex(17, "STATE_CURRENT_TASK_FINISHED");
private static final int LAUNCHER_UI_STATES =
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE
| STATE_LAUNCHER_STARTED;
- private static final int LONG_SWIPE_ENTER_STATE =
- STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED
- | STATE_APP_CONTROLLER_RECEIVED;
-
- private static final int LONG_SWIPE_START_STATE =
- STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED
- | STATE_APP_CONTROLLER_RECEIVED | STATE_SCREENSHOT_CAPTURED;
-
- private static final int QUICK_SCRUB_START_UI_STATE = STATE_LAUNCHER_STARTED
- | STATE_QUICK_SCRUB_START | STATE_APP_CONTROLLER_RECEIVED;
-
// For debugging, keep in sync with above states
- public static final String[] STATES = new String[] {
- "STATE_LAUNCHER_PRESENT",
- "STATE_LAUNCHER_STARTED",
- "STATE_LAUNCHER_DRAWN",
- "STATE_ACTIVITY_MULTIPLIER_COMPLETE",
- "STATE_APP_CONTROLLER_RECEIVED",
- "STATE_SCALED_CONTROLLER_HOME",
- "STATE_SCALED_CONTROLLER_RECENTS",
- "STATE_SCALED_CONTROLLER_LAST_TASK",
- "STATE_HANDLER_INVALIDATED",
- "STATE_GESTURE_STARTED_QUICKSTEP",
- "STATE_GESTURE_STARTED_QUICKSCRUB",
- "STATE_GESTURE_CANCELLED",
- "STATE_GESTURE_COMPLETED",
- "STATE_CURRENT_TASK_FINISHED",
- "STATE_QUICK_SCRUB_START",
- "STATE_QUICK_SCRUB_END",
- "STATE_CAPTURE_SCREENSHOT",
- "STATE_SCREENSHOT_CAPTURED",
- "STATE_SCREENSHOT_VIEW_SHOWN",
- "STATE_RESUME_LAST_TASK",
- "STATE_START_NEW_TASK",
- "STATE_ASSIST_DATA_RECEIVED",
- };
enum GestureEndTarget {
HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE),
@@ -214,11 +189,15 @@
this.containerType = containerType;
}
- // 0 is app, 1 is overview
+ /** 0 is app, 1 is overview */
public final float endShift;
+ /** The state to apply when we reach this final target */
public final int endState;
+ /** Whether the target is in the launcher activity */
public final boolean isLauncher;
+ /** Whether the user can start a new gesture while this one is finishing */
public final boolean canBeContinued;
+ /** Used to log where the user ended up after the gesture ends */
public final int containerType;
}
@@ -257,7 +236,6 @@
private final Context mContext;
private final ActivityControlHelper<T> mActivityControlHelper;
private final ActivityInitListener mActivityInitListener;
- private final TouchInteractionLog mTouchInteractionLog;
private final int mRunningTaskId;
private final RunningTaskInfo mRunningTaskInfo;
@@ -267,36 +245,25 @@
private AnimatorPlaybackController mLauncherTransitionController;
private T mActivity;
- private LayoutListener mLayoutListener;
private RecentsView mRecentsView;
private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
- private QuickScrubController mQuickScrubController;
- private AnimationFactory mAnimationFactory = (t, i) -> { };
+ private AnimationFactory mAnimationFactory = (t) -> { };
+ private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
private boolean mWasLauncherAlreadyVisible;
private boolean mPassedOverviewThreshold;
private boolean mGestureStarted;
private int mLogAction = Touch.SWIPE;
- private float mCurrentQuickScrubProgress;
- private boolean mQuickScrubBlocked;
-
- private @InteractionType int mInteractionType = INTERACTION_NORMAL;
private final RecentsAnimationWrapper mRecentsAnimationWrapper;
private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime;
- private boolean mLongSwipeMode = false;
- private float mLongSwipeDisplacement = 0;
- private LongSwipeHelper mLongSwipeController;
-
- private Bundle mAssistData;
-
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
- InputConsumerController inputConsumer, TouchInteractionLog touchInteractionLog) {
+ InputConsumerController inputConsumer) {
mContext = context;
mRunningTaskInfo = runningTaskInfo;
mRunningTaskId = runningTaskInfo.id;
@@ -305,9 +272,8 @@
mActivityInitListener = mActivityControlHelper
.createActivityInitListener(this::onActivityInit);
mContinuingLastGesture = continuingLastGesture;
- mTouchInteractionLog = touchInteractionLog;
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
- this::createNewTouchProxyHandler);
+ this::createNewInputProxyHandler);
mClipAnimationHelper = new ClipAnimationHelper(context);
mTransformParams = new ClipAnimationHelper.TransformParams();
@@ -315,24 +281,20 @@
}
private void initStateCallbacks() {
- mStateCallback = new MultiStateCallback();
+ mStateCallback = new MultiStateCallback(STATE_NAMES);
// Re-setup the recents UI when gesture starts, as the state could have been changed during
// that time by a previous window transition.
- mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_GESTURE_STARTED_QUICKSTEP,
+ mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_GESTURE_STARTED,
this::setupRecentsViewUi);
- mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED_QUICKSCRUB,
- this::initializeLauncherAnimationController);
- mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED_QUICKSTEP,
+ mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED,
this::initializeLauncherAnimationController);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
this::launcherFrameDrawn);
- mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED_QUICKSTEP,
- this::notifyGestureStartedAsync);
- mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED_QUICKSCRUB,
+ mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
this::notifyGestureStartedAsync);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
@@ -368,13 +330,8 @@
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS
| STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED
- | STATE_GESTURE_STARTED_QUICKSTEP,
+ | STATE_GESTURE_STARTED,
this::setupLauncherUiAfterSwipeUpAnimation);
- mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
- | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS
- | STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED
- | STATE_GESTURE_STARTED_QUICKSTEP | STATE_ASSIST_DATA_RECEIVED,
- this::preloadAssistData);
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
@@ -383,14 +340,8 @@
| STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled);
- mStateCallback.addCallback(QUICK_SCRUB_START_UI_STATE, this::onQuickScrubStartUi);
- mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START
- | STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub);
- mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_CURRENT_TASK_FINISHED
- | STATE_QUICK_SCRUB_END, this::switchToFinalAppAfterQuickScrub);
-
- mStateCallback.addCallback(LONG_SWIPE_ENTER_STATE, this::checkLongSwipeCanEnter);
- mStateCallback.addCallback(LONG_SWIPE_START_STATE, this::checkLongSwipeCanStart);
+ mStateCallback.addCallback(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
+ mRecentsAnimationWrapper::enableInputConsumer);
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
@@ -410,9 +361,9 @@
private void initTransitionEndpoints(DeviceProfile dp) {
mDp = dp;
- TransformedRect tempRect = new TransformedRect();
+ Rect tempRect = new Rect();
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
- dp, mContext, mInteractionType, tempRect);
+ dp, mContext, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect);
}
@@ -441,7 +392,6 @@
int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
initStateCallbacks();
mStateCallback.setState(oldState);
- mLayoutListener.setHandler(null);
}
mWasLauncherAlreadyVisible = alreadyOnHome;
mActivity = activity;
@@ -454,19 +404,18 @@
}
mRecentsView = activity.getOverviewPanel();
- SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, (applier) -> {
- mSyncTransactionApplier = applier;
- });
+ SyncRtSurfaceTransactionApplierCompat.create(mRecentsView,
+ applier -> mSyncTransactionApplier = applier );
mRecentsView.setEnableFreeScroll(false);
+
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
- if (!mLongSwipeMode && mGestureEndTarget != HOME) {
+ if (mGestureEndTarget != HOME) {
updateFinalShift();
}
});
mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
- mQuickScrubController = mRecentsView.getQuickScrubController();
- mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity);
+ mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
mStateCallback.setState(STATE_LAUNCHER_PRESENT);
if (alreadyOnHome) {
@@ -512,7 +461,7 @@
}
setupRecentsViewUi();
- mLayoutListener.open();
+ activity.getRootView().setOnApplyWindowInsetsListener(this);
mStateCallback.setState(STATE_LAUNCHER_STARTED);
}
@@ -554,45 +503,18 @@
}
private void initializeLauncherAnimationController() {
- mLayoutListener.setHandler(this);
buildAnimationController();
if (LatencyTrackerCompat.isEnabled(mContext)) {
LatencyTrackerCompat.logToggleRecents((int) (mLauncherFrameDrawnTime - mTouchTimeMs));
}
- // This method is only called when STATE_GESTURE_STARTED_QUICKSTEP/
- // STATE_GESTURE_STARTED_QUICKSCRUB is set, so we can enable the high-res thumbnail loader
- // here once we are sure that we will end up in an overview state
+ // This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
+ // high-res thumbnail loader here once we are sure that we will end up in an overview state
RecentsModel.INSTANCE.get(mContext).getThumbnailCache()
.getHighResLoadingState().setVisible(true);
}
- 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();
- scale = getTaskCurveScaleForOffsetX(offsetX, tempRect.rect.width());
- }
- mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
- QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
- }
-
private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 +
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
@@ -600,24 +522,8 @@
return TaskView.getCurveScaleForInterpolation(interpolation);
}
- @UiThread
- public void dispatchMotionEventToRecentsView(MotionEvent event, @Nullable Float velocityX) {
- if (mRecentsView == null) {
- return;
- }
- // Pass the motion events to RecentsView to allow scrolling during swipe up.
- if (!mDispatchedDownEvent) {
- // The first event we dispatch should be ACTION_DOWN.
- mDispatchedDownEvent = true;
- MotionEvent downEvent = MotionEvent.obtain(event);
- downEvent.setAction(MotionEvent.ACTION_DOWN);
- int flags = downEvent.getEdgeFlags();
- downEvent.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
- mRecentsView.simulateTouchEvent(downEvent, velocityX);
- downEvent.recycle();
- }
-
- mRecentsView.simulateTouchEvent(event, velocityX);
+ public Consumer<MotionEvent> getRecentsViewDispatcher() {
+ return mRecentsView != null ? mRecentsView::dispatchTouchEvent : null;
}
@UiThread
@@ -626,16 +532,7 @@
displacement = -displacement;
if (displacement > mTransitionDragLength && mTransitionDragLength > 0) {
mCurrentShift.updateValue(1);
-
- if (!mLongSwipeMode && !FeatureFlags.SWIPE_HOME.get()) {
- onLongSwipeEnabled();
- }
- mLongSwipeDisplacement = displacement - mTransitionDragLength;
- onLongSwipeDisplacementUpdated();
} else {
- if (mLongSwipeMode) {
- onLongSwipeDisabled();
- }
float translation = Math.max(displacement, 0);
float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
mCurrentShift.updateValue(shift);
@@ -648,22 +545,24 @@
@UiThread
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
- if (mInteractionType == INTERACTION_NORMAL) {
- mAnimationFactory.setShelfState(shelfState, interpolator, duration);
- mIsShelfPeeking = shelfState == PEEK;
- if (mRecentsView != null && shelfState.shouldPreformHaptic) {
- mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- }
+ mAnimationFactory.setShelfState(shelfState, interpolator, duration);
+ mIsShelfPeeking = shelfState == PEEK;
+ if (mRecentsView != null && shelfState.shouldPreformHaptic) {
+ mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
- /**
- * Called by {@link #mLayoutListener} when launcher layout changes
- */
- public void buildAnimationController() {
+ private void buildAnimationController() {
initTransitionEndpoints(mActivity.getDeviceProfile());
- mAnimationFactory.createActivityController(mTransitionDragLength, mInteractionType);
+ mAnimationFactory.createActivityController(mTransitionDragLength);
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
+ WindowInsets result = view.onApplyWindowInsets(windowInsets);
+ buildAnimationController();
+ return result;
}
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
@@ -676,10 +575,10 @@
private void updateFinalShift() {
float shift = mCurrentShift.value;
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
float offsetX = 0;
- if (mRecentsView != null && mInteractionType == INTERACTION_NORMAL) {
+ if (mRecentsView != null) {
int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(
mRecentsView.getRunningTaskView()));
offsetX = startScroll - mRecentsView.getScrollX();
@@ -691,19 +590,13 @@
.setSyncTransactionApplier(mSyncTransactionApplier);
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
mTransformParams);
-
- boolean passedThreshold = shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
- mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold);
- if (mActivityControlHelper.shouldMinimizeSplitScreen()) {
- mRecentsAnimationWrapper.setSplitScreenMinimizedForTransaction(passedThreshold);
- }
+ mRecentsAnimationWrapper.setWindowThresholdCrossed(
+ shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
- mLayoutListener.open();
- mLayoutListener.update(mCurrentShift.value > 1, mLongSwipeMode,
- mClipAnimationHelper.getCurrentRectWithInsets(),
+ if (mRecentsAnimationWrapper.getController() != null) {
+ mLiveTileOverlay.update(mClipAnimationHelper.getCurrentRectWithInsets(),
mClipAnimationHelper.getCurrentCornerRadius());
}
}
@@ -711,15 +604,14 @@
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (passed != mPassedOverviewThreshold) {
mPassedOverviewThreshold = passed;
- if (mInteractionType == INTERACTION_NORMAL && mRecentsView != null
- && !SWIPE_HOME.get()) {
+ if (mRecentsView != null && !SWIPE_HOME.get()) {
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
// Update insets of the non-running tasks, as we might switch to them.
int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex();
- if (mInteractionType == INTERACTION_NORMAL && runningTaskIndex >= 0) {
+ if (runningTaskIndex >= 0) {
for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) {
if (i != runningTaskIndex) {
mRecentsView.getTaskViewAt(i).setFullscreenProgress(1 - mCurrentShift.value);
@@ -778,8 +670,8 @@
mClipAnimationHelper.prepareAnimation(false /* isOpening */);
initTransitionEndpoints(dp);
- mRecentsAnimationWrapper.setController(targetSet.controller, targetSet);
- mTouchInteractionLog.startRecentsAnimationCallback(targetSet.apps.length);
+ mRecentsAnimationWrapper.setController(targetSet);
+ TOUCH_INTERACTION_LOG.startRecentsAnimationCallback(targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
mPassedOverviewThreshold = false;
@@ -787,21 +679,18 @@
@Override
public void onRecentsAnimationCanceled() {
- mRecentsAnimationWrapper.setController(null, null);
+ mRecentsAnimationWrapper.setController(null);
mActivityInitListener.unregister();
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
- mTouchInteractionLog.cancelRecentsAnimation();
+ TOUCH_INTERACTION_LOG.cancelRecentsAnimation();
}
@UiThread
public void onGestureStarted() {
notifyGestureStartedAsync();
mShiftAtGestureStart = mCurrentShift.value;
- setStateOnUiThread(mInteractionType == INTERACTION_NORMAL
- ? STATE_GESTURE_STARTED_QUICKSTEP : STATE_GESTURE_STARTED_QUICKSCRUB);
+ setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
- mRecentsAnimationWrapper.hideCurrentInputMethod();
- mRecentsAnimationWrapper.enableInputConsumer();
}
/**
@@ -825,16 +714,11 @@
setStateOnUiThread(STATE_GESTURE_COMPLETED);
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
-
- if (mLongSwipeMode) {
- onLongSwipeGestureFinish(endVelocity, isFling, velocityX);
- } else {
- handleNormalGestureEnd(endVelocity, isFling, velocityX);
- }
+ handleNormalGestureEnd(endVelocity, isFling, velocityX);
}
@UiThread
- private TouchConsumer createNewTouchProxyHandler() {
+ private InputConsumer createNewInputProxyHandler() {
mCurrentShift.finishAnimation();
if (mLauncherTransitionController != null) {
mLauncherTransitionController.getAnimationPlayer().end();
@@ -844,8 +728,7 @@
setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
}
- return OverviewTouchConsumer.newInstance(mActivityControlHelper, true,
- mTouchInteractionLog);
+ return OverviewInputConsumer.newInstance(mActivityControlHelper, true);
}
@UiThread
@@ -939,7 +822,7 @@
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
} else if (endTarget == RECENTS) {
- mRecentsAnimationWrapper.enableTouchProxy();
+ mRecentsAnimationWrapper.enableInputProxy();
if (mRecentsView != null) {
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
@@ -989,13 +872,24 @@
private void animateToProgressInternal(float start, float end, long duration,
Interpolator interpolator, GestureEndTarget target, float velocityPxPerMs) {
mGestureEndTarget = target;
- ActivityControlHelper.HomeAnimationFactory homeAnimFactory;
+
+ if (mGestureEndTarget.canBeContinued) {
+ // Because we might continue this gesture, e.g. for consecutive quick switch, we need to
+ // stabilize the task list so that tasks don't rearrange in the middle of the gesture.
+ RecentsModel.INSTANCE.get(mContext).startStabilizationSession();
+ } else if (mGestureEndTarget.isLauncher) {
+ // Otherwise, if we're going to home or overview,
+ // we reset the tasks to a consistent start state.
+ RecentsModel.INSTANCE.get(mContext).endStabilizationSession();
+ }
+
+ HomeAnimationFactory homeAnimFactory;
Animator windowAnim;
if (mGestureEndTarget == HOME) {
if (mActivity != null) {
homeAnimFactory = mActivityControlHelper.prepareHomeUI(mActivity);
} else {
- homeAnimFactory = new ActivityControlHelper.HomeAnimationFactory() {
+ homeAnimFactory = new HomeAnimationFactory() {
@NonNull
@Override
public RectF getWindowTargetRect() {
@@ -1013,7 +907,7 @@
mStateCallback.addChangeHandler(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
isPresent -> mRecentsView.startHome());
}
- windowAnim = createWindowAnimationToHome(start, homeAnimFactory.getWindowTargetRect());
+ windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
mLauncherTransitionController = null;
} else {
windowAnim = mCurrentShift.animateToValue(start, end);
@@ -1063,20 +957,25 @@
/**
* Creates an Animator that transforms the current app window into the home app.
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
- * @param endTarget Where to animate the window towards.
+ * @param homeAnimationFactory The home animation factory.
*/
- private Animator createWindowAnimationToHome(float startProgress, RectF endTarget) {
+ private Animator createWindowAnimationToHome(float startProgress,
+ HomeAnimationFactory homeAnimationFactory) {
final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet;
RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet,
mTransformParams.setProgress(startProgress)));
RectF originalTarget = new RectF(mClipAnimationHelper.getTargetRect());
- final RectF finalTarget = endTarget;
+ final RectF finalTarget = homeAnimationFactory.getWindowTargetRect();
final RectFEvaluator rectFEvaluator = new RectFEvaluator();
final RectF targetRect = new RectF();
final RectF currentRect = new RectF();
+ final View floatingView = homeAnimationFactory.getFloatingView();
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+ if (floatingView instanceof FloatingIconView) {
+ anim.addListener((FloatingIconView) floatingView);
+ }
anim.addUpdateListener(animation -> {
float progress = animation.getAnimatedFraction();
float interpolatedProgress = Interpolators.ACCEL_2.getInterpolation(progress);
@@ -1091,6 +990,10 @@
mTransformParams.setCurrentRectAndTargetAlpha(currentRect, alpha)
.setSyncTransactionApplier(mSyncTransactionApplier);
mClipAnimationHelper.applyTransform(targetSet, mTransformParams);
+
+ if (floatingView instanceof FloatingIconView) {
+ ((FloatingIconView) floatingView).update(currentRect, 1f - alpha);
+ }
});
anim.addListener(new AnimationSuccessListener() {
@Override
@@ -1113,7 +1016,7 @@
@UiThread
private void resumeLastTask() {
mRecentsAnimationWrapper.finish(false /* toRecents */, null);
- mTouchInteractionLog.finishRecentsAnimation(false);
+ TOUCH_INTERACTION_LOG.finishRecentsAnimation(false);
}
@UiThread
@@ -1131,16 +1034,12 @@
mMainThreadHandler);
});
}
- mTouchInteractionLog.finishRecentsAnimation(false);
+ TOUCH_INTERACTION_LOG.finishRecentsAnimation(false);
doLogGesture(NEW_TASK);
}
public void reset() {
- if (mInteractionType != INTERACTION_QUICK_SCRUB) {
- // Only invalidate the handler if we are not quick scrubbing, otherwise, it will be
- // invalidated after the quick scrub ends
- setStateOnUiThread(STATE_HANDLER_INVALIDATED);
- }
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
public void cancel() {
@@ -1164,13 +1063,16 @@
private void invalidateHandlerWithLauncher() {
mLauncherTransitionController = null;
- mLayoutListener.finish();
mActivityControlHelper.getAlphaProperty(mActivity).setValue(1);
mRecentsView.setEnableFreeScroll(true);
mRecentsView.setRunningTaskIconScaledDown(false);
mRecentsView.setOnScrollChangeListener(null);
- mQuickScrubController.cancelActiveQuickscrub();
+ mRecentsView.setRunningTaskHidden(false);
+ mRecentsView.setEnableDrawingLiveTile(true);
+
+ mActivity.getRootView().setOnApplyWindowInsetsListener(null);
+ mActivity.getRootView().getOverlay().remove(mLiveTileOverlay);
}
private void notifyTransitionCancelled() {
@@ -1185,20 +1087,12 @@
mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
}
- public void layoutListenerClosed() {
- mRecentsView.setRunningTaskHidden(false);
- if (mWasLauncherAlreadyVisible && mLauncherTransitionController != null) {
- mLauncherTransitionController.setPlayFraction(1);
- }
- mRecentsView.setEnableDrawingLiveTile(true);
- }
-
private void switchToScreenshot() {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
} else {
boolean finishTransitionPosted = false;
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
if (mTaskSnapshot == null) {
@@ -1249,7 +1143,7 @@
() -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
}
}
- mTouchInteractionLog.finishRecentsAnimation(true);
+ TOUCH_INTERACTION_LOG.finishRecentsAnimation(true);
}
private void finishCurrentTransitionToHome() {
@@ -1257,7 +1151,7 @@
mRecentsAnimationWrapper.finish(true /* toRecents */,
() -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
}
- mTouchInteractionLog.finishRecentsAnimation(true);
+ TOUCH_INTERACTION_LOG.finishRecentsAnimation(true);
doLogGesture(HOME);
}
@@ -1278,183 +1172,16 @@
reset();
}
- public void onQuickScrubStart() {
- if (mInteractionType != INTERACTION_NORMAL) {
- throw new IllegalArgumentException(
- "Can't change interaction type from " + mInteractionType);
- }
- mInteractionType = INTERACTION_QUICK_SCRUB;
- mRecentsAnimationWrapper.runOnInit(this::shiftAnimationDestinationForQuickscrub);
-
- setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
-
- // Start the window animation without waiting for launcher.
- long duration = FeatureFlags.QUICK_SWITCH.get()
- ? QUICK_SWITCH_FROM_APP_START_DURATION
- : QUICK_SCRUB_FROM_APP_START_DURATION;
- animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, RECENTS, 1f);
- }
-
- private void onQuickScrubStartUi() {
- if (!mQuickScrubController.prepareQuickScrub(TAG, FeatureFlags.QUICK_SWITCH.get())) {
- mQuickScrubBlocked = true;
- setStateOnUiThread(STATE_RESUME_LAST_TASK | STATE_HANDLER_INVALIDATED);
- return;
- }
- if (mLauncherTransitionController != null) {
- mLauncherTransitionController.getAnimationPlayer().end();
- mLauncherTransitionController = null;
- }
-
- mActivityControlHelper.onQuickInteractionStart(mActivity, mRunningTaskInfo, false,
- mTouchInteractionLog);
-
- // Inform the last progress in case we skipped before.
- mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
- }
-
- private void onFinishedTransitionToQuickScrub() {
- if (mQuickScrubBlocked) {
- return;
- }
- mLayoutListener.finish();
- mQuickScrubController.onFinishedTransitionToQuickScrub();
-
- mRecentsView.animateUpRunningTaskIconScale();
- if (mQuickScrubController.isQuickSwitch()) {
- // Adjust the running task so that it is centered and fills the screen.
- TaskView runningTask = mRecentsView.getRunningTaskView();
- if (runningTask != null) {
- float insetHeight = mDp.heightPx - mDp.getInsets().top - mDp.getInsets().bottom;
- // Usually insetDiff will be 0, unless we allow apps to draw under the insets. In
- // that case (insetDiff != 0), we need to center in the system-specified available
- // height rather than launcher's inset height by adding half the insetDiff.
- float insetDiff = mDp.availableHeightPx - insetHeight;
- float topMargin = mActivity.getResources().getDimension(
- R.dimen.task_thumbnail_half_top_margin);
- runningTask.setTranslationY((insetDiff / 2 - topMargin) / mRecentsView.getScaleX());
- }
- }
- RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG);
- }
-
- public void onQuickScrubProgress(float progress) {
- mCurrentQuickScrubProgress = progress;
- if (mQuickScrubController == null || mQuickScrubBlocked ||
- !mStateCallback.hasStates(QUICK_SCRUB_START_UI_STATE)) {
- return;
- }
- mQuickScrubController.onQuickScrubProgress(progress);
- }
-
- public void onQuickScrubEnd() {
- setStateOnUiThread(STATE_QUICK_SCRUB_END);
- }
-
- private void switchToFinalAppAfterQuickScrub() {
- if (mQuickScrubBlocked) {
- return;
- }
- mQuickScrubController.onQuickScrubEnd();
-
- // Normally this is handled in reset(), but since we are still scrubbing after the
- // transition into recents, we need to defer the handler invalidation for quick scrub until
- // after the gesture ends
- setStateOnUiThread(STATE_HANDLER_INVALIDATED);
- }
-
public void setGestureEndCallback(Runnable gestureEndCallback) {
mGestureEndCallback = gestureEndCallback;
}
- // Handling long swipe
- private void onLongSwipeEnabled() {
- mLongSwipeMode = true;
- checkLongSwipeCanEnter();
- checkLongSwipeCanStart();
- }
-
- private void onLongSwipeDisabled() {
- mLongSwipeMode = false;
- mStateCallback.clearState(STATE_SCREENSHOT_VIEW_SHOWN);
-
- if (mLongSwipeController != null) {
- mLongSwipeController.destroy();
- setTargetAlphaProvider((t, a1) -> a1);
-
- // Rebuild animations
- buildAnimationController();
- }
- }
-
- private void onLongSwipeDisplacementUpdated() {
- if (!mLongSwipeMode || mLongSwipeController == null) {
- return;
- }
-
- mLongSwipeController.onMove(mLongSwipeDisplacement);
- }
-
- private void checkLongSwipeCanEnter() {
- if (!mLongSwipeMode || !mStateCallback.hasStates(LONG_SWIPE_ENTER_STATE)
- || !mActivityControlHelper.supportsLongSwipe(mActivity)) {
- return;
- }
-
- // We are entering long swipe mode, make sure the screen shot is captured.
- mStateCallback.setState(STATE_CAPTURE_SCREENSHOT | STATE_SCREENSHOT_VIEW_SHOWN);
-
- }
-
- private void checkLongSwipeCanStart() {
- if (!mLongSwipeMode || !mStateCallback.hasStates(LONG_SWIPE_START_STATE)
- || !mActivityControlHelper.supportsLongSwipe(mActivity)) {
- return;
- }
-
- RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet;
- if (targetSet == null) {
- // This can happen when cancelAnimation comes on the background thread, while we are
- // processing the long swipe on the UI thread.
- return;
- }
-
- mLongSwipeController = mActivityControlHelper.getLongSwipeController(
- mActivity, mRunningTaskId);
- onLongSwipeDisplacementUpdated();
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
- }
- }
-
- private void onLongSwipeGestureFinish(float velocity, boolean isFling, float velocityX) {
- if (!mLongSwipeMode || mLongSwipeController == null) {
- mLongSwipeMode = false;
- handleNormalGestureEnd(velocity, isFling, velocityX);
- return;
- }
- mLongSwipeMode = false;
- finishCurrentTransitionToRecents();
- mLongSwipeController.end(velocity, isFling,
- () -> setStateOnUiThread(STATE_HANDLER_INVALIDATED));
-
- }
-
private void setTargetAlphaProvider(
BiFunction<RemoteAnimationTargetCompat, Float, Float> provider) {
mClipAnimationHelper.setTaskAlphaCallback(provider);
updateFinalShift();
}
- public void onAssistDataReceived(Bundle assistData) {
- mAssistData = assistData;
- setStateOnUiThread(STATE_ASSIST_DATA_RECEIVED);
- }
-
- private void preloadAssistData() {
- RecentsModel.INSTANCE.get(mContext).preloadAssistData(mRunningTaskId, mAssistData);
- }
-
public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, Float expectedAlpha) {
if (!(app.isNotInRecents
|| app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME)) {
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
similarity index 96%
rename from quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 9679b81..e254e24 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -35,7 +35,6 @@
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOverviewStateEnabled(true);
- getQuickScrubController().onFinishedTransitionToQuickScrub();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
similarity index 89%
rename from quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
index ca8c252..6b3f028 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
@@ -30,13 +30,14 @@
public class RecentsRootView extends BaseDragLayer<RecentsActivity> {
+ private static final int MIN_SIZE = 10;
private final RecentsActivity mActivity;
- private final Point mLastKnownSize = new Point(10, 10);
+ private final Point mLastKnownSize = new Point(MIN_SIZE, MIN_SIZE);
public RecentsRootView(Context context, AttributeSet attrs) {
super(context, attrs, 1 /* alphaChannelCount */);
- mActivity = (RecentsActivity) BaseActivity.fromContext(context);
+ mActivity = BaseActivity.fromContext(context);
setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| SYSTEM_UI_FLAG_LAYOUT_STABLE);
@@ -53,8 +54,8 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Check size changes before the actual measure, to avoid multiple measure calls.
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
+ int width = Math.max(MIN_SIZE, MeasureSpec.getSize(widthMeasureSpec));
+ int height = Math.max(MIN_SIZE, MeasureSpec.getSize(heightMeasureSpec));
if (mLastKnownSize.x != width || mLastKnownSize.y != height) {
mLastKnownSize.set(width, height);
mActivity.onRootViewSizeChanged();
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java
new file mode 100644
index 0000000..f2d40ec
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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.hints;
+
+import android.app.PendingIntent;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+
+public final class HintUtil {
+
+ public static final String ID_KEY = "id";
+ public static final String ICON_KEY = "icon";
+ public static final String TEXT_KEY = "text";
+ public static final String TAP_ACTION_KEY = "tap_action";
+
+ private HintUtil() {}
+
+ public static Bundle makeHint(String id, Icon icon, CharSequence text) {
+ Bundle hint = new Bundle();
+ hint.putString(ID_KEY, id);
+ hint.putParcelable(ICON_KEY, icon);
+ hint.putCharSequence(TEXT_KEY, text);
+ return hint;
+ }
+
+ public static Bundle makeHint(Icon icon, CharSequence text, PendingIntent tapAction) {
+ Bundle hint = new Bundle();
+ hint.putParcelable(ICON_KEY, icon);
+ hint.putCharSequence(TEXT_KEY, text);
+ hint.putParcelable(TAP_ACTION_KEY, tapAction);
+ return hint;
+ }
+
+ public static String getId(Bundle hint) {
+ String id = hint.getString(ID_KEY);
+ if (id == null) {
+ throw new IllegalArgumentException("Hint does not contain an ID");
+ }
+ return id;
+ }
+
+ public static Icon getIcon(Bundle hint) {
+ Icon icon = hint.getParcelable(ICON_KEY);
+ if (icon == null) {
+ throw new IllegalArgumentException("Hint does not contain an icon");
+ }
+ return icon;
+ }
+
+ public static CharSequence getText(Bundle hint) {
+ CharSequence text = hint.getCharSequence(TEXT_KEY);
+ if (text == null) {
+ throw new IllegalArgumentException("Hint does not contain text");
+ }
+ return text;
+ }
+
+ public static PendingIntent getTapAction(Bundle hint) {
+ PendingIntent tapAction = hint.getParcelable(TAP_ACTION_KEY);
+ if (tapAction == null) {
+ throw new IllegalArgumentException("Hint does not contain a tap action");
+ }
+ return tapAction;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java
new file mode 100644
index 0000000..5399cc4
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 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.hints;
+
+import static com.android.quickstep.hints.HintUtil.getIcon;
+import static com.android.quickstep.hints.HintUtil.getText;
+
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+
+public class HintView extends LinearLayout {
+ private ImageView mIconView;
+ private TextView mLabelView;
+
+ public HintView(Context context) {
+ super(context);
+ }
+
+ public HintView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public HintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public HintView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public void setHint(Bundle hint) {
+ mLabelView.setText(getText(hint));
+
+ Icon icon = getIcon(hint);
+ if (icon == null) {
+ mIconView.setVisibility(GONE);
+ } else {
+ mIconView.setImageIcon(icon);
+ mIconView.setVisibility(VISIBLE);
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mIconView = findViewById(R.id.icon);
+ mLabelView = findViewById(R.id.label);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintsContainer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintsContainer.java
new file mode 100644
index 0000000..22b1217
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintsContainer.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 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.hints;
+
+import static com.android.quickstep.hints.UiHintListenerConstants.HINTS_KEY;
+import static com.android.quickstep.hints.UiHintListenerConstants.ON_HINTS_RETURNED_CODE;
+import static com.android.quickstep.hints.UiInterfaceConstants.REQUEST_HINTS_CODE;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+
+import java.util.ArrayList;
+
+public class HintsContainer extends LinearLayout {
+
+ private static final String TAG = "HintsView";
+
+ public static final FloatProperty<HintsContainer> HINT_VISIBILITY =
+ new FloatProperty<HintsContainer>("hint_visibility") {
+ @Override
+ public void setValue(HintsContainer hintsContainer, float v) {
+ hintsContainer.setHintVisibility(v);
+ }
+
+ @Override
+ public Float get(HintsContainer hintsContainer) {
+ return hintsContainer.mHintVisibility;
+ }
+ };
+
+ private static Intent mServiceIntent =
+ new Intent("com.android.systemui.action.UI_PULL_INTERFACE")
+ .setClassName(
+ "com.android.systemui.navbarhint",
+ "com.android.systemui.navbarhint.service.HintService");
+
+ @Nullable
+ private Messenger mHintServiceInterface;
+ private UiHintListener mUiHintListener;
+ private boolean mBound = false;
+ private float mHintVisibility;
+
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+ mHintServiceInterface = new Messenger(iBinder);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ mHintServiceInterface = null;
+ attemptBinding();
+ }
+
+ @Override
+ public void onBindingDied(ComponentName componentName) {
+ mHintServiceInterface = null;
+ attemptBinding();
+ }
+ };
+
+ public HintsContainer(Context context) {
+ super(context);
+ }
+
+ public HintsContainer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public HintsContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public HintsContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (mUiHintListener == null) {
+ mUiHintListener = new UiHintListener(this);
+ }
+ if (!mBound) {
+ attemptBinding();
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (mBound) {
+ getContext().unbindService(mServiceConnection);
+ mBound = false;
+ }
+ super.onDetachedFromWindow();
+ }
+
+ public void setHintVisibility(float v) {
+ if (v == 1) {
+ getHints();
+ setVisibility(VISIBLE);
+ } else {
+ setVisibility(GONE);
+ }
+ mHintVisibility = v;
+ }
+
+ private void attemptBinding() {
+ if (mBound) {
+ getContext().unbindService(mServiceConnection);
+ mBound = false;
+ }
+ boolean success = getContext().bindService(mServiceIntent,
+ mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
+ if (success) {
+ mBound = true;
+ } else {
+ Log.w(TAG, "Binding to hint supplier failed");
+ }
+ }
+
+ private void sendOnHintTap(Bundle hint) {
+ if (mHintServiceInterface != null) {
+ Message msg = Message.obtain(null, UiInterfaceConstants.ON_HINT_TAP_CODE);
+ Bundle data = new Bundle();
+ data.putString(UiInterfaceConstants.HINT_ID_KEY, HintUtil.getId(hint));
+ data.putInt(UiInterfaceConstants.WIDTH_PX_KEY, getWidth());
+ data.putInt(UiInterfaceConstants.HEIGHT_PX_KEY, getHeight());
+ data.putInt(UiInterfaceConstants.HINT_SPACE_WIDTH_PX_KEY, 0);
+ data.putInt(UiInterfaceConstants.HINT_SPACE_HEIGHT_PX_KEY, 0);
+ msg.setData(data);
+ try {
+ mHintServiceInterface.send(msg);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send hint tap", e);
+ }
+ }
+ }
+
+ private void getHints() {
+ if (mHintServiceInterface != null) {
+ try {
+ Message m = Message.obtain(null, REQUEST_HINTS_CODE);
+ m.replyTo = new Messenger(mUiHintListener);
+ mHintServiceInterface.send(m);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send message", e);
+ }
+ }
+ }
+
+ private static class UiHintListener extends Handler {
+ private HintsContainer mView;
+
+ UiHintListener(HintsContainer v) {
+ mView = v;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case ON_HINTS_RETURNED_CODE:
+ handleHints(msg);
+ break;
+ default:
+ Log.e(TAG, "UiPullInterface got unrecognized code: " + msg.what);
+ break;
+ }
+ }
+
+ private void handleHints(Message msg) {
+ Bundle bundle = msg.getData();
+ ArrayList<Bundle> hints = bundle.getParcelableArrayList(HINTS_KEY);
+
+ if (hints != null) {
+ mView.removeAllViews();
+
+ for (Bundle hint : hints) {
+ HintView h = (HintView) LayoutInflater.from(mView.getContext()).inflate(
+ R.layout.hint, mView, false);
+ h.setHint(hint);
+ h.setOnClickListener((v) -> mView.sendOnHintTap(hint));
+ mView.addView(h);
+ }
+ }
+ }
+ }
+}
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java
similarity index 65%
rename from go/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java
index 90360ce..420033d 100644
--- a/go/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.uioverrides;
+package com.android.quickstep.hints;
-/**
- * Extension of overview state used for QuickScrub. Same as {@link OverviewState} for Go as we do
- * not support quickscrub.
- */
-public final class FastOverviewState extends OverviewState {
- public FastOverviewState(int id) {
- super(id);
- }
+public final class UiHintListenerConstants {
+
+ private UiHintListenerConstants() {}
+
+ // Operations
+ public static final int ON_HINTS_RETURNED_CODE = 5;
+
+ // Keys
+ public static final String SESSION_ID_KEY = "session_id";
+ public static final String HINTS_KEY = "hints";
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java
new file mode 100644
index 0000000..0140613
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 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.hints;
+
+public final class UiInterfaceConstants {
+
+ private UiInterfaceConstants() {}
+
+ // Operations
+ public static final int ON_HINT_TAP_CODE = 4;
+
+ public static final int REQUEST_HINTS_CODE = 7;
+
+ // Keys
+ public static final String SESSION_ID_KEY = "session_id";
+ public static final String HINT_ID_KEY = "hint_id";
+ public static final String WIDTH_PX_KEY = "width_px";
+ public static final String HEIGHT_PX_KEY = "height_px";
+ public static final String HINT_SPACE_WIDTH_PX_KEY = "hint_space_width_px";
+ public static final String HINT_SPACE_HEIGHT_PX_KEY = "hint_space_height_px";
+}
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
similarity index 89%
rename from quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index 720c1c4..4450b4b 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -15,9 +15,7 @@
*/
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -26,19 +24,15 @@
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.os.RemoteException;
-import android.view.animation.Interpolator;
-import androidx.annotation.Nullable;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
@@ -53,6 +47,8 @@
import java.util.function.BiFunction;
+import androidx.annotation.Nullable;
+
/**
* Utility class to handle window clip animation
*/
@@ -67,8 +63,6 @@
private final RectF mSourceRect = new RectF();
// The bounds of the task view in launcher window coordinates
private final RectF mTargetRect = new RectF();
- // Set when the final window destination is changed, such as offsetting for quick scrub
- private final PointF mTargetOffset = new PointF();
// The insets to be used for clipping the app window, which can be larger than mSourceInsets
// if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In
// app window coordinates.
@@ -95,11 +89,6 @@
// Corner radius currently applied to transformed window.
private float mCurrentCornerRadius;
- private float mTargetScale = 1f;
- private float mOffsetScale = 1f;
- private Interpolator mInterpolator = LINEAR;
- // We translate y slightly faster than the rest of the animation for quick scrub.
- private Interpolator mOffsetYInterpolator = LINEAR;
// Whether to boost the opening animation target layers, or the closing
private int mBoostModeTargetLayers = -1;
@@ -130,13 +119,11 @@
updateSourceStack(target);
}
- public void updateTargetRect(TransformedRect targetRect) {
- mOffsetScale = targetRect.scale;
+ public void updateTargetRect(Rect targetRect) {
mSourceRect.set(mSourceInsets.left, mSourceInsets.top,
mSourceStackBounds.width() - mSourceInsets.right,
mSourceStackBounds.height() - mSourceInsets.bottom);
- mTargetRect.set(targetRect.rect);
- Utilities.scaleRectFAboutCenter(mTargetRect, targetRect.scale);
+ mTargetRect.set(targetRect);
mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left,
mHomeStackBounds.top - mSourceStackBounds.top);
@@ -165,18 +152,11 @@
if (params.currentRect == null) {
RectF currentRect;
mTmpRectF.set(mTargetRect);
- Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale * params.offsetScale);
- float offsetYProgress = mOffsetYInterpolator.getInterpolation(params.progress);
- float progress = mInterpolator.getInterpolation(params.progress);
+ Utilities.scaleRectFAboutCenter(mTmpRectF, params.offsetScale);
+ float progress = params.progress;
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
currentRect.offset(params.offsetX, 0);
- synchronized (mTargetOffset) {
- // Stay lined up with the center of the target, since it moves for quick scrub.
- currentRect.offset(mTargetOffset.x * mOffsetScale * progress,
- mTargetOffset.y * offsetYProgress);
- }
-
final RectF sourceWindowClipInsets = params.forLiveTile
? mSourceWindowClipInsetsForLiveTile : mSourceWindowClipInsets;
mClipRectF.left = sourceWindowClipInsets.left * progress;
@@ -205,6 +185,7 @@
if (mSupportsRoundedCornersOnWindows) {
cornerRadius = Utilities.mapRange(params.progress, mWindowCornerRadius,
mTaskCornerRadius);
+ mCurrentCornerRadius = cornerRadius;
}
}
alpha = mTaskAlphaCallback.apply(app, params.targetAlpha);
@@ -246,16 +227,6 @@
mTaskAlphaCallback = callback;
}
- public void offsetTarget(float scale, float offsetX, float offsetY, Interpolator interpolator) {
- synchronized (mTargetOffset) {
- mTargetOffset.set(offsetX, offsetY);
- }
- mTargetScale = scale;
- mInterpolator = interpolator;
- mOffsetYInterpolator = Interpolators.clampToProgress(mInterpolator, 0,
- QUICK_SCRUB_TRANSLATION_Y_FACTOR);
- }
-
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
fromTaskThumbnailView(ttv, rv, null);
}
@@ -280,8 +251,8 @@
mSourceInsets.set(ttv.getInsets(fallback));
}
- TransformedRect targetRect = new TransformedRect();
- dl.getDescendantRectRelativeToSelf(ttv, targetRect.rect);
+ Rect targetRect = new Rect();
+ dl.getDescendantRectRelativeToSelf(ttv, targetRect);
updateTargetRect(targetRect);
if (target == null) {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
similarity index 83%
rename from quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
index 686e74d..62f2183 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
@@ -28,6 +28,7 @@
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
+import java.util.function.Consumer;
import androidx.annotation.UiThread;
@@ -38,6 +39,14 @@
public class RecentsAnimationListenerSet implements RecentsAnimationListener {
private final Set<SwipeAnimationListener> mListeners = new ArraySet<>();
+ private final boolean mShouldMinimizeSplitScreen;
+ private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
+
+ public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen,
+ Consumer<SwipeAnimationTargetSet> onFinishListener) {
+ mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
+ mOnFinishListener = onFinishListener;
+ }
@UiThread
public void addListener(SwipeAnimationListener listener) {
@@ -56,7 +65,8 @@
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets,
- homeContentInsets, minimizedHomeBounds);
+ homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen,
+ mOnFinishListener);
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
new file mode 100644
index 0000000..b682481
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 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.TouchInteractionService.BACKGROUND_EXECUTOR;
+import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
+
+import android.graphics.Rect;
+
+import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+import java.util.function.Consumer;
+
+/**
+ * Extension of {@link RemoteAnimationTargetSet} with additional information about swipe
+ * up animation
+ */
+public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
+
+ private final boolean mShouldMinimizeSplitScreen;
+ private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
+
+
+ public final RecentsAnimationControllerCompat controller;
+ public final Rect homeContentInsets;
+ public final Rect minimizedHomeBounds;
+
+ public SwipeAnimationTargetSet(RecentsAnimationControllerCompat controller,
+ RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
+ Rect minimizedHomeBounds, boolean shouldMinimizeSplitScreen,
+ Consumer<SwipeAnimationTargetSet> onFinishListener) {
+ super(targets, MODE_CLOSING);
+ this.controller = controller;
+ this.homeContentInsets = homeContentInsets;
+ this.minimizedHomeBounds = minimizedHomeBounds;
+ this.mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
+ this.mOnFinishListener = onFinishListener;
+ }
+
+ public void finishController(boolean toRecents, Runnable callback) {
+ mOnFinishListener.accept(this);
+ BACKGROUND_EXECUTOR.execute(() -> {
+ controller.setInputConsumerEnabled(false);
+ controller.finish(toRecents);
+
+ if (callback != null) {
+ MAIN_THREAD_EXECUTOR.execute(callback);
+ }
+ });
+ }
+
+ public void enableInputConsumer() {
+ BACKGROUND_EXECUTOR.submit(() -> {
+ controller.hideCurrentInputMethod();
+ controller.setInputConsumerEnabled(true);
+ });
+ }
+
+ public void setWindowThresholdCrossed(boolean thresholdCrossed) {
+ BACKGROUND_EXECUTOR.execute(() -> {
+ controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
+ if (mShouldMinimizeSplitScreen && thresholdCrossed) {
+ // NOTE: As a workaround for conflicting animations (Launcher animating the task
+ // leash, and SystemUI resizing the docked stack, which resizes the task), we
+ // currently only set the minimized mode, and not the inverse.
+ // TODO: Synchronize the minimize animation with the launcher animation
+ controller.setSplitScreenMinimized(thresholdCrossed);
+ }
+ });
+ }
+
+ public ThumbnailData screenshotTask(int taskId) {
+ return controller != null ? controller.screenshotTask(taskId) : null;
+ }
+
+ public interface SwipeAnimationListener {
+
+ void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet);
+
+ void onRecentsAnimationCanceled();
+ }
+
+ public interface SwipeAnimationFinishListener {
+
+ void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewDrawable.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewDrawable.java
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/views/ClearAllButton.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
similarity index 99%
rename from quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
index cbd6b2f..5fe92d5 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -80,6 +80,7 @@
mTask = task;
if (task.key.userId != UserHandle.myUserId()) {
+ setVisibility(GONE);
callback.call(1, task.titleDescription);
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/IconView.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/views/IconView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/IconView.java
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
similarity index 77%
rename from quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 5c8f53c..88fe2ee 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -15,11 +15,13 @@
*/
package com.android.quickstep.views;
-import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import android.animation.AnimatorSet;
@@ -34,15 +36,15 @@
import android.view.View;
import android.view.ViewDebug;
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.hints.HintsContainer;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import com.android.quickstep.util.LayoutUtils;
@@ -75,7 +77,7 @@
private float mTranslationYFactor;
private final TransformParams mTransformParams = new TransformParams();
- final LauncherLayoutListener mLauncherLayoutListener;
+ private HintsContainer mHintsContainer;
public LauncherRecentsView(Context context) {
this(context, null);
@@ -88,7 +90,6 @@
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setContentAlpha(0);
- mLauncherLayoutListener = new LauncherLayoutListener(BaseActivity.fromContext(context));
}
@Override
@@ -107,11 +108,21 @@
setTranslationYFactor(mTranslationYFactor);
}
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mHintsContainer = mActivity.findViewById(R.id.hints);
+ mHintsContainer.setPadding(0, 0, 0, mActivity.getDeviceProfile().chipHintBottomMarginPx);
+ }
+
public void setTranslationYFactor(float translationFactor) {
mTranslationYFactor = translationFactor;
setTranslationY(computeTranslationYForFactor(mTranslationYFactor));
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- redrawLiveTile(false);
+ LauncherState state = mActivity.getStateManager().getState();
+ if (state == OVERVIEW || state == ALL_APPS) {
+ redrawLiveTile(false);
+ }
}
}
@@ -119,6 +130,12 @@
return translationYFactor * (getPaddingBottom() - getPaddingTop());
}
+ public void setHintVisibility(float v) {
+ if (mHintsContainer != null && ENABLE_HINTS_IN_OVERVIEW.get()) {
+ mHintsContainer.setHintVisibility(v);
+ }
+ }
+
@Override
public void draw(Canvas canvas) {
maybeDrawEmptyMessage(canvas);
@@ -170,6 +187,37 @@
}
@Override
+ public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
+ PendingAnimation anim = super.createTaskLauncherAnimation(tv, duration);
+
+ if (ENABLE_HINTS_IN_OVERVIEW.get()) {
+ anim.anim.play(ObjectAnimator.ofFloat(
+ mHintsContainer, HintsContainer.HINT_VISIBILITY, 0));
+ }
+
+ return anim;
+ }
+
+ @Override
+ public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
+ boolean shouldRemoveTask, long duration) {
+ PendingAnimation anim = super.createTaskDismissAnimation(taskView, animateTaskView,
+ shouldRemoveTask, duration);
+
+ if (ENABLE_HINTS_IN_OVERVIEW.get()) {
+ anim.anim.play(ObjectAnimator.ofFloat(
+ mHintsContainer, HintsContainer.HINT_VISIBILITY, 0));
+ anim.addEndListener(onEndListener -> {
+ if (!onEndListener.isSuccess) {
+ mHintsContainer.setHintVisibility(1);
+ }
+ });
+ }
+
+ return anim;
+ }
+
+ @Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
}
@@ -200,12 +248,8 @@
@Override
public void redrawLiveTile(boolean mightNeedToRefill) {
- AbstractFloatingView layoutListener = AbstractFloatingView.getTopOpenViewWithType(
- mActivity, TYPE_QUICKSTEP_PREVIEW);
- if (layoutListener != null && layoutListener.isOpen()) {
- return;
- }
- if (mRecentsAnimationWrapper == null || mClipAnimationHelper == null) {
+ if (!mEnableDrawingLiveTile || mRecentsAnimationWrapper == null
+ || mClipAnimationHelper == null) {
return;
}
TaskView taskView = getRunningTaskView();
@@ -216,7 +260,11 @@
int offsetY = (int) (mTaskHeight * taskView.getScaleY() * getScaleY()
- mTempRect.height());
if (((mCurrentPage != 0) || mightNeedToRefill) && offsetX > 0) {
- mTempRect.right += offsetX;
+ if (mTempRect.left - offsetX < 0) {
+ mTempRect.left -= offsetX;
+ } else {
+ mTempRect.right += offsetX;
+ }
}
if (mightNeedToRefill && offsetY > 0) {
mTempRect.top -= offsetY;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
new file mode 100644
index 0000000..ab2b90f
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
@@ -0,0 +1,62 @@
+package com.android.quickstep.views;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+public class LiveTileOverlay extends Drawable {
+
+ private final Paint mPaint = new Paint();
+
+ private Rect mBoundsRect = new Rect();
+ private RectF mCurrentRect;
+ private float mCornerRadius;
+
+ private boolean mDrawEnabled = true;
+
+ public LiveTileOverlay() {
+ mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ }
+
+ public void update(RectF currentRect, float cornerRadius) {
+ invalidateSelf();
+
+ mCurrentRect = currentRect;
+ mCornerRadius = cornerRadius;
+
+ mCurrentRect.roundOut(mBoundsRect);
+ setBounds(mBoundsRect);
+ invalidateSelf();
+ }
+
+ public void setDrawEnabled(boolean drawEnabled) {
+ if (mDrawEnabled != drawEnabled) {
+ mDrawEnabled = drawEnabled;
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mCurrentRect != null && mDrawEnabled) {
+ canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint);
+ }
+ }
+
+ @Override
+ public void setAlpha(int i) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
similarity index 96%
rename from quickstep/src/com/android/quickstep/views/RecentsView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 5925c4c..a7bf2c3 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -88,19 +88,19 @@
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.ViewPool;
import com.android.quickstep.OverviewCallbacks;
-import com.android.quickstep.QuickScrubController;
import com.android.quickstep.RecentsAnimationWrapper;
import com.android.quickstep.RecentsModel;
+import com.android.quickstep.RecentsModel.TaskThumbnailChangeListener;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowCallbacksCompat;
@@ -114,7 +114,7 @@
@TargetApi(Build.VERSION_CODES.P)
public abstract class RecentsView<T extends BaseActivity> extends PagedView implements Insettable,
TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
- InvariantDeviceProfile.OnIDPChangeListener {
+ InvariantDeviceProfile.OnIDPChangeListener, TaskThumbnailChangeListener {
private static final String TAG = RecentsView.class.getSimpleName();
@@ -152,7 +152,6 @@
private static final float[] sTempFloatArray = new float[3];
protected final T mActivity;
- private final QuickScrubController mQuickScrubController;
private final float mFastFlingVelocity;
private final RecentsModel mModel;
private final int mTaskTopMargin;
@@ -168,21 +167,11 @@
private final ViewPool<TaskView> mTaskViewPool;
- @Nullable Float mSimulatedVelocityX = null;
-
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
*/
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
- public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
- if (!mHandleTaskStackChanges) {
- return;
- }
- updateThumbnail(taskId, snapshot);
- }
-
- @Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
if (!mHandleTaskStackChanges) {
return;
@@ -215,9 +204,6 @@
return;
}
- // Notify the quick scrub controller that a particular task has been removed
- mQuickScrubController.onTaskRemoved(taskId);
-
BackgroundExecutor.get().submit(() -> {
TaskView taskView = getTaskView(taskId);
if (taskView == null) {
@@ -269,7 +255,6 @@
private boolean mOverviewStateEnabled;
private boolean mHandleTaskStackChanges;
- private Runnable mNextPageSwitchRunnable;
private boolean mSwipeDownShouldLaunchApp;
private boolean mTouchDownToStartHome;
private final int mTouchSlop;
@@ -310,7 +295,6 @@
mFastFlingVelocity = getResources()
.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
mActivity = (T) BaseActivity.fromContext(context);
- mQuickScrubController = new QuickScrubController(mActivity, this);
mModel = RecentsModel.INSTANCE.get(context);
mIdp = InvariantDeviceProfile.INSTANCE.get(context);
@@ -348,6 +332,19 @@
return mIsRtl;
}
+ @Override
+ public Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData) {
+ if (mHandleTaskStackChanges) {
+ TaskView taskView = getTaskView(taskId);
+ if (taskView != null) {
+ Task task = taskView.getTask();
+ taskView.getThumbnail().setThumbnail(task, thumbnailData);
+ return task;
+ }
+ }
+ return null;
+ }
+
public TaskView updateThumbnail(int taskId, ThumbnailData thumbnailData) {
TaskView taskView = getTaskView(taskId);
if (taskView != null) {
@@ -379,6 +376,7 @@
mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mSyncTransactionApplier = new SyncRtSurfaceTransactionApplierCompat(this);
+ RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this);
mIdp.addOnChangeListener(this);
}
@@ -390,6 +388,7 @@
mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
mSyncTransactionApplier = null;
+ RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this);
mIdp.removeOnChangeListener(this);
}
@@ -429,17 +428,9 @@
updateTaskStackListenerState();
}
- public void setNextPageSwitchRunnable(Runnable r) {
- mNextPageSwitchRunnable = r;
- }
-
@Override
protected void onPageEndTransition() {
super.onPageEndTransition();
- if (mNextPageSwitchRunnable != null) {
- mNextPageSwitchRunnable.run();
- mNextPageSwitchRunnable = null;
- }
if (getNextPage() > 0) {
setSwipeDownShouldLaunchApp(true);
}
@@ -550,10 +541,6 @@
mIgnoreResetTaskId = -1;
}
resetTaskVisuals();
-
- if (oldChildCount != getChildCount()) {
- mQuickScrubController.snapToNextTaskIfAvailable();
- }
onTaskStackUpdated();
}
@@ -605,7 +592,6 @@
mTaskWidth = mTempRect.width();
mTaskHeight = mTempRect.height();
- // Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub.
mTempRect.top -= mTaskTopMargin;
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
dp.widthPx - mInsets.right - mTempRect.right,
@@ -854,10 +840,6 @@
}
}
- public QuickScrubController getQuickScrubController() {
- return mQuickScrubController;
- }
-
public void setRunningTaskIconScaledDown(boolean isScaledDown) {
if (mRunningTaskIconScaledDown != isScaledDown) {
mRunningTaskIconScaledDown = isScaledDown;
@@ -1605,7 +1587,7 @@
return;
}
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
ThumbnailData taskSnapshot = controller.screenshotTask(mRunningTaskId);
@@ -1641,18 +1623,4 @@
}
}
}
-
- public void simulateTouchEvent(MotionEvent event, @Nullable Float velocityX) {
- mSimulatedVelocityX = velocityX;
- dispatchTouchEvent(event);
- mSimulatedVelocityX = null;
- }
-
- @Override
- protected int computeXVelocity() {
- if (mSimulatedVelocityX != null) {
- return mSimulatedVelocityX.intValue();
- }
- return super.computeXVelocity();
- }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/views/TaskMenuView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
similarity index 96%
rename from quickstep/src/com/android/quickstep/views/TaskView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 88e7ea8..fb58c24 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -29,7 +29,6 @@
import android.animation.TimeInterpolator;
import android.app.ActivityOptions;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.drawable.Drawable;
@@ -215,6 +214,7 @@
* Updates this task view to the given {@param task}.
*/
public void bind(Task task) {
+ cancelPendingLoadTasks();
mTask = task;
mSnapshotView.bind(task);
}
@@ -305,15 +305,15 @@
if (mTask == null) {
return;
}
+ cancelPendingLoadTasks();
if (visible) {
// These calls are no-ops if the data is already loaded, try and load the high
// resolution thumbnail if the state permits
RecentsModel model = RecentsModel.INSTANCE.get(getContext());
TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
TaskIconCache iconCache = model.getIconCache();
- mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(mTask,
- !thumbnailCache.getHighResLoadingState().isEnabled() /* reducedResolution */,
- (task) -> mSnapshotView.setThumbnail(task, task.thumbnail));
+ mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
+ mTask, thumbnail -> mSnapshotView.setThumbnail(mTask, thumbnail));
mIconLoadRequest = iconCache.updateIconInBackground(mTask,
(task) -> {
setIcon(task.icon);
@@ -325,17 +325,22 @@
});
});
} else {
- if (mThumbnailLoadRequest != null) {
- mThumbnailLoadRequest.cancel();
- }
- if (mIconLoadRequest != null) {
- mIconLoadRequest.cancel();
- }
mSnapshotView.setThumbnail(null, null);
setIcon(null);
}
}
+ private void cancelPendingLoadTasks() {
+ if (mThumbnailLoadRequest != null) {
+ mThumbnailLoadRequest.cancel();
+ mThumbnailLoadRequest = null;
+ }
+ if (mIconLoadRequest != null) {
+ mIconLoadRequest.cancel();
+ mIconLoadRequest = null;
+ }
+ }
+
private boolean showTaskMenu() {
getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
mMenuView = TaskMenuView.showForTask(this);
@@ -412,10 +417,7 @@
public void resetVisualProperties() {
resetViewTransforms();
- if (!getRecentsView().getQuickScrubController().isQuickSwitch()) {
- // Reset full screen progress unless we are doing back to back quick switch.
- setFullscreenProgress(0);
- }
+ setFullscreenProgress(0);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 0007b37..ab5f479 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -59,10 +59,10 @@
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -112,7 +112,6 @@
private static final int APP_LAUNCH_ALPHA_DURATION = 50;
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 CLOSING_TRANSITION_DURATION_MS = 250;
@@ -135,7 +134,7 @@
private final float mClosingWindowTransY;
private DeviceProfile mDeviceProfile;
- private View mFloatingView;
+ private FloatingIconView mFloatingView;
private RemoteAnimationProvider mRemoteAnimationProvider;
@@ -181,10 +180,6 @@
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
if (hasControlRemoteAppTransitionPermission()) {
boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
- if (fromRecents && isQuickSwitchInProgress()) {
- return getQuickSwitchActivityOptions();
- }
-
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler,
true /* startAtFrontOfQueue */) {
@@ -238,20 +233,6 @@
@Nullable RemoteAnimationTargetCompat[] targets);
/**
- * Whether a quick scrub is in progress.
- *
- * @return true if in progress
- */
- protected abstract boolean isQuickSwitchInProgress();
-
- /**
- * Get activity options for a quick switch launch that include the launch animation.
- *
- * @return the activity options for a quick switch recents launch
- */
- protected abstract ActivityOptions getQuickSwitchActivityOptions();
-
- /**
* Composes the animations for a launch from the recents list.
*
* @param anim the animator set to add to
@@ -423,7 +404,7 @@
boolean toggleVisibility) {
final boolean isBubbleTextView = v instanceof BubbleTextView;
if (mFloatingView == null) {
- mFloatingView = new View(mLauncher);
+ mFloatingView = new FloatingIconView(mLauncher);
} else {
mFloatingView.setTranslationX(0);
mFloatingView.setTranslationY(0);
@@ -432,58 +413,15 @@
mFloatingView.setAlpha(1);
mFloatingView.setBackground(null);
}
- if (isBubbleTextView && v.getTag() instanceof ItemInfoWithIcon ) {
- // Create a copy of the app icon
- mFloatingView.setBackground(DrawableFactory.INSTANCE.get(mLauncher)
- .newIcon(v.getContext(), (ItemInfoWithIcon) v.getTag()));
- }
-
- // Position the floating view exactly on top of the original
Rect rect = new Rect();
- final boolean fromDeepShortcutView = v.getParent() instanceof DeepShortcutView;
- if (fromDeepShortcutView) {
- // Deep shortcut views have their icon drawn in a separate view.
- DeepShortcutView view = (DeepShortcutView) v.getParent();
- mDragLayer.getDescendantRectRelativeToSelf(view.getIconView(), rect);
- } else {
- mDragLayer.getDescendantRectRelativeToSelf(v, rect);
- }
- int viewLocationLeft = rect.left;
- int viewLocationTop = rect.top;
+ mFloatingView.matchPositionOf(mLauncher, v, toggleVisibility, rect);
- float startScale = 1f;
- if (isBubbleTextView && !fromDeepShortcutView) {
- BubbleTextView btv = (BubbleTextView) v;
- btv.getIconBounds(rect);
- Drawable dr = btv.getIcon();
- if (dr instanceof FastBitmapDrawable) {
- startScale = ((FastBitmapDrawable) dr).getAnimatedScale();
- }
- } else {
- rect.set(0, 0, rect.width(), rect.height());
- }
- viewLocationLeft += rect.left;
- viewLocationTop += rect.top;
- int viewLocationStart = mIsRtl
- ? windowTargetBounds.width() - rect.right
- : viewLocationLeft;
- LayoutParams lp = new LayoutParams(rect.width(), rect.height());
- lp.ignoreInsets = true;
- lp.leftMargin = viewLocationStart;
- lp.topMargin = viewLocationTop;
+ int viewLocationStart = mIsRtl ? windowTargetBounds.width() - rect.right : rect.left;
+ LayoutParams lp = (LayoutParams) mFloatingView.getLayoutParams();
+ // Special RTL logic is needed to handle the window target bounds.
+ lp.leftMargin = mIsRtl ? windowTargetBounds.width() - rect.right : rect.left;
mFloatingView.setLayoutParams(lp);
- // Set the properties here already to make sure they'are available when running the first
- // animation frame.
- mFloatingView.layout(viewLocationLeft, viewLocationTop,
- viewLocationLeft + rect.width(), viewLocationTop + rect.height());
-
- // Swap the two views in place.
- ((ViewGroup) mDragLayer.getParent()).getOverlay().add(mFloatingView);
- if (toggleVisibility) {
- v.setVisibility(View.INVISIBLE);
- }
-
int[] dragLayerBounds = new int[2];
mDragLayer.getLocationOnScreen(dragLayerBounds);
@@ -494,8 +432,8 @@
float xPosition = mIsRtl
? windowTargetBounds.width() - lp.getMarginStart() - rect.width()
: lp.getMarginStart();
- float dX = centerX - xPosition - (lp.width / 2);
- float dY = centerY - lp.topMargin - (lp.height / 2);
+ float dX = centerX - xPosition - (lp.width / 2f);
+ float dY = centerY - lp.topMargin - (lp.height / 2f);
ObjectAnimator x = ObjectAnimator.ofFloat(mFloatingView, View.TRANSLATION_X, 0f, dX);
ObjectAnimator y = ObjectAnimator.ofFloat(mFloatingView, View.TRANSLATION_Y, 0f, dY);
@@ -521,6 +459,14 @@
float maxScaleX = windowTargetBounds.width() / (float) rect.width();
float maxScaleY = windowTargetBounds.height() / (float) rect.height();
float scale = Math.max(maxScaleX, maxScaleY);
+ float startScale = 1f;
+ if (isBubbleTextView && !(v.getParent() instanceof DeepShortcutView)) {
+ Drawable dr = ((BubbleTextView) v).getIcon();
+ if (dr instanceof FastBitmapDrawable) {
+ startScale = ((FastBitmapDrawable) dr).getAnimatedScale();
+ }
+ }
+
ObjectAnimator scaleAnim = ObjectAnimator
.ofFloat(mFloatingView, SCALE_PROPERTY, startScale, scale);
scaleAnim.setDuration(APP_LAUNCH_DURATION)
@@ -540,6 +486,7 @@
alpha.setInterpolator(LINEAR);
appOpenAnimator.play(alpha);
+ appOpenAnimator.addListener(mFloatingView);
appOpenAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index 25e0af2..1eaa8bc 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -15,10 +15,8 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
@@ -46,11 +44,7 @@
@Override
public void onStateEnabled(Launcher launcher) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- AbstractFloatingView.closeAllOpenViews(launcher);
- } else {
- AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
- }
+ AbstractFloatingView.closeAllOpenViews(launcher);
dispatchWindowStateChanged(launcher);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 70aae13..25e1c89 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -125,8 +125,8 @@
public static void onEnterAnimationComplete(Context context) {
// After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
- // as a part of quickstep/scrub, so that high-res thumbnails can load the next time we
- // enter overview
+ // as a part of quickstep, so that high-res thumbnails can load the next time we enter
+ // overview
RecentsModel.INSTANCE.get(context).getThumbnailCache()
.getHighResLoadingState().setVisible(true);
}
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 0bdb578..eccef04 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -17,57 +17,41 @@
import android.animation.Animator;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.Region;
import android.os.Build;
import android.os.Handler;
+import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
-import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.quickstep.util.TransformedRect;
-import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+
/**
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
*/
@TargetApi(Build.VERSION_CODES.P)
public interface ActivityControlHelper<T extends BaseDraggingActivity> {
- LayoutListener createLayoutListener(T activity);
-
- /**
- * Updates the UI to indicate quick interaction.
- */
- void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo,
- boolean activityVisible, TouchInteractionLog touchInteractionLog);
-
- float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
- Context context);
-
- void executeOnWindowAvailable(T activity, Runnable action);
-
void onTransitionCancelled(T activity, boolean activityVisible);
- int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context,
- @InteractionType int interactionType, TransformedRect outRect);
+ int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);
void onSwipeUpComplete(T activity);
@@ -91,46 +75,25 @@
<T extends View> T getVisibleRecentsView();
@UiThread
- boolean switchToRecentsIfVisible(boolean fromRecentsButton);
+ boolean switchToRecentsIfVisible(Runnable onCompleteCallback);
Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target);
boolean shouldMinimizeSplitScreen();
- /**
- * @return {@code true} if recents activity should be started immediately on touchDown,
- * {@code false} if it should deferred until some threshold is crossed.
- */
- boolean deferStartingActivity(int downHitTarget);
-
- boolean supportsLongSwipe(T activity);
+ default boolean deferStartingActivity(Region activeNavBarRegion, MotionEvent ev) {
+ return true;
+ }
AlphaProperty getAlphaProperty(T activity);
/**
- * Must return a non-null controller is supportsLongSwipe was true.
- */
- LongSwipeHelper getLongSwipeController(T activity, int runningTaskId);
-
- /**
* Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
*/
int getContainerType();
boolean isInLiveTileMode();
- interface LayoutListener {
-
- void open();
-
- void setHandler(WindowTransformSwipeHandler handler);
-
- void finish();
-
- void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
- float cornerRadius);
- }
-
interface ActivityInitListener {
void register();
@@ -155,7 +118,7 @@
default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { }
- void createActivityController(long transitionLength, @InteractionType int interactionType);
+ void createActivityController(long transitionLength);
default void onTransitionCancelled() { }
@@ -165,6 +128,11 @@
interface HomeAnimationFactory {
+ /** Return the floating view that will animate in sync with the closing window. */
+ default @Nullable View getFloatingView() {
+ return null;
+ }
+
@NonNull RectF getWindowTargetRect();
@NonNull Animator createActivityAnimationToHome();
diff --git a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
new file mode 100644
index 0000000..c840132
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.UiFactory;
+import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.util.Themes;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * A base fallback recents activity that provides support for device profile changes, activity
+ * lifecycle tracking, and basic input handling from recents.
+ *
+ * This class is only used as a fallback in case the default launcher does not have a recents
+ * implementation.
+ */
+public abstract class BaseRecentsActivity extends BaseDraggingActivity {
+
+ private Configuration mOldConfig;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mOldConfig = new Configuration(getResources().getConfiguration());
+ initDeviceProfile();
+ initViews();
+
+ getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
+ Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
+ RecentsActivityTracker.onRecentsActivityCreate(this);
+ }
+
+ /**
+ * Init drag layer and overview panel views.
+ */
+ abstract protected void initViews();
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ int diff = newConfig.diff(mOldConfig);
+ if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
+ onHandleConfigChanged();
+ }
+ mOldConfig.setTo(newConfig);
+ super.onConfigurationChanged(newConfig);
+ }
+
+ /**
+ * Logic for when device configuration changes (rotation, screen size change, multi-window,
+ * etc.)
+ */
+ protected void onHandleConfigChanged() {
+ mUserEventDispatcher = null;
+ initDeviceProfile();
+
+ AbstractFloatingView.closeOpenViews(this, true,
+ AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
+ dispatchDeviceProfileChanged();
+
+ reapplyUi();
+ }
+
+ /**
+ * Initialize/update the device profile.
+ */
+ private void initDeviceProfile() {
+ mDeviceProfile = createDeviceProfile();
+ onDeviceProfileInitiated();
+ }
+
+ /**
+ * Generate the device profile to use in this activity.
+ * @return device profile
+ */
+ protected DeviceProfile createDeviceProfile() {
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
+
+ // In case we are reusing IDP, create a copy so that we don't conflict with Launcher
+ // activity.
+ return dp.copy(this);
+ }
+
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ // Workaround for b/78520668, explicitly trim memory once UI is hidden
+ onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
+ }
+
+ @Override
+ public void onEnterAnimationComplete() {
+ super.onEnterAnimationComplete();
+ UiFactory.onEnterAnimationComplete(this);
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+ UiFactory.onTrimMemory(this, level);
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ RecentsActivityTracker.onRecentsActivityNewIntent(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ RecentsActivityTracker.onRecentsActivityDestroy(this);
+ }
+
+ @Override
+ public void onBackPressed() {
+ // TODO: Launch the task we came from
+ startHome();
+ }
+
+ public void startHome() {
+ startActivity(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ }
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ super.dump(prefix, fd, writer, args);
+ writer.println(prefix + "Misc:");
+ dumpMisc(writer);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
deleted file mode 100644
index ef56cb0..0000000
--- a/quickstep/src/com/android/quickstep/LongSwipeHelper.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS;
-import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
-import static com.android.quickstep.WindowTransformSwipeHandler.MAX_SWIPE_DURATION;
-import static com.android.quickstep.WindowTransformSwipeHandler.MIN_OVERSHOOT_DURATION;
-
-import android.animation.ValueAnimator;
-import android.view.animation.Interpolator;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherStateManager;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.allapps.DiscoveryBounce;
-import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.anim.Interpolators.OvershootParams;
-import com.android.launcher3.uioverrides.PortraitStatesTouchController;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.util.FlingBlockCheck;
-import com.android.quickstep.views.RecentsView;
-
-/**
- * Utility class to handle long swipe from an app.
- * This assumes the presence of Launcher activity as long swipe is not supported on the
- * fallback activity.
- */
-public class LongSwipeHelper {
-
- private static final float SWIPE_DURATION_MULTIPLIER =
- Math.min(1 / MIN_PROGRESS_TO_ALL_APPS, 1 / (1 - MIN_PROGRESS_TO_ALL_APPS));
-
- private final Launcher mLauncher;
- private final int mRunningTaskId;
-
- private float mMaxSwipeDistance = 1;
- private AnimatorPlaybackController mAnimator;
- private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
-
- LongSwipeHelper(Launcher launcher, int runningTaskId) {
- mLauncher = launcher;
- mRunningTaskId = runningTaskId;
- init();
- }
-
- private void init() {
- mFlingBlockCheck.blockFling();
-
- // Init animations
- AllAppsTransitionController controller = mLauncher.getAllAppsController();
- // TODO: Scale it down so that we can reach all-apps in screen space
- mMaxSwipeDistance = Math.max(1, controller.getProgress() * controller.getShiftRange());
-
- AnimatorSetBuilder builder = PortraitStatesTouchController.getOverviewToAllAppsAnimation();
- mAnimator = mLauncher.getStateManager().createAnimationToNewWorkspace(ALL_APPS, builder,
- Math.round(2 * mMaxSwipeDistance), null, LauncherStateManager.ANIM_ALL);
- mAnimator.dispatchOnStart();
- }
-
- public void onMove(float displacement) {
- mAnimator.setPlayFraction(displacement / mMaxSwipeDistance);
- mFlingBlockCheck.onEvent();
- }
-
- public void destroy() {
- // TODO: We can probably also show the task view
-
- mLauncher.getStateManager().goToState(OVERVIEW, false);
- }
-
- public void end(float velocity, boolean isFling, Runnable callback) {
- float velocityPxPerMs = velocity / 1000;
- long duration = MAX_SWIPE_DURATION;
- Interpolator interpolator = DEACCEL;
-
- final float currentFraction = mAnimator.getProgressFraction();
- final boolean toAllApps;
- float endProgress;
-
- boolean blockedFling = isFling && mFlingBlockCheck.isBlocked();
- if (blockedFling) {
- isFling = false;
- }
-
- if (!isFling) {
- toAllApps = currentFraction > MIN_PROGRESS_TO_ALL_APPS;
- endProgress = toAllApps ? 1 : 0;
-
- long expectedDuration = Math.abs(Math.round((endProgress - currentFraction)
- * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
- duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
-
- if (blockedFling && !toAllApps && !QUICKSTEP_SPRINGS.get()) {
- Interpolators.OvershootParams overshoot = new OvershootParams(currentFraction,
- currentFraction, endProgress, velocityPxPerMs, (int) mMaxSwipeDistance);
- duration = (overshoot.duration + duration);
- duration = Utilities.boundToRange(duration, MIN_OVERSHOOT_DURATION,
- MAX_SWIPE_DURATION);
- interpolator = overshoot.interpolator;
- endProgress = overshoot.end;
- }
- } else {
- toAllApps = velocity < 0;
- endProgress = toAllApps ? 1 : 0;
-
- float minFlingVelocity = mLauncher.getResources()
- .getDimension(R.dimen.quickstep_fling_min_velocity);
- if (Math.abs(velocity) > minFlingVelocity && mMaxSwipeDistance > 0) {
- float distanceToTravel = (endProgress - currentFraction) * mMaxSwipeDistance;
-
- // 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));
- duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
- }
- }
-
- final boolean finalIsFling = isFling;
- mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, finalIsFling, callback));
-
- ValueAnimator animator = mAnimator.getAnimationPlayer();
- animator.setDuration(duration).setInterpolator(interpolator);
- animator.setFloatValues(currentFraction, endProgress);
-
- if (QUICKSTEP_SPRINGS.get()) {
- mAnimator.dispatchOnStartWithVelocity(endProgress, velocityPxPerMs);
- }
- animator.start();
- }
-
- private void onSwipeAnimationComplete(boolean toAllApps, boolean isFling, Runnable callback) {
- RecentsView rv = mLauncher.getOverviewPanel();
- if (!toAllApps) {
- rv.setIgnoreResetTask(mRunningTaskId);
- }
-
- mLauncher.getStateManager().goToState(toAllApps ? ALL_APPS : OVERVIEW, false);
- if (!toAllApps) {
- DiscoveryBounce.showForOverviewIfNeeded(mLauncher);
- rv.animateUpRunningTaskIconScale();
- rv.setSwipeDownShouldLaunchApp(true);
- }
-
- mLauncher.getUserEventDispatcher().logStateChangeAction(
- isFling ? Touch.FLING : Touch.SWIPE, Direction.UP,
- ContainerType.NAVBAR, ContainerType.APP,
- toAllApps ? ContainerType.ALLAPPS : ContainerType.TASKSWITCHER,
- 0);
-
- callback.run();
-
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && toAllApps) {
- rv.finishRecentsAnimation(true, null);
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/MotionEventQueue.java b/quickstep/src/com/android/quickstep/MotionEventQueue.java
deleted file mode 100644
index 3664c97..0000000
--- a/quickstep/src/com/android/quickstep/MotionEventQueue.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import static android.view.MotionEvent.ACTION_MASK;
-import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.os.Looper;
-import android.util.Log;
-import android.util.Pair;
-import android.view.Choreographer;
-import android.view.InputEvent;
-import android.view.MotionEvent;
-
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher;
-import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
-import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
-
-/**
- * Helper class for batching input events
- */
-@TargetApi(Build.VERSION_CODES.O)
-public class MotionEventQueue {
-
- private static final String TAG = "MotionEventQueue";
-
- private static final int ACTION_VIRTUAL = ACTION_MASK - 1;
-
- private static final int ACTION_QUICK_SCRUB_START =
- ACTION_VIRTUAL | (1 << ACTION_POINTER_INDEX_SHIFT);
- private static final int ACTION_QUICK_SCRUB_PROGRESS =
- ACTION_VIRTUAL | (2 << ACTION_POINTER_INDEX_SHIFT);
- private static final int ACTION_QUICK_SCRUB_END =
- ACTION_VIRTUAL | (3 << ACTION_POINTER_INDEX_SHIFT);
- private static final int ACTION_NEW_GESTURE =
- ACTION_VIRTUAL | (4 << ACTION_POINTER_INDEX_SHIFT);
- private static final int ACTION_SHOW_OVERVIEW_FROM_ALT_TAB =
- ACTION_VIRTUAL | (5 << ACTION_POINTER_INDEX_SHIFT);
- private static final int ACTION_QUICK_STEP =
- ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT);
-
- private final InputEventDispatcher mDispatcher;
- private final InputEventReceiver mReceiver;
- private final ConsumerFactory mConsumerFactory;
-
- private TouchConsumer mConsumer;
-
- public MotionEventQueue(Looper looper, Choreographer choreographer,
- ConsumerFactory consumerFactory) {
- Pair<InputEventDispatcher, InputEventReceiver> pair = InputChannelCompat.createPair(
- "sysui-callbacks", looper, choreographer, this::onInputEvent);
-
- mConsumerFactory = consumerFactory;
- mConsumer = TouchConsumer.NO_OP;
- mDispatcher = pair.first;
- mReceiver = pair.second;
- }
-
- private void onInputEvent(InputEvent ev) {
- if (!(ev instanceof MotionEvent)) {
- throw new IllegalStateException("Unknown event " + ev);
- }
- MotionEvent event = (MotionEvent) ev;
- if (event.getActionMasked() == ACTION_VIRTUAL) {
- switch (event.getAction()) {
- case ACTION_QUICK_SCRUB_START:
- mConsumer.onQuickScrubStart();
- break;
- case ACTION_QUICK_SCRUB_PROGRESS:
- mConsumer.onQuickScrubProgress(event.getX());
- break;
- case ACTION_QUICK_SCRUB_END:
- mConsumer.onQuickScrubEnd();
- break;
- case ACTION_NEW_GESTURE: {
- boolean useSharedState = mConsumer.isActive();
- mConsumer.onConsumerAboutToBeSwitched();
- mConsumer = mConsumerFactory.newConsumer(event.getSource(), useSharedState);
- break;
- }
- case ACTION_SHOW_OVERVIEW_FROM_ALT_TAB:
- mConsumer.onShowOverviewFromAltTab();
- mConsumer.onQuickScrubStart();
- break;
- case ACTION_QUICK_STEP:
- mConsumer.onQuickStep(event);
- break;
- default:
- Log.e(TAG, "Invalid virtual event: " + event.getAction());
- }
- } else {
- mConsumer.accept(event);
- }
- }
-
- public void queue(MotionEvent event) {
- mDispatcher.dispatch(event);
- }
-
- private void queueVirtualAction(int action, float param) {
- queue(MotionEvent.obtain(0, 0, action, param, 0, 0));
- }
-
- private void queueVirtualAction(int action, int param) {
- MotionEvent ev = MotionEvent.obtain(0, 0, action, 0, 0, 0);
- ev.setSource(param);
- queue(ev);
- }
-
- public void onQuickScrubStart() {
- queueVirtualAction(ACTION_QUICK_SCRUB_START, 0);
- }
-
- public void onOverviewShownFromAltTab() {
- queueVirtualAction(ACTION_SHOW_OVERVIEW_FROM_ALT_TAB, 0);
- }
-
- public void onQuickScrubProgress(float progress) {
- queueVirtualAction(ACTION_QUICK_SCRUB_PROGRESS, progress);
- }
-
- public void onQuickScrubEnd() {
- queueVirtualAction(ACTION_QUICK_SCRUB_END, 0);
- }
-
- public void onQuickStep(MotionEvent event) {
- event.setAction(ACTION_QUICK_STEP);
- queue(event);
- }
-
- public void onNewGesture(@HitTarget int downHitTarget) {
- queueVirtualAction(ACTION_NEW_GESTURE, downHitTarget);
- }
-
- /**
- * To be called by the consumer when it's no longer active.
- */
- public void onConsumerInactive(TouchConsumer caller) {
- if (mConsumer == caller) {
- mConsumer = TouchConsumer.NO_OP;
- }
- }
-
- public void dispose() {
- mDispatcher.dispose();
- mReceiver.dispose();
- }
-
- public interface ConsumerFactory {
-
- TouchConsumer newConsumer(@HitTarget int downHitTarget, boolean useSharedState);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index b6741f4..724a492 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -96,7 +96,7 @@
} else {
// The default home app is a different launcher. Use the fallback Overview instead.
overviewComponent = new ComponentName(mContext, RecentsActivity.class);
- mActivityControlHelper = new FallbackActivityControllerHelper(defaultHome);
+ mActivityControlHelper = new FallbackActivityControllerHelper();
overviewIntentCategory = Intent.CATEGORY_DEFAULT;
// User's default home app can change as a result of package updates of this app (such
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 27f1399..411e593 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -64,8 +64,6 @@
private final Handler mUiHandler;
private final Handler mBgHandler;
- private boolean mSwipeGestureInitializing = false;
-
// These are updated on the background thread
private ISystemUiProxy mISystemUiProxy;
private boolean mSwipeUpEnabled = true;
@@ -154,7 +152,7 @@
return;
}
- int flags = 0;
+ int flags = FLAG_DISABLE_QUICK_SCRUB;
if (!mSwipeUpEnabled) {
flags = FLAG_DISABLE_SWIPE_UP | FLAG_DISABLE_QUICK_SCRUB | FLAG_SHOW_OVERVIEW_BUTTON;
}
@@ -177,15 +175,6 @@
}
}
- @WorkerThread
- public void setSwipeGestureInitializing(boolean swipeGestureInitializing) {
- mSwipeGestureInitializing = swipeGestureInitializing;
- }
-
- public boolean swipeGestureInitializing() {
- return mSwipeGestureInitializing;
- }
-
public void notifySwipeUpSettingChanged(boolean swipeUpEnabled) {
mUiHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED);
mUiHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED, swipeUpEnabled ? 1 : 0, 0).
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
deleted file mode 100644
index db0150e..0000000
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep;
-
-import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASK_STABILIZER;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.animation.Interpolator;
-
-import com.android.launcher3.Alarm;
-import com.android.launcher3.BaseActivity;
-import com.android.launcher3.OnAlarmListener;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
-
-/**
- * Responds to quick scrub callbacks to page through and launch recent tasks.
- *
- * The behavior is to evenly divide the progress into sections, each of which scrolls one page.
- * The first and last section set an alarm to auto-advance backwards or forwards, respectively.
- */
-@TargetApi(Build.VERSION_CODES.P)
-public class QuickScrubController implements OnAlarmListener {
-
- public static final int QUICK_SWITCH_FROM_APP_START_DURATION = 0;
- public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240;
- 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.
- public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6;
- public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN;
-
- /**
- * Snap to a new page when crossing these thresholds. The first and last auto-advance.
- */
- private static final float[] QUICK_SCRUB_THRESHOLDS = new float[] {
- 0.05f, 0.20f, 0.35f, 0.50f, 0.65f, 0.80f, 0.95f
- };
-
- private static final FloatProperty<QuickScrubController> PROGRESS
- = new FloatProperty<QuickScrubController>("progress") {
- @Override
- public void setValue(QuickScrubController quickScrubController, float progress) {
- quickScrubController.onQuickScrubProgress(progress);
- }
-
- @Override
- public Float get(QuickScrubController quickScrubController) {
- return quickScrubController.mEndProgress;
- }
- };
-
- private static final String TAG = "QuickScrubController";
- private static final boolean ENABLE_AUTO_ADVANCE = true;
- private static final long AUTO_ADVANCE_DELAY = 500;
- private static final int QUICKSCRUB_SNAP_DURATION_PER_PAGE = 325;
- private static final int QUICKSCRUB_END_SNAP_DURATION_PER_PAGE = 60;
-
- private final Alarm mAutoAdvanceAlarm;
- private final RecentsView mRecentsView;
- private final BaseActivity mActivity;
-
- private boolean mInQuickScrub;
- private boolean mWaitingForTaskLaunch;
- private int mQuickScrubSection;
- private boolean mStartedFromHome;
- private boolean mFinishedTransitionToQuickScrub;
- private int mLaunchingTaskId;
- private Runnable mOnFinishedTransitionToQuickScrubRunnable;
- private ActivityControlHelper mActivityControlHelper;
- private TouchInteractionLog mTouchInteractionLog;
-
- private boolean mIsQuickSwitch;
- private float mStartProgress;
- private float mEndProgress;
- private float mPrevProgressDelta;
- private float mPrevPrevProgressDelta;
- private boolean mShouldSwitchToNext;
-
- public QuickScrubController(BaseActivity activity, RecentsView recentsView) {
- mActivity = activity;
- mRecentsView = recentsView;
- if (ENABLE_AUTO_ADVANCE) {
- mAutoAdvanceAlarm = new Alarm();
- mAutoAdvanceAlarm.setOnAlarmListener(this);
- }
- }
-
- public void onQuickScrubStart(boolean startingFromHome, ActivityControlHelper controlHelper,
- TouchInteractionLog touchInteractionLog) {
- prepareQuickScrub(TAG);
- mInQuickScrub = true;
- mStartedFromHome = startingFromHome;
- mQuickScrubSection = 0;
- mFinishedTransitionToQuickScrub = false;
- mActivityControlHelper = controlHelper;
- mTouchInteractionLog = touchInteractionLog;
-
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (mRecentsView.getRunningTaskView() != null) {
- mRecentsView.getRunningTaskView().setShowScreenshot(false);
- }
- }
-
- if (mIsQuickSwitch) {
- mShouldSwitchToNext = true;
- mPrevProgressDelta = 0;
- TaskView runningTaskView = mRecentsView.getRunningTaskView();
- TaskView nextTaskView = mRecentsView.getNextTaskView();
- if (runningTaskView != null) {
- runningTaskView.setFullscreenProgress(1);
- }
- if (nextTaskView != null) {
- nextTaskView.setFullscreenProgress(1);
- }
- }
-
- snapToNextTaskIfAvailable();
- mActivity.getUserEventDispatcher().resetActionDurationMillis();
- }
-
- public void onQuickScrubEnd() {
- mInQuickScrub = false;
-
- Runnable launchTaskRunnable = () -> {
- int page = mRecentsView.getPageNearestToCenterOfScreen();
- TaskView taskView = mRecentsView.getTaskViewAt(page);
- if (taskView != null) {
- mWaitingForTaskLaunch = true;
- mTouchInteractionLog.launchTaskStart();
- mLaunchingTaskId = taskView.getTask().key.id;
- taskView.launchTask(true, (result) -> {
- mTouchInteractionLog.launchTaskEnd(result);
- if (!result) {
- taskView.notifyTaskLaunchFailed(TAG);
- breakOutOfQuickScrub();
- } else {
- mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP,
- LauncherLogProto.Action.Direction.NONE, page,
- TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key));
- }
- mWaitingForTaskLaunch = false;
- if (mIsQuickSwitch) {
- mIsQuickSwitch = false;
- TaskView runningTaskView = mRecentsView.getRunningTaskView();
- TaskView nextTaskView = mRecentsView.getNextTaskView();
- if (runningTaskView != null) {
- runningTaskView.setFullscreenProgress(0);
- }
- if (nextTaskView != null) {
- nextTaskView.setFullscreenProgress(0);
- }
- }
-
- }, taskView.getHandler());
- } else {
- breakOutOfQuickScrub();
- }
- mActivityControlHelper = null;
- };
-
- if (mIsQuickSwitch) {
- float progressVelocity = mPrevPrevProgressDelta / SINGLE_FRAME_MS;
- // Move to the next frame immediately, then start the animation from the
- // following frame since it starts a frame later.
- float singleFrameProgress = progressVelocity * SINGLE_FRAME_MS;
- float fromProgress = mEndProgress + singleFrameProgress;
- onQuickScrubProgress(fromProgress);
- fromProgress += singleFrameProgress;
- float toProgress = mShouldSwitchToNext ? 1 : 0;
- int duration = (int) Math.abs((toProgress - fromProgress) / progressVelocity);
- duration = Utilities.boundToRange(duration, 80, 300);
- Animator anim = ObjectAnimator.ofFloat(this, PROGRESS, fromProgress, toProgress);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- launchTaskRunnable.run();
- }
- });
- anim.setDuration(duration).start();
- return;
- }
-
- if (ENABLE_AUTO_ADVANCE) {
- mAutoAdvanceAlarm.cancelAlarm();
- }
- int page = mRecentsView.getNextPage();
- int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen())
- * QUICKSCRUB_END_SNAP_DURATION_PER_PAGE;
- if (mRecentsView.getChildCount() > 0 && mRecentsView.snapToPage(page, snapDuration)) {
- // Settle on the page then launch it
- mRecentsView.setNextPageSwitchRunnable(launchTaskRunnable);
- } else {
- // No page move needed, just launch it
- if (mFinishedTransitionToQuickScrub) {
- launchTaskRunnable.run();
- } else {
- mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable;
- }
- }
- }
-
- public void cancelActiveQuickscrub() {
- if (!mInQuickScrub) {
- return;
- }
- Log.d(TAG, "Quickscrub was active, cancelling");
- mInQuickScrub = false;
- mActivityControlHelper = null;
- mOnFinishedTransitionToQuickScrubRunnable = null;
- mRecentsView.setNextPageSwitchRunnable(null);
- mLaunchingTaskId = 0;
- }
-
- public boolean prepareQuickScrub(String tag) {
- return prepareQuickScrub(tag, mIsQuickSwitch);
- }
-
- /**
- * Initializes the UI for quick scrub, returns true if success.
- */
- public boolean prepareQuickScrub(String tag, boolean isQuickSwitch) {
- if (mWaitingForTaskLaunch || mInQuickScrub) {
- Log.d(tag, "Waiting for last scrub to finish, will skip this interaction");
- return false;
- }
- mOnFinishedTransitionToQuickScrubRunnable = null;
- mRecentsView.setNextPageSwitchRunnable(null);
- mIsQuickSwitch = isQuickSwitch;
- return true;
- }
-
- public boolean isQuickSwitch() {
- return mIsQuickSwitch;
- }
-
- public boolean isWaitingForTaskLaunch() {
- return mWaitingForTaskLaunch;
- }
-
- /**
- * Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction.
- */
- private void breakOutOfQuickScrub() {
- if (mRecentsView.getChildCount() == 0 || mActivityControlHelper == null
- || !mActivityControlHelper.switchToRecentsIfVisible(false)) {
- mActivity.onBackPressed();
- }
- }
-
- public void onQuickScrubProgress(float progress) {
- if (mIsQuickSwitch) {
- TaskView currentPage = mRecentsView.getRunningTaskView();
- TaskView nextPage = mRecentsView.getNextTaskView();
- if (currentPage == null || nextPage == null) {
- return;
- }
- if (!mFinishedTransitionToQuickScrub || mStartProgress <= 0) {
- mStartProgress = mEndProgress = progress;
- } else {
- float progressDelta = progress - mEndProgress;
- mEndProgress = progress;
- progress = Utilities.boundToRange(progress, mStartProgress, 1);
- progress = Utilities.mapToRange(progress, mStartProgress, 1, 0, 1, LINEAR);
- if (mInQuickScrub) {
- mShouldSwitchToNext = mPrevProgressDelta > 0.007f || progressDelta > 0.007f
- || progress >= 0.5f;
- }
- mPrevPrevProgressDelta = mPrevProgressDelta;
- mPrevProgressDelta = progressDelta;
- int startScroll = mRecentsView.getScrollForPage(
- mRecentsView.indexOfChild(currentPage));
- int scrollDiff = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(nextPage))
- - startScroll;
-
- int linearScrollDiff = (int) (progress * scrollDiff);
- currentPage.setZoomScale(1 - DEACCEL_3.getInterpolation(progress)
- * TaskView.EDGE_SCALE_DOWN_FACTOR);
- if (!ENABLE_TASK_STABILIZER.get()) {
- float accelScrollDiff = ACCEL.getInterpolation(progress) * scrollDiff;
- currentPage.setTranslationX(linearScrollDiff + accelScrollDiff);
- }
- nextPage.setTranslationZ(1);
- nextPage.setTranslationY(currentPage.getTranslationY());
- mRecentsView.setScrollX(startScroll + linearScrollDiff);
- }
- return;
- }
-
- int quickScrubSection = 0;
- for (float threshold : QUICK_SCRUB_THRESHOLDS) {
- if (progress < threshold) {
- break;
- }
- quickScrubSection++;
- }
- if (quickScrubSection != mQuickScrubSection) {
- boolean cameFromAutoAdvance = mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length
- || mQuickScrubSection == 0;
- int pageToGoTo = mRecentsView.getNextPage() + quickScrubSection - mQuickScrubSection;
- if (mFinishedTransitionToQuickScrub && !cameFromAutoAdvance) {
- goToPageWithHaptic(pageToGoTo);
- }
- if (ENABLE_AUTO_ADVANCE) {
- if (quickScrubSection == QUICK_SCRUB_THRESHOLDS.length || quickScrubSection == 0) {
- mAutoAdvanceAlarm.setAlarm(AUTO_ADVANCE_DELAY);
- } else {
- mAutoAdvanceAlarm.cancelAlarm();
- }
- }
- mQuickScrubSection = quickScrubSection;
- }
- }
-
- public void onFinishedTransitionToQuickScrub() {
- mFinishedTransitionToQuickScrub = true;
- Runnable action = mOnFinishedTransitionToQuickScrubRunnable;
- // Clear the runnable before executing it, to prevent potential recursion.
- mOnFinishedTransitionToQuickScrubRunnable = null;
- if (action != null) {
- action.run();
- }
- mRecentsView.setEnableDrawingLiveTile(true);
- }
-
- public void onTaskRemoved(int taskId) {
- if (mLaunchingTaskId == taskId) {
- // The task has been removed mid-launch, break out of quickscrub and return the user
- // to where they were before (and notify the launch failed)
- TaskView taskView = mRecentsView.getTaskView(taskId);
- if (taskView != null) {
- taskView.notifyTaskLaunchFailed(TAG);
- }
- breakOutOfQuickScrub();
- }
- }
-
- public void snapToNextTaskIfAvailable() {
- if (mInQuickScrub && mRecentsView.getChildCount() > 0) {
- int duration = mIsQuickSwitch
- ? QUICK_SWITCH_FROM_APP_START_DURATION
- : mStartedFromHome
- ? QUICK_SCRUB_FROM_HOME_START_DURATION
- : QUICK_SCRUB_FROM_APP_START_DURATION;
- final int pageToGoTo;
- if (mStartedFromHome) {
- pageToGoTo = 0;
- } else if (mIsQuickSwitch) {
- TaskView tv = mRecentsView.getRunningTaskView();
- pageToGoTo = tv != null ? mRecentsView.indexOfChild(tv)
- : mRecentsView.getNextPage();
- } else {
- pageToGoTo = mRecentsView.getNextPage() + 1;
- }
- goToPageWithHaptic(pageToGoTo, duration, true /* forceHaptic */,
- QUICK_SCRUB_START_INTERPOLATOR);
- }
- }
-
- private void goToPageWithHaptic(int pageToGoTo) {
- goToPageWithHaptic(pageToGoTo, -1 /* overrideDuration */, false /* forceHaptic */, null);
- }
-
- private void goToPageWithHaptic(int pageToGoTo, int overrideDuration, boolean forceHaptic,
- Interpolator interpolator) {
- pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getTaskViewCount() - 1);
- boolean snappingToPage = pageToGoTo != mRecentsView.getNextPage();
- if (snappingToPage) {
- int duration = overrideDuration > -1 ? overrideDuration
- : Math.abs(pageToGoTo - mRecentsView.getNextPage())
- * QUICKSCRUB_SNAP_DURATION_PER_PAGE;
- mRecentsView.snapToPage(pageToGoTo, duration, interpolator);
- }
- if (snappingToPage || forceHaptic) {
- mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- }
- }
-
- @Override
- public void onAlarm(Alarm alarm) {
- int currPage = mRecentsView.getNextPage();
- boolean recentsVisible = mActivityControlHelper != null
- && mActivityControlHelper.getVisibleRecentsView() != null;
- if (!recentsVisible) {
- Log.w(TAG, "Failed to auto advance; recents not visible");
- return;
- }
- if (mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length
- && currPage < mRecentsView.getTaskViewCount() - 1) {
- goToPageWithHaptic(currPage + 1);
- } else if (mQuickScrubSection == 0 && currPage > 0) {
- goToPageWithHaptic(currPage - 1);
- }
- if (ENABLE_AUTO_ADVANCE) {
- mAutoAdvanceAlarm.setAlarm(AUTO_ADVANCE_DELAY);
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
deleted file mode 100644
index 2c3f77f..0000000
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import android.content.Context;
-
-import com.android.launcher3.MainProcessInitializer;
-import com.android.systemui.shared.system.ThreadedRendererCompat;
-
-@SuppressWarnings("unused")
-public class QuickstepProcessInitializer extends MainProcessInitializer {
-
- public QuickstepProcessInitializer(Context context) { }
-
- @Override
- protected void init(Context context) {
- super.init(context);
-
- // Elevate GPU priority for Quickstep and Remote animations.
- ThreadedRendererCompat.setContextPriority(ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index cedd952..e15a3f1 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -60,6 +60,7 @@
mBgThreadExecutor = BackgroundExecutor.get();
mKeyguardManager = new KeyguardManagerCompat(context);
mChangeId = 1;
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
}
/**
@@ -73,6 +74,14 @@
});
}
+ public void startStabilizationSession() {
+ mStabilizer.startStabilizationSession();
+ }
+
+ public void endStabilizationSession() {
+ mStabilizer.endStabilizationSession();
+ }
+
/**
* Asynchronously fetches the list of recent tasks, reusing cached list if available.
*
@@ -89,6 +98,7 @@
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
// The list is up to date, callback with the same list
mMainThreadExecutor.execute(resultCallback);
+ return requestLoadId;
}
// Kick off task loading in the background
diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
index fb6090e..0822e61 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
@@ -30,17 +30,18 @@
import java.util.function.BiPredicate;
/**
- * Utility class to track create/destroy for RecentsActivity
+ * Utility class to track create/destroy for some {@link BaseRecentsActivity}.
*/
@TargetApi(Build.VERSION_CODES.P)
-public class RecentsActivityTracker implements ActivityInitListener {
+public class RecentsActivityTracker<T extends BaseRecentsActivity> implements ActivityInitListener {
- private static WeakReference<RecentsActivity> sCurrentActivity = new WeakReference<>(null);
+ private static WeakReference<BaseRecentsActivity> sCurrentActivity =
+ new WeakReference<>(null);
private static final Scheduler sScheduler = new Scheduler();
- private final BiPredicate<RecentsActivity, Boolean> mOnInitListener;
+ private final BiPredicate<T, Boolean> mOnInitListener;
- public RecentsActivityTracker(BiPredicate<RecentsActivity, Boolean> onInitListener) {
+ public RecentsActivityTracker(BiPredicate<T, Boolean> onInitListener) {
mOnInitListener = onInitListener;
}
@@ -54,12 +55,12 @@
sScheduler.clearReference(this);
}
- private boolean init(RecentsActivity activity, boolean visible) {
+ private boolean init(T activity, boolean visible) {
return mOnInitListener.test(activity, visible);
}
- public static RecentsActivity getCurrentActivity() {
- return sCurrentActivity.get();
+ public static <T extends BaseRecentsActivity> T getCurrentActivity() {
+ return (T) sCurrentActivity.get();
}
@Override
@@ -71,17 +72,17 @@
context.startActivity(intent, options);
}
- public static void onRecentsActivityCreate(RecentsActivity activity) {
+ public static void onRecentsActivityCreate(BaseRecentsActivity activity) {
sCurrentActivity = new WeakReference<>(activity);
sScheduler.initIfPending(activity, false);
}
- public static void onRecentsActivityNewIntent(RecentsActivity activity) {
+ public static void onRecentsActivityNewIntent(BaseRecentsActivity activity) {
sScheduler.initIfPending(activity, activity.isStarted());
}
- public static void onRecentsActivityDestroy(RecentsActivity activity) {
+ public static void onRecentsActivityDestroy(BaseRecentsActivity activity) {
if (sCurrentActivity.get() == activity) {
sCurrentActivity.clear();
}
@@ -103,13 +104,14 @@
@Override
public void run() {
- RecentsActivity activity = sCurrentActivity.get();
+ BaseRecentsActivity activity = sCurrentActivity.get();
if (activity != null) {
initIfPending(activity, activity.isStarted());
}
}
- public synchronized boolean initIfPending(RecentsActivity activity, boolean alreadyOnHome) {
+ public synchronized boolean initIfPending(BaseRecentsActivity activity,
+ boolean alreadyOnHome) {
RecentsActivityTracker tracker = mPendingTracker.get();
if (tracker != null) {
if (!tracker.init(activity, alreadyOnHome)) {
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
deleted file mode 100644
index c2d4d80..0000000
--- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import static android.view.MotionEvent.ACTION_CANCEL;
-import static android.view.MotionEvent.ACTION_DOWN;
-import static android.view.MotionEvent.ACTION_UP;
-
-import android.view.MotionEvent;
-
-import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.Preconditions;
-import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.util.UiThreadHelper;
-import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
-
-import java.util.ArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.function.Supplier;
-
-import androidx.annotation.UiThread;
-
-/**
- * Wrapper around RecentsAnimationController to help with some synchronization
- */
-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;
-
- private RecentsAnimationControllerCompat mController;
- private boolean mInputConsumerEnabled = false;
- private boolean mBehindSystemBars = true;
- private boolean mSplitScreenMinimized = false;
-
- private final ExecutorService mExecutorService =
- new LooperExecutor(UiThreadHelper.getBackgroundLooper());
-
- private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
- private final InputConsumerController mInputConsumer;
- private final Supplier<TouchConsumer> mTouchProxySupplier;
-
- private TouchConsumer mTouchConsumer;
- private boolean mTouchInProgress;
-
- private boolean mFinishPending;
-
- public RecentsAnimationWrapper(InputConsumerController inputConsumer,
- Supplier<TouchConsumer> touchProxySupplier) {
- mInputConsumer = inputConsumer;
- mTouchProxySupplier = touchProxySupplier;
- }
-
- @UiThread
- public synchronized void setController(
- RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) {
- Preconditions.assertUIThread();
- TraceHelper.partitionSection("RecentsController", "Set controller " + controller);
- this.mController = controller;
- this.targetSet = targetSet;
-
- if (controller == null) {
- return;
- }
- if (mInputConsumerEnabled) {
- 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();
- }
- }
-
- /**
- * @param onFinishComplete A callback that runs on the main thread after the animation
- * controller has finished on the background thread.
- */
- public void finish(boolean toRecents, Runnable onFinishComplete) {
- if (!toRecents) {
- mExecutorService.submit(() -> finishBg(false, onFinishComplete));
- return;
- }
-
- mMainThreadExecutor.execute(() -> {
- if (mTouchInProgress) {
- mFinishPending = true;
- // Execute the callback
- if (onFinishComplete != null) {
- onFinishComplete.run();
- }
- } else {
- mExecutorService.submit(() -> finishBg(true, onFinishComplete));
- }
- });
- }
-
- protected void finishBg(boolean toRecents, Runnable onFinishComplete) {
- RecentsAnimationControllerCompat controller = mController;
- mController = null;
- TraceHelper.endSection("RecentsController", "Finish " + controller
- + ", toRecents=" + toRecents);
- if (controller != null) {
- controller.setInputConsumerEnabled(false);
- controller.finish(toRecents);
-
- if (onFinishComplete != null) {
- mMainThreadExecutor.execute(onFinishComplete);
- }
- }
- }
-
- public void enableInputConsumer() {
- mInputConsumerEnabled = true;
- if (mInputConsumerEnabled) {
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Enabling consumer on " + controller);
- if (controller != null) {
- controller.setInputConsumerEnabled(true);
- }
- });
- }
- }
-
- public void enableTouchProxy() {
- mMainThreadExecutor.execute(this::enableTouchProxyUi);
- }
-
- private void enableTouchProxyUi() {
- mInputConsumer.setTouchListener(this::onInputConsumerTouch);
- }
-
- private boolean onInputConsumerTouch(MotionEvent ev) {
- int action = ev.getAction();
- if (action == ACTION_DOWN) {
- mTouchInProgress = true;
- mTouchConsumer = mTouchProxySupplier.get();
- } else if (action == ACTION_CANCEL || action == ACTION_UP) {
- // Finish any pending actions
- mTouchInProgress = false;
- if (mFinishPending) {
- mFinishPending = false;
- mExecutorService.submit(() -> finishBg(true, null));
- }
- }
- if (mTouchConsumer != null) {
- mTouchConsumer.accept(ev);
- }
-
- return true;
- }
-
- public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
- if (mBehindSystemBars == behindSystemBars) {
- return;
- }
- mBehindSystemBars = behindSystemBars;
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Setting behind system bars on " + controller);
- if (controller != null) {
- controller.setAnimationTargetsBehindSystemBars(behindSystemBars);
- }
- });
- }
-
- /**
- * NOTE: As a workaround for conflicting animations (Launcher animating the task leash, and
- * SystemUI resizing the docked stack, which resizes the task), we currently only set the
- * minimized mode, and not the inverse.
- * TODO: Synchronize the minimize animation with the launcher animation
- */
- public void setSplitScreenMinimizedForTransaction(boolean minimized) {
- if (mSplitScreenMinimized || !minimized) {
- return;
- }
- mSplitScreenMinimized = minimized;
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Setting minimize dock on " + controller);
- if (controller != null) {
- controller.setSplitScreenMinimized(minimized);
- }
- });
- }
-
- public void hideCurrentInputMethod() {
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Hiding currentinput method on " + controller);
- if (controller != null) {
- controller.hideCurrentInputMethod();
- }
- });
- }
-
- public RecentsAnimationControllerCompat getController() {
- return mController;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index e61c00a..81a22a1 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -22,23 +22,21 @@
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.os.Build;
-import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
-import android.util.SparseArray;
-import com.android.launcher3.MainThreadExecutor;
+
import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
-import java.util.ArrayList;
-import java.util.function.Consumer;
-import androidx.annotation.WorkerThread;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
/**
* Singleton class to load and manage recents model.
@@ -52,14 +50,10 @@
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
new MainThreadInitializedObject<>(c -> new RecentsModel(c));
- private final SparseArray<Bundle> mCachedAssistData = new SparseArray<>(1);
- private final ArrayList<AssistDataListener> mAssistDataListeners = new ArrayList<>();
-
+ private final List<TaskThumbnailChangeListener> mThumbnailChangeListeners = new ArrayList<>();
private final Context mContext;
- private final MainThreadExecutor mMainThreadExecutor;
private ISystemUiProxy mSystemUiProxy;
- private boolean mClearAssistCacheOnStackChange = true;
private final RecentTasksList mTaskList;
private final TaskIconCache mIconCache;
@@ -70,9 +64,6 @@
private RecentsModel(Context context) {
mContext = context;
-
- mMainThreadExecutor = new MainThreadExecutor();
-
HandlerThread loaderThread = new HandlerThread("TaskThumbnailIconCache",
Process.THREAD_PRIORITY_BACKGROUND);
loaderThread.start();
@@ -90,6 +81,14 @@
return mThumbnailCache;
}
+ public void startStabilizationSession() {
+ mTaskList.startStabilizationSession();
+ }
+
+ public void endStabilizationSession() {
+ mTaskList.endStabilizationSession();
+ }
+
/**
* Fetches the list of recent tasks.
*
@@ -163,12 +162,14 @@
}
@Override
- public void onTaskStackChanged() {
- Preconditions.assertUIThread();
- if (mClearAssistCacheOnStackChange) {
- mCachedAssistData.clear();
- } else {
- mClearAssistCacheOnStackChange = true;
+ public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
+ mThumbnailCache.updateTaskSnapShot(taskId, snapshot);
+
+ for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
+ Task task = mThumbnailChangeListeners.get(i).onTaskThumbnailChanged(taskId, snapshot);
+ if (task != null) {
+ task.thumbnail = snapshot;
+ }
}
}
@@ -244,43 +245,16 @@
}
}
- public void resetAssistCache() {
- mCachedAssistData.clear();
+ public void addThumbnailChangeListener(TaskThumbnailChangeListener listener) {
+ mThumbnailChangeListeners.add(listener);
}
- @WorkerThread
- public void preloadAssistData(int taskId, Bundle data) {
- mMainThreadExecutor.execute(() -> {
- mCachedAssistData.put(taskId, data);
- // We expect a stack change callback after the assist data is set. So ignore the
- // very next stack change callback.
- mClearAssistCacheOnStackChange = false;
-
- int count = mAssistDataListeners.size();
- for (int i = 0; i < count; i++) {
- mAssistDataListeners.get(i).onAssistDataReceived(taskId);
- }
- });
+ public void removeThumbnailChangeListener(TaskThumbnailChangeListener listener) {
+ mThumbnailChangeListeners.remove(listener);
}
- public Bundle getAssistData(int taskId) {
- Preconditions.assertUIThread();
- return mCachedAssistData.get(taskId);
- }
+ public interface TaskThumbnailChangeListener {
- public void addAssistDataListener(AssistDataListener listener) {
- mAssistDataListeners.add(listener);
- }
-
- public void removeAssistDataListener(AssistDataListener listener) {
- mAssistDataListeners.remove(listener);
- }
-
- /**
- * Callback for receiving assist data
- */
- public interface AssistDataListener {
-
- void onAssistDataReceived(int taskId);
+ Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData);
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskListStabilizer.java b/quickstep/src/com/android/quickstep/TaskListStabilizer.java
index 3eb26b4..4c63f81 100644
--- a/quickstep/src/com/android/quickstep/TaskListStabilizer.java
+++ b/quickstep/src/com/android/quickstep/TaskListStabilizer.java
@@ -15,13 +15,10 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASK_STABILIZER;
-
import android.app.ActivityManager.RecentTaskInfo;
import android.content.ComponentName;
import android.os.Process;
import android.os.SystemClock;
-import android.util.Log;
import com.android.launcher3.util.IntArray;
import com.android.systemui.shared.recents.model.Task;
@@ -33,98 +30,77 @@
import java.util.Collections;
import java.util.List;
+/**
+ * Keeps the task list stable during quick switch gestures. So if you swipe right to switch from app
+ * A to B, you can then swipe right again to get to app C or left to get back to A.
+ */
public class TaskListStabilizer {
private static final long TASK_CACHE_TIMEOUT_MS = 5000;
- private static final int INVALID_TASK_ID = -1;
-
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskCreated(int taskId, ComponentName componentName) {
- onTaskCreatedInternal(taskId);
- }
-
- @Override
- public void onTaskMovedToFront(int taskId) {
- onTaskMovedToFrontInternal(taskId);
+ endStabilizationSession();
}
@Override
public void onTaskRemoved(int taskId) {
- onTaskRemovedInternal(taskId);
+ endStabilizationSession();
}
};
- // Task ids ordered based on recency, 0th index is the latest task
- private final IntArray mOrderedTaskIds;
+ // Task ids ordered based on recency, 0th index is the least recent task
+ private final IntArray mSystemOrder;
+ private final IntArray mStabilizedOrder;
// Wrapper objects used for sorting tasks
private final ArrayList<TaskWrapper> mTaskWrappers = new ArrayList<>();
- // Information about recent task re-order which has not been applied yet
- private int mScheduledMoveTaskId = INVALID_TASK_ID;
- private long mScheduledMoveTime = 0;
+ private boolean mInStabilizationSession;
+ private long mSessionStartTime;
public TaskListStabilizer() {
- if (ENABLE_TASK_STABILIZER.get()) {
- // Initialize the task ids map
- List<RecentTaskInfo> rawTasks = ActivityManagerWrapper.getInstance().getRecentTasks(
- Integer.MAX_VALUE, Process.myUserHandle().getIdentifier());
- mOrderedTaskIds = new IntArray(rawTasks.size());
- for (RecentTaskInfo info : rawTasks) {
- mOrderedTaskIds.add(new TaskKey(info).id);
- }
-
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
- } else {
- mOrderedTaskIds = null;
+ // Initialize the task ids map
+ List<RecentTaskInfo> rawTasks = ActivityManagerWrapper.getInstance().getRecentTasks(
+ Integer.MAX_VALUE, Process.myUserHandle().getIdentifier());
+ mSystemOrder = new IntArray(rawTasks.size());
+ for (RecentTaskInfo info : rawTasks) {
+ mSystemOrder.add(new TaskKey(info).id);
}
+ // We will lazily copy the task id's from mSystemOrder when a stabilization session starts.
+ mStabilizedOrder = new IntArray(rawTasks.size());
+
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
}
- private synchronized void onTaskCreatedInternal(int taskId) {
- applyScheduledMoveUnchecked();
- mOrderedTaskIds.add(taskId);
- }
-
- private synchronized void onTaskRemovedInternal(int taskId) {
- applyScheduledMoveUnchecked();
- mOrderedTaskIds.removeValue(taskId);
- }
-
- private void applyScheduledMoveUnchecked() {
- if (mScheduledMoveTaskId != INVALID_TASK_ID) {
- // Mode the scheduled task to front
- mOrderedTaskIds.removeValue(mScheduledMoveTaskId);
- mOrderedTaskIds.add(mScheduledMoveTaskId);
- mScheduledMoveTaskId = INVALID_TASK_ID;
+ public synchronized void startStabilizationSession() {
+ if (!mInStabilizationSession) {
+ mStabilizedOrder.clear();
+ mStabilizedOrder.addAll(mSystemOrder);
}
+ mInStabilizationSession = true;
+ mSessionStartTime = SystemClock.uptimeMillis();
}
- /**
- * Checks if the scheduled move has timed out and moves the task to front accordingly.
- */
- private void applyScheduledMoveIfTime() {
- if (mScheduledMoveTaskId != INVALID_TASK_ID
- && (SystemClock.uptimeMillis() - mScheduledMoveTime) > TASK_CACHE_TIMEOUT_MS) {
- applyScheduledMoveUnchecked();
- }
+ public synchronized void endStabilizationSession() {
+ mInStabilizationSession = false;
}
- private synchronized void onTaskMovedToFrontInternal(int taskId) {
- applyScheduledMoveIfTime();
- mScheduledMoveTaskId = taskId;
- mScheduledMoveTime = SystemClock.uptimeMillis();
- }
-
-
public synchronized ArrayList<Task> reorder(ArrayList<Task> tasks) {
- if (!ENABLE_TASK_STABILIZER.get()) {
- return tasks;
+ mSystemOrder.clear();
+ for (Task task : tasks) {
+ mSystemOrder.add(task.key.id);
}
- applyScheduledMoveIfTime();
+ if ((SystemClock.uptimeMillis() - mSessionStartTime) > TASK_CACHE_TIMEOUT_MS) {
+ endStabilizationSession();
+ }
+
+ if (!mInStabilizationSession) {
+ return tasks;
+ }
// Ensure that we have enough wrappers
int taskCount = tasks.size();
@@ -139,7 +115,7 @@
for (int i = 0; i < taskCount; i++){
TaskWrapper wrapper = listToSort.get(i);
wrapper.task = tasks.get(i);
- wrapper.index = mOrderedTaskIds.indexOf(wrapper.task.key.id);
+ wrapper.index = mStabilizedOrder.indexOf(wrapper.task.key.id);
// Ensure that missing tasks are put in the front, in the order they appear in the
// original list
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index 7a216ed..d05196b 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -26,6 +26,7 @@
import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -38,7 +39,7 @@
private final MainThreadExecutor mMainThreadExecutor;
private final int mCacheSize;
- private final TaskKeyLruCache<ThumbnailData> mCache;
+ private final ThumbnailCache mCache;
private final HighResLoadingState mHighResLoadingState;
public static class HighResLoadingState {
@@ -98,7 +99,7 @@
Resources res = context.getResources();
mCacheSize = res.getInteger(R.integer.recentsThumbnailCacheSize);
- mCache = new TaskKeyLruCache<>(mCacheSize);
+ mCache = new ThumbnailCache(mCacheSize);
}
/**
@@ -106,13 +107,20 @@
*/
public void updateThumbnailInCache(Task task) {
Preconditions.assertUIThread();
-
// Fetch the thumbnail for this task and put it in the cache
- updateThumbnailInBackground(task, true /* reducedResolution */, (t) -> {
- mCache.put(task.key, t.thumbnail);
- });
+ if (task.thumbnail == null) {
+ updateThumbnailInBackground(task.key, true /* reducedResolution */,
+ t -> task.thumbnail = t);
+ }
}
+ /**
+ * Synchronously updates the thumbnail in the cache if it is already there.
+ */
+ public void updateTaskSnapShot(int taskId, ThumbnailData thumbnail) {
+ Preconditions.assertUIThread();
+ mCache.updateIfAlreadyInCache(taskId, thumbnail);
+ }
/**
* Asynchronously fetches the icon and other task data for the given {@param task}.
@@ -120,22 +128,33 @@
* @param callback The callback to receive the task after its data has been populated.
* @return A cancelable handle to the request
*/
- public ThumbnailLoadRequest updateThumbnailInBackground(Task task, boolean reducedResolution,
- Consumer<Task> callback) {
+ public ThumbnailLoadRequest updateThumbnailInBackground(
+ Task task, Consumer<ThumbnailData> callback) {
Preconditions.assertUIThread();
+ boolean reducedResolution = !mHighResLoadingState.isEnabled();
if (task.thumbnail != null && (!task.thumbnail.reducedResolution || reducedResolution)) {
// Nothing to load, the thumbnail is already high-resolution or matches what the
// request, so just callback
- callback.accept(task);
+ callback.accept(task.thumbnail);
return null;
}
- ThumbnailData cachedThumbnail = mCache.getAndInvalidateIfModified(task.key);
+
+ return updateThumbnailInBackground(task.key, !mHighResLoadingState.isEnabled(), t -> {
+ task.thumbnail = t;
+ callback.accept(t);
+ });
+ }
+
+ private ThumbnailLoadRequest updateThumbnailInBackground(TaskKey key, boolean reducedResolution,
+ Consumer<ThumbnailData> callback) {
+ Preconditions.assertUIThread();
+
+ ThumbnailData cachedThumbnail = mCache.getAndInvalidateIfModified(key);
if (cachedThumbnail != null && (!cachedThumbnail.reducedResolution || reducedResolution)) {
// Already cached, lets use that thumbnail
- task.thumbnail = cachedThumbnail;
- callback.accept(task);
+ callback.accept(cachedThumbnail);
return null;
}
@@ -144,14 +163,14 @@
@Override
public void run() {
ThumbnailData thumbnail = ActivityManagerWrapper.getInstance().getTaskThumbnail(
- task.key.id, reducedResolution);
+ key.id, reducedResolution);
if (isCanceled()) {
// We don't call back to the provided callback in this case
return;
}
mMainThreadExecutor.execute(() -> {
- task.thumbnail = thumbnail;
- callback.accept(task);
+ mCache.put(key, thumbnail);
+ callback.accept(thumbnail);
onEnd();
});
}
@@ -196,4 +215,21 @@
this.reducedResolution = reducedResolution;
}
}
+
+ private static class ThumbnailCache extends TaskKeyLruCache<ThumbnailData> {
+
+ public ThumbnailCache(int cacheSize) {
+ super(cacheSize);
+ }
+
+ /**
+ * Updates the cache entry if it is already present in the cache
+ */
+ public void updateIfAlreadyInCache(int taskId, ThumbnailData thumbnailData) {
+ ThumbnailData oldData = getCacheEntry(taskId);
+ if (oldData != null) {
+ putCacheEntry(taskId, thumbnailData);
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index c2777e7..5f76ca7 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -16,44 +16,30 @@
package com.android.quickstep;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
-
-import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.graphics.RectF;
import android.os.UserHandle;
import android.util.Log;
-import android.view.View;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.ComponentKey;
-import com.android.quickstep.util.ClipAnimationHelper;
-import com.android.quickstep.util.MultiValueUpdateListener;
-import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.List;
/**
* Contains helpful methods for retrieving data from {@link Task}s.
*/
-public class TaskUtils {
+public final class TaskUtils {
private static final String TAG = "TaskUtils";
+ private TaskUtils() {}
+
/**
* TODO: remove this once we switch to getting the icon and label from IconCache.
*/
@@ -79,117 +65,6 @@
}
- /**
- * Try to find a TaskView that corresponds with the component of the launched view.
- *
- * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation.
- * Otherwise, we will assume we are using a normal app transition, but it's possible that the
- * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView.
- */
- public static TaskView findTaskViewToLaunch(
- BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) {
- RecentsView recentsView = activity.getOverviewPanel();
- if (v instanceof TaskView) {
- TaskView taskView = (TaskView) v;
- return recentsView.isTaskViewVisible(taskView) ? taskView : null;
- }
-
- // It's possible that the launched view can still be resolved to a visible task view, check
- // the task id of the opening task and see if we can find a match.
- if (v.getTag() instanceof ItemInfo) {
- ItemInfo itemInfo = (ItemInfo) v.getTag();
- ComponentName componentName = itemInfo.getTargetComponent();
- int userId = itemInfo.user.getIdentifier();
- if (componentName != null) {
- for (int i = 0; i < recentsView.getTaskViewCount(); i++) {
- TaskView taskView = recentsView.getTaskViewAt(i);
- if (recentsView.isTaskViewVisible(taskView)) {
- Task.TaskKey key = taskView.getTask().key;
- if (componentName.equals(key.getComponent()) && userId == key.userId) {
- return taskView;
- }
- }
- }
- }
- }
-
- if (targets == null) {
- return null;
- }
- // Resolve the opening task id
- int openingTaskId = -1;
- for (RemoteAnimationTargetCompat target : targets) {
- if (target.mode == MODE_OPENING) {
- openingTaskId = target.taskId;
- break;
- }
- }
-
- // If there is no opening task id, fall back to the normal app icon launch animation
- if (openingTaskId == -1) {
- return null;
- }
-
- // If the opening task id is not currently visible in overview, then fall back to normal app
- // icon launch animation
- TaskView taskView = recentsView.getTaskView(openingTaskId);
- if (taskView == null || !recentsView.isTaskViewVisible(taskView)) {
- return null;
- }
- return taskView;
- }
-
- /**
- * @return Animator that controls the window of the opening targets for the recents launch
- * animation.
- */
- public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
- RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) {
- ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams()
- .setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(v));
-
- final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
- appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
- appAnimator.addUpdateListener(new MultiValueUpdateListener() {
-
- // Defer fading out the view until after the app window gets faded in
- final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR);
- final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR);
-
- final RemoteAnimationTargetSet mTargetSet;
-
- final RectF mThumbnailRect;
-
- {
- mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING);
- inOutHelper.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value);
-
- inOutHelper.prepareAnimation(true /* isOpening */);
- inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(),
- mTargetSet.apps.length == 0 ? null : mTargetSet.apps[0]);
-
- mThumbnailRect = new RectF(inOutHelper.getTargetRect());
- mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY());
- Utilities.scaleRectFAboutCenter(mThumbnailRect, 1 / v.getScaleX());
- }
-
- @Override
- public void onUpdate(float percent) {
- params.setProgress(1 - percent);
- RectF taskBounds = inOutHelper.applyTransform(mTargetSet, params);
- if (!skipViewChanges) {
- float scale = taskBounds.width() / mThumbnailRect.width();
- v.setScaleX(scale);
- v.setScaleY(scale);
- v.setTranslationX(taskBounds.centerX() - mThumbnailRect.centerX());
- v.setTranslationY(taskBounds.centerY() - mThumbnailRect.centerY());
- v.setAlpha(mViewAlpha.value);
- }
- }
- });
- return appAnimator;
- }
-
public static boolean taskIsATargetWithMode(RemoteAnimationTargetCompat[] targets,
int taskId, int mode) {
for (RemoteAnimationTargetCompat target : targets) {
diff --git a/quickstep/src/com/android/quickstep/TouchConsumer.java b/quickstep/src/com/android/quickstep/TouchConsumer.java
deleted file mode 100644
index 026f715..0000000
--- a/quickstep/src/com/android/quickstep/TouchConsumer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.view.MotionEvent;
-
-import androidx.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.function.Consumer;
-
-@TargetApi(Build.VERSION_CODES.O)
-@FunctionalInterface
-public interface TouchConsumer extends Consumer<MotionEvent> {
-
- TouchConsumer NO_OP = (ev) -> {};
-
- @IntDef(flag = true, value = {
- INTERACTION_NORMAL,
- INTERACTION_QUICK_SCRUB
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface InteractionType {}
- int INTERACTION_NORMAL = 0;
- int INTERACTION_QUICK_SCRUB = 1;
-
- default void onQuickScrubStart() { }
-
- default void onQuickScrubEnd() { }
-
- default void onQuickScrubProgress(float progress) { }
-
- default void onQuickStep(MotionEvent ev) { }
-
- default void onShowOverviewFromAltTab() {}
-
- default boolean isActive() {
- return false;
- }
-
- /**
- * Called by the event queue when the consumer is about to be switched to a new consumer.
- */
- default void onConsumerAboutToBeSwitched() { }
-}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
deleted file mode 100644
index 951ba4f..0000000
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import static android.view.MotionEvent.ACTION_CANCEL;
-import static android.view.MotionEvent.ACTION_DOWN;
-import static android.view.MotionEvent.ACTION_MOVE;
-import static android.view.MotionEvent.ACTION_POINTER_DOWN;
-import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
-import static android.view.MotionEvent.ACTION_UP;
-
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
-
-import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.Service;
-import android.content.Intent;
-import android.graphics.PointF;
-import android.graphics.Region;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Looper;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.Choreographer;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Service connected by system-UI for handling touch interaction.
- */
-@TargetApi(Build.VERSION_CODES.O)
-public class TouchInteractionService extends Service {
-
- public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
-
- private static final SparseArray<String> sMotionEventNames;
-
- static {
- sMotionEventNames = new SparseArray<>(3);
- sMotionEventNames.put(ACTION_DOWN, "ACTION_DOWN");
- sMotionEventNames.put(ACTION_UP, "ACTION_UP");
- sMotionEventNames.put(ACTION_CANCEL, "ACTION_CANCEL");
- }
-
- public static final int EDGE_NAV_BAR = 1 << 8;
-
- private static final String TAG = "TouchInteractionService";
-
- private final IBinder mMyBinder = new IOverviewProxy.Stub() {
-
- public void onActiveNavBarRegionChanges(Region region) { }
-
- public void onInitialize(Bundle params) { }
-
- public void onPreMotionEvent(@HitTarget int downHitTarget) {
- mTouchInteractionLog.prepareForNewGesture();
-
- TraceHelper.beginSection("SysUiBinder");
- mEventQueue.onNewGesture(downHitTarget);
- TraceHelper.partitionSection("SysUiBinder", "Down target " + downHitTarget);
- }
-
- public void onMotionEvent(MotionEvent ev) {
- mEventQueue.queue(ev);
-
- int action = ev.getActionMasked();
- if (action == ACTION_DOWN) {
- mOverviewInteractionState.setSwipeGestureInitializing(true);
- } else if (action == ACTION_UP || action == ACTION_CANCEL) {
- mOverviewInteractionState.setSwipeGestureInitializing(false);
- }
-
- String name = sMotionEventNames.get(action);
- if (name != null){
- TraceHelper.partitionSection("SysUiBinder", name);
- }
- }
-
- public void onBind(ISystemUiProxy iSystemUiProxy) {
- mISystemUiProxy = iSystemUiProxy;
- mRecentsModel.setSystemUiProxy(mISystemUiProxy);
- mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
- }
-
- public void onQuickScrubStart() {
- mEventQueue.onQuickScrubStart();
- mOverviewInteractionState.setSwipeGestureInitializing(false);
- TraceHelper.partitionSection("SysUiBinder", "onQuickScrubStart");
- }
-
- public void onQuickScrubProgress(float progress) {
- mEventQueue.onQuickScrubProgress(progress);
- }
-
- public void onQuickScrubEnd() {
- mEventQueue.onQuickScrubEnd();
- TraceHelper.endSection("SysUiBinder", "onQuickScrubEnd");
- }
-
- @Override
- public void onOverviewToggle() {
- mOverviewCommandHelper.onOverviewToggle();
- }
-
- @Override
- public void onOverviewShown(boolean triggeredFromAltTab) {
- if (triggeredFromAltTab) {
- mEventQueue.onNewGesture(HIT_TARGET_NONE);
- mEventQueue.onOverviewShownFromAltTab();
- } else {
- mOverviewCommandHelper.onOverviewShown();
- }
- }
-
- @Override
- public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- if (triggeredFromAltTab && !triggeredFromHomeKey) {
- // onOverviewShownFromAltTab initiates quick scrub. Ending it here.
- mEventQueue.onQuickScrubEnd();
- }
- }
-
- public void onQuickStep(MotionEvent motionEvent) {
- mEventQueue.onQuickStep(motionEvent);
- mOverviewInteractionState.setSwipeGestureInitializing(false);
- TraceHelper.endSection("SysUiBinder", "onQuickStep");
- }
-
- @Override
- public void onTip(int actionType, int viewType) {
- mOverviewCommandHelper.onTip(actionType, viewType);
- }
- };
-
- private static boolean sConnected = false;
-
- public static boolean isConnected() {
- return sConnected;
- }
-
- private ActivityManagerWrapper mAM;
- private RecentsModel mRecentsModel;
- private MotionEventQueue mEventQueue;
- private ISystemUiProxy mISystemUiProxy;
- private OverviewCommandHelper mOverviewCommandHelper;
- private OverviewComponentObserver mOverviewComponentObserver;
- private OverviewInteractionState mOverviewInteractionState;
- private OverviewCallbacks mOverviewCallbacks;
- private TaskOverlayFactory mTaskOverlayFactory;
- private TouchInteractionLog mTouchInteractionLog;
- private InputConsumerController mInputConsumer;
- private SwipeSharedState mSwipeSharedState;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mAM = ActivityManagerWrapper.getInstance();
- mRecentsModel = RecentsModel.INSTANCE.get(this);
- mOverviewComponentObserver = new OverviewComponentObserver(this);
- mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver);
- mEventQueue = new MotionEventQueue(Looper.myLooper(), Choreographer.getInstance(),
- this::newConsumer);
- mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
- mOverviewCallbacks = OverviewCallbacks.get(this);
- mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
- mTouchInteractionLog = new TouchInteractionLog();
- mSwipeSharedState = new SwipeSharedState();
- mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
- mInputConsumer.registerInputConsumer();
-
- sConnected = true;
-
- // Temporarily disable model preload
- // new ModelPreload().start(this);
- }
-
- @Override
- public void onDestroy() {
- mInputConsumer.unregisterInputConsumer();
- mOverviewComponentObserver.onDestroy();
- mEventQueue.dispose();
- sConnected = false;
- super.onDestroy();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- Log.d(TAG, "Touch service connected");
- return mMyBinder;
- }
-
- private TouchConsumer newConsumer(@HitTarget int downHitTarget, boolean useSharedState) {
- RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
- if (!useSharedState) {
- mSwipeSharedState.clearAllState();
- }
-
- if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher) {
- return TouchConsumer.NO_OP;
- } else if (mSwipeSharedState.goingToLauncher ||
- mOverviewComponentObserver.getActivityControlHelper().isResumed()) {
- return OverviewTouchConsumer.newInstance(
- mOverviewComponentObserver.getActivityControlHelper(), false,
- mTouchInteractionLog);
- } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
- mOverviewComponentObserver.getActivityControlHelper().isInLiveTileMode()) {
- return OverviewTouchConsumer.newInstance(
- mOverviewComponentObserver.getActivityControlHelper(), false,
- mTouchInteractionLog, false /* waitForWindowAvailable */);
- } else {
- return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
- mOverviewComponentObserver.getOverviewIntent(),
- mOverviewComponentObserver.getActivityControlHelper(),
- downHitTarget, mOverviewCallbacks,
- mTaskOverlayFactory, mInputConsumer, mTouchInteractionLog, mEventQueue,
- mSwipeSharedState);
- }
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mTouchInteractionLog.dump(pw);
- }
-
- public static class OverviewTouchConsumer<T extends BaseDraggingActivity>
- implements TouchConsumer {
-
- private final ActivityControlHelper<T> mActivityHelper;
- private final T mActivity;
- private final BaseDragLayer mTarget;
- private final int[] mLocationOnScreen = new int[2];
- private final PointF mDownPos = new PointF();
- private final int mTouchSlop;
- private final QuickScrubController mQuickScrubController;
- private final TouchInteractionLog mTouchInteractionLog;
-
- private final boolean mStartingInActivityBounds;
-
- private boolean mTrackingStarted = false;
- private boolean mInvalidated = false;
-
- private float mLastProgress = 0;
- private boolean mStartPending = false;
- private boolean mEndPending = false;
- private boolean mWaitForWindowAvailable;
-
- OverviewTouchConsumer(ActivityControlHelper<T> activityHelper, T activity,
- boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog,
- boolean waitForWindowAvailable) {
- mActivityHelper = activityHelper;
- mActivity = activity;
- mTarget = activity.getDragLayer();
- mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
- mStartingInActivityBounds = startingInActivityBounds;
-
- mQuickScrubController = mActivity.<RecentsView>getOverviewPanel()
- .getQuickScrubController();
- mTouchInteractionLog = touchInteractionLog;
- mTouchInteractionLog.setTouchConsumer(this);
-
- mWaitForWindowAvailable = waitForWindowAvailable;
- }
-
- @Override
- public void accept(MotionEvent ev) {
- if (mInvalidated) {
- return;
- }
- mTouchInteractionLog.addMotionEvent(ev);
- int action = ev.getActionMasked();
- if (action == ACTION_DOWN) {
- if (mStartingInActivityBounds) {
- startTouchTracking(ev, false /* updateLocationOffset */);
- return;
- }
- mTrackingStarted = false;
- mDownPos.set(ev.getX(), ev.getY());
- } else if (!mTrackingStarted) {
- switch (action) {
- case ACTION_CANCEL:
- case ACTION_UP:
- startTouchTracking(ev, true /* updateLocationOffset */);
- break;
- case ACTION_MOVE: {
- float displacement = mActivity.getDeviceProfile().isLandscape ?
- ev.getX() - mDownPos.x : ev.getY() - mDownPos.y;
- if (Math.abs(displacement) >= mTouchSlop) {
- // Start tracking only when mTouchSlop is crossed.
- startTouchTracking(ev, true /* updateLocationOffset */);
- }
- }
- }
- }
-
- if (mTrackingStarted) {
- sendEvent(ev);
- }
-
- if (action == ACTION_UP || action == ACTION_CANCEL) {
- mInvalidated = true;
- }
- }
-
- private void startTouchTracking(MotionEvent ev, boolean updateLocationOffset) {
- if (updateLocationOffset) {
- mTarget.getLocationOnScreen(mLocationOnScreen);
- }
-
- // Send down touch event
- MotionEvent down = MotionEvent.obtainNoHistory(ev);
- down.setAction(ACTION_DOWN);
- sendEvent(down);
-
- mTrackingStarted = true;
- // Send pointer down for remaining pointers.
- int pointerCount = ev.getPointerCount();
- for (int i = 1; i < pointerCount; i++) {
- down.setAction(ACTION_POINTER_DOWN | (i << ACTION_POINTER_INDEX_SHIFT));
- sendEvent(down);
- }
-
- down.recycle();
- }
-
- private void sendEvent(MotionEvent ev) {
- if (!mTarget.verifyTouchDispatch(this, ev)) {
- mInvalidated = true;
- return;
- }
- int flags = ev.getEdgeFlags();
- ev.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
- ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
- if (!mTrackingStarted) {
- mTarget.onInterceptTouchEvent(ev);
- }
- mTarget.onTouchEvent(ev);
- ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
- ev.setEdgeFlags(flags);
- }
-
- @Override
- public void onQuickStep(MotionEvent ev) {
- if (mInvalidated) {
- return;
- }
- OverviewCallbacks.get(mActivity).closeAllWindows();
- ActivityManagerWrapper.getInstance()
- .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mTouchInteractionLog.startQuickStep();
- }
-
- @Override
- public void onQuickScrubStart() {
- if (mInvalidated) {
- return;
- }
- mTouchInteractionLog.startQuickScrub();
- if (!mQuickScrubController.prepareQuickScrub(TAG)) {
- mInvalidated = true;
- mTouchInteractionLog.endQuickScrub("onQuickScrubStart");
- return;
- }
- OverviewCallbacks.get(mActivity).closeAllWindows();
- ActivityManagerWrapper.getInstance()
- .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
-
- mStartPending = true;
- Runnable action = () -> {
- if (!mQuickScrubController.prepareQuickScrub(TAG)) {
- mInvalidated = true;
- mTouchInteractionLog.endQuickScrub("onQuickScrubStart");
- return;
- }
- mActivityHelper.onQuickInteractionStart(mActivity, null, true,
- mTouchInteractionLog);
- mQuickScrubController.onQuickScrubProgress(mLastProgress);
- mStartPending = false;
-
- if (mEndPending) {
- mQuickScrubController.onQuickScrubEnd();
- mEndPending = false;
- }
- };
-
- if (mWaitForWindowAvailable) {
- mActivityHelper.executeOnWindowAvailable(mActivity, action);
- } else {
- action.run();
- }
- }
-
- @Override
- public void onQuickScrubEnd() {
- mTouchInteractionLog.endQuickScrub("onQuickScrubEnd");
- if (mInvalidated) {
- return;
- }
- if (mStartPending) {
- mEndPending = true;
- } else {
- mQuickScrubController.onQuickScrubEnd();
- }
- }
-
- @Override
- public void onQuickScrubProgress(float progress) {
- mTouchInteractionLog.setQuickScrubProgress(progress);
- mLastProgress = progress;
- if (mInvalidated || mStartPending) {
- return;
- }
- mQuickScrubController.onQuickScrubProgress(progress);
- }
-
- public static TouchConsumer newInstance(ActivityControlHelper activityHelper,
- boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog) {
- return newInstance(activityHelper, startingInActivityBounds, touchInteractionLog,
- true /* waitForWindowAvailable */);
- }
-
- public static TouchConsumer newInstance(ActivityControlHelper activityHelper,
- boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog,
- boolean waitForWindowAvailable) {
- BaseDraggingActivity activity = activityHelper.getCreatedActivity();
- if (activity == null) {
- return TouchConsumer.NO_OP;
- }
- return new OverviewTouchConsumer(activityHelper, activity, startingInActivityBounds,
- touchInteractionLog, waitForWindowAvailable);
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/BinderTracker.java b/quickstep/src/com/android/quickstep/util/BinderTracker.java
new file mode 100644
index 0000000..32d0d53
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/BinderTracker.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Looper;
+import android.util.Log;
+
+import com.android.launcher3.config.FeatureFlags;
+
+/**
+ * Utility class to test and check binder calls during development.
+ */
+public class BinderTracker {
+
+ private static final String TAG = "BinderTracker";
+
+ public static void start() {
+ if (!FeatureFlags.IS_DOGFOOD_BUILD) {
+ Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
+ return;
+ }
+
+ Binder.setProxyTransactListener(new Tracker());
+ }
+
+ public static void stop() {
+ if (!FeatureFlags.IS_DOGFOOD_BUILD) {
+ Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
+ return;
+ }
+ Binder.setProxyTransactListener(null);
+ }
+
+ private static class Tracker implements Binder.ProxyTransactListener {
+
+ @Override
+ public Object onTransactStarted(IBinder iBinder, int code) {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ Log.e(TAG, "Binder call on ui thread", new Exception());
+ }
+ return null;
+ }
+
+ @Override
+ public void onTransactEnded(Object session) { }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/CachedEventDispatcher.java b/quickstep/src/com/android/quickstep/util/CachedEventDispatcher.java
new file mode 100644
index 0000000..194c7d4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/CachedEventDispatcher.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 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.systemui.shared.system.InputChannelCompat.mergeMotionEvent;
+
+import android.view.MotionEvent;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Utility class to dispatch touch events to a different class. It stores the events locally
+ * until a valid dispatcher is available.
+ */
+public class CachedEventDispatcher {
+
+ private Consumer<MotionEvent> mConsumer;
+
+ private ArrayList<MotionEvent> mCache;
+ private MotionEvent mLastEvent;
+
+ public void dispatchEvent(MotionEvent event) {
+ if (mConsumer != null) {
+ mConsumer.accept(event);
+ } else {
+ if (mLastEvent == null || !mergeMotionEvent(event, mLastEvent)) {
+ // Queue event.
+ if (mCache == null) {
+ mCache = new ArrayList<>();
+ }
+ mLastEvent = MotionEvent.obtain(event);
+ mCache.add(mLastEvent);
+ }
+ }
+ }
+
+ public void setConsumer(Consumer<MotionEvent> consumer) {
+ if (consumer == null) {
+ return;
+ }
+ mConsumer = consumer;
+ int cacheCount = mCache == null ? 0 : mCache.size();
+ for (int i = 0; i < cacheCount; i++) {
+ MotionEvent ev = mCache.get(i);
+ mConsumer.accept(ev);
+ ev.recycle();
+ }
+ mCache = null;
+ mLastEvent = null;
+ }
+
+ public boolean hasConsumer() {
+ return mConsumer != null;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index ed585c1..a06209a 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -43,6 +43,8 @@
float extraSpace;
if (dp.isVerticalBarLayout()) {
extraSpace = 0;
+ } else if (FeatureFlags.ENABLE_HINTS_IN_OVERVIEW.get()){
+ extraSpace = dp.hotseatBarSizePx + dp.verticalDragHandleSizePx + dp.chipHintHeightPx;
} else {
extraSpace = dp.hotseatBarSizePx + dp.verticalDragHandleSizePx;
}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 1156b87..21d8144 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -20,6 +20,7 @@
import android.os.SystemClock;
import android.view.MotionEvent;
+import com.android.launcher3.Alarm;
import com.android.launcher3.R;
/**
@@ -32,11 +33,15 @@
// The bigger this number, the easier it is to trigger the first pause.
private static final float RAPID_DECELERATION_FACTOR = 0.6f;
+ /** If no motion is added for this amount of time, assume the motion has paused. */
+ private static final long FORCE_PAUSE_TIMEOUT = 300;
+
private final float mSpeedVerySlow;
private final float mSpeedSomewhatFast;
private final float mSpeedFast;
private final float mMinDisplacementForPause;
private final float mMaxOrthogonalDisplacementForPause;
+ private final Alarm mForcePauseTimeout;
private Long mPreviousTime = null;
private Float mPreviousPosition = null;
@@ -59,6 +64,8 @@
mMinDisplacementForPause = res.getDimension(R.dimen.motion_pause_detector_min_displacement);
mMaxOrthogonalDisplacementForPause = res.getDimension(
R.dimen.motion_pause_detector_max_orthogonal_displacement);
+ mForcePauseTimeout = new Alarm();
+ mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
}
/**
@@ -70,6 +77,7 @@
if (mOnMotionPauseListener != null) {
mOnMotionPauseListener.onMotionPauseChanged(mIsPaused);
}
+ mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
}
/**
@@ -100,6 +108,7 @@
}
mPreviousTime = time;
mPreviousPosition = position;
+ mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
}
private void checkMotionPaused(float velocity, float prevVelocity,
@@ -129,6 +138,10 @@
boolean passedMaxOrthogonalDisplacement =
totalDisplacement.orthogonal >= mMaxOrthogonalDisplacementForPause;
isPaused &= passedMinDisplacement && !passedMaxOrthogonalDisplacement;
+ updatePaused(isPaused);
+ }
+
+ private void updatePaused(boolean isPaused) {
if (mIsPaused != isPaused) {
mIsPaused = isPaused;
if (mIsPaused) {
@@ -149,6 +162,7 @@
mTotalDisplacement.set(0, 0);
setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false;
+ mForcePauseTimeout.cancelAlarm();
}
public boolean isPaused() {
diff --git a/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
deleted file mode 100644
index 4f02acf..0000000
--- a/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
-
-import android.graphics.Rect;
-
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-
-/**
- * Extension of {@link RemoteAnimationTargetSet} with additional information about swipe
- * up animation
- */
-public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
-
- public final RecentsAnimationControllerCompat controller;
- public final Rect homeContentInsets;
- public final Rect minimizedHomeBounds;
-
- public SwipeAnimationTargetSet(RecentsAnimationControllerCompat controller,
- RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
- Rect minimizedHomeBounds) {
- super(targets, MODE_CLOSING);
- this.controller = controller;
- this.homeContentInsets = homeContentInsets;
- this.minimizedHomeBounds = minimizedHomeBounds;
- }
-
-
- public interface SwipeAnimationListener {
-
- void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet);
-
- void onRecentsAnimationCanceled();
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/TransformedRect.java b/quickstep/src/com/android/quickstep/util/TransformedRect.java
deleted file mode 100644
index 79f11e4..0000000
--- a/quickstep/src/com/android/quickstep/util/TransformedRect.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import android.graphics.Rect;
-
-/**
- * A wrapper around {@link Rect} with additional transformation properties
- */
-public class TransformedRect {
-
- public final Rect rect = new Rect();
- public float scale = 1;
-
- public void set(TransformedRect transformedRect) {
- rect.set(transformedRect.rect);
- scale = transformedRect.scale;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
deleted file mode 100644
index a8205cd..0000000
--- a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.views;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.Insettable;
-import com.android.launcher3.Launcher;
-import com.android.quickstep.ActivityControlHelper.LayoutListener;
-import com.android.quickstep.WindowTransformSwipeHandler;
-
-/**
- * Floating view which shows the task snapshot allowing it to be dragged and placed.
- */
-public class LauncherLayoutListener extends AbstractFloatingView
- implements Insettable, LayoutListener {
-
- public static LauncherLayoutListener resetAndGet(Launcher launcher) {
- LauncherRecentsView lrv = launcher.getOverviewPanel();
- LauncherLayoutListener listener = lrv.mLauncherLayoutListener;
- if (listener.isOpen()) {
- listener.close(false);
- }
- listener.setHandler(null);
- return listener;
- }
-
- private final Launcher mLauncher;
- private final Paint mPaint = new Paint();
- private WindowTransformSwipeHandler mHandler;
- private RectF mCurrentRect;
- private float mCornerRadius;
-
- private boolean mWillNotDraw;
-
- /**
- * package private
- */
- LauncherLayoutListener(Launcher launcher) {
- super(launcher, null);
- mLauncher = launcher;
- mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
- setLayoutParams(new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-
- mWillNotDraw = willNotDraw();
- super.setWillNotDraw(false);
- }
-
- @Override
- public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
- float cornerRadius) {
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (shouldFinish) {
- finish();
- }
- return;
- }
-
- mCurrentRect = currentRect;
- mCornerRadius = cornerRadius;
-
- setWillNotDraw(mCurrentRect == null || isLongSwipe);
- invalidate();
- }
-
- @Override
- public void setWillNotDraw(boolean willNotDraw) {
- // Prevent super call as that causes additional relayout.
- mWillNotDraw = willNotDraw;
- }
-
- @Override
- public void setHandler(WindowTransformSwipeHandler handler) {
- mHandler = handler;
- }
-
- @Override
- public void setInsets(Rect insets) {
- if (mHandler != null) {
- mHandler.buildAnimationController();
- }
- }
-
- @Override
- public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
- return false;
- }
-
- @Override
- protected void handleClose(boolean animate) {
- if (mIsOpen) {
- mIsOpen = false;
- // We don't support animate.
- mLauncher.getDragLayer().removeView(this);
-
- if (mHandler != null) {
- mHandler.layoutListenerClosed();
- }
- }
- }
-
- @Override
- public void open() {
- if (!mIsOpen) {
- mLauncher.getDragLayer().addView(this);
- mIsOpen = true;
- }
- }
-
- @Override
- public void logActionCommand(int command) {
- // We should probably log the weather
- }
-
- @Override
- protected boolean isOfType(int type) {
- return (type & TYPE_QUICKSTEP_PREVIEW) != 0;
- }
-
- @Override
- public void finish() {
- close(false);
- setHandler(null);
- mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (!mWillNotDraw) {
- canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint);
- }
- }
-}
diff --git a/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java b/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java
index b801b4f..7274090 100644
--- a/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java
+++ b/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java
@@ -90,11 +90,16 @@
base.evaluate();
}
- private void overrideSwipeUpEnabled(Boolean swipeUpEnabledOverride) {
+ private void overrideSwipeUpEnabled(Boolean swipeUpEnabledOverride)
+ throws Throwable {
mLauncher.overrideSwipeUpEnabled(swipeUpEnabledOverride);
mMainThreadExecutor.execute(() -> OverviewInteractionState.INSTANCE.get(
InstrumentationRegistry.getInstrumentation().getTargetContext()).
notifySwipeUpSettingChanged(mLauncher.isSwipeUpEnabled()));
+ // TODO(b/124236673): avoid using sleep().
+ mLauncher.getDevice().waitForIdle();
+ Thread.sleep(2000);
+ mLauncher.getDevice().waitForIdle();
}
};
} else {
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index c243968..fe789aa 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -63,11 +63,11 @@
public void testPressHome() {
runTest(enterEvt(Launcher.ON_CREATE_EVT),
exitEvt(Launcher.ON_CREATE_EVT),
- enterEvt(OtherActivityTouchConsumer.DOWN_EVT),
- exitEvt(OtherActivityTouchConsumer.DOWN_EVT));
+ enterEvt(OtherActivityInputConsumer.DOWN_EVT),
+ exitEvt(OtherActivityInputConsumer.DOWN_EVT));
- runTest(enterEvt(OtherActivityTouchConsumer.DOWN_EVT),
- exitEvt(OtherActivityTouchConsumer.DOWN_EVT),
+ runTest(enterEvt(OtherActivityInputConsumer.DOWN_EVT),
+ exitEvt(OtherActivityInputConsumer.DOWN_EVT),
enterEvt(Launcher.ON_CREATE_EVT),
exitEvt(Launcher.ON_CREATE_EVT));
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index e9d8bce..c60cf45 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -55,12 +55,7 @@
@Before
public void setUp() throws Exception {
super.setUp();
-
- clearLauncherData();
-
- mLauncher.pressHome();
- waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL);
- waitForResumed("Launcher internal state is still Background");
+ TaplTestsLauncher3.initialize(this);
}
private void startTestApps() throws Exception {
diff --git a/res/layout/hint_container.xml b/res/layout/hint_container.xml
new file mode 100644
index 0000000..75aa913
--- /dev/null
+++ b/res/layout/hint_container.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+-->
+<merge/>
\ No newline at end of file
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index 87078b9..91c3705 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -43,6 +43,11 @@
layout="@layout/overview_panel"
android:visibility="gone" />
+ <include
+ android:id="@+id/hints"
+ layout="@layout/hint_container"
+ android:visibility="gone"/>
+
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
<com.android.launcher3.pageindicators.WorkspacePageIndicator
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 8fdc27b..ca59afa 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Vouer: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Legstukke"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Muurpapiere"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Style en muurpapiere"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Tuis-instellings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gedeaktiveer deur jou administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Laat toe dat tuisskerm gedraai word"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 4c80204..d942e9e 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"አቃፊ፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ፍርግሞች"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"የግድግዳ ወረቀቶች"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ቅጦች እና ልጣፎች"</string>
<string name="settings_button_text" msgid="8873672322605444408">"የመነሻ ቅንብሮች"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"በእርስዎ አስተዳዳሪ የተሰናከለ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"የመነሻ ማያ ገጽ ማሽከርከርን ይፍቀዱ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 72f6e6a..bf00e95 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -84,8 +84,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"المجلد: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"الأدوات"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"الخلفيات"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"الأنماط والخلفيات"</string>
<string name="settings_button_text" msgid="8873672322605444408">"إعدادات الصفحة الرئيسية"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"أوقف المشرف هذه الميزة"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"السماح بتدوير الشاشة الرئيسية"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index f528f2b..2984603 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ৱিজেটসমূহ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ৱালপেপাৰসমূহ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ষ্টাইল & ৱালপেপাৰ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিংসমূহ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"গৃহ স্ক্ৰীণ ঘূৰোৱাৰ অনুমতি দিয়ক"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 26b5da5..5528a19 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Qovluq: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Vidcet"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Divar kağızları"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Üslub və divar kağızları"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home ayarları"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Admininiz tərəfindən deaktiv edilib"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Əsas ekranın firlanmağına icazə verin"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 7306b02..5158a78 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -81,8 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Direktorijum: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Vidžeti"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilovi i pozadine"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Podešavanja početnog ekrana"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator je onemogućio"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Dozvoli rotaciju početnog ekrana"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index a30b403..b4cf913 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Віджэты"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Шпалеры"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стылі і шпалеры"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Налады галоўнага экрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Адключаная адміністратарам"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дазволіць паварот галоўнага экрана"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 360a036..408f205 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Приспособления"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилове и тапети"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Настройки за началния екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Разрешаване на завъртането на началния екран"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 59f7d29..6d80329 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ফোল্ডার: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"উইজেট"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ওয়ালপেপারগুলি"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"স্টাইল এবং ওয়ালপেপার"</string>
<string name="settings_button_text" msgid="8873672322605444408">"হোম সেটিংস"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"হোমস্ক্রীন ঘোরানোর অনুমতি দিন"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 803fee8..53bdeb2 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -81,8 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Dodaci"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadinske slike"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilovi i pozadinske slike"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Postavke početnog ekrana"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio vaš administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Dozvoli rotiranje početnog ekrana"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 02180dc..56ef414 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fons de pantalla"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estils i fons de pantalla"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configuració de pantalla d\'inici"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desactivada per l\'administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permet la rotació de la pantalla d\'inici"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 0d78e54..692b57d 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Složka: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgety"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styly a tapety"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Nastavení plochy"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázáno administrátorem"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Povolit otáčení plochy"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index e1f1b63..a471e50 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Baggrunde"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilarter og baggrunde"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Indstillinger for startskærmen"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Deaktiveret af din administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillad rotation af startskærmen"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 4fcb8a0..1b7cd22 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Ordner: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Hintergründe"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stile und Hintergründe"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Einstellungen für den Startbildschirm"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Von deinem Administrator deaktiviert"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Drehung des Startbildschirms zulassen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 73d88a1..2363e61 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Γραφικά στοιχεία"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ταπετσαρίες"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Στιλ και ταπετσαρίες"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ρυθμίσεις Αρχ. Οθ."</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Να επιτρέπεται η περιστροφή της αρχικής οθόνης"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 0061afb..6692370 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles & wallpapers"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 0061afb..6692370 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles & wallpapers"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 0061afb..6692370 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles & wallpapers"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 3a72f4c..d10c84b 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos y fondos de pantalla"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configuración de página principal"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"El administrador inhabilitó esta función"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir la rotación de la pantalla principal"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index bad7520..ac6ffaa 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos y fondos de pantalla"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ajustes de la pantalla de inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitado por el administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotación de la pantalla de inicio"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 5892d09..cea321d 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Kaust: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Vidinad"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustapildid"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stiilid ja taustapildid"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Avaekraani seaded"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Keelas administraator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Luba avaekraani pööramine"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index e82474e..18af2fb 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Karpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgetak"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Horma-paperak"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estiloak eta horma-paperak"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Hasierako pantailaren ezarpenak"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratzaileak desgaitu du"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Baimendu hasierako pantaila biratzea"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 7ea9262..7e3cbdc 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"پوشه: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ابزارکها"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"کاغذدیواریها"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"سبک و کاغذدیواری"</string>
<string name="settings_button_text" msgid="8873672322605444408">"تنظیمات صفحه اصلی"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"توسط سرپرست سیستم غیرفعال شده است"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"امکان دادن به چرخش صفحه اصلی"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 9b56c0f..f87441f 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Kansio: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgetit"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustakuvat"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Tyylit ja taustakuvat"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Kotiasetukset"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Järjestelmänvalvoja on poistanut toiminnon käytöstä."</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Salli aloitusnäytön kiertäminen"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 3b947aa..9d0e3a0 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles et fonds d\'écran"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Paramètres d\'accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Cette fonction est désactivée par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 6a95e19..585139c 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Dossier \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles et fonds d\'écran"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Paramètres accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index e6e6ed1..769586e 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Cartafol: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos e fondos de pantalla"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configuración da pantalla de Inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Función desactivada polo administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir xirar a pantalla de inicio"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 8dfcb2c..7def3ac 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ફોલ્ડર: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"વિજેટ્સ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"વૉલપેપર્સ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"શૈલીઓ અને વૉલપેપર"</string>
<string name="settings_button_text" msgid="8873672322605444408">"હોમ સેટિંગ્સ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 0b39ffe..5f24b05 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"शॉर्टकट"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"स्टाइल और वॉलपेपर"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम पेज की सेटिंग"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपके एडमिन ने बंद किया हुआ है"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"होमस्क्रीन घुमाने की अनुमति दें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 8ea98d6..1caa27f 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -81,8 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgeti"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilovi i pozadine"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Postavke početnog zaslona"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Dopusti zakretanje početnog zaslona"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index ae0dba3..3327590 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Modulok"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Háttérképek"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stílusok és háttérképek"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Kezdőoldal beállításai"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"A rendszergazda letiltotta"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"A kezdőképernyő elforgatásának engedélyezése"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 7542b75..fbb657e 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Պանակ՝ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Վիջեթներ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Պաստառներ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Ոճեր և պաստառներ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Գլխավոր էջի կարգավորումներ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Անջատվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Թույլ տալ հիմնական էկրանի պտտումը"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 96b3d92..0841be0 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpaper"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Gaya & wallpaper"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Setelan layar Utama"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dinonaktifkan oleh admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Izinkan layar Utama diputar"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 5673a2d..d66ca32 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Græjur"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Veggfóður"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stílar og veggfóður"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Heimastillingar"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning fyrir heimaskjá"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 9cd5c0f..8c4e3c5 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Sfondi"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stili e sfondi"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Impostazioni Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Consenti rotazione della schermata Home"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 64022ce..6f5a400 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"תיקיה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"רכיבי ווידג\'ט"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"טפטים"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"סגנונות וטפטים"</string>
<string name="settings_button_text" msgid="8873672322605444408">"הגדרות דף הבית"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"הושבת על ידי מנהל המערכת שלך"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"אפשרות סיבוב של מסך דף הבית"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 952c86b..354f020 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"フォルダ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ウィジェット"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"壁紙"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"スタイルと壁紙"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ホームの設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"管理者により無効にされています"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ホーム画面の回転を許可"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index efcaeab..e9afef9 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"საქაღალდე: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ვიჯეტები"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ფონები"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"სტილები და ფონები"</string>
<string name="settings_button_text" msgid="8873672322605444408">"მთავარი გვერდის პარამეტრები"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"გათიშულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"მთავარი ეკრანის შეტრიალების დაშვება"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index fb1f71d..2e953a6 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Қалта: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Виджеттер"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тұсқағаздар"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стильдер мен тұсқағаздар"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Негізгі экран параметрлері"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Әкімші өшірді"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Негізгі экранның бұрылуына рұқсат ету"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 59a3666..b953ea3 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ថត៖ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ធាតុក្រាហ្វិក"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ផ្ទាំងរូបភាព"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"រចនាប័ទ្ម និងផ្ទាំងរូបភាព"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ការកំណត់ទំព័រដើម"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"អនុញ្ញាតការបងិ្វលអេក្រង់ដើម"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 9fc4aec..2e96a7c 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ಫೋಲ್ಡರ್: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ವಿಜೆಟ್ಗಳು"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ವಾಲ್ಪೇಪರ್ಗಳು"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ಶೈಲಿಗಳು & ವಾಲ್ಪೇಪರ್ಗಳು"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 506ffc5..c58620e 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"폴더: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"위젯"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"배경화면"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"스타일 및 배경화면"</string>
<string name="settings_button_text" msgid="8873672322605444408">"홈 설정"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"홈 화면 회전 허용"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 433bb98..36b6385 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Виджеттер"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилдер жана тушкагаздар"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Башкы беттин жөндөөлөрү"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Башкы экранды айлантууга уруксат берүү"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 2664021..afe7664 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ໂຟນເດີ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ວິດເຈັດ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ຮູບແບບ ແລະ ຮູບພື້ນຫຼັງ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າ Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 6dbf1d6..6571582 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Aplankas: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Valdikliai"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ekrano fonai"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stiliai ir ekrano fonai"</string>
<string name="settings_button_text" msgid="8873672322605444408">"„Home“ nustatymai"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Išjungė administratorius"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Leisti pasukti pagrindinį ekraną"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 2a9b772..3da0fbb 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -81,8 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mape: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Logrīki"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fona tapetes"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stili un fona tapetes"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Sākumlapas iestatījumi"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Atspējojis administrators"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Atļaut sākuma ekrāna pagriešanu"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 3d4151c..9550a5f 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилови и тапети"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Поставки за Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Оневозможено од администраторот"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дозволете ротација на Почетниот екран"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index c3cb059..d4bfbc1 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ഫോൾഡർ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"വിജറ്റുകൾ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"വാൾപേപ്പർ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"സ്റ്റൈലുകളും വാൾപേപ്പറുകളും"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ഹോം ക്രമീകരണം"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index ac01fa2..f52f461 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Виджет"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ханын зураг"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Загвар ба ханын зураг"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Нүүр хуудасны тохиргоо"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Таны админ идэвхгүй болгосон"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 3be13ef..60dc9a6 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"विजेट"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"शैली आणि वॉलपेपर"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम सेटिंग्ज"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपल्या प्रशासकाने अक्षम केले"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"मुख्यस्क्रीन फिरविण्यास अनुमती द्या"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index a97e201..7d05412 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Kertas dinding"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Gaya & kertas dinding"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Tetapan laman utama"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dilumpuhkan oleh pentadbir anda"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Benarkan putaran Skrin Utama"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 2e1e0d4..7ae4446 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"အကန့်အမည်: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ဝိဂျက်များ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"နောက်ခံများ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ပုံစံနှင့် နောက်ခံပုံများ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ပင်မဆက်တင်များ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index e3e1768..2257367 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Moduler"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunner"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stiler og bakgrunner"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Startsideinnstillinger"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratoren har slått av funksjonen"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillat rotasjon av startskjermen"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index ea6fdf5..1e7aee9 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"विजेटहरू"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वालपेपरहरु"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"शैली तथा वालपेपरहरू"</string>
<string name="settings_button_text" msgid="8873672322605444408">"गृहपृष्ठका सेटिङहरू"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"तपाईँको प्रशासकद्वारा असक्षम गरिएको"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 1ae31be..bc1b450 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Map: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergrond"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stijlen en achtergronden"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Instellingen startscherm"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Uitgeschakeld door je beheerder"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Draaien van startscherm toestaan"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 7959e11..4ddc903 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ଫୋଲ୍ଡର: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ୱିଜେଟ୍"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ୱାଲପେପର୍"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ଶୈଳୀ ଏବଂ ୱାଲ୍ପେପର୍"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ହୋମ୍ ସେଟିଙ୍ଗ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ହୋମ୍ ସ୍କ୍ରୀନ୍ ବୁଲାଇବା ଅନୁମତି ଦିଅନ୍ତୁ"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index e740cb9..0bd1911 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ਫੋਲਡਰ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ਵਿਜੇਟ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ਵਾਲਪੇਪਰ"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ਸ਼ੈਲੀਆਂ ਅਤੇ ਵਾਲਪੇਪਰ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ਹੋਮ ਸੈਟਿੰਗਾਂ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁੰਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index bab3895..e33ef7d 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widżety"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Style i tapety"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ustawienia strony głównej"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Funkcja wyłączona przez administratora"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Zezwalaj na obrót ekranu głównego"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 7cd96a5..b26b812 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imagens de fundo"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos e imagens de fundo"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Definições da página inicial"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativada pelo gestor"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação do ecrã principal"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 7c90a14..1744fa1 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Planos de fundo"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos e planos de fundo"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configurações da tela inicial"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativado pelo administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação da tela inicial"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 6885de5..a7e8f05 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -81,8 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgeturi"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imagini de fundal"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stiluri și imagini de fundal"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Setări pentru ecranul de pornire"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dezactivată de administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permiteți rotirea ecranului de pornire"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 56c9a4f..9030a75 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Виджеты"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Обои"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Темы и обои"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Настройки главного экрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Функция отключена администратором"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Разрешить поворачивать главный экран"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index d3737be..574d3ed 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ෆෝල්ඩරය: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"විජට්"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"වෝල්පේපර"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"විලාස සහ බිතුපත්"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home සැකසීම්"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ඔබගේ පරිපාලක විසින් අබල කරන ලදී"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 6d64792..77eeab2 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Miniaplikácie"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Štýly a tapety"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Nastavenia Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázané vaším správcom"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Povoliť otáčanie plochy"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 3f1b14c..044a4b4 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Pripomočki"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ozadja"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Slogi in ozadja"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Nastavitve začetnega zaslona"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Omogočanje sukanja začetnega zaslona"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 31d3f4c..48ae26e 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Dosja: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Miniaplikacionet"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imazhet e sfondit"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilet dhe imazhet e sfondit"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Cilësimet e Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit kryesor"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 5a2c0af..f74fde2 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -81,8 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Директоријум: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Позадине"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилови и позадине"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Подешавања почетног екрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администратор је онемогућио"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дозволи ротацију почетног екрана"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 74d434e..e7400a6 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgetar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunder"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Format och bakgrunder"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Startinställningar"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inaktiverat av administratören"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillåt rotering av startskärmen"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 1483dcb..7b84ed3 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Wijeti"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Mandhari"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Mitindo na mandhari"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Mipangilio ya mwanzo"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Imezimwa na msimamizi wako"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Ruhusu kuzungusha skrini ya Kwanza"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 17c0adb..47b2581 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -26,7 +26,7 @@
<string name="activity_not_available" msgid="7456344436509528827">"பயன்பாடு இல்லை"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"இறக்கிய பயன்பாடு பாதுகாப்பு முறையில் முடக்கப்பட்டது"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"பாதுகாப்புப் பயன்முறையில் விட்ஜெட்கள் முடக்கப்பட்டுள்ளன"</string>
- <string name="shortcut_not_available" msgid="2536503539825726397">"குறுக்குவழி இல்லை"</string>
+ <string name="shortcut_not_available" msgid="2536503539825726397">"ஷார்ட்கட் இல்லை"</string>
<string name="home_screen" msgid="806512411299847073">"முகப்புத் திரை"</string>
<string name="custom_actions" msgid="3747508247759093328">"தனிப்பயன் செயல்கள்"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"விட்ஜெட்டைத் தேர்வுசெய்ய தொட்டுப் பிடிக்கவும்."</string>
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"கோப்புறை: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ஷார்ட்கட்ஸ்"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"வால்பேப்பர்கள்"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ஸ்டைல்கள் & வால்பேப்பர்கள்"</string>
<string name="settings_button_text" msgid="8873672322605444408">"முகப்பு அமைப்புகள்"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"உங்கள் நிர்வாகி முடக்கியுள்ளார்"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"முகப்புத் திரை சுழற்சியை அனுமதி"</string>
@@ -127,13 +126,13 @@
<string name="action_decrease_width" msgid="1374549771083094654">"அகலத்தைக் குறை"</string>
<string name="action_decrease_height" msgid="282377193880900022">"உயரத்தைக் குறை"</string>
<string name="widget_resized" msgid="9130327887929620">"அகலம் <xliff:g id="NUMBER_0">%1$s</xliff:g> மற்றும் உயரம் <xliff:g id="NUMBER_1">%2$s</xliff:g>க்கு விட்ஜெட் அளவு மாற்றப்பட்டது"</string>
- <string name="action_deep_shortcut" msgid="2864038805849372848">"குறுக்குவழிகள்"</string>
+ <string name="action_deep_shortcut" msgid="2864038805849372848">"ஷார்ட்கட்கள்"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"ஷார்ட்கட்கள் மற்றும் அறிவிப்புகள்"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"நிராகரி"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"அறிவிப்பு நிராகரிக்கப்பட்டது"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"தனிப்பட்டவை"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"பணி"</string>
- <string name="work_profile_toggle_label" msgid="3081029915775481146">"பணி விவரம்"</string>
+ <string name="work_profile_toggle_label" msgid="3081029915775481146">"பணிக் கணக்கு"</string>
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"பணி ஆப்ஸை இங்கு காணலாம்"</string>
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"ஒவ்வொரு பணிப் பயன்பாடும் ஒரு பேட்ஜைக் கொண்டிருக்கும். இவை, ஆப்ஸ் உங்கள் நிறுவனத்தால் பாதுகாப்பாக வைக்கப்பட்டுள்ளன என்பதைக் குறிக்கின்றன. இந்த ஆப்ஸை எளிதாக அணுக, முகப்புத் திரைக்கு நகர்த்திக்கொள்ளவும்."</string>
<string name="work_mode_on_label" msgid="4781128097185272916">"உங்கள் நிறுவனம் நிர்வகிக்கிறது"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 48dd872..1b74be1 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"ఫోల్డర్: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"విడ్జెట్లు"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"వాల్పేపర్లు"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"శైలులు & వాల్పేపర్లు"</string>
<string name="settings_button_text" msgid="8873672322605444408">"హోమ్ సెట్టింగ్లు"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 829a266..fee76e6 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"โฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"วิดเจ็ต"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"วอลเปเปอร์"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"รูปแบบและวอลเปเปอร์"</string>
<string name="settings_button_text" msgid="8873672322605444408">"การตั้งค่าหน้าแรก"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ปิดใช้โดยผู้ดูแลระบบ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"อนุญาตให้หมุนหน้าจอหลัก"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index d2b6915..359934e 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Mga Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Mga Wallpaper"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Mga istilo at wallpaper"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Mga setting ng Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Na-disable ng iyong admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Payagan ang pag-rotate ng Home screen"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index edd5ed8..56f8447 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Klasör: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widget\'lar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Duvar Kağıtları"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stiller ve duvar kağıtları"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ana ekran ayarları"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Yöneticiniz tarafından devre dışı bırakıldı"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Ana ekranı döndürmeye izin ver"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 9523443..ad51464 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -82,8 +82,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Папка <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Віджети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Фонові малюнки"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилі й фонові малюнки"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Налаштування Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Вимкнув адміністратор"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дозволити обертання головного екрана"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index c01de26..5d7218d 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"فولڈر: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ویجیٹس"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"وال پیپرز"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"طرزیں اور وال پیپر"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ہوم ترتیبات"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ہوم اسکرین گھمانے کی اجازت دیں"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index d184b5c..d34a64f 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Jild: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Vidjetlar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fon rasmlari"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Mavzu va fon rasmlari"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Bosh ekran sozlamalari"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator tomonidan o‘chirilgan"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Asosiy ekranni aylantirishga ruxsat berish"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 5570567..174ec7f 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Tiện ích con"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Hình nền"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Kiểu và hình nền"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Cài đặt màn hình chính"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Bị tắt bởi quản trị viên của bạn"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Cho phép xoay Màn hình chính"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 3a99dec..fd31875 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"文件夹:<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"微件"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"壁纸"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"样式和壁纸"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主屏幕设置"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已被您的管理员停用"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"允许旋转主屏幕"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 39bf109..de0fa89 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"樣式和桌布"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主螢幕設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"允許主畫面旋轉"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 358e6e2..4d37d72 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"樣式和桌布"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home 設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由你的管理員停用"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"允許旋轉主螢幕"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 614ae35..83178fe 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -80,8 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Ifolda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Amawijethi"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Izithombe zangemuva"</string>
- <!-- no translation found for styles_wallpaper_button_text (4342122323125579619) -->
- <skip />
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Izitayela nezithombe zangemuva"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Izilungiselelo zasekhaya"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Kukhutshazwe umlawuli wakho"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Vumela ukuphendukiswa kwesikrini sasekhaya"</string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 078ce60..04e4591 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -236,4 +236,8 @@
<dimen name="snackbar_elevation">3dp</dimen>
<dimen name="snackbar_min_text_size">12sp</dimen>
<dimen name="snackbar_max_text_size">14sp</dimen>
+
+<!-- Hints -->
+ <dimen name="chip_hint_height">26dp</dimen>
+ <dimen name="chip_hint_bottom_margin">194dp</dimen>
</resources>
diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
index 54038d2..656d55c 100644
--- a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
+++ b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
@@ -26,7 +26,6 @@
@Test
public void withFlagOn() {
assertTrue(FeatureFlags.EXAMPLE_FLAG.get());
- assertFalse(FeatureFlags.QUICK_SWITCH.get());
assertFalse(FeatureFlags.STYLE_WALLPAPER.get());
}
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index e75527e..599a353 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -55,7 +55,6 @@
TYPE_DISCOVERY_BOUNCE,
TYPE_SNACKBAR,
- TYPE_QUICKSTEP_PREVIEW,
TYPE_TASK_MENU,
TYPE_OPTIONS_POPUP
})
@@ -71,25 +70,23 @@
public static final int TYPE_SNACKBAR = 1 << 7;
// Popups related to quickstep UI
- public static final int TYPE_QUICKSTEP_PREVIEW = 1 << 8;
- public static final int TYPE_TASK_MENU = 1 << 9;
- public static final int TYPE_OPTIONS_POPUP = 1 << 10;
+ public static final int TYPE_TASK_MENU = 1 << 8;
+ public static final int TYPE_OPTIONS_POPUP = 1 << 9;
public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
- | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE | TYPE_TASK_MENU
+ | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE | TYPE_TASK_MENU
| TYPE_OPTIONS_POPUP | TYPE_SNACKBAR;
// Type of popups which should be kept open during launcher rebind
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
- | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE;
+ | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE;
// Usually we show the back button when a floating view is open. Instead, hide for these types.
public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
| TYPE_SNACKBAR;
- public static final int TYPE_ACCESSIBLE = TYPE_ALL
- & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_QUICKSTEP_PREVIEW;
+ public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE;
// These view all have particular operation associated with swipe down interaction.
public static final int TYPE_STATUS_BAR_SWIPE_DOWN_DISALLOW = TYPE_WIDGETS_BOTTOM_SHEET |
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 70c8aaa..4c6824a 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -91,6 +91,7 @@
mText = getResources().getString(canRemove(item)
? R.string.remove_drop_target_label
: android.R.string.cancel);
+ setContentDescription(mText);
requestLayout();
}
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 812cf9f..01535b0 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -26,12 +26,15 @@
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.Surface;
+import android.view.View;
import android.view.WindowManager;
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+
public class DeviceProfile {
public final InvariantDeviceProfile inv;
@@ -100,6 +103,10 @@
public int folderChildTextSizePx;
public int folderChildDrawablePaddingPx;
+ // Hints
+ public int chipHintHeightPx;
+ public int chipHintBottomMarginPx;
+
// Hotseat
public int hotseatCellHeightPx;
// In portrait: size = height, in landscape: size = width
@@ -197,6 +204,9 @@
workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
+ chipHintHeightPx = res.getDimensionPixelSize(R.dimen.chip_hint_height);
+ chipHintBottomMarginPx = res.getDimensionPixelSize(R.dimen.chip_hint_bottom_margin);
+
hotseatBarTopPaddingPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
hotseatBarBottomPaddingPx = (isTallDevice ? 0
@@ -312,7 +322,7 @@
// Workspace
final boolean isVerticalLayout = isVerticalBarLayout();
float invIconSizePx = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
- iconSizePx = (int) (Utilities.pxFromDp(invIconSizePx, dm) * scale);
+ iconSizePx = Math.max(1, (int) (Utilities.pxFromDp(invIconSizePx, dm) * scale));
iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale);
iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
@@ -574,6 +584,33 @@
}
}
+ /**
+ * Gets an item's location on the home screen. This is useful if the home screen
+ * is animating, otherwise use {@link View#getLocationOnScreen(int[])}.
+ *
+ * TODO(b/123900446): Handle landscape mode
+ * @param pageDiff The page difference relative to the current page.
+ */
+ public void getItemLocation(int cellX, int cellY, int spanX, int spanY, int container,
+ int pageDiff, Rect outBounds) {
+ outBounds.setEmpty();
+ outBounds.left = mInsets.left
+ + workspacePadding.left + cellLayoutPaddingLeftRightPx + (cellX * getCellSize().x);
+ outBounds.top = mInsets.top;
+ if (container == CONTAINER_HOTSEAT) {
+ outBounds.top += workspacePadding.top
+ + (inv.numRows * getCellSize().y)
+ + verticalDragHandleSizePx
+ - verticalDragHandleOverlapWorkspace;
+ outBounds.bottom = outBounds.top + hotseatBarSizePx - hotseatBarBottomPaddingPx;
+ } else {
+ outBounds.top += workspacePadding.top + (cellY * getCellSize().y);
+ outBounds.bottom = outBounds.top + (getCellSize().y * spanY);
+ outBounds.left += (pageDiff) * availableWidthPx;
+ }
+ outBounds.right = outBounds.left + (getCellSize().x * spanX);
+ }
+
private static Context getContext(Context c, int orientation) {
Configuration context = new Configuration(c.getResources().getConfiguration());
context.orientation = orientation;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 245e470..f571aa3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -257,9 +257,8 @@
private RotationHelper mRotationHelper;
-
private final Handler mHandler = new Handler();
- private final Runnable mLogOnDelayedResume = this::logOnDelayedResume;
+ private final Runnable mHandleDeferredResume = this::handleDeferredResume;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -756,6 +755,7 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onStop();
}
+
getUserEventDispatcher().logActionCommand(Action.Command.STOP,
mStateManager.getState().containerType, -1);
@@ -782,11 +782,13 @@
RaceConditionTracker.onEvent(ON_START_EVT, EXIT);
}
- private void logOnDelayedResume() {
+ private void handleDeferredResume() {
if (hasBeenResumed()) {
getUserEventDispatcher().logActionCommand(Action.Command.RESUME,
mStateManager.getState().containerType, -1);
getUserEventDispatcher().startSession();
+
+ UiFactory.onLauncherStateOrResumeChanged(this);
}
}
@@ -797,8 +799,8 @@
super.onResume();
TraceHelper.partitionSection("ON_RESUME", "superCall");
- mHandler.removeCallbacks(mLogOnDelayedResume);
- Utilities.postAsyncCallback(mHandler, mLogOnDelayedResume);
+ mHandler.removeCallbacks(mHandleDeferredResume);
+ Utilities.postAsyncCallback(mHandler, mHandleDeferredResume);
setOnResumeCallback(null);
// Process any items that were added while Launcher was away.
@@ -812,7 +814,6 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onResume();
}
- UiFactory.onLauncherStateOrResumeChanged(this);
TraceHelper.endSection("ON_RESUME");
RaceConditionTracker.onEvent(ON_RESUME_EVT, EXIT);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index beef97e..6d85612 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -19,6 +19,11 @@
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
@@ -27,7 +32,6 @@
import com.android.launcher3.states.SpringLoadedState;
import com.android.launcher3.uioverrides.AllAppsState;
import com.android.launcher3.uioverrides.BackgroundAppState;
-import com.android.launcher3.uioverrides.FastOverviewState;
import com.android.launcher3.uioverrides.OverviewState;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -78,18 +82,20 @@
/**
* TODO: Create a separate class for NORMAL state.
*/
- public static final LauncherState NORMAL = new LauncherState(0, ContainerType.WORKSPACE, 0,
+ public static final LauncherState NORMAL = new LauncherState(NORMAL_STATE_ORDINAL,
+ ContainerType.WORKSPACE, 0,
FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
FLAG_HAS_SYS_UI_SCRIM);
/**
* Various Launcher states arranged in the increasing order of UI layers
*/
- public static final LauncherState SPRING_LOADED = new SpringLoadedState(1);
- public static final LauncherState OVERVIEW = new OverviewState(2);
- public static final LauncherState FAST_OVERVIEW = new FastOverviewState(3);
- public static final LauncherState ALL_APPS = new AllAppsState(4);
- public static final LauncherState BACKGROUND_APP = new BackgroundAppState(5);
+ public static final LauncherState SPRING_LOADED = new SpringLoadedState(
+ SPRING_LOADED_STATE_ORDINAL);
+ public static final LauncherState OVERVIEW = new OverviewState(OVERVIEW_STATE_ORDINAL);
+ public static final LauncherState ALL_APPS = new AllAppsState(ALL_APPS_STATE_ORDINAL);
+ public static final LauncherState BACKGROUND_APP = new BackgroundAppState(
+ BACKGROUND_APP_STATE_ORDINAL);
public final int ordinal;
@@ -187,6 +193,7 @@
* translationY factor where 0 is top aligned and 0.5 is centered vertically
*/
public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
+ // TODO: Simplify to use a constant value instead of a factor.
return new float[] {1.1f, 0f};
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index df8ac99..a877141 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -147,10 +147,17 @@
}
/**
+ * Returns true if the state changes should be animated.
+ */
+ public boolean shouldAnimateStateChange() {
+ return !mLauncher.isForceInvisible() && mLauncher.isStarted();
+ }
+
+ /**
* @see #goToState(LauncherState, boolean, Runnable)
*/
public void goToState(LauncherState state) {
- goToState(state, !mLauncher.isForceInvisible() && mLauncher.isStarted() /* animated */);
+ goToState(state, shouldAnimateStateChange());
}
/**
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 018ec5f..00da6fa 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1024,8 +1024,8 @@
return;
}
- if (amount < 0) {
- super.scrollTo(amount, getScrollY());
+ if (overScrollAmount < 0) {
+ super.scrollTo(overScrollAmount, getScrollY());
} else {
super.scrollTo(mMaxScrollX + overScrollAmount, getScrollY());
}
@@ -1134,7 +1134,9 @@
final int activePointerId = mActivePointerId;
final int pointerIndex = ev.findPointerIndex(activePointerId);
final float x = ev.getX(pointerIndex);
- int velocityX = computeXVelocity();
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId);
final int deltaX = (int) (x - mDownMotionX);
final int pageWidth = getPageAt(mCurrentPage).getMeasuredWidth();
boolean isSignificantMove = Math.abs(deltaX) > pageWidth *
@@ -1238,12 +1240,6 @@
return true;
}
- protected int computeXVelocity() {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- return (int) velocityTracker.getXVelocity(mActivePointerId);
- }
-
protected boolean shouldFlingForVelocity(int velocityX) {
return Math.abs(velocityX) > mFlingThresholdVelocity;
}
diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/TestProtocol.java
index 0a3b86d..23df79e 100644
--- a/src/com/android/launcher3/TestProtocol.java
+++ b/src/com/android/launcher3/TestProtocol.java
@@ -22,6 +22,12 @@
public final class TestProtocol {
public static final String GET_SCROLL_MESSAGE = "TAPL_GET_SCROLL";
public static final String SCROLL_Y_FIELD = "scrollY";
+ public static final String STATE_FIELD = "state";
public static final String SWITCHED_TO_STATE_MESSAGE = "TAPL_SWITCHED_TO_STATE";
public static final String RESPONSE_MESSAGE_POSTFIX = "_RESPONSE";
+ public static final int NORMAL_STATE_ORDINAL = 0;
+ public static final int SPRING_LOADED_STATE_ORDINAL = 1;
+ public static final int OVERVIEW_STATE_ORDINAL = 2;
+ public static final int ALL_APPS_STATE_ORDINAL = 3;
+ public static final int BACKGROUND_APP_STATE_ORDINAL = 4;
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 1dec173..e5ab2d1 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -52,6 +52,8 @@
import android.view.animation.Interpolator;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.util.IntArray;
import java.io.Closeable;
@@ -65,6 +67,9 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+
/**
* Various utilities shared amongst the Launcher's classes.
*/
@@ -541,4 +546,48 @@
public static String getPointString(int x, int y) {
return String.format(Locale.ENGLISH, "%d,%d", x, y);
}
+
+ /**
+ * Returns the location bounds of a view.
+ * - For DeepShortcutView, we return the bounds of the icon view.
+ * - For BubbleTextView, we return the icon bounds.
+ */
+ public static void getLocationBoundsForView(Launcher launcher, View v, Rect outRect) {
+ final DragLayer dragLayer = launcher.getDragLayer();
+ final boolean isBubbleTextView = v instanceof BubbleTextView;
+ final Rect rect = new Rect();
+
+ final boolean fromDeepShortcutView = v.getParent() instanceof DeepShortcutView;
+ if (fromDeepShortcutView) {
+ // Deep shortcut views have their icon drawn in a separate view.
+ DeepShortcutView view = (DeepShortcutView) v.getParent();
+ dragLayer.getDescendantRectRelativeToSelf(view.getIconView(), rect);
+ } else if (isBubbleTextView && v.getTag() instanceof ItemInfo
+ && (((ItemInfo) v.getTag()).container == CONTAINER_DESKTOP
+ || ((ItemInfo) v.getTag()).container == CONTAINER_HOTSEAT)) {
+ BubbleTextView btv = (BubbleTextView) v;
+ CellLayout pageViewIsOn = ((CellLayout) btv.getParent().getParent());
+ int pageNum = launcher.getWorkspace().indexOfChild(pageViewIsOn);
+
+ DeviceProfile dp = launcher.getDeviceProfile();
+ ItemInfo info = ((ItemInfo) btv.getTag());
+ dp.getItemLocation(info.cellX, info.cellY, info.spanX, info.spanY,
+ info.container, pageNum - launcher.getCurrentWorkspaceScreen(), rect);
+ } else {
+ dragLayer.getDescendantRectRelativeToSelf(v, rect);
+ }
+ int viewLocationLeft = rect.left;
+ int viewLocationTop = rect.top;
+
+ if (isBubbleTextView && !fromDeepShortcutView) {
+ BubbleTextView btv = (BubbleTextView) v;
+ btv.getIconBounds(rect);
+ } else {
+ rect.set(0, 0, rect.width(), rect.height());
+ }
+ viewLocationLeft += rect.left;
+ viewLocationTop += rect.top;
+ outRect.set(viewLocationLeft, viewLocationTop, viewLocationLeft + rect.width(),
+ viewLocationTop + rect.height());
+ }
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2db6cd9..7f5ca42 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -34,6 +34,7 @@
import android.app.WallpaperManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -97,6 +98,7 @@
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
@@ -2889,6 +2891,88 @@
return layouts;
}
+ /**
+ * Returns a list of all the CellLayouts on the Homescreen, starting with
+ * {@param startPage}, then going outward alternating between pages prior to the startPage,
+ * and then the pages after the startPage.
+ * ie. if there are 5 pages [0, 1, 2, 3, 4] and startPage is 1, we return [1, 0, 2, 3, 4].
+ */
+ private CellLayout[] getWorkspaceCellLayouts(int startPage) {
+ int screenCount = getChildCount();
+ final CellLayout[] layouts = new CellLayout[screenCount];
+ int screen = 0;
+
+ layouts[screen] = (CellLayout) getChildAt(startPage);
+ screen++;
+
+ for (int i = 1; screen < screenCount; ++i) {
+ CellLayout prevPage = (CellLayout) getChildAt(startPage - i);
+ CellLayout nextPage = (CellLayout) getChildAt(startPage + i);
+
+ if (prevPage != null) {
+ layouts[screen] = prevPage;
+ screen++;
+ }
+ if (nextPage != null) {
+ layouts[screen] = nextPage;
+ screen++;
+ }
+ }
+ return layouts;
+ }
+
+ /**
+ * Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
+ * animation.
+ *
+ * @param component The component of the task being dismissed.
+ */
+ public View getFirstMatchForAppClose(ComponentName component) {
+ final int curPage = getCurrentPage();
+ final CellLayout currentPage = (CellLayout) getPageAt(curPage);
+ final Workspace.ItemOperator isItemComponent = (info, view) ->
+ info != null && Objects.equals(info.getTargetComponent(), component);
+ final Workspace.ItemOperator isItemInFolder = (info, view) -> {
+ if (info instanceof FolderInfo) {
+ FolderInfo folderInfo = (FolderInfo) info;
+ for (ShortcutInfo shortcutInfo : folderInfo.contents) {
+ if (Objects.equals(shortcutInfo.getTargetComponent(), component)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ CellLayout[] hotseatAndCurrentPage = new CellLayout[] { getHotseat(), currentPage };
+ // First we look if the app itself is in the hotseat or on the current workspace page.
+ View icon = getFirstMatch(hotseatAndCurrentPage, isItemComponent);
+ if (icon != null) {
+ return icon;
+ }
+ // Then we look if the app is in a folder on the hotseat or current workspace page.
+ icon = getFirstMatch(hotseatAndCurrentPage, isItemInFolder);
+ if (icon != null) {
+ return icon;
+ }
+ // Continue searching for the app or for a folder with the app on other pages of the
+ // workspace. We skip the current page, since we already searched above.
+ CellLayout[] allPages = getWorkspaceCellLayouts(curPage);
+ CellLayout[] page = new CellLayout[1];
+ for (int i = 1; i < allPages.length; ++i) {
+ page[0] = allPages[i];
+ icon = getFirstMatch(page, isItemComponent);
+ if (icon != null) {
+ return icon;
+ }
+ icon = getFirstMatch(page, isItemInFolder);
+ if (icon != null) {
+ return icon;
+ }
+ }
+ return null;
+ }
+
public View getHomescreenIconByItemId(final int id) {
return getFirstMatch((info, v) -> info != null && info.id == id);
}
@@ -2914,6 +2998,23 @@
return value[0];
}
+ private View getFirstMatch(CellLayout[] cellLayouts, final ItemOperator operator) {
+ final View[] value = new View[1];
+ for (CellLayout cellLayout : cellLayouts) {
+ mapOverCellLayout(MAP_NO_RECURSE, cellLayout, (info, v) -> {
+ if (operator.evaluate(info, v)) {
+ value[0] = v;
+ return true;
+ }
+ return false;
+ });
+ if (value[0] != null) {
+ break;
+ }
+ }
+ return value[0];
+ }
+
void clearDropTargets() {
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
@Override
@@ -2992,31 +3093,38 @@
*/
public void mapOverItems(boolean recurse, ItemOperator op) {
for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
- ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets();
- // map over all the shortcuts on the workspace
- final int itemCount = container.getChildCount();
- for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
- View item = container.getChildAt(itemIdx);
- ItemInfo info = (ItemInfo) item.getTag();
- if (recurse && info instanceof FolderInfo && item instanceof FolderIcon) {
- FolderIcon folder = (FolderIcon) item;
- ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder();
- // map over all the children in the folder
- final int childCount = folderChildren.size();
- for (int childIdx = 0; childIdx < childCount; childIdx++) {
- View child = folderChildren.get(childIdx);
- info = (ItemInfo) child.getTag();
- if (op.evaluate(info, child)) {
- return;
- }
+ if (mapOverCellLayout(recurse, layout, op)) {
+ return;
+ }
+ }
+ }
+
+ private boolean mapOverCellLayout(boolean recurse, CellLayout layout, ItemOperator op) {
+ ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets();
+ // map over all the shortcuts on the workspace
+ final int itemCount = container.getChildCount();
+ for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
+ View item = container.getChildAt(itemIdx);
+ ItemInfo info = (ItemInfo) item.getTag();
+ if (recurse && info instanceof FolderInfo && item instanceof FolderIcon) {
+ FolderIcon folder = (FolderIcon) item;
+ ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder();
+ // map over all the children in the folder
+ final int childCount = folderChildren.size();
+ for (int childIdx = 0; childIdx < childCount; childIdx++) {
+ View child = folderChildren.get(childIdx);
+ info = (ItemInfo) child.getTag();
+ if (op.evaluate(info, child)) {
+ return true;
}
- } else {
- if (op.evaluate(info, item)) {
- return;
- }
+ }
+ } else {
+ if (op.evaluate(info, item)) {
+ return true;
}
}
}
+ return false;
}
void updateShortcuts(ArrayList<ShortcutInfo> shortcuts) {
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 6feb1e9..51e914c 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -52,11 +52,14 @@
return (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
- public static void sendEventToTest(Context context, String eventTag) {
+ public static void sendStateEventToTest(Context context, int stateOrdinal) {
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
if (accessibilityManager == null) return;
- sendEventToTest(accessibilityManager, eventTag, null);
+ final Bundle parcel = new Bundle();
+ parcel.putInt(TestProtocol.STATE_FIELD, stateOrdinal);
+
+ sendEventToTest(accessibilityManager, TestProtocol.SWITCHED_TO_STATE_MESSAGE, parcel);
}
private static void sendEventToTest(
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index b921d29..882529d 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -88,10 +88,6 @@
// trying to make them fit the orientation the device is in.
public static final boolean OVERVIEW_USE_SCREENSHOT_ORIENTATION = true;
- public static final ToggleableGlobalSettingsFlag QUICK_SWITCH
- = new ToggleableGlobalSettingsFlag("QUICK_SWITCH", false,
- "Swiping right on the nav bar while in an app switches to the previous app");
-
public static final ToggleableGlobalSettingsFlag STYLE_WALLPAPER
= new ToggleableGlobalSettingsFlag("STYLE_WALLPAPER", false,
"Direct users to the new ThemePicker based WallpaperPicker");
@@ -102,10 +98,6 @@
public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
"APPLY_CONFIG_AT_RUNTIME", true, "Apply display changes dynamically");
- public static final ToggleableGlobalSettingsFlag ENABLE_TASK_STABILIZER
- = new ToggleableGlobalSettingsFlag("ENABLE_TASK_STABILIZER", false,
- "Stable task list across fast task switches");
-
public static final TogglableFlag QUICKSTEP_SPRINGS = new TogglableFlag("QUICKSTEP_SPRINGS",
false, "Enable springs for quickstep animations");
@@ -116,6 +108,10 @@
= new ToggleableGlobalSettingsFlag("SWIPE_HOME", false,
"Swiping up on the nav bar goes home. Swipe and hold goes to recent apps.");
+ public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag(
+ "ENABLE_HINTS_IN_OVERVIEW", false,
+ "Show chip hints and gleams on the overview screen");
+
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index ccc15f1..0d499c1 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -384,6 +384,7 @@
openAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ setAlpha(1f);
announceAccessibilityChanges();
mOpenCloseAnimator = null;
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 0e2ed6c..c125c10 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -522,8 +522,7 @@
}
mLauncher.getStateManager().goToState(targetState, false /* animated */);
- AccessibilityManagerCompat.sendEventToTest(
- mLauncher, TestProtocol.SWITCHED_TO_STATE_MESSAGE);
+ AccessibilityManagerCompat.sendStateEventToTest(mLauncher, targetState.ordinal);
}
}
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
new file mode 100644
index 0000000..07318c9
--- /dev/null
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 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 android.animation.Animator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.InsettableFrameLayout.LayoutParams;
+import com.android.launcher3.ItemInfoWithIcon;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.graphics.DrawableFactory;
+
+/**
+ * A view that is created to look like another view with the purpose of creating fluid animations.
+ */
+public class FloatingIconView extends View implements Animator.AnimatorListener {
+
+ private Runnable mStartRunnable;
+ private Runnable mEndRunnable;
+
+ public FloatingIconView(Context context) {
+ super(context);
+ }
+
+ public void setRunnables(Runnable startRunnable, Runnable endRunnable) {
+ mStartRunnable = startRunnable;
+ mEndRunnable = endRunnable;
+ }
+
+ /**
+ * Positions this view to match the size and location of {@param rect}.
+ */
+ public void update(RectF rect, float alpha) {
+ setAlpha(alpha);
+
+ LayoutParams lp = (LayoutParams) getLayoutParams();
+ float dX = rect.left - lp.leftMargin;
+ float dY = rect.top - lp.topMargin;
+ setTranslationX(dX);
+ setTranslationY(dY);
+
+ float scaleX = rect.width() / (float) getWidth();
+ float scaleY = rect.height() / (float) getHeight();
+ float scale = Math.min(scaleX, scaleY);
+ setPivotX(0);
+ setPivotY(0);
+ setScaleX(scale);
+ setScaleY(scale);
+ }
+
+ @Override
+ public void onAnimationStart(Animator animator) {
+ if (mStartRunnable != null) {
+ mStartRunnable.run();
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (mEndRunnable != null) {
+ mEndRunnable.run();
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {
+ }
+
+ /**
+ * Sets the size and position of this view to match {@param v}.
+ *
+ * @param v The view to copy
+ * @param hideOriginal If true, it will hide {@param v} while this view is visible.
+ * @param positionOut Rect that will hold the size and position of v.
+ */
+ public void matchPositionOf(Launcher launcher, View v, boolean hideOriginal, Rect positionOut) {
+ Utilities.getLocationBoundsForView(launcher, v, positionOut);
+ final LayoutParams lp = new LayoutParams(positionOut.width(), positionOut.height());
+ lp.ignoreInsets = true;
+
+ // Position the floating view exactly on top of the original
+ lp.leftMargin = positionOut.left;
+ lp.topMargin = positionOut.top;
+ setLayoutParams(lp);
+ // Set the properties here already to make sure they are available when running the first
+ // animation frame.
+ layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
+ + lp.height);
+
+ if (v instanceof BubbleTextView && v.getTag() instanceof ItemInfoWithIcon ) {
+ // Create a copy of the app icon
+ setBackground(DrawableFactory.INSTANCE.get(launcher)
+ .newIcon(v.getContext(), (ItemInfoWithIcon) v.getTag()));
+ }
+
+ // We need to add it to the overlay, but keep it invisible until animation starts..
+ final DragLayer dragLayer = launcher.getDragLayer();
+ setVisibility(INVISIBLE);
+ ((ViewGroup) dragLayer.getParent()).getOverlay().add(this);
+
+ setRunnables(() -> {
+ setVisibility(VISIBLE);
+ if (hideOriginal) {
+ v.setVisibility(INVISIBLE);
+ }
+ },
+ () -> {
+ ((ViewGroup) dragLayer.getParent()).getOverlay().remove(this);
+ if (hideOriginal) {
+ v.setVisibility(VISIBLE);
+ }
+ });
+ }
+}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/FastOverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/FastOverviewState.java
deleted file mode 100644
index 147d194..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/FastOverviewState.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.uioverrides;
-
-/**
- * A dummy overview state
- */
-public class FastOverviewState extends OverviewState {
-
- public FastOverviewState(int id) {
- super(id);
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
deleted file mode 100644
index fdf87be..0000000
--- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.android.launcher3.ui;
-
-import android.content.pm.LauncherActivityInfo;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test for dragging an icon from all-apps to homescreen.
- */
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class AllAppsIconToHomeTest extends AbstractLauncherUiTest {
-
- @Test
- @PortraitLandscape
- public void testDragIcon() throws Throwable {
- LauncherActivityInfo settingsApp = getSettingsApp();
-
- clearHomescreen();
-
- final String appName = settingsApp.getLabel().toString();
- // 1. Open all apps and wait for load complete.
- // 2. Drag icon to homescreen.
- // 3. Verify that the icon works on homescreen.
- mLauncher.pressHome().
- switchToAllApps().
- getAppIcon(appName).
- dragToWorkspace().
- getWorkspaceAppIcon(appName).
- launch(settingsApp.getComponentName().getPackageName());
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java
deleted file mode 100644
index 1fea4d5..0000000
--- a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.android.launcher3.ui;
-
-import static org.junit.Assert.assertTrue;
-
-import android.content.pm.LauncherActivityInfo;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.popup.ArrowPopup;
-import com.android.launcher3.tapl.AppIconMenu;
-import com.android.launcher3.tapl.AppIconMenuItem;
-import com.android.launcher3.views.OptionsPopupView;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test for verifying that shortcuts are shown and can be launched after long pressing an app
- */
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class ShortcutsLaunchTest extends AbstractLauncherUiTest {
-
- private boolean isOptionsPopupVisible(Launcher launcher) {
- final ArrowPopup popup = OptionsPopupView.getOptionsPopup(launcher);
- return popup != null && popup.isShown();
- }
-
- @Test
- @PortraitLandscape
- public void testAppLauncher() throws Exception {
- mActivityMonitor.startLauncher();
- final LauncherActivityInfo testApp = getSettingsApp();
-
- final AppIconMenu menu = mLauncher.
- pressHome().
- switchToAllApps().
- getAppIcon(testApp.getLabel().toString()).
- openMenu();
-
- executeOnLauncher(
- launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu",
- isOptionsPopupVisible(launcher)));
-
- final AppIconMenuItem menuItem = menu.getMenuItem(1);
- final String itemName = menuItem.getText();
-
- menuItem.launch(testApp.getComponentName().getPackageName(), itemName);
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java
deleted file mode 100644
index 4c2c959..0000000
--- a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.android.launcher3.ui;
-
-import android.content.pm.LauncherActivityInfo;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.launcher3.tapl.AppIconMenuItem;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test for dragging a deep shortcut to the home screen.
- */
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class ShortcutsToHomeTest extends AbstractLauncherUiTest {
-
- @Test
- @PortraitLandscape
- public void testDragIcon() throws Throwable {
- clearHomescreen();
- mActivityMonitor.startLauncher();
-
- LauncherActivityInfo testApp = getSettingsApp();
-
- // 1. Open all apps and wait for load complete.
- // 2. Find the app and long press it to show shortcuts.
- // 3. Press icon center until shortcuts appear
- final AppIconMenuItem menuItem = mLauncher.
- getWorkspace().
- switchToAllApps().
- getAppIcon(testApp.getLabel().toString()).
- openMenu().
- getMenuItem(0);
- final String shortcutName = menuItem.getText();
-
- // 4. Drag the first shortcut to the home screen.
- // 5. Verify that the shortcut works on home screen
- // (the app opens and has the same text as the shortcut).
- menuItem.
- dragToWorkspace().
- getWorkspaceAppIcon(shortcutName).
- launch(testApp.getComponentName().getPackageName(), shortcutName);
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index ab5761d..6f2f280 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Intent;
+import android.content.pm.LauncherActivityInfo;
import android.util.Log;
import androidx.test.filters.LargeTest;
@@ -33,8 +34,12 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.popup.ArrowPopup;
import com.android.launcher3.tapl.AllApps;
import com.android.launcher3.tapl.AppIcon;
+import com.android.launcher3.tapl.AppIconMenu;
+import com.android.launcher3.tapl.AppIconMenuItem;
+import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.views.OptionsPopupView;
@@ -100,12 +105,19 @@
@Before
public void setUp() throws Exception {
super.setUp();
+ initialize(this);
+ }
- clearLauncherData();
-
- mLauncher.pressHome();
- waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL);
- waitForResumed("Launcher internal state is still Background");
+ public static void initialize(AbstractLauncherUiTest test) throws Exception {
+ test.clearLauncherData();
+ if (TestHelpers.isInLauncherProcess()) {
+ test.mActivityMonitor.returnToHome();
+ } else {
+ test.mDevice.pressHome();
+ }
+ test.waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
+ test.waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL);
+ test.waitForResumed("Launcher internal state is still Background");
}
// Please don't add negative test cases for methods that fail only after a long wait.
@@ -284,4 +296,74 @@
private int getWidgetsScroll(Launcher launcher) {
return getWidgetsView(launcher).getCurrentScrollY();
}
+
+ private boolean isOptionsPopupVisible(Launcher launcher) {
+ final ArrowPopup popup = OptionsPopupView.getOptionsPopup(launcher);
+ return popup != null && popup.isShown();
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testLaunchMenuItem() throws Exception {
+ if (!TestHelpers.isInLauncherProcess()) return;
+ final LauncherActivityInfo testApp = getSettingsApp();
+
+ final AppIconMenu menu = mLauncher.
+ getWorkspace().
+ switchToAllApps().
+ getAppIcon(testApp.getLabel().toString()).
+ openMenu();
+
+ executeOnLauncher(
+ launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu",
+ isOptionsPopupVisible(launcher)));
+
+ final AppIconMenuItem menuItem = menu.getMenuItem(1);
+ final String itemName = menuItem.getText();
+
+ menuItem.launch(testApp.getComponentName().getPackageName(), itemName);
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testDragAppIcon() throws Throwable {
+ LauncherActivityInfo settingsApp = getSettingsApp();
+
+ final String appName = settingsApp.getLabel().toString();
+ // 1. Open all apps and wait for load complete.
+ // 2. Drag icon to homescreen.
+ // 3. Verify that the icon works on homescreen.
+ mLauncher.getWorkspace().
+ switchToAllApps().
+ getAppIcon(appName).
+ dragToWorkspace().
+ getWorkspaceAppIcon(appName).
+ launch(settingsApp.getComponentName().getPackageName());
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testDragShortcut() throws Throwable {
+ if (!TestHelpers.isInLauncherProcess()) return;
+ LauncherActivityInfo testApp = getSettingsApp();
+
+ // 1. Open all apps and wait for load complete.
+ // 2. Find the app and long press it to show shortcuts.
+ // 3. Press icon center until shortcuts appear
+ final AppIconMenuItem menuItem = mLauncher.
+ getWorkspace().
+ switchToAllApps().
+ getAppIcon(testApp.getLabel().toString()).
+ openMenu().
+ getMenuItem(0);
+ final String shortcutName = menuItem.getText();
+
+ // 4. Drag the first shortcut to the home screen.
+ // 5. Verify that the shortcut works on home screen
+ // (the app opens and has the same text as the shortcut).
+ menuItem.
+ dragToWorkspace().
+ getWorkspaceAppIcon(shortcutName).
+ launch(testApp.getComponentName().getPackageName(), shortcutName);
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
index 42817c1..2642815 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+
import android.graphics.Point;
import androidx.annotation.NonNull;
@@ -45,7 +47,7 @@
final Point start = qsb.getVisibleCenter();
final int endY = (int) (mLauncher.getDevice().getDisplayHeight() * 0.6);
LauncherInstrumentation.log("AllAppsFromOverview.switchBackToOverview before swipe");
- mLauncher.swipe(start.x, start.y, start.x, endY);
+ mLauncher.swipe(start.x, start.y, start.x, endY, OVERVIEW_STATE_ORDINAL);
return new Overview(mLauncher);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 08d2889..606cf37 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -16,6 +16,7 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
@@ -50,23 +51,28 @@
@NonNull
public BaseOverview switchToOverview() {
verifyActiveContainer();
- goToOverviewUnchecked();
+ goToOverviewUnchecked(BACKGROUND_APP_STATE_ORDINAL);
assertTrue("Overview not visible", mLauncher.getDevice().wait(
Until.hasObject(By.pkg(getOverviewPackageName())), WAIT_TIME_MS));
return new BaseOverview(mLauncher);
}
-
- protected void goToOverviewUnchecked() {
+ protected void goToOverviewUnchecked(int expectedState) {
if (mLauncher.isSwipeUpEnabled()) {
final int height = mLauncher.getDevice().getDisplayHeight();
final UiObject2 navBar = mLauncher.getSystemUiObject("navigation_bar_frame");
+ int swipeLength = Math.round(getSwipeLength() * mLauncher.getDisplayDensity());
mLauncher.swipe(
navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
- navBar.getVisibleBounds().centerX(), height - 400);
+ navBar.getVisibleBounds().centerX(), height - swipeLength,
+ expectedState);
} else {
mLauncher.getSystemUiObject("recent_apps").click();
}
}
+
+ protected int getSwipeLength() {
+ return 200;
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index 522ce14..f8bd85a 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+
import androidx.annotation.NonNull;
/**
@@ -47,7 +49,7 @@
@Override
public Overview switchToOverview() {
verifyActiveContainer();
- goToOverviewUnchecked();
+ goToOverviewUnchecked(OVERVIEW_STATE_ORDINAL);
return new Overview(mLauncher);
}
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 7e2c966..481281a 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -74,8 +74,11 @@
*/
public Workspace dragToWorkspace() {
final UiDevice device = mLauncher.getDevice();
- mObject.drag(new Point(
- device.getDisplayWidth() / 2, device.getDisplayHeight() / 2), DRAG_SPEED);
+ Workspace.dragIconToWorkspace(
+ mLauncher,
+ this,
+ new Point(device.getDisplayWidth() / 2, device.getDisplayHeight() / 2),
+ DRAG_SPEED);
return new Workspace(mLauncher);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index acdcd75..7473189 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -104,13 +104,13 @@
public LauncherInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
mDevice = UiDevice.getInstance(instrumentation);
- final boolean swipeUpEnabledDefault =
- !SwipeUpSetting.isSwipeUpSettingAvailable() ||
- SwipeUpSetting.isSwipeUpEnabledDefaultValue();
- mSwipeUpEnabled = Settings.Secure.getInt(
- instrumentation.getTargetContext().getContentResolver(),
- SWIPE_UP_SETTING_NAME,
- swipeUpEnabledDefault ? 1 : 0) == 1;
+ final boolean swipeUpEnabledDefaultValue = SwipeUpSetting.isSwipeUpEnabledDefaultValue();
+ mSwipeUpEnabled = SwipeUpSetting.isSwipeUpSettingAvailable() ?
+ Settings.Secure.getInt(
+ instrumentation.getTargetContext().getContentResolver(),
+ SWIPE_UP_SETTING_NAME,
+ swipeUpEnabledDefaultValue ? 1 : 0) == 1 :
+ swipeUpEnabledDefaultValue;
// Launcher should run in test harness so that custom accessibility protocol between
// Launcher and TAPL is enabled. In-process tests enable this protocol with a direct call
@@ -154,7 +154,7 @@
fail(message + ". " + "Actual: " + actual);
}
- static public void assertEquals(String message, int expected, int actual) {
+ static private void assertEquals(String message, int expected, int actual) {
if (expected != actual) {
fail(message + " expected: " + expected + " but was: " + actual);
}
@@ -412,16 +412,18 @@
}
@NonNull
- UiDevice getDevice() {
+ public UiDevice getDevice() {
return mDevice;
}
- void swipe(int startX, int startY, int endX, int endY) {
- executeAndWaitForEvent(
+ void swipe(int startX, int startY, int endX, int endY, int expectedState) {
+ final Bundle parcel = (Bundle) executeAndWaitForEvent(
() -> mDevice.swipe(startX, startY, endX, endY, 60),
event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()),
"Swipe failed to receive an event for the swipe end: " + startX + ", " + startY
+ ", " + endX + ", " + endY);
+ assertEquals("Swipe switched launcher to a wrong state",
+ expectedState, parcel.getInt(TestProtocol.STATE_FIELD));
}
void waitForIdle() {
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 9e0c07f..0208144 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+
import android.graphics.Point;
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
@@ -51,7 +53,7 @@
final UiObject2 navBar = mLauncher.getSystemUiObject("navigation_bar_frame");
final Point start = navBar.getVisibleCenter();
LauncherInstrumentation.log("Overview.switchToAllApps before swipe");
- mLauncher.swipe(start.x, start.y, start.x, 0);
+ mLauncher.swipe(start.x, start.y, start.x, 0, ALL_APPS_STATE_ORDINAL);
return new AllAppsFromOverview(mLauncher);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 48686c4..7ccd49b 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -24,6 +24,7 @@
* A recent task in the overview panel carousel.
*/
public final class OverviewTask {
+ static final int FLING_SPEED = 3000;
private final LauncherInstrumentation mLauncher;
private final UiObject2 mTask;
private final BaseOverview mOverview;
@@ -45,7 +46,7 @@
public void dismiss() {
verifyActiveContainer();
// Dismiss the task via flinging it up.
- mTask.fling(Direction.DOWN);
+ mTask.fling(Direction.DOWN, (int) (FLING_SPEED * mLauncher.getDisplayDensity()));
mLauncher.waitForIdle();
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 587c712..5cd41f9 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+
import static junit.framework.TestCase.assertTrue;
import android.graphics.Point;
@@ -55,7 +57,8 @@
start.x,
start.y,
start.x,
- endY
+ endY,
+ ALL_APPS_STATE_ORDINAL
);
return new AllApps(mLauncher);
@@ -96,7 +99,13 @@
public void ensureWorkspaceIsScrollable() {
final UiObject2 workspace = verifyActiveContainer();
if (!isWorkspaceScrollable(workspace)) {
- dragIconToNextScreen(getHotseatAppIcon("Messages"), workspace);
+ dragIconToWorkspace(
+ mLauncher,
+ getHotseatAppIcon("Messages"),
+ new Point(mLauncher.getDevice().getDisplayWidth(),
+ workspace.getVisibleBounds().centerY()),
+ ICON_DRAG_SPEED);
+ verifyActiveContainer();
}
assertTrue("Home screen workspace didn't become scrollable",
isWorkspaceScrollable(workspace));
@@ -112,12 +121,10 @@
mHotseat, AppIcon.getAppIconSelector(appName, mLauncher)));
}
- private void dragIconToNextScreen(AppIcon app, UiObject2 workspace) {
- final Point dest = new Point(
- mLauncher.getDevice().getDisplayWidth(), workspace.getVisibleBounds().centerY());
- app.getObject().drag(dest, ICON_DRAG_SPEED);
- mLauncher.waitUntilGone("drop_target_bar");
- verifyActiveContainer();
+ static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
+ Point dest, int icon_drag_speed) {
+ launchable.getObject().drag(dest, icon_drag_speed);
+ launcher.waitUntilGone("drop_target_bar");
}
/**
@@ -153,4 +160,9 @@
mLauncher.getDevice().pressKeyCode(KeyEvent.KEYCODE_W, KeyEvent.META_CTRL_ON);
return new Widgets(mLauncher);
}
+
+ @Override
+ protected int getSwipeLength() {
+ return 100;
+ }
}
\ No newline at end of file