Merging from ub-launcher3-master @ build 6767682

Test: manual, presubmit on the source branch
x20/teams/android-launcher/merge/ub-launcher3-master_master_6767682.html

Change-Id: I5e9c73a7ac3033fe82006c4bd72824f56b8988f8
This commit is contained in:
Mehdi Alizadeh
2020-08-16 12:31:21 -07:00
276 changed files with 4751 additions and 3199 deletions
+5 -12
View File
@@ -48,7 +48,7 @@ LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ --proto_path=$(LOCAL_PA
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java
LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
LOCAL_MIN_SDK_VERSION := 26
LOCAL_MODULE := Launcher3CommonDepsLib
LOCAL_PRIVILEGED_MODULE := true
LOCAL_MANIFEST_FILE := AndroidManifest-common.xml
@@ -77,7 +77,7 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
LOCAL_MIN_SDK_VERSION := 26
LOCAL_PACKAGE_NAME := Launcher3
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SYSTEM_EXT_MODULE := true
@@ -108,7 +108,7 @@ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/go/res
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
LOCAL_MIN_SDK_VERSION := 26
LOCAL_PACKAGE_NAME := Launcher3Go
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SYSTEM_EXT_MODULE := true
@@ -149,12 +149,9 @@ LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
$(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, src_shortcuts_overrides)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
LOCAL_PROGUARD_ENABLED := disabled
@@ -183,9 +180,7 @@ LOCAL_SYSTEM_EXT_MODULE := true
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
@@ -220,12 +215,10 @@ LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
$(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, go/src)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res \
$(LOCAL_PATH)/go/res
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-18
View File
@@ -29,12 +29,6 @@
at compile time. Note that the components defined in AndroidManifest.xml are also required,
with some minor changed based on the derivative app.
-->
<permission
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="dangerous"
android:label="@string/permlab_install_shortcut"
android:description="@string/permdesc_install_shortcut" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
@@ -79,17 +73,6 @@
android:restoreAnyVersion="true"
android:supportsRtl="true" >
<!-- Intent received used to install shortcuts from other applications -->
<receiver
android:name="com.android.launcher3.InstallShortcutReceiver"
android:permission="com.android.launcher.permission.INSTALL_SHORTCUT"
android:exported="true"
android:enabled="@bool/enable_install_shortcut_api" >
<intent-filter>
<action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
</intent-filter>
</receiver>
<!-- Intent received when a session is committed -->
<receiver
android:name="com.android.launcher3.SessionCommitReceiver"
@@ -116,7 +99,6 @@
<service
android:name="com.android.launcher3.notification.NotificationListener"
android:label="@string/notification_dots_service_title"
android:enabled="@bool/notification_dots_enabled"
android:exported="true"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
+1 -1
View File
@@ -20,7 +20,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
<uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
<uses-sdk android:targetSdkVersion="29" android:minSdkVersion="26"/>
<!--
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
Refer comments around specific entries on how to extend individual components.
+38
View File
@@ -0,0 +1,38 @@
160759508
144170434
144170434
161801331
162564471
160361464
161901771
160568387
162623012
162012217
160718310
160361464
160718310
162012217
160748731
154951045
162861289
149934536
149934536
144170434
144170434
162454040
161273376
149934536
149934536
158701272
162871508
149934536
161939759
154964045
161536946
149934536
161685099
162812884
162480567
162480567
149934536
149934536
+24
View File
@@ -0,0 +1,24 @@
144170434
149934536
154951045
154964045
158701272
160361464
160568387
160718310
160748731
160759508
161273376
161536946
161685099
161801331
161901771
161939759
162012217
162454040
162480567
162564471
162623012
162812884
162861289
162871508
+24
View File
@@ -0,0 +1,24 @@
144170434 twickham P1 FIXED Improve Overview -> Home transition ----
149934536 twickham P2 FIXED Update gesture nav pullback logic ----
154951045 peanutbutter P1 FIXED Odd animation occuring at times when swiping to home ----
154964045 awickham P2 FIXED "Clear all" text is not in the middle of app's window vertically ----
158701272 twickham P4 FIXED Discontinuities when long-swiping to home ----
160361464 tracyzhou P2 FIXED Place launcher above the target app in live tile mode ----
160568387 twickham P2 FIXED Can't get to app switcher by swiping up (motion pause not detected) ----
160718310 xuqiu P1 FIXED With "Select" overview action selected, App icon is missing in other overview apps after orientation change ----
160748731 sunnygoyal P2 ASSIGNED Unify prediction model with Launcher model ----
160759508 twickham P2 FIXED Swipe up cannot back to home screen in overview. ----
161273376 xuqiu P2 FIXED [Overview Actions] Add logging and helpful messages ----
161536946 twickham P2 FIXED Haptics don't indicate snap-to in overview, ----
161685099 winsonc P2 FIXED Screen still stay at the quick settings/notification when I swipe up with 3 finger to check the all apps. ----
161801331 hyunyoungs P2 FIXED Change AllAppsSearch plugin to support only data fetch ----
161901771 xuqiu P1 FIXED Overlapping layer of highlights with app layout getting darker when keep rotating the device from "Feedback" viewpoint in split screen ----
161939759 sunnygoyal P2 FIXED RD1A: Going to overview in landscape mode clips the screen content ----
162012217 perumaal P2 ASSIGNED Leaked Activity Caused by Gleams ----
162454040 bookatz P2 ASSIGNED Create multiuser test that checks that opening an app works properly ----
162480567 sfufa P4 FIXED Enable Item Decorations for search items ----
162564471 tracyzhou P2 FIXED [Live tile] Handle tapping overview actions in live tile mode ----
162623012 zakcohen P1 ASSIGNED Enable chips flag ----
162812884 winsonc P2 ASSIGNED [R]The color have not changed in some page after turning on the dark theme. ----
162861289 hyunyoungs P2 FIXED Add FocusIndicator support to DEVICE_SEARCH feature in S ----
162871508 sfufa P2 ASSIGNED Introduce support for Hero app section ----
+1133
View File
File diff suppressed because it is too large Load Diff
-20
View File
@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<resources>
<!-- Dynamic Grid -->
<dimen name="dynamic_grid_hotseat_size">60dp</dimen>
</resources>
@@ -20,7 +20,6 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.util.LooperExecutor;
/**
* Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
@@ -29,12 +28,7 @@ public class LoaderResults extends BaseLoaderResults {
public LoaderResults(LauncherAppState app, BgDataModel dataModel,
AllAppsList allAppsList, Callbacks[] callbacks) {
this(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
}
public LoaderResults(LauncherAppState app, BgDataModel dataModel,
AllAppsList allAppsList, Callbacks[] callbacks, LooperExecutor executor) {
super(app, dataModel, allAppsList, callbacks, executor);
super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
}
@Override
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<color name="chip_hint_foreground_color">#fff</color>
<color name="chip_scrim_start_color">#39000000</color>
<color name="all_apps_label_text">#61000000</color>
<color name="all_apps_label_text_dark">#61FFFFFF</color>
<color name="all_apps_prediction_row_separator">#3c000000</color>
<color name="all_apps_prediction_row_separator_dark">#3cffffff</color>
</resources>
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<integer name="max_depth_blur_radius">150</integer>
</resources>
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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_vertical_offset">16dp</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>
<dimen name="all_apps_prediction_row_divider_height">17dp</dimen>
<dimen name="all_apps_label_top_padding">16dp</dimen>
<dimen name="all_apps_label_bottom_padding">8dp</dimen>
<dimen name="all_apps_label_text_size">14sp</dimen>
<!-- Minimum distance to swipe to trigger accessibility gesture -->
<dimen name="accessibility_gesture_min_swipe_distance">80dp</dimen>
</resources>
@@ -0,0 +1,2 @@
Temp file to prevent build breakage.
Will be removed in followup cl.
@@ -1,138 +0,0 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.model;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
import android.content.Context;
import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.util.Executors;
import com.android.quickstep.logging.StatsLogCompatManager;
import java.util.List;
/**
* Model delegate which loads prediction items
*/
public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChangeListener {
public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
private final InvariantDeviceProfile mIDP;
private final AppEventProducer mAppEventProducer;
private AppPredictor mAllAppsPredictor;
private boolean mActive = false;
public QuickstepModelDelegate(Context context) {
mAppEventProducer = new AppEventProducer(context, this::onAppTargetEvent);
mIDP = InvariantDeviceProfile.INSTANCE.get(context);
mIDP.addOnChangeListener(this);
StatsLogCompatManager.LOGS_CONSUMER.add(mAppEventProducer);
}
@Override
public void loadItems() {
// TODO: Implement caching and preloading
super.loadItems();
mDataModel.extraItems.put(
CONTAINER_PREDICTION, new FixedContainerItems(CONTAINER_PREDICTION));
mActive = true;
recreatePredictors();
}
@Override
public void validateData() {
super.validateData();
if (mAllAppsPredictor != null) {
mAllAppsPredictor.requestPredictionUpdate();
}
}
@Override
public void destroy() {
super.destroy();
mActive = false;
StatsLogCompatManager.LOGS_CONSUMER.remove(mAppEventProducer);
destroyPredictors();
mIDP.removeOnChangeListener(this);
}
private void destroyPredictors() {
if (mAllAppsPredictor != null) {
mAllAppsPredictor.destroy();
mAllAppsPredictor = null;
}
}
@WorkerThread
private void recreatePredictors() {
destroyPredictors();
if (!mActive) {
return;
}
Context context = mApp.getContext();
AppPredictionManager apm = context.getSystemService(AppPredictionManager.class);
if (apm == null) {
return;
}
int count = mIDP.numAllAppsColumns;
mAllAppsPredictor = apm.createAppPredictionSession(
new AppPredictionContext.Builder(context)
.setUiSurface("home")
.setPredictedTargetCount(count)
.build());
mAllAppsPredictor.registerPredictionUpdates(
Executors.MODEL_EXECUTOR, this::onAllAppsPredictionChanged);
mAllAppsPredictor.requestPredictionUpdate();
}
private void onAllAppsPredictionChanged(List<AppTarget> targets) {
mApp.getModel().enqueueModelUpdateTask(
new PredictionUpdateTask(CONTAINER_PREDICTION, targets));
}
@Override
public void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
if ((changeFlags & CHANGE_FLAG_GRID) != 0) {
// Reinitialize everything
Executors.MODEL_EXECUTOR.execute(this::recreatePredictors);
}
}
private void onAppTargetEvent(AppTargetEvent event) {
if (mAllAppsPredictor != null) {
mAllAppsPredictor.notifyAppTargetEvent(event);
}
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.uioverrides.states;
import com.android.launcher3.Launcher;
public class OverviewPeekState extends OverviewState {
private static final float OVERVIEW_OFFSET = 0.7f;
public OverviewPeekState(int id) {
super(id);
}
@Override
public float[] getOverviewScaleAndOffset(Launcher launcher) {
return new float[] {NO_SCALE, OVERVIEW_OFFSET};
}
}
@@ -1,279 +0,0 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.views.RecentsView;
/**
* Touch controller which handles swipe and hold to go to Overview
*/
public class FlingAndHoldTouchController extends PortraitStatesTouchController {
private static final long PEEK_IN_ANIM_DURATION = 240;
private static final long PEEK_OUT_ANIM_DURATION = 100;
private static final float MAX_DISPLACEMENT_PERCENT = 0.75f;
protected final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
private final float mMotionPauseMaxDisplacement;
private AnimatorSet mPeekAnim;
public FlingAndHoldTouchController(Launcher l) {
super(l, false /* allowDragToOverview */);
mMotionPauseDetector = new MotionPauseDetector(l);
mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
mMotionPauseMaxDisplacement = getMotionPauseMaxDisplacement();
}
protected float getMotionPauseMaxDisplacement() {
return getShiftRange() * MAX_DISPLACEMENT_PERCENT;
}
@Override
protected long getAtomicDuration() {
return QuickstepAtomicAnimationFactory.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
}
@Override
public void onDragStart(boolean start, float startDisplacement) {
mMotionPauseDetector.clear();
super.onDragStart(start, startDisplacement);
if (handlingOverviewAnim()) {
mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
}
if (mAtomicAnim != null) {
mAtomicAnim.cancel();
}
}
protected void onMotionPauseChanged(boolean isPaused) {
RecentsView recentsView = mLauncher.getOverviewPanel();
recentsView.setOverviewStateEnabled(isPaused);
if (mPeekAnim != null) {
mPeekAnim.cancel();
}
LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK;
LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL;
long peekDuration = isPaused ? PEEK_IN_ANIM_DURATION : PEEK_OUT_ANIM_DURATION;
StateAnimationConfig config = new StateAnimationConfig();
config.duration = peekDuration;
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
fromState, toState, config);
mPeekAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mPeekAnim = null;
}
});
mPeekAnim.start();
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
mLauncher.getDragLayer().getScrim().createSysuiMultiplierAnim(isPaused ? 0 : 1)
.setDuration(peekDuration).start();
}
/**
* @return Whether we are handling the overview animation, rather than
* having it as part of the existing animation to the target state.
*/
protected boolean handlingOverviewAnim() {
int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
return mStartState == NORMAL && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
}
@Override
protected StateAnimationConfig getConfigForStates(
LauncherState fromState, LauncherState toState) {
if (fromState == NORMAL && toState == ALL_APPS) {
StateAnimationConfig builder = new StateAnimationConfig();
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
- OVERVIEW.getVerticalProgress(mLauncher);
builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
ACCEL,
0,
ALL_APPS_CONTENT_FADE_THRESHOLD));
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
ACCEL,
progressToReachOverview,
progressToReachOverview + ALL_APPS_CONTENT_FADE_THRESHOLD));
// Get workspace out of the way quickly, to prepare for potential pause.
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
return builder;
} else if (fromState == ALL_APPS && toState == NORMAL) {
StateAnimationConfig builder = new StateAnimationConfig();
// Keep all apps/predictions opaque until the very end of the transition.
float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
DEACCEL,
progressToReachOverview - ALL_APPS_CONTENT_FADE_THRESHOLD,
progressToReachOverview));
builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
DEACCEL,
1 - ALL_APPS_CONTENT_FADE_THRESHOLD,
1));
return builder;
}
return super.getConfigForStates(fromState, toState);
}
@Override
public boolean onDrag(float displacement, MotionEvent event) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "FlingAndHoldTouchController");
}
float upDisplacement = -displacement;
mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
|| upDisplacement < mMotionPauseMinDisplacement
|| upDisplacement > mMotionPauseMaxDisplacement);
mMotionPauseDetector.addPosition(event);
return super.onDrag(displacement, event);
}
@Override
public void onDragEnd(float velocity) {
if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
goToOverviewOnDragEnd(velocity);
} else {
super.onDragEnd(velocity);
}
View searchView = mLauncher.getAppsView().getSearchView();
if (searchView instanceof FeedbackHandler) {
((FeedbackHandler) searchView).resetFeedback();
}
mMotionPauseDetector.clear();
}
protected void goToOverviewOnDragEnd(float velocity) {
if (mPeekAnim != null) {
mPeekAnim.cancel();
}
Animator overviewAnim = mLauncher.createAtomicAnimationFactory()
.createStateElementAnimation(INDEX_PAUSE_TO_OVERVIEW_ANIM);
mAtomicAnim = new AnimatorSet();
mAtomicAnim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
onSwipeInteractionCompleted(OVERVIEW, Touch.SWIPE);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (mCancelled) {
StateAnimationConfig config = new StateAnimationConfig();
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
config.duration = PEEK_OUT_ANIM_DURATION;
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
mFromState, mToState, config);
mPeekAnim.start();
}
mAtomicAnim = null;
}
});
mAtomicAnim.play(overviewAnim);
mAtomicAnim.start();
}
@Override
protected void goToTargetState(LauncherState targetState, int logAction) {
if (mPeekAnim != null && mPeekAnim.isStarted()) {
// Don't jump to the target state until overview is no longer peeking.
mPeekAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
FlingAndHoldTouchController.super.goToTargetState(targetState, logAction);
}
});
} else {
super.goToTargetState(targetState, logAction);
}
}
@Override
@AnimationFlags
protected int updateAnimComponentsOnReinit(@AnimationFlags int animComponents) {
if (handlingOverviewAnim()) {
// We don't want the state transition to all apps to animate overview,
// as that will cause a jump after our atomic animation.
return animComponents | SKIP_OVERVIEW;
} else {
return animComponents;
}
}
/**
* Interface for views with feedback animation requiring reset
*/
public interface FeedbackHandler {
/**
* reset searchWidget feedback
*/
void resetFeedback();
}
}
@@ -1,105 +0,0 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep.util;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.view.animation.Interpolator;
import com.android.launcher3.Launcher;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.uioverrides.states.OverviewState;
/**
* Animates the shelf between states HIDE, PEEK, and OVERVIEW.
*/
public class ShelfPeekAnim {
public static final Interpolator INTERPOLATOR = OVERSHOOT_1_2;
public static final long DURATION = 240;
private final Launcher mLauncher;
private ShelfAnimState mShelfState;
private boolean mIsPeeking;
public ShelfPeekAnim(Launcher launcher) {
mLauncher = launcher;
}
/**
* Animates to the given state, canceling the previous animation if it was still running.
*/
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
if (mShelfState == shelfState || FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
return;
}
mLauncher.getStateManager().cancelStateElementAnimation(INDEX_SHELF_ANIM);
mShelfState = shelfState;
mIsPeeking = mShelfState == ShelfAnimState.PEEK || mShelfState == ShelfAnimState.HIDE;
if (mShelfState == ShelfAnimState.CANCEL) {
return;
}
float shelfHiddenProgress = BACKGROUND_APP.getVerticalProgress(mLauncher);
float shelfOverviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
// Peek based on default overview progress so we can see hotseat if we're showing
// that instead of predictions in overview.
float defaultOverviewProgress = OverviewState.getDefaultVerticalProgress(mLauncher);
float shelfPeekingProgress = shelfHiddenProgress
- (shelfHiddenProgress - defaultOverviewProgress) * 0.25f;
float toProgress = mShelfState == ShelfAnimState.HIDE
? shelfHiddenProgress
: mShelfState == ShelfAnimState.PEEK
? shelfPeekingProgress
: shelfOverviewProgress;
Animator shelfAnim = mLauncher.getStateManager()
.createStateElementAnimation(INDEX_SHELF_ANIM, toProgress);
shelfAnim.setInterpolator(interpolator);
shelfAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
mShelfState = ShelfAnimState.CANCEL;
}
@Override
public void onAnimationEnd(Animator animator) {
mIsPeeking = mShelfState == ShelfAnimState.PEEK;
}
});
shelfAnim.setDuration(duration).start();
}
/** @return Whether the shelf is currently peeking or animating to or from peeking. */
public boolean isPeeking() {
return mIsPeeking;
}
/** The various shelf states we can animate to. */
public enum ShelfAnimState {
HIDE(true), PEEK(true), OVERVIEW(false), CANCEL(false);
ShelfAnimState(boolean shouldPreformHaptic) {
this.shouldPreformHaptic = shouldPreformHaptic;
}
public final boolean shouldPreformHaptic;
}
}
@@ -23,5 +23,4 @@
android:text="@string/recents_clear_all"
android:textColor="?attr/workspaceTextColor"
android:textSize="14sp"
android:translationY="@dimen/task_thumbnail_half_top_margin"
/>
android:translationY="@dimen/task_thumbnail_half_top_margin" />
+8
View File
@@ -16,4 +16,12 @@
<resources>
<color name="back_arrow_color_light">#FFFFFFFF</color>
<color name="back_arrow_color_dark">#99000000</color>
<color name="chip_hint_foreground_color">#fff</color>
<color name="chip_scrim_start_color">#39000000</color>
<color name="all_apps_label_text">#61000000</color>
<color name="all_apps_label_text_dark">#61FFFFFF</color>
<color name="all_apps_prediction_row_separator">#3c000000</color>
<color name="all_apps_prediction_row_separator_dark">#3cffffff</color>
</resources>
+4
View File
@@ -16,6 +16,8 @@
<resources>
<string name="task_overlay_factory_class" translatable="false"/>
<string name="overscroll_plugin_factory_class" translatable="false" />
<!-- Activities which block home gesture -->
<string-array name="gesture_blocking_activities" translatable="false">
<item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
@@ -35,4 +37,6 @@
<integer name="assistant_gesture_corner_deg_threshold">20</integer>
<string name="wellbeing_provider_pkg" translatable="false"/>
<integer name="max_depth_blur_radius">150</integer>
</resources>
+22 -1
View File
@@ -30,7 +30,6 @@
<dimen name="recents_page_spacing">10dp</dimen>
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
<dimen name="overview_peek_distance">96dp</dimen>
<!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
loading full resolution screenshots. -->
@@ -102,4 +101,26 @@
<dimen name="swipe_edu_circle_size">64dp</dimen>
<dimen name="swipe_edu_width">80dp</dimen>
<dimen name="swipe_edu_max_height">184dp</dimen>
<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_vertical_offset">16dp</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>
<dimen name="all_apps_prediction_row_divider_height">17dp</dimen>
<dimen name="all_apps_label_top_padding">16dp</dimen>
<dimen name="all_apps_label_bottom_padding">8dp</dimen>
<dimen name="all_apps_label_text_size">14sp</dimen>
<!-- Minimum distance to swipe to trigger accessibility gesture -->
<dimen name="accessibility_gesture_min_swipe_distance">80dp</dimen>
</resources>
@@ -32,4 +32,3 @@
<string name="model_delegate_class" translatable="false">com.android.launcher3.model.QuickstepModelDelegate</string>
</resources>
@@ -32,7 +32,7 @@ import android.view.MotionEvent;
import android.view.Surface;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.DisplayController;
import org.junit.Before;
import org.junit.Ignore;
@@ -50,7 +50,7 @@ public class OrientationTouchTransformerTest {
private OrientationTouchTransformer mTouchTransformer;
Resources mResources;
private DefaultDisplay.Info mInfo;
private DisplayController.Info mInfo;
@Before
@@ -231,12 +231,12 @@ public class OrientationTouchTransformerTest {
assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion2.getX(), inRegion2.getY()));
}
private DefaultDisplay.Info createDisplayInfo(int rotation) {
private DisplayController.Info createDisplayInfo(int rotation) {
Point p = new Point(SIZE_WIDTH, SIZE_HEIGHT);
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
p = new Point(SIZE_HEIGHT, SIZE_WIDTH);
}
return new DefaultDisplay.Info(0, rotation, 0, p, p, p, null);
return new DisplayController.Info(0, rotation, 0, p, p, p, null);
}
private float generateTouchRegionHeight(int rotation) {
@@ -60,9 +60,9 @@ public class RecentsActivityTest {
FallbackRecentsView frv = activity.getOverviewPanel();
RunningTaskInfo dummyTask = new RunningTaskInfo();
dummyTask.taskId = 22;
frv.showCurrentTask(dummyTask);
RunningTaskInfo placeholderTask = new RunningTaskInfo();
placeholderTask.taskId = 22;
frv.showCurrentTask(placeholderTask);
doLayout(activity);
ThumbnailData thumbnailData = new ThumbnailData();
@@ -27,7 +27,7 @@ import android.view.SurfaceControl;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.shadows.LShadowDisplay;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.LauncherActivityInterface;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -144,7 +144,7 @@ public class TaskViewSimulatorTest {
LauncherActivityInterface.INSTANCE);
tvs.setDp(mDeviceProfile);
int launcherRotation = DefaultDisplay.INSTANCE.get(mContext).getInfo().rotation;
int launcherRotation = DisplayController.INSTANCE.get(mContext).getInfo().rotation;
if (mAppRotation < 0) {
mAppRotation = launcherRotation;
}
@@ -50,7 +50,6 @@ import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.QuickstepOnboardingPrefs;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -73,8 +72,6 @@ public abstract class BaseQuickstepLauncher extends Launcher
(context, arg1, arg2) -> SystemUiProxy.INSTANCE.get(context).setBackButtonAlpha(
Float.intBitsToFloat(arg1), arg2 != 0);
private final ShelfPeekAnim mShelfPeekAnim = new ShelfPeekAnim(this);
private OverviewActionsView mActionsView;
protected HotseatPredictionController mHotseatPredictionController;
@@ -196,7 +193,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
}
private boolean isOverviewActionsEnabled() {
return FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this);
return removeShelfFromOverview(this);
}
public <T extends OverviewActionsView> T getActionsView() {
@@ -317,10 +314,6 @@ public abstract class BaseQuickstepLauncher extends Launcher
Stream.of(WellbeingModel.SHORTCUT_FACTORY));
}
public ShelfPeekAnim getShelfPeekAnim() {
return mShelfPeekAnim;
}
/**
* Returns Prediction controller for hybrid hotseat
*/
@@ -16,7 +16,7 @@
package com.android.launcher3;
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
import android.animation.Animator;
@@ -45,7 +45,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -55,7 +54,6 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
@@ -94,7 +92,6 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
* home and/or all-apps. Not used for 3p launchers.
*/
@TargetApi(Build.VERSION_CODES.O)
@SuppressWarnings("unused")
public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTransitionManager
implements OnDeviceProfileChangeListener {
@@ -1,4 +1,4 @@
/**
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -42,6 +42,7 @@ import com.android.launcher3.R;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.Themes;
@@ -90,7 +91,8 @@ public class AppsDividerView extends View implements StateListener<LauncherState
mLauncher = Launcher.getLauncher(context);
boolean isMainColorDark = Themes.getAttrBoolean(context, R.attr.isMainColorDark);
mPaint.setStrokeWidth(getResources().getDimensionPixelSize(R.dimen.all_apps_divider_height));
mPaint.setStrokeWidth(
getResources().getDimensionPixelSize(R.dimen.all_apps_divider_height));
mStrokeColor = ContextCompat.getColor(context, isMainColorDark
? R.color.all_apps_prediction_row_separator_dark
@@ -134,7 +136,7 @@ public class AppsDividerView extends View implements StateListener<LauncherState
if (row == this) {
break;
} else if (row.shouldDraw()) {
sectionCount ++;
sectionCount++;
}
}
@@ -181,6 +183,11 @@ public class AppsDividerView extends View implements StateListener<LauncherState
}
private void updateViewVisibility() {
// hide divider since we have item decoration for prediction row
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
setVisibility(GONE);
return;
}
setVisibility(mDividerType == DividerType.NONE
? GONE
: (mIsScrolledOut ? INVISIBLE : VISIBLE));
@@ -303,4 +310,9 @@ public class AppsDividerView extends View implements StateListener<LauncherState
public Class<AppsDividerView> getTypeClass() {
return AppsDividerView.class;
}
@Override
public View getFocusedChild() {
return null;
}
}
@@ -45,10 +45,12 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsSectionDecorator;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusIndicatorHelper;
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
@@ -110,6 +112,8 @@ public class PredictionRowView extends LinearLayout implements
private boolean mPredictionsEnabled = false;
AllAppsSectionDecorator.SectionDecorationHandler mDecorationHandler;
public PredictionRowView(@NonNull Context context) {
this(context, null);
}
@@ -128,6 +132,11 @@ public class PredictionRowView extends LinearLayout implements
mIconFullTextAlpha = Color.alpha(mIconTextColor);
mIconCurrentTextAlpha = mIconFullTextAlpha;
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
mDecorationHandler = new AllAppsSectionDecorator.SectionDecorationHandler(getContext(),
false);
}
updateVisibility();
}
@@ -153,6 +162,15 @@ public class PredictionRowView extends LinearLayout implements
@Override
protected void dispatchDraw(Canvas canvas) {
if (mDecorationHandler != null) {
mDecorationHandler.reset();
int childrenCount = getChildCount();
for (int i = 0; i < childrenCount; i++) {
mDecorationHandler.extendBounds(getChildAt(i));
}
mDecorationHandler.onDraw(canvas);
mDecorationHandler.onFocusDraw(canvas, getFocusedChild());
}
mFocusHelper.draw(canvas);
super.dispatchDraw(canvas);
}
@@ -166,7 +184,7 @@ public class PredictionRowView extends LinearLayout implements
@Override
public boolean shouldDraw() {
return getVisibility() != GONE;
return getVisibility() == VISIBLE;
}
@Override
@@ -347,4 +365,9 @@ public class PredictionRowView extends LinearLayout implements
public Class<PredictionRowView> getTypeClass() {
return PredictionRowView.class;
}
@Override
public View getFocusedChild() {
return getChildAt(0);
}
}
@@ -284,4 +284,3 @@ public class HotseatEduController {
return new Intent(SETTINGS_ACTION).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}
@@ -21,6 +21,7 @@ import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKE
import android.app.prediction.AppTarget;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
@@ -29,6 +30,7 @@ import android.os.UserHandle;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -43,27 +45,22 @@ import java.util.stream.Collectors;
public class PredictionUpdateTask extends BaseModelUpdateTask {
private final List<AppTarget> mTargets;
private final int mContainerId;
private final PredictorState mPredictorState;
PredictionUpdateTask(int containerId, List<AppTarget> targets) {
mContainerId = containerId;
PredictionUpdateTask(PredictorState predictorState, List<AppTarget> targets) {
mPredictorState = predictorState;
mTargets = targets;
}
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
// TODO: persist the whole list
Utilities.getDevicePrefs(app.getContext()).edit()
Context context = app.getContext();
// TODO: remove this
Utilities.getDevicePrefs(context).edit()
.putBoolean(LAST_PREDICTION_ENABLED_STATE, !mTargets.isEmpty()).apply();
FixedContainerItems fci;
synchronized (dataModel) {
fci = dataModel.extraItems.get(mContainerId);
if (fci == null) {
return;
}
}
FixedContainerItems fci = mPredictorState.items;
Set<UserHandle> usersForChangedShortcuts = new HashSet<>(fci.items.stream()
.filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT)
.map(info -> info.user)
@@ -75,7 +72,7 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
ShortcutInfo si = target.getShortcutInfo();
if (si != null) {
usersForChangedShortcuts.add(si.getUserHandle());
itemInfo = new WorkspaceItemInfo(si, app.getContext());
itemInfo = new WorkspaceItemInfo(si, context);
app.getIconCache().getShortcutIcon(itemInfo, si);
} else {
String className = target.getClassName();
@@ -87,16 +84,18 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
UserHandle user = target.getUser();
itemInfo = apps.data.stream()
.filter(info -> user.equals(info.user) && cn.equals(info.componentName))
.map(AppInfo::makeWorkspaceItem)
.map(ai -> {
app.getIconCache().getTitleAndIcon(ai, false);
return ai.makeWorkspaceItem();
})
.findAny()
.orElseGet(() -> {
LauncherActivityInfo lai = app.getContext()
.getSystemService(LauncherApps.class)
LauncherActivityInfo lai = context.getSystemService(LauncherApps.class)
.resolveActivity(AppInfo.makeLaunchIntent(cn), user);
if (lai == null) {
return null;
}
AppInfo ai = new AppInfo(app.getContext(), lai, user);
AppInfo ai = new AppInfo(context, lai, user);
app.getIconCache().getTitleAndIcon(ai, lai, false);
return ai.makeWorkspaceItem();
});
@@ -106,12 +105,15 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
}
}
itemInfo.container = mContainerId;
itemInfo.container = fci.containerId;
fci.items.add(itemInfo);
}
bindExtraContainerItems(fci);
usersForChangedShortcuts.forEach(
u -> dataModel.updateShortcutPinnedState(app.getContext(), u));
// Save to disk
mPredictorState.storage.write(context, fci.items);
}
}
@@ -0,0 +1,273 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.model;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.PersistedItemArray;
import com.android.quickstep.logging.StatsLogCompatManager;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.IntStream;
/**
* Model delegate which loads prediction items
*/
public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChangeListener {
public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
private final PredictorState mAllAppsState =
new PredictorState(CONTAINER_PREDICTION, "all_apps_predictions");
private final InvariantDeviceProfile mIDP;
private final AppEventProducer mAppEventProducer;
private boolean mActive = false;
public QuickstepModelDelegate(Context context) {
mAppEventProducer = new AppEventProducer(context, this::onAppTargetEvent);
mIDP = InvariantDeviceProfile.INSTANCE.get(context);
mIDP.addOnChangeListener(this);
StatsLogCompatManager.LOGS_CONSUMER.add(mAppEventProducer);
}
@Override
public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
// TODO: Implement caching and preloading
super.loadItems(ums, pinnedShortcuts);
WorkspaceItemFactory factory =
new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, mIDP.numAllAppsColumns);
mAllAppsState.items.setItems(
mAllAppsState.storage.read(mApp.getContext(), factory, ums.allUsers::get));
mDataModel.extraItems.put(CONTAINER_PREDICTION, mAllAppsState.items);
mActive = true;
recreatePredictors();
}
@Override
public void validateData() {
super.validateData();
if (mAllAppsState.predictor != null) {
mAllAppsState.predictor.requestPredictionUpdate();
}
}
@Override
public void destroy() {
super.destroy();
mActive = false;
StatsLogCompatManager.LOGS_CONSUMER.remove(mAppEventProducer);
destroyPredictors();
mIDP.removeOnChangeListener(this);
}
private void destroyPredictors() {
mAllAppsState.destroyPredictor();
}
@WorkerThread
private void recreatePredictors() {
destroyPredictors();
if (!mActive) {
return;
}
Context context = mApp.getContext();
AppPredictionManager apm = context.getSystemService(AppPredictionManager.class);
if (apm == null) {
return;
}
int count = mIDP.numAllAppsColumns;
mAllAppsState.predictor = apm.createAppPredictionSession(
new AppPredictionContext.Builder(context)
.setUiSurface("home")
.setPredictedTargetCount(count)
.build());
mAllAppsState.predictor.registerPredictionUpdates(
Executors.MODEL_EXECUTOR, t -> handleUpdate(mAllAppsState, t));
mAllAppsState.predictor.requestPredictionUpdate();
}
private void handleUpdate(PredictorState state, List<AppTarget> targets) {
if (state.setTargets(targets)) {
// No diff, skip
return;
}
mApp.getModel().enqueueModelUpdateTask(new PredictionUpdateTask(state, targets));
}
@Override
public void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
if ((changeFlags & CHANGE_FLAG_GRID) != 0) {
// Reinitialize everything
Executors.MODEL_EXECUTOR.execute(this::recreatePredictors);
}
}
private void onAppTargetEvent(AppTargetEvent event) {
if (mAllAppsState.predictor != null) {
mAllAppsState.predictor.notifyAppTargetEvent(event);
}
}
static class PredictorState {
public final FixedContainerItems items;
public final PersistedItemArray storage;
public AppPredictor predictor;
private List<AppTarget> mLastTargets;
PredictorState(int container, String storageName) {
items = new FixedContainerItems(container);
storage = new PersistedItemArray(storageName);
mLastTargets = Collections.emptyList();
}
public void destroyPredictor() {
if (predictor != null) {
predictor.destroy();
predictor = null;
}
}
/**
* Sets the new targets and returns true if it was different than before.
*/
boolean setTargets(List<AppTarget> newTargets) {
List<AppTarget> oldTargets = mLastTargets;
mLastTargets = newTargets;
int size = oldTargets.size();
return size == newTargets.size() && IntStream.range(0, size)
.allMatch(i -> areAppTargetsSame(oldTargets.get(i), newTargets.get(i)));
}
}
/**
* Compares two targets for the properties which we care about
*/
private static boolean areAppTargetsSame(AppTarget t1, AppTarget t2) {
if (!Objects.equals(t1.getPackageName(), t2.getPackageName())
|| !Objects.equals(t1.getUser(), t2.getUser())
|| !Objects.equals(t1.getClassName(), t2.getClassName())) {
return false;
}
ShortcutInfo s1 = t1.getShortcutInfo();
ShortcutInfo s2 = t2.getShortcutInfo();
if (s1 != null) {
if (s2 == null || !Objects.equals(s1.getId(), s2.getId())) {
return false;
}
} else if (s2 != null) {
return false;
}
return true;
}
private static class WorkspaceItemFactory implements PersistedItemArray.ItemFactory {
private final LauncherAppState mAppState;
private final UserManagerState mUMS;
private final Map<ShortcutKey, ShortcutInfo> mPinnedShortcuts;
private final int mMaxCount;
private int mReadCount = 0;
protected WorkspaceItemFactory(LauncherAppState appState, UserManagerState ums,
Map<ShortcutKey, ShortcutInfo> pinnedShortcuts, int maxCount) {
mAppState = appState;
mUMS = ums;
mPinnedShortcuts = pinnedShortcuts;
mMaxCount = maxCount;
}
@Nullable
@Override
public ItemInfo createInfo(int itemType, UserHandle user, Intent intent) {
if (mReadCount >= mMaxCount) {
return null;
}
switch (itemType) {
case ITEM_TYPE_APPLICATION: {
LauncherActivityInfo lai = mAppState.getContext()
.getSystemService(LauncherApps.class)
.resolveActivity(intent, user);
if (lai == null) {
return null;
}
AppInfo info = new AppInfo(lai, user, mUMS.isUserQuiet(user));
mAppState.getIconCache().getTitleAndIcon(info, lai, false);
mReadCount++;
return info.makeWorkspaceItem();
}
case ITEM_TYPE_DEEP_SHORTCUT: {
ShortcutKey key = ShortcutKey.fromIntent(intent, user);
if (key == null) {
return null;
}
ShortcutInfo si = mPinnedShortcuts.get(key);
if (si == null) {
return null;
}
WorkspaceItemInfo wii = new WorkspaceItemInfo(si, mAppState.getContext());
mAppState.getIconCache().getShortcutIcon(wii, si);
mReadCount++;
return wii;
}
}
return null;
}
}
}
@@ -24,11 +24,13 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MO
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.util.FloatProperty;
@@ -63,6 +65,7 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher);
RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]);
ADJACENT_PAGE_OFFSET.set(mRecentsView, scaleAndOffset[1]);
TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f);
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
@@ -97,6 +100,8 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
setter.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1],
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
@@ -30,6 +30,7 @@ import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.content.Intent;
import android.content.res.Configuration;
@@ -59,7 +60,6 @@ import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.NoButtonNavbarToOverviewTouchController;
@@ -79,6 +79,7 @@ import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -170,6 +171,13 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
}
}
@Override
protected void showAllAppsFromIntent(boolean alreadyOnHome) {
ActivityManagerWrapper.getInstance().closeSystemWindows(
CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
super.showAllAppsFromIntent(alreadyOnHome);
}
@Override
public void folderCreatedFromItem(Folder folder, WorkspaceItemInfo itemInfo) {
super.folderCreatedFromItem(folder, itemInfo);
@@ -298,14 +306,7 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.2");
}
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.3");
}
list.add(new NoButtonNavbarToOverviewTouchController(this));
} else {
list.add(new FlingAndHoldTouchController(this));
}
list.add(new NoButtonNavbarToOverviewTouchController(this));
} else {
if (getDeviceProfile().isVerticalBarLayout()) {
list.add(new OverviewToAllAppsTouchController(this));
@@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
@@ -57,7 +58,7 @@ public final class RecentsViewStateController extends
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
}
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state);
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig(), state);
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
}
@@ -75,17 +76,19 @@ public final class RecentsViewStateController extends
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
}
setAlphas(builder, toState);
setAlphas(builder, config, toState);
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
toState.getOverviewFullscreenProgress(), LINEAR);
}
private void setAlphas(PropertySetter propertySetter, LauncherState state) {
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
LauncherState state) {
float buttonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
buttonAlpha, LINEAR);
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
MultiValueAlpha.VALUE, buttonAlpha, LINEAR);
MultiValueAlpha.VALUE, buttonAlpha, config.getInterpolator(
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
}
@Override
@@ -16,8 +16,7 @@
package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.Context;
@@ -25,7 +24,6 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
/**
* Definition for AllApps state
@@ -65,13 +63,7 @@ public class AllAppsState extends LauncherState {
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW
.getWorkspaceScaleAndTranslation(launcher);
if (SysUINavigationMode.getMode(launcher) == NO_BUTTON && !ENABLE_OVERVIEW_ACTIONS.get()) {
float normalScale = 1;
// Scale down halfway to where we'd be in overview, to prepare for a potential pause.
scaleAndTranslation.scale = (scaleAndTranslation.scale + normalScale) / 2;
} else {
scaleAndTranslation.scale = 1;
}
scaleAndTranslation.scale = 1;
return scaleAndTranslation;
}
@@ -92,7 +84,8 @@ public class AllAppsState extends LauncherState {
@Override
public float[] getOverviewScaleAndOffset(Launcher launcher) {
return new float[] {0.9f, 0};
float offset = removeShelfFromOverview(launcher) ? 1 : 0;
return new float[] {0.9f, offset};
}
@Override
@@ -16,7 +16,6 @@
package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
@@ -65,7 +64,7 @@ public class OverviewState extends LauncherState {
public int getTransitionDuration(Context context) {
// In no-button mode, overview comes in all the way from the left, so give it more time.
boolean isNoButtonMode = SysUINavigationMode.INSTANCE.get(context).getMode() == NO_BUTTON;
return isNoButtonMode && ENABLE_OVERVIEW_ACTIONS.get() ? 380 : 250;
return isNoButtonMode ? 380 : 250;
}
@Override
@@ -108,8 +107,7 @@ public class OverviewState extends LauncherState {
@Override
public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) {
if (this == OVERVIEW && ENABLE_OVERVIEW_ACTIONS.get()
&& removeShelfFromOverview(launcher)) {
if (this == OVERVIEW && removeShelfFromOverview(launcher)) {
// Treat the QSB as part of the hotseat so they move together.
return getHotseatScaleAndTranslation(launcher);
}
@@ -129,7 +127,7 @@ public class OverviewState extends LauncherState {
@Override
public int getVisibleElements(Launcher launcher) {
RecentsView recentsView = launcher.getOverviewPanel();
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher) ||
if (removeShelfFromOverview(launcher) ||
hideShelfInTwoButtonLandscape(launcher, recentsView.getPagedOrientationHandler())) {
return OVERVIEW_BUTTONS;
} else if (launcher.getDeviceProfile().isVerticalBarLayout()) {
@@ -191,10 +189,6 @@ public class OverviewState extends LauncherState {
return new BackgroundAppState(id);
}
public static OverviewState newPeekState(int id) {
return new OverviewPeekState(id);
}
public static OverviewState newSwitchState(int id) {
return new QuickSwitchState(id);
}
@@ -22,27 +22,24 @@ import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
@@ -163,10 +160,15 @@ public class QuickstepAtomicAnimationFactory extends
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
config.setInterpolator(ANIM_ALL_APPS_FADE, ACCEL);
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
Workspace workspace = mActivity.getWorkspace();
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
} else {
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
}
Workspace workspace = mActivity.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
if (isWorkspaceVisible) {
@@ -184,30 +186,23 @@ public class QuickstepAtomicAnimationFactory extends
if (!isHotseatVisible) {
hotseat.setScaleX(0.92f);
hotseat.setScaleY(0.92f);
if (ENABLE_OVERVIEW_ACTIONS.get()) {
AllAppsContainerView qsbContainer = mActivity.getAppsView();
View qsb = qsbContainer.getSearchView();
boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
if (!qsbVisible) {
qsbContainer.setScaleX(0.92f);
qsbContainer.setScaleY(0.92f);
}
AllAppsContainerView qsbContainer = mActivity.getAppsView();
View qsb = qsbContainer.getSearchView();
boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
if (!qsbVisible) {
qsbContainer.setScaleX(0.92f);
qsbContainer.setScaleY(0.92f);
}
}
} else if (toState == NORMAL && fromState == OVERVIEW_PEEK) {
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
} else if (toState == OVERVIEW_PEEK && fromState == NORMAL) {
config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
} else if ((fromState == NORMAL || fromState == HINT_STATE) && toState == OVERVIEW) {
if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
config.setInterpolator(ANIM_WORKSPACE_SCALE,
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
} else {
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
// Scale up the recents, if it is not coming from the side
RecentsView overview = mActivity.getOverviewPanel();
@@ -219,13 +214,11 @@ public class QuickstepAtomicAnimationFactory extends
config.setInterpolator(ANIM_ALL_APPS_FADE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_DEPTH, OVERSHOOT_1_2);
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
&& removeShelfFromOverview(mActivity)
Interpolator translationInterpolator = removeShelfFromOverview(mActivity)
? OVERSHOOT_1_2
: OVERSHOOT_1_7;
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
} else if (fromState == HINT_STATE && toState == NORMAL) {
config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
if (mHintToNormalDuration == -1) {
@@ -19,13 +19,13 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_APPS_EDU;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.ValueAnimator;
@@ -45,6 +45,7 @@ import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.OverviewScrim;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.testing.TestProtocol;
@@ -52,7 +53,9 @@ import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -63,6 +66,8 @@ public class NavBarToHomeTouchController implements TouchController,
SingleAxisSwipeDetector.Listener {
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
// How much of the overview scrim we can remove during the transition.
private static final float OVERVIEW_TO_HOME_SCRIM_PROGRESS = 0.5f;
private final Launcher mLauncher;
private final SingleAxisSwipeDetector mSwipeDetector;
@@ -156,8 +161,13 @@ public class NavBarToHomeTouchController implements TouchController,
final PendingAnimation builder = new PendingAnimation(accuracy);
if (mStartState.overviewUi) {
RecentsView recentsView = mLauncher.getOverviewPanel();
builder.setFloat(recentsView, ADJACENT_PAGE_OFFSET,
-mPullbackDistance / recentsView.getPageOffsetScale(), PULLBACK_INTERPOLATOR);
AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
builder);
float endScrimAlpha = Utilities.mapRange(OVERVIEW_TO_HOME_SCRIM_PROGRESS,
mStartState.getOverviewScrimAlpha(mLauncher),
mEndState.getOverviewScrimAlpha(mLauncher));
builder.setFloat(mLauncher.getDragLayer().getOverviewScrim(),
OverviewScrim.SCRIM_PROGRESS, endScrimAlpha, PULLBACK_INTERPOLATOR);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
builder.addOnFrameCallback(recentsView::redrawLiveTile);
}
@@ -211,8 +221,13 @@ public class NavBarToHomeTouchController implements TouchController,
recentsView.switchToScreenshot(null,
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
}
mLauncher.getStateManager().goToState(mEndState, true,
() -> onSwipeInteractionCompleted(mEndState));
if (mStartState == OVERVIEW) {
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState))
.animateWithVelocity(velocity);
} else {
mLauncher.getStateManager().goToState(mEndState, true,
() -> onSwipeInteractionCompleted(mEndState));
}
if (mStartState != mEndState) {
logStateChange(mStartState.containerType, logAction);
}
@@ -16,33 +16,45 @@
package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.PointF;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.OverviewScrim;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
/**
@@ -50,7 +62,7 @@ import com.android.quickstep.views.RecentsView;
* the nav bar falls back to go to All Apps. Swiping from the nav bar without holding goes to the
* first home screen instead of to Overview.
*/
public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchController {
public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouchController {
// How much of the movement to use for translating overview after swipe and hold.
@@ -59,32 +71,29 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
private static final float TRANSLATION_ANIM_VELOCITY_DP_PER_MS = 0.8f;
private final RecentsView mRecentsView;
private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
private boolean mDidTouchStartInNavBar;
private boolean mReachedOverview;
private boolean mIsOverviewRehidden;
private boolean mIsHomeStaggeredAnimFinished;
// The last recorded displacement before we reached overview.
private PointF mStartDisplacement = new PointF();
private float mStartY;
private AnimatorPlaybackController mOverviewResistYAnim;
// Normal to Hint animation has flag SKIP_OVERVIEW, so we update this scrim with this animator.
private ObjectAnimator mNormalToHintOverviewScrimAnimator;
public NoButtonNavbarToOverviewTouchController(Launcher l) {
super(l);
super(l, false /* allowDragToOverview */);
mRecentsView = l.getOverviewPanel();
mMotionPauseDetector = new MotionPauseDetector(l);
mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NoButtonNavbarToOverviewTouchController.ctor");
}
}
@Override
protected float getMotionPauseMaxDisplacement() {
// No need to disallow pause when swiping up all the way up the screen (unlike
// FlingAndHoldTouchController where user is probably intending to go to all apps).
return Float.MAX_VALUE;
}
@Override
protected boolean canInterceptTouch(MotionEvent ev) {
mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
@@ -115,6 +124,13 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
@Override
public void onDragStart(boolean start, float startDisplacement) {
super.onDragStart(start, startDisplacement);
mMotionPauseDetector.clear();
if (handlingOverviewAnim()) {
mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
}
if (mFromState == NORMAL && mToState == HINT_STATE) {
mNormalToHintOverviewScrimAnimator = ObjectAnimator.ofFloat(
mLauncher.getDragLayer().getOverviewScrim(),
@@ -123,6 +139,7 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
mToState.getOverviewScrimAlpha(mLauncher));
}
mReachedOverview = false;
mOverviewResistYAnim = null;
}
@Override
@@ -135,8 +152,24 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
@Override
public void onDragEnd(float velocity) {
super.onDragEnd(velocity);
if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
goToOverviewOrHomeOnDragEnd(velocity);
} else {
super.onDragEnd(velocity);
}
View searchView = mLauncher.getAppsView().getSearchView();
if (searchView instanceof FeedbackHandler) {
((FeedbackHandler) searchView).resetFeedback();
}
mMotionPauseDetector.clear();
mNormalToHintOverviewScrimAnimator = null;
if (mLauncher.isInState(OVERVIEW)) {
// Normally we would cleanup the state based on mCurrentAnimation, but since we stop
// using that when we pause to go to Overview, we need to clean up ourselves.
clearState();
}
}
@Override
@@ -152,14 +185,16 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
}
}
@Override
protected void onMotionPauseChanged(boolean isPaused) {
private void onMotionPauseChanged(boolean isPaused) {
if (mCurrentAnimation == null) {
return;
}
mNormalToHintOverviewScrimAnimator = null;
mCurrentAnimation.dispatchOnCancelWithoutCancelRunnable(() -> {
mLauncher.getStateManager().goToState(OVERVIEW, true, () -> {
mOverviewResistYAnim = AnimatorControllerWithResistance
.createRecentsResistanceFromOverviewAnim(mLauncher, null)
.createPlaybackController();
mReachedOverview = true;
maybeSwipeInteractionToOverviewComplete();
});
@@ -173,16 +208,10 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
}
}
// Used if flinging back to home after reaching overview
private void maybeSwipeInteractionToHomeComplete() {
if (mIsHomeStaggeredAnimFinished && mIsOverviewRehidden) {
onSwipeInteractionCompleted(NORMAL, Touch.FLING);
}
}
@Override
protected boolean handlingOverviewAnim() {
return mDidTouchStartInNavBar && super.handlingOverviewAnim();
private boolean handlingOverviewAnim() {
int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
return mDidTouchStartInNavBar && mStartState == NORMAL
&& (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
}
@Override
@@ -193,54 +222,37 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
if (mMotionPauseDetector.isPaused()) {
if (!mReachedOverview) {
mStartDisplacement.set(xDisplacement, yDisplacement);
mStartY = event.getY();
} else {
mRecentsView.setTranslationX((xDisplacement - mStartDisplacement.x)
* OVERVIEW_MOVEMENT_FACTOR);
mRecentsView.setTranslationY((yDisplacement - mStartDisplacement.y)
* OVERVIEW_MOVEMENT_FACTOR);
float yProgress = (mStartDisplacement.y - yDisplacement) / mStartY;
if (yProgress > 0 && mOverviewResistYAnim != null) {
mOverviewResistYAnim.setPlayFraction(yProgress);
} else {
mRecentsView.setTranslationY((yDisplacement - mStartDisplacement.y)
* OVERVIEW_MOVEMENT_FACTOR);
}
}
// Stay in Overview.
return true;
}
float upDisplacement = -yDisplacement;
mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
|| upDisplacement < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(event);
return super.onDrag(yDisplacement, xDisplacement, event);
}
@Override
protected void goToOverviewOnDragEnd(float velocity) {
private void goToOverviewOrHomeOnDragEnd(float velocity) {
float velocityDp = dpiFromPx(velocity);
boolean isFling = Math.abs(velocityDp) > 1;
StateManager<LauncherState> stateManager = mLauncher.getStateManager();
boolean goToHomeInsteadOfOverview = isFling;
if (goToHomeInsteadOfOverview) {
if (velocity > 0) {
stateManager.goToState(NORMAL, true,
() -> onSwipeInteractionCompleted(NORMAL, Touch.FLING));
} else {
mIsHomeStaggeredAnimFinished = mIsOverviewRehidden = false;
StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim(
mLauncher, velocity, false /* animateOverviewScrim */);
staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
mIsHomeStaggeredAnimFinished = true;
maybeSwipeInteractionToHomeComplete();
}
}).start();
// StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
stateManager.cancelAnimation();
StateAnimationConfig config = new StateAnimationConfig();
config.duration = OVERVIEW.getTransitionDuration(mLauncher);
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
AnimatorSet anim = stateManager.createAtomicAnimation(
stateManager.getState(), NORMAL, config);
anim.addListener(AnimationSuccessListener.forRunnable(() -> {
mIsOverviewRehidden = true;
maybeSwipeInteractionToHomeComplete();
}));
anim.start();
}
new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
.animateWithVelocity(velocity);
}
if (mReachedOverview) {
float distanceDp = dpiFromPx(Math.max(
@@ -256,10 +268,67 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
.withEndAction(goToHomeInsteadOfOverview
? null
: this::maybeSwipeInteractionToOverviewComplete);
if (!goToHomeInsteadOfOverview) {
// Return to normal properties for the overview state.
StateAnimationConfig config = new StateAnimationConfig();
config.duration = duration;
LauncherState state = mLauncher.getStateManager().getState();
mLauncher.getStateManager().createAtomicAnimation(state, state, config).start();
}
}
}
private float dpiFromPx(float pixels) {
return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics());
}
@Override
protected StateAnimationConfig getConfigForStates(
LauncherState fromState, LauncherState toState) {
if (fromState == NORMAL && toState == ALL_APPS) {
StateAnimationConfig builder = new StateAnimationConfig();
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
- OVERVIEW.getVerticalProgress(mLauncher);
builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
ACCEL,
0,
ALL_APPS_CONTENT_FADE_THRESHOLD));
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
ACCEL,
progressToReachOverview,
progressToReachOverview + ALL_APPS_CONTENT_FADE_THRESHOLD));
// Get workspace out of the way quickly, to prepare for potential pause.
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
return builder;
} else if (fromState == ALL_APPS && toState == NORMAL) {
StateAnimationConfig builder = new StateAnimationConfig();
// Keep all apps/predictions opaque until the very end of the transition.
float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
DEACCEL,
progressToReachOverview - ALL_APPS_CONTENT_FADE_THRESHOLD,
progressToReachOverview));
builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
DEACCEL,
1 - ALL_APPS_CONTENT_FADE_THRESHOLD,
1));
return builder;
}
return super.getConfigForStates(fromState, toState);
}
/**
* Interface for views with feedback animation requiring reset
*/
public interface FeedbackHandler {
/**
* reset searchWidget feedback
*/
void resetFeedback();
}
}
@@ -15,18 +15,15 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
@@ -39,14 +36,12 @@ import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
@@ -60,10 +55,8 @@ import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.OverviewScrim;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
@@ -74,11 +67,11 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.LauncherRecentsView;
@@ -90,16 +83,16 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
BothAxesSwipeDetector.Listener, MotionPauseDetector.OnMotionPauseListener {
/** The minimum progress of the scale/translationY animation until drag end. */
private static final float Y_ANIM_MIN_PROGRESS = 0.15f;
private static final float Y_ANIM_MIN_PROGRESS = 0.25f;
private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_5;
private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75;
private static final Interpolator SCALE_DOWN_INTERPOLATOR = DEACCEL;
private static final Interpolator SCALE_DOWN_INTERPOLATOR = LINEAR;
private final BaseQuickstepLauncher mLauncher;
private final BothAxesSwipeDetector mSwipeDetector;
private final ShelfPeekAnim mShelfPeekAnim;
private final float mXRange;
private final float mYRange;
private final float mMaxYProgress;
private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
private final LauncherRecentsView mRecentsView;
@@ -113,16 +106,16 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
// and the other two to set overview properties based on x and y progress.
private AnimatorPlaybackController mNonOverviewAnim;
private AnimatorPlaybackController mXOverviewAnim;
private AnimatorPlaybackController mYOverviewAnim;
private AnimatedFloat mYOverviewAnim;
public NoButtonQuickSwitchTouchController(BaseQuickstepLauncher launcher) {
mLauncher = launcher;
mSwipeDetector = new BothAxesSwipeDetector(mLauncher, this);
mShelfPeekAnim = mLauncher.getShelfPeekAnim();
mRecentsView = mLauncher.getOverviewPanel();
mXRange = mLauncher.getDeviceProfile().widthPx / 2f;
mYRange = LayoutUtils.getShelfTrackingDistance(
mLauncher, mLauncher.getDeviceProfile(), mRecentsView.getPagedOrientationHandler());
mMaxYProgress = mLauncher.getDeviceProfile().heightPx / mYRange;
mMotionPauseDetector = new MotionPauseDetector(mLauncher);
mMotionPauseMinDisplacement = mLauncher.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
@@ -187,25 +180,6 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
@Override
public void onMotionPauseChanged(boolean isPaused) {
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
return;
}
ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
if (shelfState == PEEK) {
// Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
allAppsController.setAlphas(
NORMAL, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
// Hotseat was hidden, but we need it visible when peeking.
mLauncher.getHotseat().setAlpha(1);
}
}
mShelfPeekAnim.setShelfState(shelfState, ShelfPeekAnim.INTERPOLATOR,
ShelfPeekAnim.DURATION);
}
private void setupAnimators() {
@@ -270,8 +244,18 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
SCALE_DOWN_INTERPOLATOR);
yAnim.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
toState.getOverviewFullscreenProgress(), SCALE_DOWN_INTERPOLATOR);
mYOverviewAnim = yAnim.createPlaybackController();
mYOverviewAnim.dispatchOnStart();
AnimatorPlaybackController yNormalController = yAnim.createPlaybackController();
AnimatorControllerWithResistance yAnimWithResistance = AnimatorControllerWithResistance
.createForRecents(yNormalController, mLauncher,
mRecentsView.getPagedViewOrientedState(), mLauncher.getDeviceProfile(),
mRecentsView, RECENTS_SCALE_PROPERTY, mRecentsView,
TASK_SECONDARY_TRANSLATION);
mYOverviewAnim = new AnimatedFloat(() -> {
if (mYOverviewAnim != null) {
yAnimWithResistance.setProgress(mYOverviewAnim.value, mMaxYProgress);
}
});
yNormalController.dispatchOnStart();
}
@Override
@@ -287,10 +271,6 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
mIsHomeScreenVisible = FADE_OUT_INTERPOLATOR.getInterpolation(xProgress)
<= 1 - ALPHA_CUTOFF_THRESHOLD;
if (wasHomeScreenVisible && !mIsHomeScreenVisible) {
// Get the shelf all the way offscreen so it pops up when we decide to peek it.
mShelfPeekAnim.setShelfState(HIDE, LINEAR, 0);
}
// Only allow motion pause if the home screen is invisible, since some
// home screen elements will appear in the shelf on motion pause.
@@ -298,16 +278,11 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|| -displacement.y < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(ev);
if (mIsHomeScreenVisible) {
// Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
mShelfPeekAnim.setShelfState(CANCEL, LINEAR, 0);
}
if (mXOverviewAnim != null) {
mXOverviewAnim.setPlayFraction(xProgress);
}
if (mYOverviewAnim != null) {
mYOverviewAnim.setPlayFraction(yProgress);
mYOverviewAnim.updateValue(yProgress);
}
return true;
}
@@ -354,9 +329,11 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
} else if (verticalFling) {
targetState = velocity.y > 0 ? QUICK_SWITCH : NORMAL;
} else {
// If user isn't flinging, just snap to the closest state based on x progress.
// If user isn't flinging, just snap to the closest state.
boolean passedHorizontalThreshold = mXOverviewAnim.getInterpolatedProgress() > 0.5f;
targetState = passedHorizontalThreshold ? QUICK_SWITCH : NORMAL;
boolean passedVerticalThreshold = mYOverviewAnim.value > 1f;
targetState = passedHorizontalThreshold && !passedVerticalThreshold
? QUICK_SWITCH : NORMAL;
}
// Animate the various components to the target state.
@@ -375,9 +352,9 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
boolean flingUpToNormal = verticalFling && velocity.y < 0 && targetState == NORMAL;
float yProgress = mYOverviewAnim.getProgressFraction();
float yProgress = mYOverviewAnim.value;
float startYProgress = Utilities.boundToRange(yProgress
- velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, 1f);
- velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, mMaxYProgress);
final float endYProgress;
if (flingUpToNormal) {
endYProgress = 1;
@@ -387,12 +364,11 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
} else {
endYProgress = 0;
}
long yDuration = BaseSwipeDetector.calculateDuration(velocity.y,
Math.abs(endYProgress - startYProgress));
ValueAnimator yOverviewAnim = mYOverviewAnim.getAnimationPlayer();
yOverviewAnim.setFloatValues(startYProgress, endYProgress);
float yDistanceToCover = Math.abs(endYProgress - startYProgress) * mYRange;
long yDuration = (long) (yDistanceToCover / Math.max(1f, Math.abs(velocity.y)));
ValueAnimator yOverviewAnim = mYOverviewAnim.animateToValue(startYProgress, endYProgress);
yOverviewAnim.setDuration(yDuration);
mYOverviewAnim.dispatchOnStart();
mYOverviewAnim.updateValue(startYProgress);
ValueAnimator nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
if (flingUpToNormal && !mIsHomeScreenVisible) {
@@ -457,9 +433,8 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
mXOverviewAnim.getAnimationPlayer().cancel();
}
if (mYOverviewAnim != null) {
mYOverviewAnim.getAnimationPlayer().cancel();
mYOverviewAnim.cancelAnimation();
}
mShelfPeekAnim.setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
mMotionPauseDetector.clear();
}
@@ -24,7 +24,6 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
@@ -142,6 +141,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
"PortraitStatesTouchController.getTargetState 1");
}
if (removeShelfFromOverview(mLauncher)) {
// Don't allow swiping down to overview.
return NORMAL;
}
return TouchInteractionService.isConnected() ?
mLauncher.getStateManager().getLastState() : NORMAL;
} else if (fromState == OVERVIEW) {
@@ -150,7 +153,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
"PortraitStatesTouchController.getTargetState 2");
}
LauncherState positiveDragTarget = ALL_APPS;
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(mLauncher)) {
if (removeShelfFromOverview(mLauncher)) {
// Don't allow swiping up to all apps.
positiveDragTarget = OVERVIEW;
}
@@ -245,7 +248,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
final StateAnimationConfig config = totalShift == 0 ? new StateAnimationConfig()
: getConfigForStates(mFromState, mToState);
config.animFlags = updateAnimComponentsOnReinit(animFlags);
config.animFlags = animFlags;
config.duration = maxAccuracy;
cancelPendingAnim();
@@ -279,14 +282,6 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
return 1 / totalShift;
}
/**
* Give subclasses the chance to update the animation when we re-initialize towards a new state.
*/
@AnimationFlags
protected int updateAnimComponentsOnReinit(@AnimationFlags int animComponents) {
return animComponents;
}
private void cancelPendingAnim() {
if (mPendingAnimation != null) {
mPendingAnimation.finish(false, Touch.SWIPE);
@@ -24,6 +24,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
@@ -205,14 +206,19 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
long maxDuration = 2 * secondaryLayerDimension;
int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl);
int secondaryTaskDimension = orientationHandler.getSecondaryDimension(mTaskBeingDragged);
// The interpolator controlling the most prominent visual movement. We use this to determine
// whether we passed SUCCESS_TRANSITION_PROGRESS.
final Interpolator currentInterpolator;
if (goingUp) {
currentInterpolator = Interpolators.LINEAR;
mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
true /* animateTaskView */, true /* removeTask */, maxDuration);
mEndDisplacement = -secondaryTaskDimension;
} else {
currentInterpolator = Interpolators.ZOOM_IN;
mPendingAnimation = mRecentsView.createTaskLaunchAnimation(
mTaskBeingDragged, maxDuration, Interpolators.ZOOM_IN);
mTaskBeingDragged, maxDuration, currentInterpolator);
// Since the thumbnail is what is filling the screen, based the end displacement on it.
View thumbnailView = mTaskBeingDragged.getThumbnail();
@@ -227,6 +233,9 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
}
mCurrentAnimation = mPendingAnimation.createPlaybackController()
.setOnCancelRunnable(this::clearState);
// Setting this interpolator doesn't affect the visual motion, but is used to determine
// whether we successfully reached the target state in onDragEnd().
mCurrentAnimation.getTarget().setInterpolator(currentInterpolator);
onUserControlledAnimationCreated(mCurrentAnimation);
mCurrentAnimation.getTarget().addListener(this);
mCurrentAnimation.dispatchOnStart();
@@ -20,17 +20,15 @@ import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_GESTURE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
@@ -42,13 +40,10 @@ import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINI
import static com.android.quickstep.GestureState.STATE_END_TARGET_SET;
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -75,7 +70,6 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
@@ -93,10 +87,9 @@ import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.LiveTileOverlay;
@@ -207,15 +200,14 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsShelfPeeking;
private boolean mIsMotionPaused;
private boolean mContinuingLastGesture;
private ThumbnailData mTaskSnapshot;
// Used to control launcher components throughout the swipe gesture.
private AnimatorPlaybackController mLauncherTransitionController;
private boolean mHasLauncherTransitionControllerStarted;
private AnimatorControllerWithResistance mLauncherTransitionController;
private AnimationFactory mAnimationFactory = (t) -> { };
@@ -494,7 +486,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
* Called when motion pause is detected
*/
public void onMotionPauseChanged(boolean isPaused) {
setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
mIsMotionPaused = isPaused;
maybeUpdateRecentsAttachedState();
performHapticFeedback();
}
public void maybeUpdateRecentsAttachedState() {
@@ -525,9 +519,23 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
// The window is going away so make sure recents is always visible in this case.
recentsAttachedToAppWindow = true;
} else {
recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
recentsAttachedToAppWindow = mIsMotionPaused || mIsLikelyToStartNewTask;
}
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
// Reapply window transform throughout the attach animation, as the animation affects how
// much the window is bound by overscroll (vs moving freely).
if (animate) {
ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1);
reapplyWindowTransformAnim.addUpdateListener(anim -> {
if (mRunningWindowAnim == null) {
applyWindowTransform();
}
});
reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start();
} else {
applyWindowTransform();
}
}
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
@@ -541,19 +549,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
}
}
@UiThread
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
mAnimationFactory.setShelfState(shelfState, interpolator, duration);
boolean wasShelfPeeking = mIsShelfPeeking;
mIsShelfPeeking = shelfState == PEEK;
if (mIsShelfPeeking != wasShelfPeeking) {
maybeUpdateRecentsAttachedState();
}
if (shelfState.shouldPreformHaptic) {
performHapticFeedback();
}
}
private void buildAnimationController() {
if (!canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
@@ -564,11 +559,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
/**
* We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
* (it has its own animation) or if we're already animating the current controller.
* (it has its own animation).
* @return Whether we can create the launcher controller or update its progress.
*/
private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
return mGestureState.getEndTarget() != HOME;
}
@Override
@@ -578,10 +573,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
return result;
}
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
private void onAnimatorPlaybackControllerCreated(AnimatorControllerWithResistance anim) {
mLauncherTransitionController = anim;
mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
mLauncherTransitionController.dispatchOnStart();
mLauncherTransitionController.getNormalController().dispatchOnStart();
updateLauncherTransitionProgress();
}
@@ -621,10 +615,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
|| !canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
}
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
// anyway. The controller mimics the drag length factor by applying it to its interpolators.
float progress = mCurrentShift.value / mDragLengthFactor;
mLauncherTransitionController.setPlayFraction(progress);
mLauncherTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor);
}
/**
@@ -845,7 +836,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
if (isCancel) {
endTarget = LAST_TASK;
} else if (mDeviceState.isFullyGesturalNavMode()) {
if (mIsShelfPeeking) {
if (mIsMotionPaused) {
endTarget = RECENTS;
} else if (goingToNewTask) {
endTarget = NEW_TASK;
@@ -867,7 +858,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
endTarget = HOME;
} else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsShelfPeeking) {
} else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsMotionPaused) {
// If swiping at a diagonal, base end target on the faster velocity.
endTarget = NEW_TASK;
} else if (isSwipeUp) {
@@ -935,7 +926,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
mInputConsumerProxy.enable();
}
if (endTarget == HOME) {
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
} else if (endTarget == RECENTS) {
LiveTileOverlay.INSTANCE.startIconAnimation();
@@ -951,9 +941,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
}
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
if (mDeviceState.isFullyGesturalNavMode()) {
setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
}
}
// Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
@@ -1052,6 +1039,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
}
if (mGestureState.getEndTarget() == HOME) {
mTaskViewSimulator.setDrawsBelowRecents(false);
HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration);
RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
@@ -1112,31 +1100,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
windowAnim.start();
mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
}
// Always play the entire launcher animation when going home, since it is separate from
// the animation that has been controlled thus far.
if (mGestureState.getEndTarget() == HOME) {
start = 0;
}
// We want to use the same interpolator as the window, but need to adjust it to
// interpolate over the remaining progress (end - start).
TimeInterpolator adjustedInterpolator = Interpolators.mapToProgress(
interpolator, start, end);
if (mLauncherTransitionController == null) {
return;
}
if (start == end || duration <= 0) {
mLauncherTransitionController.dispatchSetInterpolator(t -> end);
} else {
mLauncherTransitionController.dispatchSetInterpolator(adjustedInterpolator);
}
mLauncherTransitionController.getAnimationPlayer().setDuration(Math.max(0, duration));
if (UNSTABLE_SPRINGS.get()) {
mLauncherTransitionController.dispatchOnStart();
}
mLauncherTransitionController.getAnimationPlayer().start();
mHasLauncherTransitionControllerStarted = true;
}
private void computeRecentsScrollIfInvisible() {
@@ -1261,10 +1224,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
private void cancelCurrentAnimation() {
mCanceled = true;
mCurrentShift.cancelAnimation();
if (mLauncherTransitionController != null && mLauncherTransitionController
.getAnimationPlayer().isStarted()) {
mLauncherTransitionController.getAnimationPlayer().cancel();
}
}
private void invalidateHandler() {
@@ -1288,9 +1247,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
}
private void endLauncherTransitionController() {
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
if (mLauncherTransitionController != null) {
mLauncherTransitionController.getAnimationPlayer().end();
// End the animation, but stay at the same visual progress.
mLauncherTransitionController.getNormalController().dispatchSetInterpolator(
t -> Utilities.boundToRange(mCurrentShift.value, 0, 1));
mLauncherTransitionController.getNormalController().getAnimationPlayer().end();
mLauncherTransitionController = null;
}
}
@@ -1572,8 +1533,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
*/
protected void applyWindowTransform() {
if (mWindowTransitionController != null) {
float progress = mCurrentShift.value / mDragLengthFactor;
mWindowTransitionController.setPlayFraction(progress);
mWindowTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor);
}
if (mRecentsAnimationTargets != null) {
if (mRecentsViewScrollLinked) {
@@ -79,8 +79,8 @@ final class AppToOverviewAnimationProvider<T extends StatefulActivity<?>> extend
BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI(
mDeviceState,
wasVisible, (controller) -> {
controller.dispatchOnStart();
controller.getAnimationPlayer().end();
controller.getNormalController().dispatchOnStart();
controller.getNormalController().getAnimationPlayer().end();
});
factory.createActivityInterface(RECENTS_LAUNCH_DURATION);
factory.setRecentsAttachedToAppWindow(true, false);
@@ -18,7 +18,6 @@ package com.android.quickstep;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.SysUINavigationMode.getMode;
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
@@ -28,6 +27,7 @@ import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_REC
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.animation.Animator;
import android.annotation.TargetApi;
@@ -36,7 +36,6 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Build;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -52,7 +51,7 @@ import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -106,7 +105,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
public abstract void onAssistantVisibilityChanged(float visibility);
public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorPlaybackController> callback);
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
public abstract ActivityInitListener createActivityInitListener(
Predicate<Boolean> onInitListener);
@@ -297,9 +296,6 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
default void onTransitionCancelled() { }
default void setShelfState(ShelfPeekAnim.ShelfAnimState animState,
Interpolator interpolator, long duration) { }
/**
* @param attached Whether to show RecentsView alongside the app window. If false, recents
* will be hidden by some property we can animate, e.g. alpha.
@@ -312,11 +308,11 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
protected final ACTIVITY_TYPE mActivity;
private final STATE_TYPE mStartState;
private final Consumer<AnimatorPlaybackController> mCallback;
private final Consumer<AnimatorControllerWithResistance> mCallback;
private boolean mIsAttachedToWindow;
DefaultAnimationFactory(Consumer<AnimatorPlaybackController> callback) {
DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
mCallback = callback;
mActivity = getCreatedActivity();
@@ -344,7 +340,14 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
controller.setEndAction(() -> mActivity.getStateManager().goToState(
controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState,
false));
mCallback.accept(controller);
RecentsView recentsView = mActivity.getOverviewPanel();
AnimatorControllerWithResistance controllerWithResistance =
AnimatorControllerWithResistance.createForRecents(controller, mActivity,
recentsView.getPagedViewOrientedState(), mActivity.getDeviceProfile(),
recentsView, RECENTS_SCALE_PROPERTY, recentsView,
TASK_SECONDARY_TRANSLATION);
mCallback.accept(controllerWithResistance);
// Creating the activity controller animation sometimes reapplies the launcher state
// (because we set the animation as the current state animation), so we reapply the
@@ -400,6 +403,6 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
}
protected static boolean showOverviewActions(Context context) {
return ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context);
return removeShelfFromOverview(context);
}
}
@@ -27,11 +27,11 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -84,7 +84,7 @@ public final class FallbackActivityInterface extends
/** 6 */
@Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback);
factory.initUI();
return factory;
@@ -27,7 +27,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.Log;
import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -39,7 +38,6 @@ import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DepthController.ClampedDepthProperty;
@@ -49,8 +47,8 @@ import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.plugins.shared.LauncherOverlayManager;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -118,15 +116,9 @@ public final class LauncherActivityInterface extends
@Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
@Override
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
long duration) {
mActivity.getShelfPeekAnim().setShelfState(shelfState, interpolator, duration);
}
@Override
protected void createBackgroundToOverviewAnim(BaseQuickstepLauncher activity,
PendingAnimation pa) {
@@ -37,7 +37,7 @@ import android.view.Surface;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.DisplayController.Info;
import java.io.PrintWriter;
@@ -85,7 +85,7 @@ class OrientationTouchTransformer {
* QUICKSTEP_ROTATION_UNINITIALIZED, then user has not tapped on an active nav region.
* Otherwise it will be the rotation of the display when the user first interacted with the
* active nav bar region.
* The "session" ends when {@link #enableMultipleRegions(boolean, DefaultDisplay.Info)} is
* The "session" ends when {@link #enableMultipleRegions(boolean, Info)} is
* called - usually from a timeout or if user starts interacting w/ the foreground app.
*
* This is different than {@link #mLastRectTouched} as it can get reset by the system whereas
@@ -108,7 +108,7 @@ class OrientationTouchTransformer {
mNavBarGesturalHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
}
private void refreshTouchRegion(DefaultDisplay.Info info, Resources newRes) {
private void refreshTouchRegion(Info info, Resources newRes) {
// Swipe touch regions are independent of nav mode, so we have to clear them explicitly
// here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
// It tries to cache and reuse swipe regions whenever possible based only on rotation
@@ -117,7 +117,7 @@ class OrientationTouchTransformer {
resetSwipeRegions(info);
}
void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info,
void setNavigationMode(SysUINavigationMode.Mode newMode, Info info,
Resources newRes) {
if (mMode == newMode) {
return;
@@ -126,7 +126,7 @@ class OrientationTouchTransformer {
refreshTouchRegion(info, newRes);
}
void setGesturalHeight(int newGesturalHeight, DefaultDisplay.Info info, Resources newRes) {
void setGesturalHeight(int newGesturalHeight, Info info, Resources newRes) {
if (mNavBarGesturalHeight == newGesturalHeight) {
return;
}
@@ -140,9 +140,9 @@ class OrientationTouchTransformer {
* alongside other regions.
* Ok to call multiple times
*
* @see #enableMultipleRegions(boolean, DefaultDisplay.Info)
* @see #enableMultipleRegions(boolean, Info)
*/
void createOrAddTouchRegion(DefaultDisplay.Info info) {
void createOrAddTouchRegion(Info info) {
mCurrentDisplayRotation = info.rotation;
if (mQuickStepStartingRotation > QUICKSTEP_ROTATION_UNINITIALIZED
&& mCurrentDisplayRotation == mQuickStepStartingRotation) {
@@ -170,7 +170,7 @@ class OrientationTouchTransformer {
* @param enableMultipleRegions Set to true to start tracking multiple nav bar regions
* @param info The current displayInfo which will be the start of the quickswitch gesture
*/
void enableMultipleRegions(boolean enableMultipleRegions, DefaultDisplay.Info info) {
void enableMultipleRegions(boolean enableMultipleRegions, Info info) {
mEnableMultipleRegions = enableMultipleRegions &&
mMode != SysUINavigationMode.Mode.TWO_BUTTONS;
if (mEnableMultipleRegions) {
@@ -191,7 +191,7 @@ class OrientationTouchTransformer {
*
* @param displayInfo The display whos rotation will be used as the current active rotation
*/
void setSingleActiveRegion(DefaultDisplay.Info displayInfo) {
void setSingleActiveRegion(Info displayInfo) {
mActiveTouchRotation = displayInfo.rotation;
resetSwipeRegions(displayInfo);
}
@@ -202,7 +202,7 @@ class OrientationTouchTransformer {
* To be called whenever we want to stop tracking more than one swipe region.
* Ok to call multiple times.
*/
private void resetSwipeRegions(DefaultDisplay.Info region) {
private void resetSwipeRegions(Info region) {
if (DEBUG) {
Log.d(TAG, "clearing all regions except rotation: " + mCurrentDisplayRotation);
}
@@ -226,7 +226,7 @@ class OrientationTouchTransformer {
}
}
private OrientationRectF createRegionForDisplay(DefaultDisplay.Info display) {
private OrientationRectF createRegionForDisplay(Info display) {
if (DEBUG) {
Log.d(TAG, "creating rotation region for: " + mCurrentDisplayRotation);
}
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep;
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import com.android.launcher3.R;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.systemui.plugins.OverscrollPlugin;
/**
* Resource overrideable factory for forcing a local overscroll plugin.
* Override {@link R.string#overscroll_plugin_factory_class} to set a different class.
*/
public class OverscrollPluginFactory implements ResourceBasedOverride {
public static final MainThreadInitializedObject<OverscrollPluginFactory> INSTANCE = forOverride(
OverscrollPluginFactory.class,
R.string.overscroll_plugin_factory_class);
/**
* Get the plugin that is defined locally in launcher, as opposed to a dynamic side loaded one.
*/
public OverscrollPlugin getLocalOverscrollPlugin() {
return null;
}
}
@@ -53,12 +53,6 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
Bundle::putInt, PortraitStatesTouchController::getHotseatTop);
}
case TestProtocol.REQUEST_OVERVIEW_ACTIONS_ENABLED: {
response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get());
return response;
}
case TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED: {
response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
FeatureFlags.ENABLE_OVERVIEW_SHARE.get());
@@ -17,8 +17,8 @@ package com.android.quickstep;
import static android.content.Intent.ACTION_USER_UNLOCKED;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ALL;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_FRAME_DELAY;
import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_FRAME_DELAY;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
@@ -56,7 +56,10 @@ import androidx.annotation.BinderThread;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayHolder;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.SecureSettingsObserver;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.SysUINavigationMode.OneHandedModeChangeListener;
@@ -76,14 +79,14 @@ import java.util.stream.Collectors;
*/
public class RecentsAnimationDeviceState implements
NavigationModeChangeListener,
DefaultDisplay.DisplayInfoChangeListener,
DisplayInfoChangeListener,
OneHandedModeChangeListener {
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
private final Context mContext;
private final SysUINavigationMode mSysUiNavMode;
private final DefaultDisplay mDefaultDisplay;
private final DisplayHolder mDisplayHolder;
private final int mDisplayId;
private final RotationTouchHelper mRotationTouchHelper;
@@ -98,6 +101,7 @@ public class RecentsAnimationDeviceState implements
private float mAssistantVisibility;
private boolean mIsOneHandedModeEnabled;
private boolean mIsSwipeToNotificationEnabled;
private final boolean mIsOneHandedModeSupported;
private boolean mIsUserUnlocked;
private final ArrayList<Runnable> mUserUnlockedActions = new ArrayList<>();
@@ -119,12 +123,17 @@ public class RecentsAnimationDeviceState implements
private boolean mIsUserSetupComplete;
public RecentsAnimationDeviceState(Context context) {
this(context, DisplayController.getDefaultDisplay(context));
}
public RecentsAnimationDeviceState(Context context, DisplayHolder displayHolder) {
mContext = context;
mDisplayHolder = displayHolder;
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
mDefaultDisplay = DefaultDisplay.INSTANCE.get(context);
mDisplayId = mDefaultDisplay.getInfo().id;
runOnDestroy(() -> mDefaultDisplay.removeChangeListener(this));
mRotationTouchHelper = new RotationTouchHelper(context);
mDisplayId = mDisplayHolder.getInfo().id;
mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
runOnDestroy(() -> mDisplayHolder.removeChangeListener(this));
mRotationTouchHelper = new RotationTouchHelper(context, mDisplayHolder);
runOnDestroy(mRotationTouchHelper::destroy);
// Register for user unlocked if necessary
@@ -167,7 +176,7 @@ public class RecentsAnimationDeviceState implements
}
}
if (SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
if (mIsOneHandedModeSupported) {
SecureSettingsObserver oneHandedEnabledObserver =
SecureSettingsObserver.newOneHandedSettingsObserver(
mContext, enabled -> mIsOneHandedModeEnabled = enabled);
@@ -230,9 +239,9 @@ public class RecentsAnimationDeviceState implements
@Override
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
mDefaultDisplay.removeChangeListener(this);
mDefaultDisplay.addChangeListener(this);
onDisplayInfoChanged(mDefaultDisplay.getInfo(), CHANGE_ALL);
mDisplayHolder.removeChangeListener(this);
mDisplayHolder.addChangeListener(this);
onDisplayInfoChanged(mDisplayHolder.getInfo(), CHANGE_ALL);
if (newMode == NO_BUTTON) {
mExclusionListener.register();
@@ -240,12 +249,12 @@ public class RecentsAnimationDeviceState implements
mExclusionListener.unregister();
}
mNavBarPosition = new NavBarPosition(newMode, mDefaultDisplay.getInfo());
mNavBarPosition = new NavBarPosition(newMode, mDisplayHolder.getInfo());
mMode = newMode;
}
@Override
public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) {
public void onDisplayInfoChanged(Info info, int flags) {
if (info.id != getDisplayId() || flags == CHANGE_FRAME_DELAY) {
// ignore displays that aren't running launcher and frame refresh rate changes
return;
@@ -522,19 +531,18 @@ public class RecentsAnimationDeviceState implements
* @return whether the given motion event can trigger the one handed mode.
*/
public boolean canTriggerOneHandedAction(MotionEvent ev) {
if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
if (!mIsOneHandedModeSupported) {
return false;
}
if (!mIsOneHandedModeEnabled && !mIsSwipeToNotificationEnabled) {
return false;
if (mIsOneHandedModeEnabled || mIsSwipeToNotificationEnabled) {
final Info displayInfo = mDisplayHolder.getInfo();
return (mRotationTouchHelper.touchInOneHandedModeRegion(ev)
&& displayInfo.rotation != Surface.ROTATION_90
&& displayInfo.rotation != Surface.ROTATION_270
&& displayInfo.metrics.densityDpi < DisplayMetrics.DENSITY_600);
}
final DefaultDisplay.Info displayInfo = mDefaultDisplay.getInfo();
return (mRotationTouchHelper.touchInOneHandedModeRegion(ev)
&& displayInfo.rotation != Surface.ROTATION_90
&& displayInfo.rotation != Surface.ROTATION_270
&& displayInfo.metrics.densityDpi < DisplayMetrics.DENSITY_600);
return false;
}
public boolean isOneHandedModeEnabled() {
@@ -160,9 +160,9 @@ public class RecentsModel extends TaskStackChangeListener {
@Override
public void onTaskRemoved(int taskId) {
Task.TaskKey dummyKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
mThumbnailCache.remove(dummyKey);
mIconCache.onTaskRemoved(dummyKey);
Task.TaskKey stubKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
mThumbnailCache.remove(stubKey);
mIconCache.onTaskRemoved(stubKey);
}
public void onTrimMemory(int level) {
@@ -17,8 +17,8 @@ package com.android.quickstep;
import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ALL;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_FRAME_DELAY;
import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_FRAME_DELAY;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
@@ -28,8 +28,9 @@ import android.view.MotionEvent;
import android.view.OrientationEventListener;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.DisplayController.DisplayHolder;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -40,10 +41,10 @@ import java.util.ArrayList;
public class RotationTouchHelper implements
SysUINavigationMode.NavigationModeChangeListener,
DefaultDisplay.DisplayInfoChangeListener {
DisplayInfoChangeListener {
private final OrientationTouchTransformer mOrientationTouchTransformer;
private final DefaultDisplay mDefaultDisplay;
private final DisplayHolder mDisplayHolder;
private final SysUINavigationMode mSysUiNavMode;
private final int mDisplayId;
private int mDisplayRotation;
@@ -120,12 +121,12 @@ public class RotationTouchHelper implements
private final Context mContext;
public RotationTouchHelper(Context context) {
public RotationTouchHelper(Context context, DisplayHolder displayHolder) {
mContext = context;
mDisplayHolder = displayHolder;
Resources resources = mContext.getResources();
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
mDefaultDisplay = DefaultDisplay.INSTANCE.get(context);
mDisplayId = mDefaultDisplay.getInfo().id;
mDisplayId = mDisplayHolder.getInfo().id;
mOrientationTouchTransformer = new OrientationTouchTransformer(resources, mMode,
() -> QuickStepContract.getWindowCornerRadius(resources));
@@ -200,7 +201,7 @@ public class RotationTouchHelper implements
return;
}
mOrientationTouchTransformer.createOrAddTouchRegion(mDefaultDisplay.getInfo());
mOrientationTouchTransformer.createOrAddTouchRegion(mDisplayHolder.getInfo());
}
/**
@@ -222,11 +223,11 @@ public class RotationTouchHelper implements
@Override
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
mDefaultDisplay.removeChangeListener(this);
mDefaultDisplay.addChangeListener(this);
onDisplayInfoChanged(mDefaultDisplay.getInfo(), CHANGE_ALL);
mDisplayHolder.removeChangeListener(this);
mDisplayHolder.addChangeListener(this);
onDisplayInfoChanged(mDisplayHolder.getInfo(), CHANGE_ALL);
mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo(),
mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayHolder.getInfo(),
mContext.getResources());
if (!mMode.hasGestures && newMode.hasGestures) {
setupOrientationSwipeHandler();
@@ -242,7 +243,7 @@ public class RotationTouchHelper implements
}
@Override
public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) {
public void onDisplayInfoChanged(Info info, int flags) {
if (info.id != mDisplayId|| flags == CHANGE_FRAME_DELAY) {
// ignore displays that aren't running launcher and frame refresh rate changes
return;
@@ -275,7 +276,7 @@ public class RotationTouchHelper implements
* Sets the gestural height.
*/
void setGesturalHeight(int newGesturalHeight) {
mOrientationTouchTransformer.setGesturalHeight(newGesturalHeight, mDefaultDisplay.getInfo(),
mOrientationTouchTransformer.setGesturalHeight(newGesturalHeight, mDisplayHolder.getInfo(),
mContext.getResources());
}
@@ -292,7 +293,7 @@ public class RotationTouchHelper implements
}
private void enableMultipleRegions(boolean enable) {
mOrientationTouchTransformer.enableMultipleRegions(enable, mDefaultDisplay.getInfo());
mOrientationTouchTransformer.enableMultipleRegions(enable, mDisplayHolder.getInfo());
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
if (enable && !mInOverview && !TestProtocol.sDisableSensorRotation) {
// Clear any previous state from sensor manager
@@ -355,7 +356,7 @@ public class RotationTouchHelper implements
* notifies system UI of the primary rotation the user is interacting with
*/
private void toggleSecondaryNavBarsForRotation() {
mOrientationTouchTransformer.setSingleActiveRegion(mDefaultDisplay.getInfo());
mOrientationTouchTransformer.setSingleActiveRegion(mDisplayHolder.getInfo());
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
}
@@ -16,7 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.animation.Animator;
import android.content.Context;
@@ -24,7 +24,6 @@ import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
@@ -35,6 +34,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -45,7 +45,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.
public abstract class SwipeUpAnimationLogic {
protected static final Rect TEMP_RECT = new Rect();
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
protected DeviceProfile mDp;
@@ -66,12 +65,8 @@ public abstract class SwipeUpAnimationLogic {
protected int mTransitionDragLength;
// How much further we can drag past recents, as a factor of mTransitionDragLength.
protected float mDragLengthFactor = 1;
// Start resisting when swiping past this factor of mTransitionDragLength.
private float mDragLengthFactorStartPullback = 1f;
// This is how far down we can scale down, where 0f is full screen and 1f is recents.
private float mDragLengthFactorMaxPullback = 1f;
protected AnimatorPlaybackController mWindowTransitionController;
protected AnimatorControllerWithResistance mWindowTransitionController;
public SwipeUpAnimationLogic(Context context, RecentsAnimationDeviceState deviceState,
GestureState gestureState, TransformParams transformParams) {
@@ -84,6 +79,7 @@ public abstract class SwipeUpAnimationLogic {
mTaskViewSimulator.setLayoutRotation(
mDeviceState.getRotationTouchHelper().getCurrentActiveRotation(),
mDeviceState.getRotationTouchHelper().getDisplayRotation());
mTaskViewSimulator.setDrawsBelowRecents(true);
}
protected void initTransitionEndpoints(DeviceProfile dp) {
@@ -97,19 +93,17 @@ public abstract class SwipeUpAnimationLogic {
if (mDeviceState.isFullyGesturalNavMode()) {
// We can drag all the way to the top of the screen.
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
float startScale = mTaskViewSimulator.getFullScreenScale();
// Start pulling back when RecentsView scale is 0.75f, and let it go down to 0.5f.
mDragLengthFactorStartPullback = (0.75f - startScale) / (1 - startScale);
mDragLengthFactorMaxPullback = (0.5f - startScale) / (1 - startScale);
} else {
mDragLengthFactor = 1;
mDragLengthFactorStartPullback = mDragLengthFactorMaxPullback = 1;
mDragLengthFactor = 1 + AnimatorControllerWithResistance.TWO_BUTTON_EXTRA_DRAG_FACTOR;
}
PendingAnimation pa = new PendingAnimation(mTransitionDragLength * 2);
mTaskViewSimulator.addAppToOverviewAnim(pa, t -> t * mDragLengthFactor);
mWindowTransitionController = pa.createPlaybackController();
mTaskViewSimulator.addAppToOverviewAnim(pa, LINEAR);
AnimatorPlaybackController normalController = pa.createPlaybackController();
mWindowTransitionController = AnimatorControllerWithResistance.createForRecents(
normalController, mContext, mTaskViewSimulator.getOrientationState(),
mDp, mTaskViewSimulator.recentsViewScale, AnimatedFloat.VALUE,
mTaskViewSimulator.recentsViewSecondaryTranslation, AnimatedFloat.VALUE);
}
@UiThread
@@ -122,13 +116,6 @@ public abstract class SwipeUpAnimationLogic {
} else {
float translation = Math.max(displacement, 0);
shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
if (shift > mDragLengthFactorStartPullback) {
float pullbackProgress = Utilities.getProgress(shift,
mDragLengthFactorStartPullback, mDragLengthFactor);
pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
shift = mDragLengthFactorStartPullback + pullbackProgress
* (mDragLengthFactorMaxPullback - mDragLengthFactorStartPullback);
}
}
mCurrentShift.updateValue(shift);
@@ -183,7 +170,7 @@ public abstract class SwipeUpAnimationLogic {
HomeAnimationFactory homeAnimationFactory) {
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor);
mCurrentShift.updateValue(startProgress);
mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());
@@ -18,7 +18,7 @@ package com.android.quickstep;
import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
@@ -39,13 +39,12 @@ import com.android.launcher3.R;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -91,20 +90,22 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
return shortcuts;
}
public static final MainThreadInitializedObject<TaskOverlayFactory> INSTANCE =
forOverride(TaskOverlayFactory.class, R.string.task_overlay_factory_class);
/**
* @return a launcher-provided OverscrollPlugin if available, otherwise null
*/
public OverscrollPlugin getLocalOverscrollPlugin() {
return null;
}
public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) {
return new TaskOverlay(thumbnailView);
}
/**
* Subclasses can attach any system listeners in this method, must be paired with
* {@link #removeListeners()}
*/
public void initListeners() { }
/**
* Subclasses should remove any system listeners in this method, must be paired with
* {@link #initListeners()}
*/
public void removeListeners() { }
/** Note that these will be shown in order from top to bottom, if available for the task. */
private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[]{
TaskShortcutFactory.APP_INFO,
@@ -156,6 +157,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
getActionsView().setCallbacks(new OverlayUICallbacks() {
@Override
public void onShare() {
endLiveTileMode(isAllowedByPolicy);
if (isAllowedByPolicy) {
mImageApi.startShareActivity();
} else {
@@ -166,12 +168,30 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
@SuppressLint("NewApi")
@Override
public void onScreenshot() {
endLiveTileMode(isAllowedByPolicy);
saveScreenshot(task);
}
});
}
}
/**
* End rendering live tile in Overview.
*
* @param showScreenshot if it's true, we take a screenshot and switch to it.
*/
public void endLiveTileMode(boolean showScreenshot) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
if (showScreenshot) {
recentsView.switchToScreenshot(
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
} else {
recentsView.finishRecentsAnimation(true /* toRecents */, null);
}
}
}
/**
* Called to save screenshot of the task thumbnail.
*/
@@ -18,7 +18,6 @@ package com.android.quickstep;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SELECTIONS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP;
@@ -310,16 +309,11 @@ public interface TaskShortcutFactory {
TaskShortcutFactory WELLBEING = (activity, view) ->
WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, view.getItemInfo());
TaskShortcutFactory SCREENSHOT = (activity, tv) -> {
if (ENABLE_OVERVIEW_ACTIONS.get()) {
return tv.getThumbnail().getTaskOverlay()
.getScreenshotShortcut(activity, tv.getItemInfo());
}
return null;
};
TaskShortcutFactory SCREENSHOT = (activity, tv) -> tv.getThumbnail().getTaskOverlay()
.getScreenshotShortcut(activity, tv.getItemInfo());
TaskShortcutFactory MODAL = (activity, tv) -> {
if (ENABLE_OVERVIEW_ACTIONS.get() && ENABLE_OVERVIEW_SELECTIONS.get()) {
if (ENABLE_OVERVIEW_SELECTIONS.get()) {
return tv.getThumbnail().getTaskOverlay().getModalStateSystemShortcut(tv.getItemInfo());
}
return null;
@@ -41,7 +41,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -146,7 +146,7 @@ public final class TaskViewUtils {
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
// RecentsView never updates the display rotation until swipe-up so the value may be stale.
// Use the display value instead.
int displayRotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
int displayRotation = DisplayController.getDefaultDisplay(context).getInfo().rotation;
TaskViewSimulator topMostSimulator = null;
if (targets.apps.length > 0) {
@@ -101,24 +101,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Wrapper around a list for processing arguments.
*/
class ArgList extends LinkedList<String> {
public ArgList(List<String> l) {
super(l);
}
public String peekArg() {
return peekFirst();
}
public String nextArg() {
return pollFirst().toLowerCase();
}
}
/**
* Service connected by system-UI for handling touch interaction.
@@ -238,23 +220,6 @@ public class TouchInteractionService extends Service implements PluginListener<O
WindowBounds wb = new WindowBounds(bounds, insets);
MAIN_EXECUTOR.execute(() -> SplitScreenBounds.INSTANCE.setSecondaryWindowBounds(wb));
}
/** Deprecated methods **/
public void onQuickStep(MotionEvent motionEvent) { }
public void onQuickScrubEnd() { }
public void onQuickScrubProgress(float progress) { }
public void onQuickScrubStart() { }
public void onPreMotionEvent(int downHitTarget) { }
public void onMotionEvent(MotionEvent ev) {
ev.recycle();
}
public void onBind(ISystemUiProxy iSystemUiProxy) { }
};
private static boolean sConnected = false;
@@ -616,9 +581,8 @@ public class TouchInteractionService extends Service implements PluginListener<O
if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
OverscrollPlugin plugin = null;
if (FeatureFlags.FORCE_LOCAL_OVERSCROLL_PLUGIN.get()) {
TaskOverlayFactory factory =
TaskOverlayFactory.INSTANCE.get(getApplicationContext());
plugin = factory.getLocalOverscrollPlugin(); // may be null
plugin = OverscrollPluginFactory.INSTANCE.get(
getApplicationContext()).getLocalOverscrollPlugin();
}
// If not local plugin was forced, use the actual overscroll plugin if available.
@@ -842,10 +806,10 @@ public class TouchInteractionService extends Service implements PluginListener<O
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) {
ArgList args = new ArgList(Arrays.asList(rawArgs));
switch (args.nextArg()) {
LinkedList<String> args = new LinkedList(Arrays.asList(rawArgs));
switch (args.pollFirst()) {
case "cmd":
if (args.peekArg() == null) {
if (args.peekFirst() == null) {
printAvailableCommands(pw);
} else {
onCommand(pw, args);
@@ -886,8 +850,8 @@ public class TouchInteractionService extends Service implements PluginListener<O
pw.println(" clear-touch-log: Clears the touch interaction log");
}
private void onCommand(PrintWriter pw, ArgList args) {
switch (args.nextArg()) {
private void onCommand(PrintWriter pw, LinkedList<String> args) {
switch (args.pollFirst()) {
case "clear-touch-log":
ActiveGestureLog.INSTANCE.clear();
break;
@@ -21,7 +21,7 @@ import android.view.MotionEvent;
import androidx.annotation.Nullable;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.SysUINavigationMode;
@@ -43,7 +43,7 @@ public class FallbackNavBarTouchController implements TouchController,
SysUINavigationMode.Mode sysUINavigationMode = SysUINavigationMode.getMode(mActivity);
if (sysUINavigationMode == SysUINavigationMode.Mode.NO_BUTTON) {
NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode,
DefaultDisplay.INSTANCE.get(mActivity).getInfo());
DisplayController.getDefaultDisplay(mActivity).getInfo());
mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity,
true /* disableHorizontalSwipe */, navBarPosition,
null /* onInterceptTouch */, this);
@@ -19,6 +19,7 @@ import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
@@ -26,6 +27,7 @@ import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
@@ -86,6 +88,8 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
setter.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1],
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
setter.setFloat(mRecentsView, TASK_MODALNESS, state.getOverviewModalness(),
config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
@@ -101,20 +101,20 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
}
@Override
protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) {
protected boolean shouldAddStubTaskView(RunningTaskInfo runningTaskInfo) {
if (mHomeTaskInfo != null && runningTaskInfo != null &&
mHomeTaskInfo.taskId == runningTaskInfo.taskId
&& getTaskViewCount() == 0) {
// Do not add a dummy task if we are running over home with empty recents, so that we
// show the empty recents message instead of showing a dummy task and later removing it.
// Do not add a stub task if we are running over home with empty recents, so that we
// show the empty recents message instead of showing a stub task and later removing it.
return false;
}
return super.shouldAddDummyTaskView(runningTaskInfo);
return super.shouldAddStubTaskView(runningTaskInfo);
}
@Override
protected void applyLoadPlan(ArrayList<Task> tasks) {
// When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
// When quick-switching on 3p-launcher, we add a "stub" tile corresponding to Launcher
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
// track the index of the next task appropriately, as if we are switching on any other app.
if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == mRunningTaskId && !tasks.isEmpty()) {

Some files were not shown because too many files have changed in this diff Show More