Merge "Import translations. DO NOT MERGE" into ub-launcher3-master
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/src/com/android/quickstep/LauncherActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java
index ac559ba..8f31e9f 100644
--- a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -44,18 +44,6 @@
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 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);
@@ -148,23 +136,11 @@
}
@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
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/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/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 16d2b67..5ec699c 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/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/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 1a61be6..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
@@ -23,6 +23,8 @@
import android.os.Build;
import android.util.FloatProperty;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
@@ -30,8 +32,6 @@
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
-import androidx.annotation.NonNull;
-
/**
* State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing
* the basic view properties, this class also manages changes in the task visuals.
@@ -50,6 +50,9 @@
if (state.overviewUi) {
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
+ mRecentsView.setHintVisibility(1);
+ } else {
+ mRecentsView.setHintVisibility(0);
}
}
@@ -60,6 +63,7 @@
if (!toState.overviewUi) {
builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals);
+ mRecentsView.setHintVisibility(0);
}
if (toState.overviewUi) {
@@ -71,6 +75,7 @@
updateAnim.setDuration(config.duration);
builder.play(updateAnim);
mRecentsView.updateEmptyMessage();
+ builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1));
}
}
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 930cdc5..ffd3b4b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -43,7 +43,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.TestProtocol;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.SpringObjectAnimator;
@@ -55,7 +54,6 @@
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
-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;
@@ -73,16 +71,6 @@
public final class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
@Override
- public LayoutListener createLayoutListener(Launcher activity) {
- return LauncherLayoutListener.resetAndGet(activity);
- }
-
- @Override
- public void executeOnWindowAvailable(Launcher activity, Runnable action) {
- activity.getWorkspace().runOnOverlayHidden(action);
- }
-
- @Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
if (dp.isVerticalBarLayout()) {
@@ -385,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/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
similarity index 63%
rename from quickstep/src/com/android/quickstep/RecentsActivity.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index b76a1ab..8d7039e 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,12 +15,11 @@
*/
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.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.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/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
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 100%
rename from quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
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/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/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index bb64c2b..eccef04 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -49,10 +49,6 @@
@TargetApi(Build.VERSION_CODES.P)
public interface ActivityControlHelper<T extends BaseDraggingActivity> {
- LayoutListener createLayoutListener(T activity);
-
- void executeOnWindowAvailable(T activity, Runnable action);
-
void onTransitionCancelled(T activity, boolean activityVisible);
int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);
@@ -89,34 +85,15 @@
return true;
}
- boolean supportsLongSwipe(T activity);
-
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();
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/FallbackActivityControllerHelper.java b/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
index b655d1d..a84d230 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
@@ -57,11 +57,6 @@
}
@Override
- public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) {
- action.run();
- }
-
- @Override
public void onTransitionCancelled(RecentsActivity activity, boolean activityVisible) {
// TODO:
}
@@ -152,26 +147,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);
@@ -211,16 +186,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/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/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java
index ba66293..9fceab4 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java
@@ -44,6 +44,11 @@
* 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;
@@ -68,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);
@@ -109,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;
+ private String convertToFlagNames(int flags) {
+ StringJoiner joiner = new StringJoiner(", ", "[", " (" + flags + ")]");
for (int i = 0; i < mStateNames.length; i++) {
- if ((state & (i << i)) != 0) {
- currentStateStr.add(mStateNames[i]);
- }
- if (stateFlag == (1 << i)) {
- stateFlagStr = mStateNames[i] + " (" + stateFlag + ")";
+ 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/src/com/android/quickstep/OtherActivityTouchConsumer.java
index a335827..77f900f 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -24,6 +24,7 @@
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;
@@ -35,7 +36,6 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
-import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
@@ -43,15 +43,17 @@
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;
@@ -59,9 +61,6 @@
import java.util.function.Consumer;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
/**
* Touch consumer for handling events originating from an activity other than Launcher
*/
@@ -71,6 +70,7 @@
public static final String DOWN_EVT = "OtherActivityTouchConsumer.DOWN";
private static final String UP_EVT = "OtherActivityTouchConsumer.UP";
+ private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
private final RecentsModel mRecentsModel;
private final Intent mHomeIntent;
@@ -143,6 +143,19 @@
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();
@@ -219,7 +232,7 @@
if (mPassedDragSlop && mInteractionHandler != null) {
// Move
- dispatchMotion(ev, displacement - mStartDisplacement, null);
+ mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
if (FeatureFlags.SWIPE_HOME.get()) {
boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
@@ -244,14 +257,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;
@@ -288,32 +293,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));
}
}
@@ -331,8 +320,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
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index 2c3f77f..befeee0 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -16,17 +16,36 @@
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.
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index cedd952..00b3e90 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -73,6 +73,14 @@
});
}
+ public void startStabilizationSession() {
+ mStabilizer.startStabilizationSession();
+ }
+
+ public void endStabilizationSession() {
+ mStabilizer.endStabilizationSession();
+ }
+
/**
* Asynchronously fetches the list of recent tasks, reusing cached list if available.
*
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
index c2d4d80..5e7c1a1 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -21,17 +21,11 @@
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.quickstep.util.SwipeAnimationTargetSet;
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;
@@ -45,17 +39,10 @@
// than the state callbacks as these run on the current worker thread.
private final ArrayList<Runnable> mCallbacks = new ArrayList<>();
- public RemoteAnimationTargetSet targetSet;
+ public SwipeAnimationTargetSet targetSet;
- private RecentsAnimationControllerCompat mController;
- private boolean mInputConsumerEnabled = false;
- private boolean mBehindSystemBars = true;
- private boolean mSplitScreenMinimized = false;
+ private boolean mWindowThresholdCrossed = false;
- private final ExecutorService mExecutorService =
- new LooperExecutor(UiThreadHelper.getBackgroundLooper());
-
- private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
private final InputConsumerController mInputConsumer;
private final Supplier<TouchConsumer> mTouchProxySupplier;
@@ -71,19 +58,14 @@
}
@UiThread
- public synchronized void setController(
- RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) {
+ public synchronized void setController(SwipeAnimationTargetSet targetSet) {
Preconditions.assertUIThread();
- TraceHelper.partitionSection("RecentsController", "Set controller " + controller);
- this.mController = controller;
this.targetSet = targetSet;
- if (controller == null) {
+ if (targetSet == null) {
return;
}
- if (mInputConsumerEnabled) {
- enableInputConsumer();
- }
+ targetSet.setWindowThresholdCrossed(mWindowThresholdCrossed);
if (!mCallbacks.isEmpty()) {
for (Runnable action : new ArrayList<>(mCallbacks)) {
@@ -105,13 +87,12 @@
* @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) {
- mExecutorService.submit(() -> finishBg(false, onFinishComplete));
- return;
- }
-
- mMainThreadExecutor.execute(() -> {
+ finishAndClear(false, onFinishComplete);
+ } else {
if (mTouchInProgress) {
mFinishPending = true;
// Execute the callback
@@ -119,45 +100,39 @@
onFinishComplete.run();
}
} else {
- mExecutorService.submit(() -> finishBg(true, onFinishComplete));
+ finishAndClear(true, onFinishComplete);
}
- });
+ }
}
- protected void finishBg(boolean toRecents, Runnable onFinishComplete) {
- RecentsAnimationControllerCompat controller = mController;
- mController = null;
- TraceHelper.endSection("RecentsController", "Finish " + controller
- + ", toRecents=" + toRecents);
+ private void finishAndClear(boolean toRecents, Runnable onFinishComplete) {
+ SwipeAnimationTargetSet controller = targetSet;
+ targetSet = null;
if (controller != null) {
- controller.setInputConsumerEnabled(false);
- controller.finish(toRecents);
-
- if (onFinishComplete != null) {
- mMainThreadExecutor.execute(onFinishComplete);
- }
+ controller.finishController(toRecents, 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);
- }
- });
+ 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 enableTouchProxy() {
- mMainThreadExecutor.execute(this::enableTouchProxyUi);
- }
-
- private void enableTouchProxyUi() {
mInputConsumer.setTouchListener(this::onInputConsumerTouch);
}
@@ -171,7 +146,7 @@
mTouchInProgress = false;
if (mFinishPending) {
mFinishPending = false;
- mExecutorService.submit(() -> finishBg(true, null));
+ finishAndClear(true /* toRecents */, null);
}
}
if (mTouchConsumer != null) {
@@ -181,54 +156,7 @@
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;
+ public SwipeAnimationTargetSet getController() {
+ return targetSet;
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index e61c00a..f3e1545 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
@@ -28,6 +26,7 @@
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;
@@ -35,11 +34,14 @@
import com.android.systemui.shared.recents.model.Task;
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 static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
+
/**
* Singleton class to load and manage recents model.
*/
@@ -52,14 +54,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 Context mContext;
private final MainThreadExecutor mMainThreadExecutor;
private ISystemUiProxy mSystemUiProxy;
- private boolean mClearAssistCacheOnStackChange = true;
private final RecentTasksList mTaskList;
private final TaskIconCache mIconCache;
@@ -90,6 +88,14 @@
return mThumbnailCache;
}
+ public void startStabilizationSession() {
+ mTaskList.startStabilizationSession();
+ }
+
+ public void endStabilizationSession() {
+ mTaskList.endStabilizationSession();
+ }
+
/**
* Fetches the list of recent tasks.
*
@@ -162,16 +168,6 @@
});
}
- @Override
- public void onTaskStackChanged() {
- Preconditions.assertUIThread();
- if (mClearAssistCacheOnStackChange) {
- mCachedAssistData.clear();
- } else {
- mClearAssistCacheOnStackChange = true;
- }
- }
-
public void setSystemUiProxy(ISystemUiProxy systemUiProxy) {
mSystemUiProxy = systemUiProxy;
}
@@ -243,44 +239,4 @@
+ ": ", e);
}
}
-
- public void resetAssistCache() {
- mCachedAssistData.clear();
- }
-
- @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 Bundle getAssistData(int taskId) {
- Preconditions.assertUIThread();
- return mCachedAssistData.get(taskId);
- }
-
- 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);
- }
}
diff --git a/quickstep/src/com/android/quickstep/SwipeSharedState.java b/quickstep/src/com/android/quickstep/SwipeSharedState.java
index 15914ba..7c6638a 100644
--- a/quickstep/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/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/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/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index cc49d46..d979c99 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/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/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 74ac1c6..0ccd141 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -37,6 +37,8 @@
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;
@@ -55,6 +57,9 @@
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;
@@ -174,7 +179,7 @@
mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
mOverviewCallbacks = OverviewCallbacks.get(this);
mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
- mSwipeSharedState = new SwipeSharedState();
+ mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver);
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mInputConsumer.registerInputConsumer();
@@ -249,10 +254,8 @@
mOverviewComponentObserver.getActivityControlHelper();
boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
- mOverviewComponentObserver.getOverviewIntent(),
- mOverviewComponentObserver.getActivityControlHelper(),
- shouldDefer, mOverviewCallbacks,
- mTaskOverlayFactory, mInputConsumer,
+ mOverviewComponentObserver.getOverviewIntent(), activityControl,
+ shouldDefer, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer,
this::onConsumerInactive, mSwipeSharedState);
}
}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index aeb648d..f578149 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -53,14 +53,16 @@
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.util.Log;
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;
@@ -73,7 +75,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;
@@ -87,31 +88,30 @@
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
-import com.android.quickstep.ActivityControlHelper.LayoutListener;
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.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.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.Nullable;
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;
@@ -164,21 +164,11 @@
getFlagForIndex(16, "STATE_START_NEW_TASK");
private static final int STATE_CURRENT_TASK_FINISHED =
getFlagForIndex(17, "STATE_CURRENT_TASK_FINISHED");
- private static final int STATE_ASSIST_DATA_RECEIVED =
- getFlagForIndex(18, "STATE_ASSIST_DATA_RECEIVED");
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;
-
// For debugging, keep in sync with above states
enum GestureEndTarget {
@@ -200,11 +190,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;
}
@@ -252,10 +246,10 @@
private AnimatorPlaybackController mLauncherTransitionController;
private T mActivity;
- private LayoutListener mLayoutListener;
private RecentsView mRecentsView;
private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
private AnimationFactory mAnimationFactory = (t) -> { };
+ private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
private boolean mWasLauncherAlreadyVisible;
@@ -268,12 +262,6 @@
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) {
@@ -345,11 +333,6 @@
| STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED
| 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 | STATE_ASSIST_DATA_RECEIVED,
- this::preloadAssistData);
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
@@ -358,8 +341,8 @@
| STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled);
- 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,7 +393,6 @@
int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
initStateCallbacks();
mStateCallback.setState(oldState);
- mLayoutListener.setHandler(null);
}
mWasLauncherAlreadyVisible = alreadyOnHome;
mActivity = activity;
@@ -423,18 +405,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);
- mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity);
+ mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
mStateCallback.setState(STATE_LAUNCHER_PRESENT);
if (alreadyOnHome) {
@@ -480,7 +462,7 @@
}
setupRecentsViewUi();
- mLayoutListener.open();
+ activity.getRootView().setOnApplyWindowInsetsListener(this);
mStateCallback.setState(STATE_LAUNCHER_STARTED);
}
@@ -522,7 +504,6 @@
}
private void initializeLauncherAnimationController() {
- mLayoutListener.setHandler(this);
buildAnimationController();
if (LatencyTrackerCompat.isEnabled(mContext)) {
@@ -542,24 +523,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
@@ -568,16 +533,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);
@@ -598,14 +554,18 @@
}
}
- /**
- * Called by {@link #mLayoutListener} when launcher layout changes
- */
- public void buildAnimationController() {
+ private void buildAnimationController() {
initTransitionEndpoints(mActivity.getDeviceProfile());
mAnimationFactory.createActivityController(mTransitionDragLength);
}
+ @Override
+ public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
+ WindowInsets result = view.onApplyWindowInsets(windowInsets);
+ buildAnimationController();
+ return result;
+ }
+
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
mLauncherTransitionController = anim;
mLauncherTransitionController.dispatchOnStart();
@@ -616,7 +576,7 @@
private void updateFinalShift() {
float shift = mCurrentShift.value;
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
float offsetX = 0;
if (mRecentsView != null) {
@@ -631,19 +591,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());
}
}
@@ -717,7 +671,7 @@
mClipAnimationHelper.prepareAnimation(false /* isOpening */);
initTransitionEndpoints(dp);
- mRecentsAnimationWrapper.setController(targetSet.controller, targetSet);
+ mRecentsAnimationWrapper.setController(targetSet);
TOUCH_INTERACTION_LOG.startRecentsAnimationCallback(targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
@@ -726,7 +680,7 @@
@Override
public void onRecentsAnimationCanceled() {
- mRecentsAnimationWrapper.setController(null, null);
+ mRecentsAnimationWrapper.setController(null);
mActivityInitListener.unregister();
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
TOUCH_INTERACTION_LOG.cancelRecentsAnimation();
@@ -738,8 +692,6 @@
mShiftAtGestureStart = mCurrentShift.value;
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
- mRecentsAnimationWrapper.hideCurrentInputMethod();
- mRecentsAnimationWrapper.enableInputConsumer();
}
/**
@@ -763,12 +715,7 @@
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
@@ -926,6 +873,17 @@
private void animateToProgressInternal(float start, float end, long duration,
Interpolator interpolator, GestureEndTarget target, float velocityPxPerMs) {
mGestureEndTarget = target;
+
+ 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) {
@@ -1106,12 +1064,16 @@
private void invalidateHandlerWithLauncher() {
mLauncherTransitionController = null;
- mLayoutListener.finish();
mActivityControlHelper.getAlphaProperty(mActivity).setValue(1);
mRecentsView.setEnableFreeScroll(true);
mRecentsView.setRunningTaskIconScaledDown(false);
mRecentsView.setOnScrollChangeListener(null);
+ mRecentsView.setRunningTaskHidden(false);
+ mRecentsView.setEnableDrawingLiveTile(true);
+
+ mActivity.getRootView().setOnApplyWindowInsetsListener(null);
+ mActivity.getRootView().getOverlay().remove(mLiveTileOverlay);
}
private void notifyTransitionCancelled() {
@@ -1126,20 +1088,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) {
@@ -1223,94 +1177,12 @@
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/hints/HintUtil.java b/quickstep/src/com/android/quickstep/hints/HintUtil.java
new file mode 100644
index 0000000..f2d40ec
--- /dev/null
+++ b/quickstep/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/src/com/android/quickstep/hints/HintView.java b/quickstep/src/com/android/quickstep/hints/HintView.java
new file mode 100644
index 0000000..5399cc4
--- /dev/null
+++ b/quickstep/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/src/com/android/quickstep/hints/HintsContainer.java b/quickstep/src/com/android/quickstep/hints/HintsContainer.java
new file mode 100644
index 0000000..22b1217
--- /dev/null
+++ b/quickstep/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/quickstep/src/com/android/quickstep/hints/UiHintListenerConstants.java b/quickstep/src/com/android/quickstep/hints/UiHintListenerConstants.java
new file mode 100644
index 0000000..420033d
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/hints/UiHintListenerConstants.java
@@ -0,0 +1,28 @@
+/*
+ * 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 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/src/com/android/quickstep/hints/UiInterfaceConstants.java b/quickstep/src/com/android/quickstep/hints/UiInterfaceConstants.java
new file mode 100644
index 0000000..0140613
--- /dev/null
+++ b/quickstep/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/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/RecentsAnimationListenerSet.java b/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
index 686e74d..62f2183 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
+++ b/quickstep/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/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
index 4f02acf..b682481 100644
--- a/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
+++ b/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
@@ -15,32 +15,79 @@
*/
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) {
+ 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 {
@@ -48,4 +95,9 @@
void onRecentsAnimationCanceled();
}
+
+ public interface SwipeAnimationFinishListener {
+
+ void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet);
+ }
}
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/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 1ee5110..88fe2ee 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -15,13 +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;
@@ -36,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;
@@ -77,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);
@@ -90,7 +90,6 @@
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setContentAlpha(0);
- mLauncherLayoutListener = new LauncherLayoutListener(BaseActivity.fromContext(context));
}
@Override
@@ -109,6 +108,13 @@
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));
@@ -124,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);
@@ -175,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);
}
@@ -205,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();
diff --git a/quickstep/src/com/android/quickstep/views/LiveTileOverlay.java b/quickstep/src/com/android/quickstep/views/LiveTileOverlay.java
new file mode 100644
index 0000000..ab2b90f
--- /dev/null
+++ b/quickstep/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/src/com/android/quickstep/views/RecentsView.java
index 0c1867d..8faf95d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -93,13 +93,13 @@
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;
@@ -166,8 +166,6 @@
private final ViewPool<TaskView> mTaskViewPool;
- @Nullable Float mSimulatedVelocityX = null;
-
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
*/
@@ -1590,7 +1588,7 @@
return;
}
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
ThumbnailData taskSnapshot = controller.screenshotTask(mRunningTaskId);
@@ -1626,18 +1624,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/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/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 296c951..7aea870 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -103,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
@@ -200,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
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index cf16759..f571aa3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -257,7 +257,6 @@
private RotationHelper mRotationHelper;
-
private final Handler mHandler = new Handler();
private final Runnable mHandleDeferredResume = this::handleDeferredResume;
@@ -756,6 +755,7 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onStop();
}
+
getUserEventDispatcher().logActionCommand(Action.Command.STOP,
mStateManager.getState().containerType, -1);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 471d28d..6d85612 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -21,6 +21,7 @@
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;
@@ -81,7 +82,8 @@
/**
* 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);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 018ec5f..4b7d8b4 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -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 f19b0e0..23df79e 100644
--- a/src/com/android/launcher3/TestProtocol.java
+++ b/src/com/android/launcher3/TestProtocol.java
@@ -25,6 +25,7 @@
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;
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) {