Merge "Migrate QSB logging to WW" into ub-launcher3-rvc-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index 7c4f3ec..f1ce72e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -52,6 +52,7 @@
private final Launcher mLauncher;
private final Hotseat mHotseat;
+ private final HotseatRestoreHelper mRestoreHelper;
private List<WorkspaceItemInfo> mPredictedApps;
private HotseatEduDialog mActiveDialog;
@@ -59,9 +60,10 @@
private IntArray mNewScreens = null;
private Runnable mOnOnboardingComplete;
- HotseatEduController(Launcher launcher, Runnable runnable) {
+ HotseatEduController(Launcher launcher, HotseatRestoreHelper restoreHelper, Runnable runnable) {
mLauncher = launcher;
mHotseat = launcher.getHotseat();
+ mRestoreHelper = restoreHelper;
mOnOnboardingComplete = runnable;
}
@@ -69,11 +71,14 @@
* Checks what type of migration should be used and migrates hotseat
*/
void migrate() {
+ mRestoreHelper.createBackup();
if (FeatureFlags.HOTSEAT_MIGRATE_TO_FOLDER.get()) {
migrateToFolder();
} else {
migrateHotseatWhole();
}
+ Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_enabled, R.string.hotseat_turn_off,
+ null, () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION)));
}
/**
@@ -84,7 +89,6 @@
*/
private int migrateToFolder() {
ArrayDeque<FolderInfo> folders = new ArrayDeque<>();
-
ArrayList<WorkspaceItemInfo> putIntoFolder = new ArrayList<>();
//separate folders and items that can get in folders
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index fa137f8..99cb3b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -16,7 +16,8 @@
package com.android.launcher3.hybridhotseat;
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.HYBRID_HOTSEAT_CANCELED;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType
+ .HYBRID_HOTSEAT_CANCELED;
import android.animation.PropertyValuesHolder;
import android.content.Context;
@@ -144,11 +145,23 @@
int rightInset = insets.right - mInsets.right;
int bottomInset = insets.bottom - mInsets.bottom;
mInsets.set(insets);
- setPadding(leftInset, getPaddingTop(), rightInset, 0);
- mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
- mHotseatWrapper.getPaddingRight(), bottomInset);
- mHotseatWrapper.getLayoutParams().height =
- mLauncher.getDeviceProfile().hotseatBarSizePx + insets.bottom;
+ if (mLauncher.getOrientation() == Configuration.ORIENTATION_PORTRAIT) {
+ setPadding(leftInset, getPaddingTop(), rightInset, 0);
+ mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
+ mHotseatWrapper.getPaddingRight(), bottomInset);
+ mHotseatWrapper.getLayoutParams().height =
+ mLauncher.getDeviceProfile().hotseatBarSizePx + insets.bottom;
+
+ } else {
+ setPadding(0, getPaddingTop(), 0, 0);
+ mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
+ mHotseatWrapper.getPaddingRight(),
+ (int) getResources().getDimension(R.dimen.bottom_sheet_edu_padding));
+ ((TextView) findViewById(R.id.hotseat_edu_heading)).setText(
+ R.string.hotseat_edu_title_migrate_landscape);
+ ((TextView) findViewById(R.id.hotseat_edu_content)).setText(
+ R.string.hotseat_edu_message_migrate_landscape);
+ }
}
private void logUserAction(boolean migrated, int pageIndex) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 05bcb57..bd4d713 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -92,6 +92,8 @@
private Launcher mLauncher;
private final Hotseat mHotseat;
+ private final HotseatRestoreHelper mRestoreHelper;
+
private List<ComponentKeyMapper> mComponentKeyMappers = new ArrayList<>();
private DynamicItemCache mDynamicItemCache;
@@ -129,6 +131,7 @@
mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
launcher.getDeviceProfile().inv.addOnChangeListener(this);
mHotseat.addOnAttachStateChangeListener(this);
+ mRestoreHelper = new HotseatRestoreHelper(mLauncher);
if (mHotseat.isAttachedToWindow()) {
onViewAttachedToWindow(mHotseat);
}
@@ -297,7 +300,8 @@
});
setPauseUIUpdate(false);
if (!isEduSeen()) {
- mHotseatEduController = new HotseatEduController(mLauncher, this::createPredictor);
+ mHotseatEduController = new HotseatEduController(mLauncher, mRestoreHelper,
+ this::createPredictor);
}
}
@@ -320,9 +324,11 @@
updateDependencies();
bindItems(items, false, null);
}
-
private void setPredictedApps(List<AppTarget> appTargets) {
mComponentKeyMappers.clear();
+ if (appTargets.isEmpty()) {
+ mRestoreHelper.restoreBackup();
+ }
StringBuilder predictionLog = new StringBuilder("predictedApps: [\n");
ArrayList<ComponentKey> componentKeys = new ArrayList<>();
for (AppTarget appTarget : appTargets) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
new file mode 100644
index 0000000..8c1db4e
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
@@ -0,0 +1,86 @@
+/*
+ * 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.hybridhotseat;
+
+import static com.android.launcher3.LauncherSettings.Favorites.HYBRID_HOTSEAT_BACKUP_TABLE;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.model.GridBackupTable;
+import com.android.launcher3.provider.LauncherDbUtils;
+
+/**
+ * A helper class to manage migration revert restoration for hybrid hotseat
+ */
+public class HotseatRestoreHelper {
+ private final Launcher mLauncher;
+ private boolean mBackupRestored = false;
+
+ HotseatRestoreHelper(Launcher context) {
+ mLauncher = context;
+ }
+
+ /**
+ * Creates a snapshot backup of Favorite table for future restoration use.
+ */
+ public void createBackup() {
+ MODEL_EXECUTOR.execute(() -> {
+ try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
+ LauncherSettings.Settings.call(
+ mLauncher.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
+ .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
+ InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
+ GridBackupTable backupTable = new GridBackupTable(mLauncher,
+ transaction.getDb(), idp.numHotseatIcons, idp.numColumns,
+ idp.numRows);
+ backupTable.createCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE);
+ transaction.commit();
+ LauncherSettings.Settings.call(mLauncher.getContentResolver(),
+ LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE);
+ }
+ });
+ }
+
+ /**
+ * Finds and restores a previously saved snapshow of Favorites table
+ */
+ public void restoreBackup() {
+ if (mBackupRestored) return;
+ MODEL_EXECUTOR.execute(() -> {
+ try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
+ LauncherSettings.Settings.call(
+ mLauncher.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
+ .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
+ if (!tableExists(transaction.getDb(), HYBRID_HOTSEAT_BACKUP_TABLE)) {
+ return;
+ }
+ InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
+ GridBackupTable backupTable = new GridBackupTable(mLauncher,
+ transaction.getDb(), idp.numHotseatIcons, idp.numColumns,
+ idp.numRows);
+ backupTable.restoreFromCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE, true);
+ transaction.commit();
+ mBackupRestored = true;
+ mLauncher.getModel().forceReload();
+ }
+ });
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index a487869..79dc3e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -37,6 +37,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;
@@ -210,6 +211,7 @@
}
config.setInterpolator(ANIM_WORKSPACE_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)
? OVERSHOOT_1_2
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
index c18a0fd..e5782e7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -33,11 +33,11 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
/**
* Provider for the atomic (for 3-button mode) remote window animation from the app to the overview.
@@ -132,8 +132,7 @@
TransformParams params = new TransformParams()
.setTargetSet(targets)
- .setSyncTransactionApplier(
- new SyncRtSurfaceTransactionApplierCompat(mActivity.getRootView()));
+ .setSyncTransactionApplier(new SurfaceTransactionApplier(mActivity.getRootView()));
AnimatedFloat recentsAlpha = new AnimatedFloat(() -> { });
params.setBaseBuilderProxy((builder, app, p)
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index 737d837..6cbe794 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -40,13 +40,14 @@
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.ArrayList;
import java.util.function.Consumer;
@@ -114,10 +115,10 @@
public abstract Intent getLaunchIntent();
protected void linkRecentsViewScroll() {
- SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
+ SurfaceTransactionApplier.create(mRecentsView, applier -> {
mTransformParams.setSyncTransactionApplier(applier);
runOnRecentsAnimationStart(() ->
- mRecentsAnimationTargets.addDependentTransactionApplier(applier));
+ mRecentsAnimationTargets.addReleaseCheck(applier));
});
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
@@ -356,7 +357,8 @@
if (mWindowTransitionController != null) {
float progress = mCurrentShift.value / mDragLengthFactor;
mWindowTransitionController.setPlayFraction(progress);
-
+ }
+ if (mRecentsAnimationTargets != null) {
if (mRecentsViewScrollLinked) {
mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset());
}
@@ -364,6 +366,17 @@
}
}
+ @Override
+ protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
+ HomeAnimationFactory homeAnimationFactory) {
+ RectFSpringAnim anim =
+ super.createWindowAnimationToHome(startProgress, homeAnimationFactory);
+ if (mRecentsAnimationTargets != null) {
+ mRecentsAnimationTargets.addReleaseCheck(anim);
+ }
+ return anim;
+ }
+
public interface Factory {
BaseSwipeUpHandler newHandler(
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
index fd17551..e49c466 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
@@ -33,6 +33,7 @@
import com.android.launcher3.BuildConfig;
import com.android.quickstep.util.ImageActionUtils;
+import com.android.systemui.shared.recents.model.Task;
import java.util.function.Supplier;
@@ -85,11 +86,11 @@
* @param screenshotBounds the location of where the bitmap was laid out on the screen in
* screen coordinates.
* @param visibleInsets that are used to draw the screenshot within the bounds.
- * @param taskId of the task that the screenshot was taken of.
+ * @param task of the task that the screenshot was taken of.
*/
public void saveScreenshot(Bitmap screenshot, Rect screenshotBounds,
- Insets visibleInsets, int taskId) {
+ Insets visibleInsets, Task.TaskKey task) {
ImageActionUtils.saveScreenshot(mSystemUiProxy, screenshot, screenshotBounds, visibleInsets,
- taskId);
+ task);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 62eb235..4801d71 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -310,8 +310,8 @@
@Override
protected float getExtraSpace(Context context, DeviceProfile dp,
PagedOrientationHandler orientationHandler) {
- if (dp.isVerticalBarLayout() ||
- hideShelfInTwoButtonLandscape(context, orientationHandler)) {
+ if ((dp.isVerticalBarLayout() && !showOverviewActions(context))
+ || hideShelfInTwoButtonLandscape(context, orientationHandler)) {
return 0;
} else {
Resources res = context.getResources();
@@ -319,12 +319,14 @@
//TODO: this needs to account for the swipe gesture height and accessibility
// UI when shown.
float actionsBottomMargin = 0;
- if (getMode(context) == Mode.THREE_BUTTONS) {
- actionsBottomMargin = res.getDimensionPixelSize(
+ if (!dp.isVerticalBarLayout()) {
+ if (getMode(context) == Mode.THREE_BUTTONS) {
+ actionsBottomMargin = res.getDimensionPixelSize(
R.dimen.overview_actions_bottom_margin_three_button);
- } else {
- actionsBottomMargin = res.getDimensionPixelSize(
+ } else {
+ actionsBottomMargin = res.getDimensionPixelSize(
R.dimen.overview_actions_bottom_margin_gesture);
+ }
}
float actionsHeight = actionsBottomMargin
+ res.getDimensionPixelSize(R.dimen.overview_actions_height);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 0d49b2b..a28dabc 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -79,12 +79,13 @@
@Override
protected Activity getCurrentActivity() {
- OverviewComponentObserver observer = new OverviewComponentObserver(mContext,
- new RecentsAnimationDeviceState(mContext));
+ RecentsAnimationDeviceState rads = new RecentsAnimationDeviceState(mContext);
+ OverviewComponentObserver observer = new OverviewComponentObserver(mContext, rads);
try {
return observer.getActivityInterface().getCreatedActivity();
} finally {
observer.onDestroy();
+ rads.destroy();
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index 042c542..3cfff7e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -126,7 +126,7 @@
public void onScreenshot() {
if (isAllowedByPolicy) {
imageApi.saveScreenshot(mThumbnailView.getThumbnail(),
- getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key.id);
+ getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key);
} else {
showBlockedByPolicyMessage();
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
index 021d39d..3623e67 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
@@ -18,6 +18,8 @@
import static android.view.Display.DEFAULT_DISPLAY;
+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;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import android.app.Activity;
@@ -35,6 +37,8 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
import com.android.launcher3.model.WellbeingModel;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -68,7 +72,16 @@
static WorkspaceItemInfo dummyInfo(TaskView view) {
Task task = view.getTask();
- WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
+ WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo(){
+ /**
+ * Helps to log events as {@link LauncherAtom.Task}
+ * instead of {@link LauncherAtom.ItemInfo}.
+ */
+ @Override
+ public LauncherAtom.ItemInfo buildProto() {
+ return view.buildProto();
+ }
+ };
dummyInfo.intent = new Intent();
ComponentName component = task.getTopComponent();
dummyInfo.getIntent().setComponent(component);
@@ -83,10 +96,12 @@
private final int mIconRes;
private final int mTextRes;
+ private final LauncherEvent mLauncherEvent;
- MultiWindowFactory(int iconRes, int textRes) {
+ MultiWindowFactory(int iconRes, int textRes, LauncherEvent launcherEvent) {
mIconRes = iconRes;
mTextRes = textRes;
+ mLauncherEvent = launcherEvent;
}
protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId);
@@ -102,7 +117,8 @@
if (!isAvailable(activity, task.key.displayId)) {
return null;
}
- return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this);
+ return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this,
+ mLauncherEvent);
}
}
@@ -114,11 +130,12 @@
private final TaskThumbnailView mThumbnailView;
private final TaskView mTaskView;
private final MultiWindowFactory mFactory;
+ private final LauncherEvent mLauncherEvent;
- public MultiWindowSystemShortcut(int iconRes, int textRes,
- BaseDraggingActivity activity, TaskView taskView, MultiWindowFactory factory) {
+ public MultiWindowSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity,
+ TaskView taskView, MultiWindowFactory factory, LauncherEvent launcherEvent) {
super(iconRes, textRes, activity, dummyInfo(taskView));
-
+ mLauncherEvent = launcherEvent;
mHandler = new Handler(Looper.getMainLooper());
mTaskView = taskView;
mRecentsView = activity.getOverviewPanel();
@@ -203,12 +220,13 @@
WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
future, animStartedListener, mHandler, true /* scaleUp */,
taskKey.displayId);
+ mTarget.getStatsLogManager().log(mLauncherEvent, mTaskView.buildProto());
}
}
}
- TaskShortcutFactory SPLIT_SCREEN = new MultiWindowFactory(
- R.drawable.ic_split_screen, R.string.recent_task_option_split_screen) {
+ TaskShortcutFactory SPLIT_SCREEN = new MultiWindowFactory(R.drawable.ic_split_screen,
+ R.string.recent_task_option_split_screen, LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP) {
@Override
protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
@@ -241,8 +259,8 @@
}
};
- TaskShortcutFactory FREE_FORM = new MultiWindowFactory(
- R.drawable.ic_split_screen, R.string.recent_task_option_freeform) {
+ TaskShortcutFactory FREE_FORM = new MultiWindowFactory(R.drawable.ic_split_screen,
+ R.string.recent_task_option_freeform, LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP) {
@Override
protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
@@ -302,6 +320,8 @@
};
mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler());
dismissTaskMenuView(mTarget);
+ mTarget.getStatsLogManager().log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP,
+ mTaskView.buildProto());
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
index c68d6e2..e2e25f3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
@@ -42,6 +42,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.util.DefaultDisplay;
+import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.RecentsView;
@@ -49,7 +50,6 @@
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
/**
* Utility class for helpful methods related to {@link TaskView} objects and their tasks.
@@ -128,11 +128,10 @@
RemoteAnimationTargetCompat[] wallpaperTargets, DepthController depthController,
PendingAnimation out) {
- SyncRtSurfaceTransactionApplierCompat applier =
- new SyncRtSurfaceTransactionApplierCompat(v);
+ SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
final RemoteAnimationTargets targets =
new RemoteAnimationTargets(appTargets, wallpaperTargets, MODE_OPENING);
- targets.addDependentTransactionApplier(applier);
+ targets.addReleaseCheck(applier);
TransformParams params = new TransformParams()
.setSyncTransactionApplier(applier)
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 8c77240..226c818 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -30,6 +30,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.Service;
@@ -81,6 +82,7 @@
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
+import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.util.ProtoTracer;
@@ -133,10 +135,10 @@
private static final int MAX_BACK_NOTIFICATION_COUNT = 3;
/**
- * System Action ID to show all apps. This ID should follow the ones in
- * com.android.systemui.accessibility.SystemActions.
+ * System Action ID to show all apps.
+ * TODO: Use AccessibilityService's corresponding global action constant in S
*/
- private static final int SYSTEM_ACTION_ID_ALL_APPS = 100;
+ private static final int SYSTEM_ACTION_ID_ALL_APPS = 14;
private int mBackGestureNotificationCounter = -1;
@Nullable
@@ -466,10 +468,17 @@
final int action = event.getAction();
if (action == ACTION_DOWN) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "TouchInteractionService.onInputEvent:DOWN");
+ }
mDeviceState.setOrientationTransformIfNeeded(event);
GestureState newGestureState;
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME,
+ "TouchInteractionService.onInputEvent:isInSwipeUpTouchRegion");
+ }
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
// onConsumerInactive and wipe the previous gesture state
GestureState prevGestureState = new GestureState(mGestureState);
@@ -479,18 +488,22 @@
ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName());
mUncheckedConsumer = mConsumer;
- } else if (mDeviceState.isUserUnlocked()
- && mDeviceState.isFullyGesturalNavMode()
- && mDeviceState.canTriggerAssistantAction(event)) {
+ } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()) {
newGestureState = createGestureState();
- // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we should
- // not interrupt it. QuickSwitch assumes that interruption can only happen if the
- // next gesture is also quick switch.
- mUncheckedConsumer = new AssistantInputConsumer(
- this,
- newGestureState,
- InputConsumer.NO_OP, mInputMonitorCompat,
- mOverviewComponentObserver.assistantGestureIsConstrained());
+ ActivityManager.RunningTaskInfo runningTask = newGestureState.getRunningTask();
+ if (mDeviceState.canTriggerAssistantAction(event, runningTask)) {
+ // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
+ // should not interrupt it. QuickSwitch assumes that interruption can only
+ // happen if the next gesture is also quick switch.
+ mUncheckedConsumer = new AssistantInputConsumer(
+ this,
+ newGestureState,
+ InputConsumer.NO_OP, mInputMonitorCompat,
+ mOverviewComponentObserver.assistantGestureIsConstrained());
+ } else {
+ newGestureState = DEFAULT_STATE;
+ mUncheckedConsumer = InputConsumer.NO_OP;
+ }
} else {
newGestureState = DEFAULT_STATE;
mUncheckedConsumer = InputConsumer.NO_OP;
@@ -536,6 +549,9 @@
private InputConsumer newConsumer(GestureState previousGestureState,
GestureState newGestureState, MotionEvent event) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "newConsumer");
+ }
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
if (!mDeviceState.isUserUnlocked()) {
@@ -547,6 +563,9 @@
return mResetGestureInputConsumer;
}
}
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "newConsumer:user is unlocked");
+ }
// When there is an existing recents animation running, bypass systemState check as this is
// a followup gesture and the first gesture started in a valid system state.
@@ -558,7 +577,7 @@
handleOrientationSetup(base);
}
if (mDeviceState.isFullyGesturalNavMode()) {
- if (mDeviceState.canTriggerAssistantAction(event)) {
+ if (mDeviceState.canTriggerAssistantAction(event, newGestureState.getRunningTask())) {
base = new AssistantInputConsumer(
this,
newGestureState,
@@ -588,6 +607,13 @@
}
}
+ // If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
+ // instead of going all the way home when a swipe up is detected.
+ if (mDeviceState.isBubblesExpanded() || mDeviceState.isGlobalActionsShowing()) {
+ base = new SysUiOverlayInputConsumer(
+ getBaseContext(), mDeviceState, mInputMonitorCompat);
+ }
+
if (mDeviceState.isScreenPinningActive()) {
// Note: we only allow accessibility to wrap this, and it replaces the previous
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
@@ -725,12 +751,13 @@
if (!mDeviceState.isUserUnlocked()) {
return;
}
+
if (mDeviceState.isButtonNavMode() && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
// Prevent the overview from being started before the real home on first boot.
return;
}
- if (RestoreDbTask.isPending(this)) {
+ if (RestoreDbTask.isPending(this) || !mDeviceState.isUserSetupComplete()) {
// Preloading while a restore is pending may cause launcher to start the restore
// too early.
return;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
new file mode 100644
index 0000000..3f833c0
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
@@ -0,0 +1,86 @@
+/*
+ * 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.inputconsumers;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.PointF;
+import android.view.MotionEvent;
+
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.TestProtocol;
+import com.android.quickstep.InputConsumer;
+import com.android.quickstep.RecentsAnimationDeviceState;
+import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+/**
+ * Input consumer used when a fullscreen System UI overlay is showing (such as the expanded Bubbles
+ * UI).
+ *
+ * This responds to swipes up by sending a closeSystemDialogs broadcast (causing overlays to close)
+ * rather than closing the app behind the overlay and sending the user all the way home.
+ */
+public class SysUiOverlayInputConsumer implements InputConsumer,
+ TriggerSwipeUpTouchTracker.OnSwipeUpListener {
+
+ private final Context mContext;
+ private final InputMonitorCompat mInputMonitor;
+ private final TriggerSwipeUpTouchTracker mTriggerSwipeUpTracker;
+
+ public SysUiOverlayInputConsumer(
+ Context context,
+ RecentsAnimationDeviceState deviceState,
+ InputMonitorCompat inputMonitor) {
+ mContext = context;
+ mInputMonitor = inputMonitor;
+ mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(context, true,
+ deviceState.getNavBarPosition(), this::onInterceptTouch, this);
+ }
+
+ @Override
+ public int getType() {
+ return TYPE_SYSUI_OVERLAY;
+ }
+
+ @Override
+ public boolean allowInterceptByParent() {
+ return !mTriggerSwipeUpTracker.interceptedTouch();
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent ev) {
+ mTriggerSwipeUpTracker.onMotionEvent(ev);
+ }
+
+ private void onInterceptTouch() {
+ if (mInputMonitor != null) {
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_PILFER, "pilferPointers");
+ mInputMonitor.pilferPointers();
+ }
+ }
+
+ @Override
+ public void onSwipeUp(boolean wasFling, PointF finalVelocity) {
+ // Close system dialogs when a swipe up is detected.
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ }
+
+ @Override
+ public void onSwipeUpCancelled() {
+
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
index 8a6c4a1..e5d2c53 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -29,6 +29,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.FlingSpringAnim;
import com.android.launcher3.util.DynamicResource;
+import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
import com.android.systemui.plugins.ResourceProvider;
import java.util.ArrayList;
@@ -39,7 +40,7 @@
* Applies spring forces to animate from a starting rect to a target rect,
* while providing update callbacks to the caller.
*/
-public class RectFSpringAnim {
+public class RectFSpringAnim extends ReleaseCheck {
private static final FloatPropertyCompat<RectFSpringAnim> RECT_CENTER_X =
new FloatPropertyCompat<RectFSpringAnim>("rectCenterXSpring") {
@@ -116,6 +117,7 @@
ResourceProvider rp = DynamicResource.provider(context);
mMinVisChange = rp.getDimension(R.dimen.swipe_up_fling_min_visible_change);
mYOvershoot = rp.getDimension(R.dimen.swipe_up_y_overshoot);
+ setCanRelease(true);
}
public void onTargetPositionChanged() {
@@ -190,10 +192,12 @@
maybeOnEnd();
});
+ setCanRelease(false);
+ mAnimsStarted = true;
+
mRectXAnim.start();
mRectYAnim.start();
mRectScaleAnim.start();
- mAnimsStarted = true;
for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
animatorListener.onAnimationStart(null);
}
@@ -245,6 +249,7 @@
private void maybeOnEnd() {
if (mAnimsStarted && isEnded()) {
mAnimsStarted = false;
+ setCanRelease(true);
for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
animatorListener.onAnimationEnd(null);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index ebc9f96..e7b965b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -121,8 +121,11 @@
addStaggeredAnimationForView(child, grid.inv.numRows + 1, totalRows);
}
- View qsb = launcher.findViewById(R.id.search_container_all_apps);
- addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
+ if (launcher.getAppsView().getSearchUiManager()
+ .isQsbVisible(NORMAL.getVisibleElements(launcher))) {
+ addStaggeredAnimationForView(launcher.getAppsView().getSearchView(),
+ grid.inv.numRows + 2, totalRows);
+ }
}
if (animateOverviewScrim) {
@@ -199,6 +202,12 @@
.setStartVelocity(mVelocity)
.build(v, VIEW_TRANSLATE_Y);
springTransY.setStartDelay(startDelay);
+ springTransY.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ v.setTranslationY(0f);
+ }
+ });
mAnimators.play(springTransY);
v.setAlpha(0);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SurfaceTransactionApplier.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SurfaceTransactionApplier.java
new file mode 100644
index 0000000..0a3e3ec
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SurfaceTransactionApplier.java
@@ -0,0 +1,136 @@
+/*
+ * 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.util;
+
+import static com.android.systemui.shared.system.TransactionCompat.deferTransactionUntil;
+import static com.android.systemui.shared.system.TransactionCompat.setEarlyWakeup;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.View;
+
+import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
+import com.android.systemui.shared.system.ViewRootImplCompat;
+
+import java.util.function.Consumer;
+
+
+/**
+ * Helper class to apply surface transactions in sync with RenderThread similar to
+ * android.view.SyncRtSurfaceTransactionApplier
+ * with some Launcher specific utility methods
+ */
+@TargetApi(Build.VERSION_CODES.R)
+public class SurfaceTransactionApplier extends ReleaseCheck {
+
+ private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
+
+ private final SurfaceControl mBarrierSurfaceControl;
+ private final ViewRootImplCompat mTargetViewRootImpl;
+ private final Handler mApplyHandler;
+
+ private int mLastSequenceNumber = 0;
+
+ /**
+ * @param targetView The view in the surface that acts as synchronization anchor.
+ */
+ public SurfaceTransactionApplier(View targetView) {
+ mTargetViewRootImpl = new ViewRootImplCompat(targetView);
+ mBarrierSurfaceControl = mTargetViewRootImpl.getRenderSurfaceControl();
+ mApplyHandler = new Handler(this::onApplyMessage);
+ }
+
+ protected boolean onApplyMessage(Message msg) {
+ if (msg.what == MSG_UPDATE_SEQUENCE_NUMBER) {
+ setCanRelease(msg.arg1 == mLastSequenceNumber);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Schedules applying surface parameters on the next frame.
+ *
+ * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
+ * this method to avoid synchronization issues.
+ */
+ public void scheduleApply(final SurfaceParams... params) {
+ View view = mTargetViewRootImpl.getView();
+ if (view == null) {
+ return;
+ }
+
+ mLastSequenceNumber++;
+ final int toApplySeqNo = mLastSequenceNumber;
+ setCanRelease(false);
+ mTargetViewRootImpl.registerRtFrameCallback(frame -> {
+ if (mBarrierSurfaceControl == null || !mBarrierSurfaceControl.isValid()) {
+ Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
+ .sendToTarget();
+ return;
+ }
+ Transaction t = new Transaction();
+ for (int i = params.length - 1; i >= 0; i--) {
+ SurfaceParams surfaceParams = params[i];
+ if (surfaceParams.surface.isValid()) {
+ deferTransactionUntil(t, surfaceParams.surface, mBarrierSurfaceControl, frame);
+ surfaceParams.applyTo(t);
+ }
+ }
+ setEarlyWakeup(t);
+ t.apply();
+ Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
+ .sendToTarget();
+ });
+
+ // Make sure a frame gets scheduled.
+ view.invalidate();
+ }
+
+ /**
+ * Creates an instance of SyncRtSurfaceTransactionApplier, deferring until the target view is
+ * attached if necessary.
+ */
+ public static void create(
+ final View targetView, final Consumer<SurfaceTransactionApplier> callback) {
+ if (targetView == null) {
+ // No target view, no applier
+ callback.accept(null);
+ } else if (new ViewRootImplCompat(targetView).isValid()) {
+ // Already attached, we're good to go
+ callback.accept(new SurfaceTransactionApplier(targetView));
+ } else {
+ // Haven't been attached before we can get the view root
+ targetView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ targetView.removeOnAttachStateChangeListener(this);
+ callback.accept(new SurfaceTransactionApplier(targetView));
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ // Do nothing
+ }
+ });
+ }
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 3c9762b..196a7c4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -258,9 +258,9 @@
mMatrix.postScale(scale, scale);
mMatrix.postTranslate(insets.left, insets.top);
- // Apply TaskView matrix: scale, translate, scroll
- mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2);
+ // Apply TaskView matrix: translate, scale, scroll
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
+ mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2);
mOrientationState.getOrientationHandler().set(
mMatrix, MATRIX_POST_TRANSLATE, mScrollState.scroll);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
index 9bb508e..7a62e83 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
@@ -57,7 +57,7 @@
private float mTargetAlpha;
private float mCornerRadius;
private RemoteAnimationTargets mTargetSet;
- private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
+ private SurfaceTransactionApplier mSyncTransactionApplier;
private BuilderProxy mHomeBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
private BuilderProxy mBaseBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
@@ -112,7 +112,7 @@
* are computed based on these TransformParams.
*/
public TransformParams setSyncTransactionApplier(
- SyncRtSurfaceTransactionApplierCompat applier) {
+ SurfaceTransactionApplier applier) {
mSyncTransactionApplier = applier;
return this;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
index 83287c4..08c3dc9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
@@ -21,6 +21,7 @@
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.Context;
+import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -33,6 +34,7 @@
import com.android.launcher3.R;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
@@ -129,6 +131,12 @@
updateHiddenFlags(HIDDEN_UNSUPPORTED_NAVIGATION, !removeShelfFromOverview(getContext()));
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
+ }
+
public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) {
if (enable) {
mHiddenFlags |= visibilityFlags;
@@ -152,10 +160,13 @@
return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA);
}
- /** Updates vertical margins for different navigation mode. */
- public void updateVerticalMarginForNavModeChange(Mode mode) {
- int bottomMargin = 0;
- if (mode == Mode.THREE_BUTTONS) {
+ /** Updates vertical margins for different navigation mode or configuration changes. */
+ public void updateVerticalMargin(Mode mode) {
+ int bottomMargin;
+ int orientation = getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ bottomMargin = 0;
+ } else if (mode == Mode.THREE_BUTTONS) {
bottomMargin = getResources()
.getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_three_button);
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 324aaec..64d90cf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -127,6 +127,7 @@
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitScreenBounds;
+import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
@@ -135,7 +136,6 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.LauncherEventUtil;
import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
@@ -211,7 +211,7 @@
protected final BaseActivityInterface mSizeStrategy;
protected RecentsAnimationController mRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
- protected SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
+ protected SurfaceTransactionApplier mSyncTransactionApplier;
protected int mTaskWidth;
protected int mTaskHeight;
protected boolean mEnableDrawingLiveTile = false;
@@ -492,6 +492,7 @@
public void init(OverviewActionsView actionsView) {
mActionsView = actionsView;
+ mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0);
}
@Override
@@ -501,7 +502,7 @@
mModel.getThumbnailCache().getHighResLoadingState().addCallback(this);
mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
- mSyncTransactionApplier = new SyncRtSurfaceTransactionApplierCompat(this);
+ mSyncTransactionApplier = new SurfaceTransactionApplier(this);
RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this);
mIdp.addOnChangeListener(this);
mIPinnedStackAnimationListener.setActivity(mActivity);
@@ -1626,8 +1627,10 @@
: View.LAYOUT_DIRECTION_RTL);
mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
mActivity.getDragLayer().recreateControllers();
+ boolean isInLandscape = touchRotation != 0
+ || mOrientationState.getLauncherRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
- touchRotation != 0 || mOrientationState.getLauncherRotation() != ROTATION_0);
+ !mOrientationState.canLauncherRotate() && isInLandscape);
resetPaddingFromTaskSize();
requestLayout();
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index 78ac1cc..3299736 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -227,8 +227,8 @@
protected void onDraw(Canvas canvas) {
RectF currentDrawnInsets = mFullscreenParams.mCurrentDrawnInsets;
canvas.save();
- canvas.translate(currentDrawnInsets.left, currentDrawnInsets.top);
canvas.scale(mFullscreenParams.mScale, mFullscreenParams.mScale);
+ canvas.translate(currentDrawnInsets.left, currentDrawnInsets.top);
// Draw the insets if we're being drawn fullscreen (we do this for quick switch).
drawOnCanvas(canvas,
-currentDrawnInsets.left,
@@ -357,6 +357,7 @@
mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
mPaint.setShader(mBitmapShader);
}
+ getTaskView().updateCurrentFullscreenParams(mPreviewPositionHelper);
invalidate();
// Update can be called from {@link #onSizeChanged} during layout, post handling of overlay
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 6b759ba..429ccf5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -30,6 +30,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import android.animation.Animator;
@@ -222,8 +223,10 @@
setOutlineProvider(mOutlineProvider);
}
- /* Builds proto for logging */
- protected LauncherAtom.ItemInfo buildProto() {
+ /**
+ * Builds proto for logging
+ */
+ public LauncherAtom.ItemInfo buildProto() {
ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(getTask().key);
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(componentKey.user != Process.myUserHandle());
@@ -424,6 +427,7 @@
private boolean showTaskMenu(int action) {
getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
mMenuView = TaskMenuView.showForTask(this);
+ mActivity.getStatsLogManager().log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS, buildProto());
UserEventDispatcher.newInstance(getContext()).logActionOnItem(action, Direction.NONE,
LauncherLogProto.ItemType.TASK_ICON);
if (mMenuView != null) {
@@ -951,11 +955,7 @@
setClipToPadding(!isFullscreen);
TaskThumbnailView thumbnail = getThumbnail();
- mCurrentFullscreenParams.setProgress(
- mFullscreenProgress,
- getRecentsView().getScaleX(),
- getWidth(), mActivity.getDeviceProfile(),
- thumbnail.getPreviewPositionHelper());
+ updateCurrentFullscreenParams(thumbnail.getPreviewPositionHelper());
if (!getRecentsView().isTaskIconScaledDown(this)) {
// Some of the items in here are dependent on the current fullscreen params, but don't
@@ -968,6 +968,14 @@
invalidateOutline();
}
+ void updateCurrentFullscreenParams(PreviewPositionHelper previewPositionHelper) {
+ mCurrentFullscreenParams.setProgress(
+ mFullscreenProgress,
+ getRecentsView().getScaleX(),
+ getWidth(), mActivity.getDeviceProfile(),
+ previewPositionHelper);
+ }
+
public boolean isRunningTask() {
if (getRecentsView() == null) {
return false;
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 74197be..459d65f 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -16,7 +16,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/gesture_tutorial_background_color">
+ android:background="?android:attr/colorBackground">
<View
android:id="@+id/gesture_tutorial_ripple_view"
@@ -49,6 +49,7 @@
android:background="@android:color/transparent"
android:accessibilityTraversalAfter="@id/gesture_tutorial_fragment_titles_container"
android:contentDescription="@string/gesture_tutorial_close_button_content_description"
+ android:tint="?android:attr/textColorPrimary"
android:src="@drawable/gesture_tutorial_close_button"/>
<LinearLayout
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 6d81b8e..77d9904 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"የመተግበሪያ አስተያየቶች"</string>
<string name="all_apps_label" msgid="8542784161730910663">"ሁሉም መተግበሪያዎች"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"የእርስዎ የሚገመቱ መተግበሪያዎች"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"በብዛት ስራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ይድረሱ"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel እርስዎ ቀጥለው የሚፈልጓቸውን መተግበሪያዎች ይገምታል፣ በዚያው በመነሻ ገጽዎ ላይ። ለማዋቀር መታ ያድርጉ።"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"በመነሻ ገጽዎ ታችኛው ረድፍ ላይ የመተግበሪያ አስተያየት ጥቆማዎችን ያግኙ"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"በጣም ስራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ። በታችኛው ረድፍ ላይ ያሉ መተግበሪያዎች ወደ መነሻ ገጽዎ ይወሰዳሉ።"</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"በጣም ስራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ። በታችኛው ረድፍ ላይ ያሉ መተግበሪያዎች ወደ አዲስ አቃፊ ይወሰዳሉ።"</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"በብዛት ስራ ላይ የዋሉ መተግበሪያዎች እዚህ ይመጣሉ፣ እና በዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"የመተግበሪያ ጥቆማዎችን ለማግኘት መተግበሪያዎችን ከታችኛው ረድፍ ይጎትቱ"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"የመተግበሪያ አስተያየት ጥቆማዎች ወደ ባዶ ቦታ ታክለዋል"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"የተገመተው መተግበሪያ፦ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"አጋራ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 6f07cec..a309331 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"App-Vorschläge"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Alle Apps"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"App-Vorschläge für dich"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Einfacher Zugriff auf deine meistverwendeten Apps"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel prognostiziert, welche Apps du als nächste brauchst, und setzt diese direkt auf den Startbildschirm. Zum Einrichten tippen."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Lass dir in der unteren Reihe auf deinem Startbildschirm Vorschläge für Apps anzeigen"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge richten sich nach deiner gewöhnlichen Nutzung. Apps in der unteren Reihe werden nach oben auf den Startbildschirm verschoben."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge richten sich nach deiner gewöhnlichen Nutzung. Apps in der unteren Reihe werden in einen neuen Ordner verschoben."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Hier erscheinen die meistverwendeten Apps. Die Angaben können sich je nach deiner gewöhnlichen Nutzung ändern"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Ziehe Apps aus der unteren Reihe heraus, um Vorschläge für Apps zu bekommen"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"App-Vorschläge in freiem Bereich hinzugefügt"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App-Vorhersage: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Teilen"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 688426c..7fca75e 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Προτεινόμενες εφαρμογές"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Όλες οι εφαρμογές"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Προβλέψεις εφαρμογών"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Εύκολη πρόσβαση στις εφαρμογές που χρησιμοποιείτε περισσότερο"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Το Pixel προβλέπει τις εφαρμογές που θα χρειαστείτε μετά, απευθείας στην αρχική οθόνη. Πατήστε για ρύθμιση."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Δείτε τις προτεινόμενες εφαρμογές στην κάτω σειρά της αρχικής οθόνης"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Αποκτήστε εύκολα πρόσβαση στις εφαρμογές που χρησιμοποιείτε περισσότερο απευθείας από την αρχική οθόνη. Οι προτάσεις θα αλλάζουν με βάση τις ρουτίνες σας. Οι εφαρμογές στην κάτω σειρά θα μετακινηθούν προς τα επάνω στην αρχική οθόνη."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Αποκτήστε εύκολα πρόσβαση στις εφαρμογές που χρησιμοποιείτε περισσότερο, απευθείας από την αρχική οθόνη. Οι προτάσεις θα αλλάζουν με βάση τις ρουτίνες σας. Οι εφαρμογές στην κάτω σειρά θα μεταφερθούν σε νέο φάκελο."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Οι εφαρμογές που χρησιμοποιείτε περισσότερο εμφανίζονται εδώ και αλλάζουν με βάση τις ρουτίνες"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Σύρετε εφαρμογές μακριά από την κάτω σειρά, για να δείτε τις προτεινόμενες εφαρμογές"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Οι προτεινόμενες εφαρμογές προστέθηκαν στον κενό χώρο"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Εφαρμογή από πρόβλεψη: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Κοινοποίηση"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 70753e2..c166708 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"App suggestions"</string>
<string name="all_apps_label" msgid="8542784161730910663">"All apps"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Your predicted apps"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Easily access your most-used apps"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel predicts apps youll need next, right on your Home screen. Tap to set up."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Get app suggestions on the bottom row of your Home screen"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move up to your Home screen."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Easily access your most-used apps, right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move to a new folder."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Most-used apps appear here, and change based on routines"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Drag apps off the bottom row to get app suggestions"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"App suggestions added to empty space"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicted app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 0ada754..7fa7710 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -32,10 +32,8 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Sugerencias de aplicaciones"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Todas las apps"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Predicción de tus apps"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Accede fácilmente a las apps que más usas"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel predice las apps que usarás la próxima vez en la pantalla principal. Presiona para configurar esta opción."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Obtén sugerencias de aplicaciones en la fila inferior de la pantalla principal"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accede fácilmente en la pantalla principal a las apps que más usas. Las sugerencias cambiarán según tus rutinas. Las apps de la fila inferior se moverán hacia arriba en la pantalla principal."</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accede fácilmente en la pantalla principal a las apps que más usas. Las sugerencias cambiarán según tus rutinas. Las apps de la fila inferior se desplazarán hacia arriba en la pantalla principal."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Accede fácilmente a las apps que más usas en la pantalla principal. Las sugerencias cambiarán según tus rutinas. Las apps de la fila inferior se moverán a una nueva carpeta."</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"Obtén sugerencias de aplicaciones"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"No, gracias"</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Las apps que más se usan se muestran aquí y cambian según las rutinas"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Arrastra apps fuera de la fila inferior para obtener sugerencias"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Se agregaron sugerencias de aplicaciones a un espacio vacío"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicción de app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Compartir"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index aa31197..9a3972a 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Applications suggérées"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Toutes les applications"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Applications prévues pour vous"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Accédez facilement à vos applications les plus utilisées"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel prédit les applications dont vous pourriez avoir besoin par la suite et les affiche sur votre écran d\'accueil. Appuyez ici pour configurer ce paramètre."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Retrouvez vos applications favorites au bas de votre écran d\'accueil"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Les suggestions d\'applications permettent d\'afficher vos applications favorites au bas de votre écran d\'accueil. Elles s\'adaptent à vos habitudes d\'utilisation. Les icônes auparavant affichées au bas de l\'écran seront déplacées vers le haut."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Les suggestions d\'applications permettent d\'afficher vos applications favorites au bas de votre écran d\'accueil. Elles s\'adaptent à vos habitudes d\'utilisation. Les icônes auparavant affichées au bas de l\'écran seront placées dans un nouveau dossier."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Les applications dont vous vous servez le plus s\'affichent ici (ces suggestions peuvent varier en fonction de vos habitudes d\'utilisation)"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Faites glisser des applications hors de la rangée du bas pour obtenir des suggestions d\'applications"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Des suggestions d\'applications ont été ajoutées à un emplacement vide"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Application prédite : <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Partager"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index ecc195f..4c68663 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"앱 제안"</string>
<string name="all_apps_label" msgid="8542784161730910663">"모든 앱"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"추천 앱"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"가장 많이 사용한 앱에 간편하게 액세스"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel에서 다음번에 사용할 앱을 예상하여 홈 화면에 바로 표시해 줍니다. 설정하려면 탭하세요."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"홈 화면 하단 행에서 앱 제안을 확인하세요."</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"홈 화면에서 가장 많이 사용한 앱에 바로 액세스할 수 있습니다. 제안은 루틴에 따라 달라집니다. 하단 행의 앱이 홈 화면으로 이동합니다."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"홈 화면에서 가장 많이 사용한 앱에 바로 액세스할 수 있습니다. 제안은 루틴에 따라 달라집니다. 하단 행의 앱이 새로운 폴더로 이동합니다."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"가장 많이 사용한 앱이 여기에 표시되며 루틴에 따라 달라짐"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"하단 행에서 앱을 드래그하여 앱 제안 받기"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"빈 공간에 앱 제안 추가됨"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"예상 앱: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"공유"</string>
<string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 66402f2..388fee2 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -32,9 +32,7 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Санал болгож буй аппууд"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Бүх апп"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Таны таамагласан аппууд"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Хамгийн их ашигладаг аппууддаа хялбархан хандаарай"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel утас танд дараагийн удаа хэрэг болох аппуудыг таамаглаж, таны Үндсэн нүүрэнд харуулна. Тохируулахын тулд товшино уу."</string>
- <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Үндсэн нүүрнийхээ доод мөр дээр санал болгож буй аппуудыг аваарай"</string>
+ <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Үндсэн нүүрнийхээ доод мөрөнд санал болгож буй аппуудыг аваарай"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Хамгийн их ашигладаг аппууддаа Үндсэн нүүрээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөр дэх аппуудыг таны Үндсэн нүүр лүү дээш зөөнө."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Хамгийн их ашигладаг аппууддаа Үндсэн нүүрээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөр дэх аппуудыг шинэ фолдер луу зөөнө."</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"Санал болгож буй аппуудыг авах"</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Хамгийн их ашигладаг аппуудыг энд харуулах бөгөөд хэвшлээс хамаарч өөрчилдөг"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Санал болгож буй аппуудыг авахын тулд доод мөрөөс аппуудыг чирж гаргаарай"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Санал болгож буй аппуудыг хоосон зайд нэмсэн"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Таамаглаж буй апп: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Хуваалцах"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index d1dacf2..435259e 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -32,17 +32,17 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Sugestões de apps"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Todos os apps"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Suas predições de apps"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Acesse os apps mais usados de forma simples"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"O Pixel prevê de quais apps você precisará, diretamente na tela inicial. Toque para configurar."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Receba sugestões de apps na linha inferior da tela inicial"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Acesse os apps mais usados na tela inicial de forma simples. As sugestões mudarão de acordo com sua rotina. Os apps na linha inferior subirão para a tela inicial."</string>
- <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Acesse os apps mais usados na tela inicial de forma simples. As sugestões mudarão de acordo com sua rotina. Os apps na linha inferior serão movidos para uma nova pasta."</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Acesse diretamente na tela inicial os apps que você mais usa. As sugestões mudarão de acordo com sua rotina. Os apps na linha inferior serão movidos para a tela inicial."</string>
+ <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Acesse diretamente na tela inicial os apps que você mais usa. As sugestões mudarão de acordo com sua rotina. Os apps na linha inferior serão movidos para uma nova pasta."</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"Receber sugestões de apps"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"Não"</string>
<string name="hotseat_turn_off" msgid="7808360330229368470">"Configurações"</string>
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Os apps mais usados aparecem aqui e mudam de acordo com sua rotina"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Arraste apps da linha inferior para receber sugestões de apps"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Sugestões de apps adicionadas a um espaço vazio"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App previsto: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Compartilhar"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 285d4d2..73b99f4 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -32,17 +32,17 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Návrhy aplikácií"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Všetky aplikácie"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Vaše predpovedané aplikácie"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Získajte jednoduchý prístup k najpoužívanejším aplikáciám"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel predpovedá aplikácie, ktoré budete potrebovať, priamo na ploche. Klepnutím prejdete na nastavenie."</string>
- <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Získajte návrhy aplikácií v spodnom riadku plochy"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Získajte jednoduchý prístup k najpoužívanejším aplikáciám priamo na ploche. Návrhy sa budú meniť podľa vašich postupov. Aplikácie v spodnom riadku sa presunú nahor na plochu."</string>
- <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Získajte jednoduchý prístup k najpoužívanejším aplikáciám priamo na ploche. Návrhy sa budú meniť podľa vašich postupov. Aplikácie v spodnom riadku sa presunú do nového priečinka."</string>
- <string name="hotseat_edu_accept" msgid="1611544083278999837">"Získavať návrhy aplikácií"</string>
+ <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Nechajte si v spodnom riadku na ploche zobrazovať návrhy aplikácií"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Získajte jednoduchý prístup k najpoužívanejším aplikáciám priamo na ploche. Návrhy sa budú meniť podľa vašich zvyklostí. Aplikácie v spodnom riadku sa presunú nahor na plochu."</string>
+ <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Získajte jednoduchý prístup k najpoužívanejším aplikáciám priamo na ploche. Návrhy sa budú meniť podľa vašich zvyklostí. Aplikácie v spodnom riadku sa presunú do nového priečinka."</string>
+ <string name="hotseat_edu_accept" msgid="1611544083278999837">"Zobrazovať návrhy aplikácií"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"Nie, ďakujem"</string>
<string name="hotseat_turn_off" msgid="7808360330229368470">"Nastavenia"</string>
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Tu sú zobrazené najpoužívanejšie aplikácie a menia sa podľa postupov"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Ak chcete získať návrhy aplikácií, presuňte aplikácie zo spodného riadka"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Návrhy aplikácie boli pridané na prázdne miesto"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predpovedaná aplikácia: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Zdieľať"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snímka obrazovky"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 54c8c14..cf9fa5e 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Predlagane aplikacije"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Vse aplikacije"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Predvidene aplikacije"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Preprost dostop do najpogosteje uporabljenih aplikacij"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel že na začetnem zaslonu predvidi, katere aplikacije boste potrebovali v nadaljevanju. Dotaknite se, če želite nastaviti."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Oglejte si predlagane aplikacije v spodnji vrstici začetnega zaslona"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Preprosto dostopajte do najpogosteje uporabljenih aplikacij kar na začetnem zaslonu. Predlogi se spreminjajo na podlagi dejanj, ki jih pogosto izvajate. Aplikacije se iz spodnje vrstice premaknejo na začetni zaslon."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Preprosto dostopajte do najpogosteje uporabljenih aplikacij kar na začetnem zaslonu. Predlogi se spreminjajo na podlagi dejanj, ki jih pogosto izvajate. Aplikacije se iz spodnje vrstice premaknejo v novo mapo."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Tukaj so navedene najpogosteje uporabljene aplikacije in spremembe na podlagi rutin"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Če si želite ogledati predlagane aplikacije, povlecite aplikacije iz spodnje vrstice"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Predlagane aplikacije so bile dodane v prazni prostor"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predvidena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Deli"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 1e1df6a..1986370 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -32,8 +32,6 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"Mapendekezo ya programu"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Programu zote"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Programu zako zinazopendekezwa"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"Fikia kwa urahisi programu unazotumia zaidi"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel hutabiri programu zinazofuata utakazohitaji, moja kwa moja kwenye Skrini yako ya kwanza. Gusa ili uweke mipangilio."</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Pata mapendekezo ya programu kwenye safu mlalo ya chini ya Skrini yako ya kwanza"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Fikia kwa urahisi programu unazotumia sana moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye safu mlalo ya chini zitahamishiwa kwenye Skrini yako ya kwanza."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Fikia kwa urahisi programu unazotumia zaidi, moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye safu mlalo ya chini zitahamishiwa kwenye folda mpya."</string>
@@ -43,6 +41,8 @@
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Programu zinazotumiwa zaidi huonekana hapa na hubadilika kulingana na ratiba"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Buruta programu kutoka kwenye safu mlalo ya chini ili upate mapendekezo ya programu"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Mapendekezo ya programu yamewekwa kwenye nafasi isiyo na kitu"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Programu iliyotabiriwa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Shiriki"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Picha ya skrini"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 0c9c830..28bea34 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -32,17 +32,17 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"คำแนะนำเกี่ยวกับแอป"</string>
<string name="all_apps_label" msgid="8542784161730910663">"แอปทั้งหมด"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"แอปที่คาดการณ์ไว้"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"เข้าถึงแอปที่ใช้มากที่สุดได้โดยง่าย"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel จะคาดคะเนว่าคุณต้องการใช้แอปใดต่อไป และจะแสดงแอปนั้นในหน้าจอหลัก แตะเพื่อตั้งค่า"</string>
- <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"ดูคำแนะนำเกี่ยวกับแอปที่แถวล่างของหน้าจอหลัก"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"เข้าถึงแอปที่ใช้มากที่สุดได้โดยง่ายในหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามการใช้งานประจำ แอปในแถวล่างจะย้ายขึ้นมาอยู่ในหน้าจอหลัก"</string>
- <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"เข้าถึงแอปที่ใช้มากที่สุดได้โดยง่ายในหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามการใช้งานประจำ แอปในแถวล่างจะย้ายไปอยู่ในโฟลเดอร์ใหม่"</string>
- <string name="hotseat_edu_accept" msgid="1611544083278999837">"ดูคำแนะนำเกี่ยวกับแอป"</string>
+ <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"รับคำแนะนำเกี่ยวกับแอปที่แถวล่างของหน้าจอหลัก"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"เข้าถึงแอปที่คุณใช้มากที่สุดได้อย่างง่ายดายจากหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามแอปที่ใช้งานเป็นประจำ แอปในแถวล่างจะย้ายขึ้นมาอยู่ในหน้าจอหลัก"</string>
+ <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"เข้าถึงแอปที่คุณใช้มากที่สุดได้อย่างง่ายดายจากหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามแอปที่ใช้งานเป็นประจำ แอปในแถวล่างจะย้ายไปอยู่ในโฟลเดอร์ใหม่"</string>
+ <string name="hotseat_edu_accept" msgid="1611544083278999837">"รับคำแนะนำเกี่ยวกับแอป"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"ไม่เป็นไร"</string>
<string name="hotseat_turn_off" msgid="7808360330229368470">"การตั้งค่า"</string>
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"แอปที่ใช้มากที่สุดจะปรากฎที่นี่และจะเปลี่ยนไปตามการใช้งานประจำ"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"ลากแอปออกจากแถวล่างเพื่อดูคำแนะนำเกี่ยวกับแอป"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"มีการเพิ่มคำแนะนำเกี่ยวกับแอปในพื้นที่ว่าง"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"แอปที่คาดว่าจะใช้: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"แชร์"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 7694212..0e3da7f 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -32,17 +32,17 @@
<string name="title_app_suggestions" msgid="4185902664111965088">"ایپس کی تجاویز"</string>
<string name="all_apps_label" msgid="8542784161730910663">"تمام ایپس"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"آپ کی پیشن گوئی کردہ ایپس"</string>
- <string name="hotseat_edu_prompt_title" msgid="5595771595144175752">"آسانی سے اپنی سب سے زیادہ مستعمل ایپس تک رسائی حاصل کریں"</string>
- <string name="hotseat_edu_prompt_content" msgid="5709176001504149521">"Pixel پیش گوئی کرتا ہے کہ آپ کو ہوم اسکرین پر ہی، آپ کے اگلے ایپس کی ضرورت ہوگی۔ سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"اپنی ہوم اسکرین کی نچلی قطار پر ایپ کی تجاویز حاصل کریں"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"ہوم اسکرین پر آسانی سے اپنی سب سے زیادہ مستعمل ایپس تک رسائی حاصل کریں۔ آپ کے روٹینز کی بنیاد پر تجاویز تبدیل ہوں گی۔ نچلی قطار میں موجود ایپس آپ کی ہوم اسکرین کے اوپر منتقل ہونگیں۔"</string>
- <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"ہوم اسکرین پر، آسانی سے اپنی سب سے زیادہ مستعمل ایپس تک رسائی حاصل کریں۔ آپ کے روٹینز کی بنیاد پر تجاویز تبدیل ہوں گی۔ نچلی قطار میں موجود ایپس نئے فولڈر میں منتقل ہونگیں۔"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"ہوم اسکرین پر آسانی سے اپنی سب سے زیادہ مستعمل ایپس تک رسائی حاصل کریں۔ آپ کی روٹینز کی بنیاد پر تجاویز تبدیل ہوں گی۔ نچلی قطار میں موجود ایپس آپ کی ہوم اسکرین کے اوپر منتقل ہوں گی۔"</string>
+ <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"ہوم اسکرین پر، آسانی سے اپنی سب سے زیادہ مستعمل ایپس تک رسائی حاصل کریں۔ آپ کی روٹینز کی بنیاد پر تجاویز تبدیل ہوں گی۔ نچلی قطار میں موجود ایپس نئے فولڈر میں منتقل ہوں گی۔"</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"ایپس کی تجاویز حاصل کریں"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"نہیں شکریہ"</string>
<string name="hotseat_turn_off" msgid="7808360330229368470">"ترتیبات"</string>
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"سب سے زیادہ مستعمل ایپس یہاں ظاہر ہوتی ہیں، اور روٹینز کی بنیاد پر تبدیل ہوتی ہیں"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"ایپس کی تجاویز حاصل کرنے کیلئے ایپس کو نچلی قطار سے نیچے گھسیٹیں"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"ایپس کی تجاویز کو خالی اسپیس میں شامل کر دیا گیا"</string>
+ <!-- no translation found for hotsaet_tip_prediction_enabled (4589474727906410667) -->
+ <skip />
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"پیشن گوئی کردہ ایپ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"اشتراک کریں"</string>
<string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 3583676..40da136 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -14,5 +14,6 @@
limitations under the License.
-->
<resources>
+ <color name="back_arrow_color_light">#FFFFFFFF</color>
<color name="back_arrow_color_dark">#99000000</color>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index be1d47b..a27c127 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -65,8 +65,10 @@
<!-- Hotseat educational strings for users who don't qualify for migration -->
<string name="hotseat_edu_title_migrate">Get app suggestions on the bottom row of your Home screen</string>
+ <string name="hotseat_edu_title_migrate_landscape">Get app suggestions on favorites row of your Home screen</string>
<string name="hotseat_edu_message_migrate">Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move up to your Home screen. </string>
+ <string name="hotseat_edu_message_migrate_landscape">Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps in favorites row will move to your Home screen. </string>
<string name="hotseat_edu_message_migrate_alt">Easily access your most-used apps, right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move to a new folder.</string>
<!-- Button text to opt in for fully predicted hotseat -->
@@ -83,11 +85,12 @@
<string name="hotseat_tip_no_empty_slots">Drag apps off the bottom row to get app suggestions</string>
<!-- tip shown if user declines migration and has some open spots for prediction -->
<string name="hotseat_tip_gaps_filled">App suggestions added to empty space</string>
+ <!-- tip shown when user migrates and predictions are enabled in hotseat -->
+ <string name="hotsaet_tip_prediction_enabled">App suggestions Enabled</string>
<!-- content description for hotseat items -->
<string name="hotseat_prediction_content_description">Predicted app: <xliff:g id="title" example="Chrome">%1$s</xliff:g></string>
-
<!-- Title shown during interactive part of Back gesture tutorial for right edge. [CHAR LIMIT=30] -->
<string name="back_gesture_tutorial_playground_title_swipe_inward_right_edge" translatable="false">Try the back gesture</string>
<!-- Subtitle shown during interactive parts of Back gesture tutorial for right edge. [CHAR LIMIT=60] -->
@@ -111,7 +114,6 @@
<!-- Subtitle shown on the confirmation screen after successful gesture. [CHAR LIMIT=60] -->
<string name="back_gesture_tutorial_confirm_subtitle" translatable="false">To change the sensitivity of the back gesture, go to Settings</string>
-
<!-- Title shown during interactive part of Home gesture tutorial. [CHAR LIMIT=30] -->
<string name="home_gesture_tutorial_playground_title" translatable="false">Tutorial: Go Home</string>
<!-- Subtitle shown during interactive parts of Home gesture tutorial. [CHAR LIMIT=60] -->
@@ -123,6 +125,28 @@
<!-- Feedback shown during interactive parts of Home gesture tutorial when the gesture is horizontal instead of vertical. [CHAR LIMIT=100] -->
<string name="home_gesture_feedback_wrong_swipe_direction" translatable="false">Make sure you swipe straight up</string>
+ <!-- Title shown during interactive part of Overview gesture tutorial. [CHAR LIMIT=30] -->
+ <string name="overview_gesture_tutorial_playground_title" translatable="false">Tutorial: Switch Apps</string>
+ <!-- Subtitle shown during interactive parts of Overview gesture tutorial. [CHAR LIMIT=60] -->
+ <string name="overview_gesture_tutorial_playground_subtitle" translatable="false">Swipe up from the bottom of the screen and hold</string>
+ <!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is started too far from the edge. [CHAR LIMIT=100] -->
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" translatable="false">Make sure you swipe from the bottom edge of the screen</string>
+ <!-- Feedback shown during interactive parts of Overview gesture tutorial when the Home gesture is detected. [CHAR LIMIT=100] -->
+ <string name="overview_gesture_feedback_home_detected" translatable="false">Try holding the window for longer before releasing</string>
+ <!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is horizontal instead of vertical. [CHAR LIMIT=100] -->
+ <string name="overview_gesture_feedback_wrong_swipe_direction" translatable="false">Make sure you swipe straight up and pause</string>
+
+ <!-- Title shown during interactive part of Assistant gesture tutorial. [CHAR LIMIT=30] -->
+ <string name="assistant_gesture_tutorial_playground_title" translatable="false">Tutorial: Assistant</string>
+ <!-- Subtitle shown during interactive parts of Assistant gesture tutorial. [CHAR LIMIT=60] -->
+ <string name="assistant_gesture_tutorial_playground_subtitle" translatable="false">Try swiping diagonally from a bottom corner of the screen</string>
+ <!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture is started too far from the corner. [CHAR LIMIT=100] -->
+ <string name="assistant_gesture_feedback_swipe_too_far_from_corner" translatable="false">Make sure you swipe from a bottom corner of the screen</string>
+ <!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture doesn't go diagonally enough. [CHAR LIMIT=100] -->
+ <string name="assistant_gesture_feedback_swipe_not_diagonal" translatable="false">Make sure you swipe diagonally</string>
+ <!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture doesn't go far enough. [CHAR LIMIT=100] -->
+ <string name="assistant_gesture_feedback_swipe_not_long_enough" translatable="false">Try swiping further</string>
+
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
<string name="gesture_tutorial_confirm_title" translatable="false">All set</string>
<!-- Button text shown on a button on the confirm screen to leave the tutorial. [CHAR LIMIT=14] -->
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 90957e4..8d054b4 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -35,14 +35,14 @@
<style name="TextAppearance.GestureTutorial.Title"
parent="TextAppearance.GestureTutorial">
<item name="android:gravity">center</item>
- <item name="android:textColor">@color/gesture_tutorial_title_color</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">28sp</item>
</style>
<style name="TextAppearance.GestureTutorial.Subtitle"
parent="TextAppearance.GestureTutorial">
<item name="android:gravity">center</item>
- <item name="android:textColor">@color/gesture_tutorial_subtitle_color</item>
+ <item name="android:textColor">?android:attr/textColorTertiary</item>
<item name="android:letterSpacing">0.03</item>
<item name="android:textSize">21sp</item>
</style>
@@ -50,7 +50,7 @@
<style name="TextAppearance.GestureTutorial.Feedback"
parent="TextAppearance.GestureTutorial">
<item name="android:gravity">center</item>
- <item name="android:textColor">@color/gesture_tutorial_feedback_color</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:letterSpacing">0.03</item>
<item name="android:textSize">21sp</item>
</style>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 0968d8e..4874307 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -93,7 +93,7 @@
public void onNavigationModeChanged(Mode newMode) {
getDragLayer().recreateControllers();
if (mActionsView != null && isOverviewActionsEnabled()) {
- mActionsView.updateVerticalMarginForNavModeChange(newMode);
+ mActionsView.updateVerticalMargin(newMode);
}
}
@@ -175,7 +175,7 @@
// Overview is above all other launcher elements, including qsb, so move it to the top.
getOverviewPanel().bringToFront();
mActionsView.bringToFront();
- mActionsView.updateVerticalMarginForNavModeChange(SysUINavigationMode.getMode(this));
+ mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
}
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 25c07f1..fe7b946 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -82,6 +82,7 @@
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
+import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.QuickStepContract;
@@ -89,7 +90,6 @@
import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -455,9 +455,9 @@
RemoteAnimationTargets openingTargets = new RemoteAnimationTargets(appTargets,
wallpaperTargets, MODE_OPENING);
- SyncRtSurfaceTransactionApplierCompat surfaceApplier =
- new SyncRtSurfaceTransactionApplierCompat(floatingView);
- openingTargets.addDependentTransactionApplier(surfaceApplier);
+ SurfaceTransactionApplier surfaceApplier =
+ new SurfaceTransactionApplier(floatingView);
+ openingTargets.addReleaseCheck(surfaceApplier);
// Scale the app icon to take up the entire screen. This simplifies the math when
// animating the app window position / scale.
@@ -712,8 +712,7 @@
*/
private Animator getUnlockWindowAnimator(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets) {
- SyncRtSurfaceTransactionApplierCompat surfaceApplier =
- new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
+ SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
ValueAnimator unlockAnimator = ValueAnimator.ofFloat(0, 1);
unlockAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
float cornerRadius = mDeviceProfile.isMultiWindowMode ? 0 :
@@ -741,8 +740,7 @@
*/
private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets) {
- SyncRtSurfaceTransactionApplierCompat surfaceApplier =
- new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
+ SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
Matrix matrix = new Matrix();
Point tmpPos = new Point();
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index 2181aa8..f42b124 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -77,6 +77,7 @@
private static final String EXTRA_ACTION = "action";
private static final String EXTRA_MAX_NUM_ACTIONS_SHOWN = "max_num_actions_shown";
private static final String EXTRA_PACKAGES = "packages";
+ private static final String EXTRA_SUCCESS = "success";
public static final MainThreadInitializedObject<WellbeingModel> INSTANCE =
new MainThreadInitializedObject<>(WellbeingModel::new);
@@ -221,6 +222,7 @@
params.putInt(EXTRA_MAX_NUM_ACTIONS_SHOWN, 1);
// Perform wellbeing call .
remoteActionBundle = client.call(METHOD_GET_ACTIONS, null, params);
+ if (!remoteActionBundle.getBoolean(EXTRA_SUCCESS, true)) return false;
synchronized (mModelLock) {
// Remove the entries for requested packages, and then update the fist with what we
@@ -281,9 +283,9 @@
// Remove all existing messages
mWorkerHandler.removeCallbacksAndMessages(null);
final String[] packageNames = mContext.getSystemService(LauncherApps.class)
- .getActivityList(null, Process.myUserHandle()).stream()
- .map(li -> li.getApplicationInfo().packageName).distinct()
- .toArray(String[]::new);
+ .getActivityList(null, Process.myUserHandle()).stream()
+ .map(li -> li.getApplicationInfo().packageName).distinct()
+ .toArray(String[]::new);
if (!updateActions(packageNames)) {
scheduleRefreshRetry(msg);
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index fcffaed..ebe9e26 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -17,6 +17,7 @@
package com.android.launcher3.statehandlers;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
import android.os.IBinder;
@@ -191,11 +192,12 @@
float toDepth = toState.getDepth(mLauncher);
if (Float.compare(mDepth, toDepth) != 0) {
- animation.setFloat(this, DEPTH, toDepth, LINEAR);
+ animation.setFloat(this, DEPTH, toDepth, config.getInterpolator(ANIM_DEPTH, LINEAR));
}
}
private void setDepth(float depth) {
+ depth = Utilities.boundToRange(depth, 0, 1);
// Round out the depth to dedupe frequent, non-perceptable updates
int depthI = (int) (depth * 256);
float depthF = depthI / 256f;
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index d411a77..ec720d5 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -34,6 +34,7 @@
int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
int TYPE_RESET_GESTURE = 1 << 8;
int TYPE_OVERSCROLL = 1 << 9;
+ int TYPE_SYSUI_OVERLAY = 1 << 10;
String[] NAMES = new String[] {
"TYPE_NO_OP", // 0
@@ -46,6 +47,7 @@
"TYPE_OVERVIEW_WITHOUT_FOCUS", // 7
"TYPE_RESET_GESTURE", // 8
"TYPE_OVERSCROLL", // 9
+ "TYPE_SYSUI_OVERLAY" // 10
};
InputConsumer NO_OP = () -> TYPE_NO_OP;
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index d06393a..3375c53 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -36,6 +36,7 @@
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
import java.io.PrintWriter;
@@ -157,8 +158,9 @@
mMode != SysUINavigationMode.Mode.TWO_BUTTONS;
if (mEnableMultipleRegions) {
mQuickStepStartingRotation = info.rotation;
- } else if (!enableMultipleRegions) {
- mLastRectRotation = mQuickStepStartingRotation = QUICKSTEP_ROTATION_UNINITIALIZED;
+ } else {
+ mLastRectRotation = 0;
+ mQuickStepStartingRotation = QUICKSTEP_ROTATION_UNINITIALIZED;
}
resetSwipeRegions(info);
}
@@ -245,6 +247,10 @@
}
boolean touchInValidSwipeRegions(float x, float y) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "touchInValidSwipeRegions " + x + "," + y + " in "
+ + mLastRectTouched);
+ }
if (mLastRectTouched != null) {
return mLastRectTouched.contains(x, y);
}
@@ -286,13 +292,20 @@
for (int i = 0; i < MAX_ORIENTATIONS; i++) {
OrientationRectF rect = mSwipeTouchRegions.get(i);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "transform:DOWN, rect=" + rect);
+ }
if (rect == null) {
continue;
}
if (rect.applyTransform(event, false)) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "setting mLastRectTouched");
+ }
mLastRectTouched = rect;
mLastRectRotation = rect.mRotation;
if (mEnableMultipleRegions && mCurrentDisplayRotation == mLastRectRotation) {
+ // TODO(b/154580671) might make this block unnecessary
// Start a touch session for the default nav region for the display
mQuickStepStartingRotation = mLastRectTouched.mRotation;
resetSwipeRegions();
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 8758821..161cc73 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -27,6 +27,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -45,6 +46,7 @@
import android.graphics.Region;
import android.os.Process;
import android.os.UserManager;
+import android.provider.Settings;
import android.text.TextUtils;
import android.view.MotionEvent;
@@ -53,6 +55,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DefaultDisplay;
+import com.android.launcher3.util.SecureSettingsObserver;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -128,6 +131,8 @@
private boolean mInOverview;
private boolean mTaskListFrozen;
+ private boolean mIsUserSetupComplete;
+
public RecentsAnimationDeviceState(Context context) {
mContext = context;
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
@@ -178,6 +183,17 @@
ComponentName.unflattenFromString(blockingActivity));
}
}
+
+ SecureSettingsObserver userSetupObserver = new SecureSettingsObserver(
+ context.getContentResolver(),
+ e -> mIsUserSetupComplete = e,
+ Settings.Secure.USER_SETUP_COMPLETE,
+ 0);
+ mIsUserSetupComplete = userSetupObserver.getValue();
+ if (!mIsUserSetupComplete) {
+ userSetupObserver.register();
+ runOnDestroy(userSetupObserver::unregister);
+ }
}
private void setupOrientationSwipeHandler() {
@@ -318,6 +334,13 @@
return mIsUserUnlocked;
}
+ /**
+ * @return whether the user has completed setup wizard
+ */
+ public boolean isUserSetupComplete() {
+ return mIsUserSetupComplete;
+ }
+
private void notifyUserUnlocked() {
for (Runnable action : mUserUnlockedActions) {
action.run();
@@ -364,7 +387,6 @@
return (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
&& (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
&& (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0
- && (mSystemUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) == 0
&& ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
|| (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0);
}
@@ -385,6 +407,20 @@
}
/**
+ * @return whether the bubble stack is expanded
+ */
+ public boolean isBubblesExpanded() {
+ return (mSystemUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
+ }
+
+ /**
+ * @return whether the global actions dialog is showing
+ */
+ public boolean isGlobalActionsShowing() {
+ return (mSystemUiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0;
+ }
+
+ /**
* @return whether lock-task mode is active
*/
public boolean isLockToAppActive() {
@@ -497,13 +533,15 @@
/**
* @param ev An ACTION_DOWN motion event
- * @return whether the given motion event can trigger the assistant.
+ * @param task Info for the currently running task
+ * @return whether the given motion event can trigger the assistant over the current task.
*/
- public boolean canTriggerAssistantAction(MotionEvent ev) {
+ public boolean canTriggerAssistantAction(MotionEvent ev, ActivityManager.RunningTaskInfo task) {
return mAssistantAvailable
&& !QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags)
&& mOrientationTouchTransformer.touchInAssistantRegion(ev)
- && !isLockToAppActive();
+ && !isLockToAppActive()
+ && !isGestureBlockedActivity(task);
}
/**
diff --git a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
index f90df45..ab5e3ba 100644
--- a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
@@ -16,19 +16,16 @@
package com.android.quickstep;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
-import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Queue;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* Holds a collection of RemoteAnimationTargets, filtered by different properties.
*/
public class RemoteAnimationTargets {
- private final Queue<SyncRtSurfaceTransactionApplierCompat> mDependentTransactionAppliers =
- new ArrayDeque<>(1);
+ private final CopyOnWriteArrayList<ReleaseCheck> mReleaseChecks = new CopyOnWriteArrayList<>();
public final RemoteAnimationTargetCompat[] unfilteredApps;
public final RemoteAnimationTargetCompat[] apps;
@@ -36,6 +33,8 @@
public final int targetMode;
public final boolean hasRecents;
+ private boolean mReleased = false;
+
public RemoteAnimationTargets(RemoteAnimationTargetCompat[] apps,
RemoteAnimationTargetCompat[] wallpapers, int targetMode) {
ArrayList<RemoteAnimationTargetCompat> filteredApps = new ArrayList<>();
@@ -76,21 +75,65 @@
return false;
}
- public void addDependentTransactionApplier(SyncRtSurfaceTransactionApplierCompat delay) {
- mDependentTransactionAppliers.add(delay);
+ public void addReleaseCheck(ReleaseCheck check) {
+ mReleaseChecks.add(check);
}
public void release() {
- SyncRtSurfaceTransactionApplierCompat applier = mDependentTransactionAppliers.poll();
- if (applier == null) {
- for (RemoteAnimationTargetCompat target : unfilteredApps) {
- target.release();
+ if (mReleased) {
+ return;
+ }
+ for (ReleaseCheck check : mReleaseChecks) {
+ if (!check.mCanRelease) {
+ check.addOnSafeToReleaseCallback(this::release);
+ return;
}
- for (RemoteAnimationTargetCompat target : wallpapers) {
- target.release();
+ }
+ mReleaseChecks.clear();
+ mReleased = true;
+
+ for (RemoteAnimationTargetCompat target : unfilteredApps) {
+ target.release();
+ }
+ for (RemoteAnimationTargetCompat target : wallpapers) {
+ target.release();
+ }
+ }
+
+ /**
+ * Interface for intercepting surface release method
+ */
+ public static class ReleaseCheck {
+
+ boolean mCanRelease = false;
+ private Runnable mAfterApplyCallback;
+
+ protected void setCanRelease(boolean canRelease) {
+ mCanRelease = canRelease;
+ if (mCanRelease && mAfterApplyCallback != null) {
+ Runnable r = mAfterApplyCallback;
+ mAfterApplyCallback = null;
+ r.run();
}
- } else {
- applier.addAfterApplyCallback(this::release);
+ }
+
+ /**
+ * Adds a callback to notify when the surface can safely be released
+ */
+ void addOnSafeToReleaseCallback(Runnable callback) {
+ if (mCanRelease) {
+ callback.run();
+ } else {
+ if (mAfterApplyCallback == null) {
+ mAfterApplyCallback = callback;
+ } else {
+ final Runnable oldCallback = mAfterApplyCallback;
+ mAfterApplyCallback = () -> {
+ callback.run();
+ oldCallback.run();
+ };
+ }
+ }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 20d133c..299e9e5 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -31,6 +31,7 @@
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.systemui.shared.recents.model.Task;
/**
* Holds the reference to SystemUI.
@@ -344,4 +345,17 @@
}
}
}
+
+ @Override
+ public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
+ Insets visibleInsets, Task.TaskKey task) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSystemUiProxy.handleImageBundleAsScreenshot(screenImageBundle, locationInScreen,
+ visibleInsets, task);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call handleImageBundleAsScreenshot");
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
new file mode 100644
index 0000000..6862f07
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
@@ -0,0 +1,129 @@
+/*
+ * 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.interaction;
+
+import static com.android.quickstep.interaction.TutorialController.TutorialType.ASSISTANT_COMPLETE;
+
+import android.graphics.PointF;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
+import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
+
+/** A {@link TutorialController} for the Assistant tutorial. */
+final class AssistantGestureTutorialController extends TutorialController {
+
+ AssistantGestureTutorialController(AssistantGestureTutorialFragment fragment,
+ TutorialType tutorialType) {
+ super(fragment, tutorialType);
+ }
+
+ @Override
+ Integer getTitleStringId() {
+ switch (mTutorialType) {
+ case ASSISTANT:
+ return R.string.assistant_gesture_tutorial_playground_title;
+ case ASSISTANT_COMPLETE:
+ return R.string.gesture_tutorial_confirm_title;
+ }
+ return null;
+ }
+
+ @Override
+ Integer getSubtitleStringId() {
+ if (mTutorialType == TutorialType.ASSISTANT) {
+ return R.string.assistant_gesture_tutorial_playground_subtitle;
+ }
+ return null;
+ }
+
+ @Override
+ Integer getActionButtonStringId() {
+ if (mTutorialType == ASSISTANT_COMPLETE) {
+ return R.string.gesture_tutorial_action_button_label_done;
+ }
+ return null;
+ }
+
+ @Override
+ void onActionButtonClicked(View button) {
+ mTutorialFragment.closeTutorial();
+ }
+
+ @Override
+ public void onBackGestureAttempted(BackGestureResult result) {
+ switch (mTutorialType) {
+ case ASSISTANT:
+ switch (result) {
+ case BACK_COMPLETED_FROM_LEFT:
+ case BACK_COMPLETED_FROM_RIGHT:
+ case BACK_CANCELLED_FROM_LEFT:
+ case BACK_CANCELLED_FROM_RIGHT:
+ showFeedback(R.string.assistant_gesture_feedback_swipe_too_far_from_corner);
+ break;
+ }
+ break;
+ case ASSISTANT_COMPLETE:
+ if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
+ || result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) {
+ mTutorialFragment.closeTutorial();
+ }
+ break;
+ }
+ }
+
+
+ @Override
+ public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
+ switch (mTutorialType) {
+ case ASSISTANT:
+ switch (result) {
+ case HOME_GESTURE_COMPLETED:
+ case OVERVIEW_GESTURE_COMPLETED:
+ case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
+ case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
+ case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
+ case HOME_OR_OVERVIEW_CANCELLED:
+ showFeedback(R.string.assistant_gesture_feedback_swipe_too_far_from_corner);
+ break;
+ case ASSISTANT_COMPLETED:
+ hideFeedback();
+ hideHandCoachingAnimation();
+ showRippleEffect(
+ () -> mTutorialFragment.changeController(ASSISTANT_COMPLETE));
+ break;
+ case ASSISTANT_NOT_STARTED_BAD_ANGLE:
+ showFeedback(R.string.assistant_gesture_feedback_swipe_not_diagonal);
+ break;
+ case ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT:
+ showFeedback(R.string.assistant_gesture_feedback_swipe_not_long_enough);
+ break;
+ }
+ break;
+ case ASSISTANT_COMPLETE:
+ if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
+ mTutorialFragment.closeTutorial();
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void setAssistantProgress(float progress) {
+ // TODO: Create an animation.
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java
new file mode 100644
index 0000000..70181fb
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java
@@ -0,0 +1,48 @@
+/*
+ * 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.interaction;
+
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.quickstep.interaction.TutorialController.TutorialType;
+
+/** Shows the Home gesture interactive tutorial. */
+public class AssistantGestureTutorialFragment extends TutorialFragment {
+ @Override
+ int getHandAnimationResId() {
+ return R.drawable.assistant_gesture;
+ }
+
+ @Override
+ TutorialController createController(TutorialType type) {
+ return new AssistantGestureTutorialController(this, type);
+ }
+
+ @Override
+ Class<? extends TutorialController> getControllerClass() {
+ return AssistantGestureTutorialController.class;
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && mTutorialController != null) {
+ mTutorialController.setRippleHotspot(motionEvent.getX(), motionEvent.getY());
+ }
+ return super.onTouch(view, motionEvent);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 41e86e0..921e568 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -21,8 +21,6 @@
import android.graphics.PointF;
import android.view.View;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.R;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
@@ -35,14 +33,6 @@
}
@Override
- void transitToController() {
- super.transitToController();
- if (mTutorialType != BACK_NAVIGATION_COMPLETE) {
- showHandCoachingAnimation();
- }
- }
-
- @Override
Integer getTitleStringId() {
switch (mTutorialType) {
case RIGHT_EDGE_BACK_NAVIGATION:
@@ -164,7 +154,4 @@
}
}
}
-
- @Override
- public void setNavBarGestureProgress(@Nullable Float displacement) {}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
index 5bf5026..0521db4 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
@@ -280,7 +280,11 @@
new SpringForce()
.setStiffness(SpringForce.STIFFNESS_MEDIUM)
.setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
- mPaint.setColor(context.getColor(R.color.back_arrow_color_dark));
+ int currentNightMode =
+ context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ mPaint.setColor(context.getColor(currentNightMode == Configuration.UI_MODE_NIGHT_YES
+ ? R.color.back_arrow_color_light
+ : R.color.back_arrow_color_dark));
loadDimens();
updateArrowDirection();
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 1113bc2..0edabd4 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -15,142 +15,23 @@
*/
package com.android.quickstep.interaction;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
-import static com.android.quickstep.BaseSwipeUpHandlerV2.MAX_SWIPE_DURATION;
import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Insets;
-import android.graphics.Outline;
import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.RectF;
import android.os.Build;
-import android.view.SurfaceControl;
import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.WindowInsets.Type;
-import android.view.WindowManager;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
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.PendingAnimation;
-import com.android.quickstep.AnimatedFloat;
-import com.android.quickstep.GestureState;
-import com.android.quickstep.OverviewComponentObserver;
-import com.android.quickstep.RecentsAnimationDeviceState;
-import com.android.quickstep.SwipeUpAnimationLogic;
-import com.android.quickstep.SwipeUpAnimationLogic.RunningWindowAnim;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
-import com.android.quickstep.util.RectFSpringAnim;
-import com.android.quickstep.util.TransformParams;
-import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
/** A {@link TutorialController} for the Home tutorial. */
@TargetApi(Build.VERSION_CODES.R)
-final class HomeGestureTutorialController extends TutorialController {
-
- private float mFakeTaskViewRadius;
- private Rect mFakeTaskViewRect = new Rect();
-
- private final ViewSwipeUpAnimation mViewSwipeUpAnimation;
- private RunningWindowAnim mRunningWindowAnim;
+final class HomeGestureTutorialController extends SwipeUpGestureTutorialController {
HomeGestureTutorialController(HomeGestureTutorialFragment fragment, TutorialType tutorialType) {
super(fragment, tutorialType);
-
- RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(mContext);
- OverviewComponentObserver observer = new OverviewComponentObserver(mContext, deviceState);
- mViewSwipeUpAnimation = new ViewSwipeUpAnimation(mContext, deviceState,
- new GestureState(observer, -1));
- observer.onDestroy();
-
- DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext)
- .getDeviceProfile(mContext)
- .copy(mContext);
- Insets insets = mContext.getSystemService(WindowManager.class)
- .getCurrentWindowMetrics()
- .getWindowInsets()
- .getInsets(Type.systemBars());
- dp.updateInsets(new Rect(insets.left, insets.top, insets.right, insets.bottom));
- mViewSwipeUpAnimation.initDp(dp);
-
- mFakeTaskViewRadius = QuickStepContract.getWindowCornerRadius(mContext.getResources());
-
- mFakeTaskView.setClipToOutline(true);
- mFakeTaskView.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRoundRect(mFakeTaskViewRect, mFakeTaskViewRadius);
- }
- });
- }
-
- private void cancelRunningAnimation() {
- if (mRunningWindowAnim != null) {
- mRunningWindowAnim.cancel();
- }
- mRunningWindowAnim = null;
- }
-
- /** Fades the task view, optionally after animating to a fake Overview. */
- private void fadeOutFakeTaskView(boolean toOverviewFirst, @Nullable Runnable onEndRunnable) {
- cancelRunningAnimation();
- PendingAnimation anim = new PendingAnimation(300);
- AnimatorListenerAdapter resetTaskView = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation, boolean isReverse) {
- mFakeTaskView.setVisibility(View.INVISIBLE);
- mFakeTaskView.setAlpha(1);
- mRunningWindowAnim = null;
- }
- };
- if (toOverviewFirst) {
- anim.setFloat(mViewSwipeUpAnimation.getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation, boolean isReverse) {
- PendingAnimation fadeAnim = new PendingAnimation(300);
- fadeAnim.setViewAlpha(mFakeTaskView, 0, ACCEL);
- fadeAnim.addListener(resetTaskView);
- AnimatorSet animset = fadeAnim.buildAnim();
- animset.setStartDelay(100);
- animset.start();
- mRunningWindowAnim = RunningWindowAnim.wrap(animset);
- }
- });
- } else {
- anim.setViewAlpha(mFakeTaskView, 0, ACCEL);
- anim.addListener(resetTaskView);
- }
- if (onEndRunnable != null) {
- anim.addListener(AnimationSuccessListener.forRunnable(onEndRunnable));
- }
- AnimatorSet animset = anim.buildAnim();
- animset.start();
- mRunningWindowAnim = RunningWindowAnim.wrap(animset);
- }
-
- @Override
- void transitToController() {
- super.transitToController();
- if (mTutorialType != HOME_NAVIGATION_COMPLETE) {
- showHandCoachingAnimation();
- }
}
@Override
@@ -189,6 +70,14 @@
public void onBackGestureAttempted(BackGestureResult result) {
switch (mTutorialType) {
case HOME_NAVIGATION:
+ switch (result) {
+ case BACK_COMPLETED_FROM_LEFT:
+ case BACK_COMPLETED_FROM_RIGHT:
+ case BACK_CANCELLED_FROM_LEFT:
+ case BACK_CANCELLED_FROM_RIGHT:
+ showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge);
+ break;
+ }
break;
case HOME_NAVIGATION_COMPLETE:
if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
@@ -205,17 +94,8 @@
case HOME_NAVIGATION:
switch (result) {
case HOME_GESTURE_COMPLETED: {
- hideFeedback();
- cancelRunningAnimation();
- hideHandCoachingAnimation();
- RectFSpringAnim rectAnim =
- mViewSwipeUpAnimation.handleSwipeUpToHome(finalVelocity);
- // After home animation finishes, fade out and then move to the next screen.
- rectAnim.addAnimatorListener(AnimationSuccessListener.forRunnable(
- () -> fadeOutFakeTaskView(false,
- () -> mTutorialFragment.changeController(
- HOME_NAVIGATION_COMPLETE))));
- mRunningWindowAnim = RunningWindowAnim.wrap(rectAnim);
+ animateFakeTaskViewHome(finalVelocity, () ->
+ mTutorialFragment.changeController(HOME_NAVIGATION_COMPLETE));
break;
}
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
@@ -241,93 +121,4 @@
}
}
- @Override
- public void setNavBarGestureProgress(@Nullable Float displacement) {
- if (displacement == null || mTutorialType == HOME_NAVIGATION_COMPLETE) {
- mFakeTaskView.setVisibility(View.INVISIBLE);
- } else {
- mFakeTaskView.setVisibility(View.VISIBLE);
- if (mRunningWindowAnim == null) {
- mViewSwipeUpAnimation.updateDisplacement(displacement);
- }
- }
- }
-
- private class ViewSwipeUpAnimation extends SwipeUpAnimationLogic {
-
- ViewSwipeUpAnimation(Context context, RecentsAnimationDeviceState deviceState,
- GestureState gestureState) {
- super(context, deviceState, gestureState, new FakeTransformParams());
- }
-
- void initDp(DeviceProfile dp) {
- initTransitionEndpoints(dp);
- mTaskViewSimulator.setPreviewBounds(
- new Rect(0, 0, dp.widthPx, dp.heightPx), dp.getInsets());
- }
-
- @Override
- public void updateFinalShift() {
- float progress = mCurrentShift.value / mDragLengthFactor;
- mWindowTransitionController.setPlayFraction(progress);
- mTaskViewSimulator.apply(mTransformParams);
- }
-
- AnimatedFloat getCurrentShift() {
- return mCurrentShift;
- }
-
- RectFSpringAnim handleSwipeUpToHome(PointF velocity) {
- PointF velocityPxPerMs = new PointF(velocity.x, velocity.y);
- float currentShift = mCurrentShift.value;
- final float startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
- * getSingleFrameMs(mContext) / mTransitionDragLength, 0, mDragLengthFactor);
- float distanceToTravel = (1 - currentShift) * mTransitionDragLength;
-
- // we want the page's snap velocity to approximately match the velocity at
- // which the user flings, so we scale the duration by a value near to the
- // derivative of the scroll interpolator at zero, ie. 2.
- long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
- long duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
- HomeAnimationFactory homeAnimFactory = new HomeAnimationFactory(null) {
- @Override
- public AnimatorPlaybackController createActivityAnimationToHome() {
- return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
- }
-
- @NonNull
- @Override
- public RectF getWindowTargetRect() {
- int fakeHomeIconSizePx = mDp.allAppsIconSizePx;
- int fakeHomeIconLeft = (mDp.widthPx - fakeHomeIconSizePx) / 2;
- int fakeHomeIconTop = mDp.heightPx - (mDp.allAppsCellHeightPx * 3);
- return new RectF(fakeHomeIconLeft, fakeHomeIconTop,
- fakeHomeIconLeft + fakeHomeIconSizePx,
- fakeHomeIconTop + fakeHomeIconSizePx);
- }
- };
- RectFSpringAnim windowAnim = createWindowAnimationToHome(startShift, homeAnimFactory);
- windowAnim.start(mContext, velocityPxPerMs);
- return windowAnim;
- }
- }
-
- private class FakeTransformParams extends TransformParams {
-
- @Override
- public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
- SurfaceParams.Builder builder = new SurfaceParams.Builder((SurfaceControl) null);
- proxy.onBuildTargetParams(builder, null, this);
- return new SurfaceParams[] {builder.build()};
- }
-
- @Override
- public void applySurfaceParams(SurfaceParams[] params) {
- SurfaceParams p = params[0];
- mFakeTaskView.setAnimationMatrix(p.matrix);
- mFakeTaskViewRect.set(p.windowCrop);
- mFakeTaskViewRadius = p.cornerRadius;
- mFakeTaskView.invalidateOutline();
- }
- }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 4069c09..0e2312b 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -15,6 +15,10 @@
*/
package com.android.quickstep.interaction;
+import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_COMPLETED;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_BAD_ANGLE;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_GESTURE_COMPLETED;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_NOT_STARTED_TOO_FAR_FROM_EDGE;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_OR_OVERVIEW_CANCELLED;
@@ -22,38 +26,69 @@
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.OVERVIEW_GESTURE_COMPLETED;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.RectF;
+import android.os.SystemClock;
import android.view.Display;
+import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
import androidx.annotation.Nullable;
+import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
+import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
+import com.android.systemui.shared.system.QuickStepContract;
-/** Utility class to handle home gestures. */
+/** Utility class to handle Home and Assistant gestures. */
public class NavBarGestureHandler implements OnTouchListener,
TriggerSwipeUpTouchTracker.OnSwipeUpListener {
private static final String LOG_TAG = "NavBarGestureHandler";
+ private static final long RETRACT_GESTURE_ANIMATION_DURATION_MS = 300;
+ private final Context mContext;
private final Point mDisplaySize = new Point();
private final TriggerSwipeUpTouchTracker mSwipeUpTouchTracker;
- private int mBottomGestureHeight;
+ private final int mBottomGestureHeight;
+ private final GestureDetector mAssistantGestureDetector;
+ private final int mAssistantAngleThreshold;
+ private final RectF mAssistantLeftRegion = new RectF();
+ private final RectF mAssistantRightRegion = new RectF();
+ private final float mAssistantDragDistThreshold;
+ private final float mAssistantFlingDistThreshold;
+ private final long mAssistantTimeThreshold;
+ private final float mAssistantSquaredSlop;
+ private final PointF mAssistantStartDragPos = new PointF();
+ private final PointF mDownPos = new PointF();
+ private final PointF mLastPos = new PointF();
+ private boolean mTouchCameFromAssistantCorner;
private boolean mTouchCameFromNavBar;
- private float mDownY;
+ private boolean mPassedAssistantSlop;
+ private boolean mAssistantGestureActive;
+ private boolean mLaunchedAssistant;
+ private long mAssistantDragStartTime;
+ private float mAssistantDistance;
+ private float mAssistantTimeFraction;
+ private float mAssistantLastProgress;
+ @Nullable
private NavBarGestureAttemptCallback mGestureCallback;
NavBarGestureHandler(Context context) {
- final Display display = context.getDisplay();
+ mContext = context;
+ final Display display = mContext.getDisplay();
final int displayRotation;
if (display == null) {
displayRotation = Surface.ROTATION_0;
@@ -61,7 +96,6 @@
displayRotation = display.getRotation();
display.getRealSize(mDisplaySize);
}
- mDownY = mDisplaySize.y;
mSwipeUpTouchTracker =
new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
new NavBarPosition(Mode.NO_BUTTON, displayRotation),
@@ -70,6 +104,27 @@
final Resources resources = context.getResources();
mBottomGestureHeight =
ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, resources);
+ mAssistantDragDistThreshold =
+ resources.getDimension(R.dimen.gestures_assistant_drag_threshold);
+ mAssistantFlingDistThreshold =
+ resources.getDimension(R.dimen.gestures_assistant_fling_threshold);
+ mAssistantTimeThreshold =
+ resources.getInteger(R.integer.assistant_gesture_min_time_threshold);
+ mAssistantAngleThreshold =
+ resources.getInteger(R.integer.assistant_gesture_corner_deg_threshold);
+
+ mAssistantGestureDetector = new GestureDetector(context, new AssistantGestureListener());
+ int assistantWidth = resources.getDimensionPixelSize(R.dimen.gestures_assistant_width);
+ final float assistantHeight = Math.max(mBottomGestureHeight,
+ QuickStepContract.getWindowCornerRadius(resources));
+ mAssistantLeftRegion.bottom = mAssistantRightRegion.bottom = mDisplaySize.y;
+ mAssistantLeftRegion.top = mAssistantRightRegion.top = mDisplaySize.y - assistantHeight;
+ mAssistantLeftRegion.left = 0;
+ mAssistantLeftRegion.right = assistantWidth;
+ mAssistantRightRegion.right = mDisplaySize.x;
+ mAssistantRightRegion.left = mDisplaySize.x - assistantWidth;
+ float slop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mAssistantSquaredSlop = slop * slop;
}
void registerNavBarGestureAttemptCallback(NavBarGestureAttemptCallback callback) {
@@ -82,7 +137,7 @@
@Override
public void onSwipeUp(boolean wasFling, PointF finalVelocity) {
- if (mGestureCallback == null) {
+ if (mGestureCallback == null || mAssistantGestureActive) {
return;
}
finalVelocity.set(finalVelocity.x / 1000, finalVelocity.y / 1000);
@@ -98,36 +153,128 @@
@Override
public void onSwipeUpCancelled() {
- if (mGestureCallback != null) {
+ if (mGestureCallback != null && !mAssistantGestureActive) {
mGestureCallback.onNavBarGestureAttempted(HOME_OR_OVERVIEW_CANCELLED, new PointF());
}
}
@Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- int action = motionEvent.getAction();
+ public boolean onTouch(View view, MotionEvent event) {
+ int action = event.getAction();
boolean intercepted = mSwipeUpTouchTracker.interceptedTouch();
- if (action == MotionEvent.ACTION_DOWN) {
- mDownY = motionEvent.getY();
- mTouchCameFromNavBar = mDownY >= mDisplaySize.y - mBottomGestureHeight;
- if (!mTouchCameFromNavBar) {
- mGestureCallback.setNavBarGestureProgress(null);
- }
- mSwipeUpTouchTracker.init();
- } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) {
- mGestureCallback.onNavBarGestureAttempted(
- HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, new PointF());
- intercepted = true;
- }
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mDownPos.set(event.getX(), event.getY());
+ mLastPos.set(mDownPos);
+ mTouchCameFromAssistantCorner =
+ mAssistantLeftRegion.contains(event.getX(), event.getY())
+ || mAssistantRightRegion.contains(event.getX(), event.getY());
+ mAssistantGestureActive = mTouchCameFromAssistantCorner;
+ mTouchCameFromNavBar = !mTouchCameFromAssistantCorner
+ && mDownPos.y >= mDisplaySize.y - mBottomGestureHeight;
+ if (!mTouchCameFromNavBar && mGestureCallback != null) {
+ mGestureCallback.setNavBarGestureProgress(null);
+ }
+ mLaunchedAssistant = false;
+ mSwipeUpTouchTracker.init();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!mAssistantGestureActive) {
+ break;
+ }
+ mLastPos.set(event.getX(), event.getY());
+
+ if (!mPassedAssistantSlop) {
+ // Normal gesture, ensure we pass the slop before we start tracking the gesture
+ if (squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y)
+ > mAssistantSquaredSlop) {
+
+ mPassedAssistantSlop = true;
+ mAssistantStartDragPos.set(mLastPos.x, mLastPos.y);
+ mAssistantDragStartTime = SystemClock.uptimeMillis();
+
+ mAssistantGestureActive = isValidAssistantGestureAngle(
+ mDownPos.x - mLastPos.x, mDownPos.y - mLastPos.y);
+ if (!mAssistantGestureActive && mGestureCallback != null) {
+ mGestureCallback.onNavBarGestureAttempted(
+ ASSISTANT_NOT_STARTED_BAD_ANGLE, new PointF());
+ }
+ }
+ } else {
+ // Movement
+ mAssistantDistance = (float) Math.hypot(mLastPos.x - mAssistantStartDragPos.x,
+ mLastPos.y - mAssistantStartDragPos.y);
+ if (mAssistantDistance >= 0) {
+ final long diff = SystemClock.uptimeMillis() - mAssistantDragStartTime;
+ mAssistantTimeFraction = Math.min(diff * 1f / mAssistantTimeThreshold, 1);
+ updateAssistantProgress();
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) {
+ mGestureCallback.onNavBarGestureAttempted(
+ HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, new PointF());
+ intercepted = true;
+ break;
+ }
+ if (mAssistantGestureActive && !mLaunchedAssistant && mGestureCallback != null) {
+ mGestureCallback.onNavBarGestureAttempted(
+ ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT, new PointF());
+ ValueAnimator animator = ValueAnimator.ofFloat(mAssistantLastProgress, 0)
+ .setDuration(RETRACT_GESTURE_ANIMATION_DURATION_MS);
+ animator.addUpdateListener(valueAnimator -> {
+ float progress = (float) valueAnimator.getAnimatedValue();
+ mGestureCallback.setAssistantProgress(progress);
+ });
+ animator.setInterpolator(Interpolators.DEACCEL_2);
+ animator.start();
+ }
+ mPassedAssistantSlop = false;
+ break;
}
if (mTouchCameFromNavBar && mGestureCallback != null) {
- mGestureCallback.setNavBarGestureProgress(motionEvent.getY() - mDownY);
+ mGestureCallback.setNavBarGestureProgress(event.getY() - mDownPos.y);
}
- mSwipeUpTouchTracker.onMotionEvent(motionEvent);
+ mSwipeUpTouchTracker.onMotionEvent(event);
+ mAssistantGestureDetector.onTouchEvent(event);
return intercepted;
}
+ /**
+ * Determine if angle is larger than threshold for assistant detection
+ */
+ private boolean isValidAssistantGestureAngle(float deltaX, float deltaY) {
+ float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
+
+ // normalize so that angle is measured clockwise from horizontal in the bottom right corner
+ // and counterclockwise from horizontal in the bottom left corner
+ angle = angle > 90 ? 180 - angle : angle;
+ return (angle > mAssistantAngleThreshold && angle < 90);
+ }
+
+ private void updateAssistantProgress() {
+ if (!mLaunchedAssistant) {
+ mAssistantLastProgress =
+ Math.min(mAssistantDistance * 1f / mAssistantDragDistThreshold, 1)
+ * mAssistantTimeFraction;
+ if (mAssistantDistance >= mAssistantDragDistThreshold && mAssistantTimeFraction >= 1) {
+ startAssistant(new PointF());
+ } else if (mGestureCallback != null) {
+ mGestureCallback.setAssistantProgress(mAssistantLastProgress);
+ }
+ }
+ }
+
+ private void startAssistant(PointF velocity) {
+ if (mGestureCallback != null) {
+ mGestureCallback.onNavBarGestureAttempted(ASSISTANT_COMPLETED, velocity);
+ }
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(VibratorWrapper.EFFECT_CLICK);
+ mLaunchedAssistant = true;
+ }
+
enum NavBarGestureResult {
UNKNOWN,
HOME_GESTURE_COMPLETED,
@@ -135,7 +282,10 @@
HOME_NOT_STARTED_TOO_FAR_FROM_EDGE,
OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE,
HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, // Side swipe on nav bar.
- HOME_OR_OVERVIEW_CANCELLED
+ HOME_OR_OVERVIEW_CANCELLED,
+ ASSISTANT_COMPLETED,
+ ASSISTANT_NOT_STARTED_BAD_ANGLE,
+ ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT,
}
/** Callback to let the UI react to attempted nav bar gestures. */
@@ -144,6 +294,28 @@
void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity);
/** Indicates how far a touch originating in the nav bar has moved from the nav bar. */
- void setNavBarGestureProgress(@Nullable Float displacement);
+ default void setNavBarGestureProgress(@Nullable Float displacement) {}
+
+ /** Indicates the progress of an Assistant gesture. */
+ default void setAssistantProgress(float progress) {}
+ }
+
+ private class AssistantGestureListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ if (!mLaunchedAssistant && mTouchCameFromAssistantCorner) {
+ PointF velocity = new PointF(velocityX, velocityY);
+ if (!isValidAssistantGestureAngle(velocityX, -velocityY)) {
+ if (mGestureCallback != null) {
+ mGestureCallback.onNavBarGestureAttempted(ASSISTANT_NOT_STARTED_BAD_ANGLE,
+ velocity);
+ }
+ } else if (mAssistantDistance >= mAssistantFlingDistThreshold) {
+ mAssistantLastProgress = 1;
+ startAssistant(velocity);
+ }
+ }
+ return true;
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
new file mode 100644
index 0000000..c636eba
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -0,0 +1,124 @@
+/*
+ * 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.interaction;
+
+import static com.android.quickstep.interaction.TutorialController.TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
+
+import android.annotation.TargetApi;
+import android.graphics.PointF;
+import android.os.Build;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
+import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
+
+/** A {@link TutorialController} for the Overview tutorial. */
+@TargetApi(Build.VERSION_CODES.R)
+final class OverviewGestureTutorialController extends SwipeUpGestureTutorialController {
+
+ OverviewGestureTutorialController(OverviewGestureTutorialFragment fragment,
+ TutorialType tutorialType) {
+ super(fragment, tutorialType);
+ }
+
+ @Override
+ Integer getTitleStringId() {
+ switch (mTutorialType) {
+ case OVERVIEW_NAVIGATION:
+ return R.string.overview_gesture_tutorial_playground_title;
+ case OVERVIEW_NAVIGATION_COMPLETE:
+ return R.string.gesture_tutorial_confirm_title;
+ }
+ return null;
+ }
+
+ @Override
+ Integer getSubtitleStringId() {
+ if (mTutorialType == TutorialType.OVERVIEW_NAVIGATION) {
+ return R.string.overview_gesture_tutorial_playground_subtitle;
+ }
+ return null;
+ }
+
+ @Override
+ Integer getActionButtonStringId() {
+ if (mTutorialType == OVERVIEW_NAVIGATION_COMPLETE) {
+ return R.string.gesture_tutorial_action_button_label_done;
+ }
+ return null;
+ }
+
+ @Override
+ void onActionButtonClicked(View button) {
+ mTutorialFragment.closeTutorial();
+ }
+
+ @Override
+ public void onBackGestureAttempted(BackGestureResult result) {
+ switch (mTutorialType) {
+ case OVERVIEW_NAVIGATION:
+ switch (result) {
+ case BACK_COMPLETED_FROM_LEFT:
+ case BACK_COMPLETED_FROM_RIGHT:
+ case BACK_CANCELLED_FROM_LEFT:
+ case BACK_CANCELLED_FROM_RIGHT:
+ showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
+ break;
+ }
+ break;
+ case OVERVIEW_NAVIGATION_COMPLETE:
+ if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
+ || result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) {
+ mTutorialFragment.closeTutorial();
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
+ switch (mTutorialType) {
+ case OVERVIEW_NAVIGATION:
+ switch (result) {
+ case HOME_GESTURE_COMPLETED: {
+ animateFakeTaskViewHome(finalVelocity, () ->
+ showFeedback(R.string.overview_gesture_feedback_home_detected));
+ break;
+ }
+ case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
+ case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
+ showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
+ break;
+ case OVERVIEW_GESTURE_COMPLETED:
+ fadeOutFakeTaskView(true, () ->
+ mTutorialFragment.changeController(OVERVIEW_NAVIGATION_COMPLETE));
+ break;
+ case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
+ case HOME_OR_OVERVIEW_CANCELLED:
+ fadeOutFakeTaskView(false, null);
+ showFeedback(R.string.overview_gesture_feedback_wrong_swipe_direction);
+ break;
+ }
+ break;
+ case OVERVIEW_NAVIGATION_COMPLETE:
+ if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
+ mTutorialFragment.closeTutorial();
+ }
+ break;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
new file mode 100644
index 0000000..3357b70
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -0,0 +1,37 @@
+/*
+ * 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.interaction;
+
+import com.android.launcher3.R;
+import com.android.quickstep.interaction.TutorialController.TutorialType;
+
+/** Shows the Overview gesture interactive tutorial. */
+public class OverviewGestureTutorialFragment extends TutorialFragment {
+ @Override
+ int getHandAnimationResId() {
+ return R.drawable.overview_gesture;
+ }
+
+ @Override
+ TutorialController createController(TutorialType type) {
+ return new OverviewGestureTutorialController(this, type);
+ }
+
+ @Override
+ Class<? extends TutorialController> getControllerClass() {
+ return OverviewGestureTutorialController.class;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
new file mode 100644
index 0000000..14e00dc
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -0,0 +1,246 @@
+/*
+ * 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.interaction;
+
+import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
+import static com.android.quickstep.BaseSwipeUpHandlerV2.MAX_SWIPE_DURATION;
+import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
+import static com.android.quickstep.interaction.TutorialController.TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Insets;
+import android.graphics.Outline;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Build;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.quickstep.AnimatedFloat;
+import com.android.quickstep.GestureState;
+import com.android.quickstep.OverviewComponentObserver;
+import com.android.quickstep.RecentsAnimationDeviceState;
+import com.android.quickstep.SwipeUpAnimationLogic;
+import com.android.quickstep.SwipeUpAnimationLogic.RunningWindowAnim;
+import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.TransformParams;
+import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
+
+@TargetApi(Build.VERSION_CODES.R)
+abstract class SwipeUpGestureTutorialController extends TutorialController {
+ private final ViewSwipeUpAnimation mViewSwipeUpAnimation;
+ private float mFakeTaskViewRadius;
+ private Rect mFakeTaskViewRect = new Rect();
+ private RunningWindowAnim mRunningWindowAnim;
+
+ SwipeUpGestureTutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) {
+ super(tutorialFragment, tutorialType);
+ RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(mContext);
+ OverviewComponentObserver observer = new OverviewComponentObserver(mContext, deviceState);
+ mViewSwipeUpAnimation = new ViewSwipeUpAnimation(mContext, deviceState,
+ new GestureState(observer, -1));
+ observer.onDestroy();
+ deviceState.destroy();
+
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext)
+ .getDeviceProfile(mContext)
+ .copy(mContext);
+ Insets insets = mContext.getSystemService(WindowManager.class)
+ .getCurrentWindowMetrics()
+ .getWindowInsets()
+ .getInsets(WindowInsets.Type.systemBars());
+ dp.updateInsets(new Rect(insets.left, insets.top, insets.right, insets.bottom));
+ mViewSwipeUpAnimation.initDp(dp);
+
+ mFakeTaskViewRadius = QuickStepContract.getWindowCornerRadius(mContext.getResources());
+ mFakeTaskView.setClipToOutline(true);
+ mFakeTaskView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(mFakeTaskViewRect, mFakeTaskViewRadius);
+ }
+ });
+ }
+
+ private void cancelRunningAnimation() {
+ if (mRunningWindowAnim != null) {
+ mRunningWindowAnim.cancel();
+ }
+ mRunningWindowAnim = null;
+ }
+
+ /** Fades the task view, optionally after animating to a fake Overview. */
+ void fadeOutFakeTaskView(boolean toOverviewFirst, @Nullable Runnable onEndRunnable) {
+ hideFeedback();
+ hideHandCoachingAnimation();
+ cancelRunningAnimation();
+ PendingAnimation anim = new PendingAnimation(300);
+ AnimatorListenerAdapter resetTaskView = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation, boolean isReverse) {
+ mFakeTaskView.setVisibility(View.INVISIBLE);
+ mFakeTaskView.setAlpha(1);
+ mRunningWindowAnim = null;
+ }
+ };
+ if (toOverviewFirst) {
+ anim.setFloat(mViewSwipeUpAnimation.getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation, boolean isReverse) {
+ PendingAnimation fadeAnim = new PendingAnimation(300);
+ fadeAnim.setViewAlpha(mFakeTaskView, 0, ACCEL);
+ fadeAnim.addListener(resetTaskView);
+ AnimatorSet animset = fadeAnim.buildAnim();
+ animset.setStartDelay(100);
+ animset.start();
+ mRunningWindowAnim = RunningWindowAnim.wrap(animset);
+ }
+ });
+ } else {
+ anim.setViewAlpha(mFakeTaskView, 0, ACCEL);
+ anim.addListener(resetTaskView);
+ }
+ if (onEndRunnable != null) {
+ anim.addListener(AnimationSuccessListener.forRunnable(onEndRunnable));
+ }
+ AnimatorSet animset = anim.buildAnim();
+ animset.start();
+ mRunningWindowAnim = RunningWindowAnim.wrap(animset);
+ }
+
+ void animateFakeTaskViewHome(PointF finalVelocity, @Nullable Runnable onEndRunnable) {
+ hideFeedback();
+ hideHandCoachingAnimation();
+ cancelRunningAnimation();
+ RectFSpringAnim rectAnim =
+ mViewSwipeUpAnimation.handleSwipeUpToHome(finalVelocity);
+ // After home animation finishes, fade out and run onEndRunnable.
+ rectAnim.addAnimatorListener(AnimationSuccessListener.forRunnable(
+ () -> fadeOutFakeTaskView(false, onEndRunnable)));
+ mRunningWindowAnim = RunningWindowAnim.wrap(rectAnim);
+ }
+
+ @Override
+ public void setNavBarGestureProgress(@Nullable Float displacement) {
+ if (displacement == null || mTutorialType == HOME_NAVIGATION_COMPLETE
+ || mTutorialType == OVERVIEW_NAVIGATION_COMPLETE) {
+ mFakeTaskView.setVisibility(View.INVISIBLE);
+ } else {
+ mFakeTaskView.setVisibility(View.VISIBLE);
+ if (mRunningWindowAnim == null) {
+ mViewSwipeUpAnimation.updateDisplacement(displacement);
+ }
+ }
+ }
+
+ class ViewSwipeUpAnimation extends SwipeUpAnimationLogic {
+
+ ViewSwipeUpAnimation(Context context, RecentsAnimationDeviceState deviceState,
+ GestureState gestureState) {
+ super(context, deviceState, gestureState, new FakeTransformParams());
+ }
+
+ void initDp(DeviceProfile dp) {
+ initTransitionEndpoints(dp);
+ mTaskViewSimulator.setPreviewBounds(
+ new Rect(0, 0, dp.widthPx, dp.heightPx), dp.getInsets());
+ }
+
+ @Override
+ public void updateFinalShift() {
+ float progress = mCurrentShift.value / mDragLengthFactor;
+ mWindowTransitionController.setPlayFraction(progress);
+ mTaskViewSimulator.apply(mTransformParams);
+ }
+
+ AnimatedFloat getCurrentShift() {
+ return mCurrentShift;
+ }
+
+ RectFSpringAnim handleSwipeUpToHome(PointF velocity) {
+ PointF velocityPxPerMs = new PointF(velocity.x, velocity.y);
+ float currentShift = mCurrentShift.value;
+ final float startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
+ * getSingleFrameMs(mContext) / mTransitionDragLength, 0, mDragLengthFactor);
+ float distanceToTravel = (1 - currentShift) * mTransitionDragLength;
+
+ // we want the page's snap velocity to approximately match the velocity at
+ // which the user flings, so we scale the duration by a value near to the
+ // derivative of the scroll interpolator at zero, ie. 2.
+ long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
+ long duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
+ HomeAnimationFactory homeAnimFactory = new HomeAnimationFactory(null) {
+ @Override
+ public AnimatorPlaybackController createActivityAnimationToHome() {
+ return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
+ }
+
+ @NonNull
+ @Override
+ public RectF getWindowTargetRect() {
+ int fakeHomeIconSizePx = mDp.allAppsIconSizePx;
+ int fakeHomeIconLeft = (mDp.widthPx - fakeHomeIconSizePx) / 2;
+ int fakeHomeIconTop = mDp.heightPx - (mDp.allAppsCellHeightPx * 3);
+ return new RectF(fakeHomeIconLeft, fakeHomeIconTop,
+ fakeHomeIconLeft + fakeHomeIconSizePx,
+ fakeHomeIconTop + fakeHomeIconSizePx);
+ }
+ };
+ RectFSpringAnim windowAnim = createWindowAnimationToHome(startShift, homeAnimFactory);
+ windowAnim.start(mContext, velocityPxPerMs);
+ return windowAnim;
+ }
+ }
+
+ private class FakeTransformParams extends TransformParams {
+
+ @Override
+ public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
+ SurfaceParams.Builder builder = new SurfaceParams.Builder((SurfaceControl) null);
+ proxy.onBuildTargetParams(builder, null, this);
+ return new SurfaceParams[] {builder.build()};
+ }
+
+ @Override
+ public void applySurfaceParams(SurfaceParams[] params) {
+ SurfaceParams p = params[0];
+ mFakeTaskView.setAnimationMatrix(p.matrix);
+ mFakeTaskViewRect.set(p.windowCrop);
+ mFakeTaskViewRadius = p.cornerRadius;
+ mFakeTaskView.invalidateOutline();
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index f27d500..c1918c2 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -140,6 +140,9 @@
void onActionTextButtonClicked(View button) {}
void showHandCoachingAnimation() {
+ if (isComplete()) {
+ return;
+ }
mHandCoachingAnimation.startLoopedAnimation(mTutorialType);
}
@@ -153,6 +156,12 @@
hideFeedback();
updateTitles();
updateActionButtons();
+
+ if (isComplete()) {
+ hideHandCoachingAnimation();
+ } else {
+ showHandCoachingAnimation();
+ }
}
private void updateTitles() {
@@ -190,12 +199,23 @@
button.setOnClickListener(listener);
}
+ private boolean isComplete() {
+ return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE
+ || mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE
+ || mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE
+ || mTutorialType == TutorialType.ASSISTANT_COMPLETE;
+ }
+
/** Denotes the type of the tutorial. */
enum TutorialType {
RIGHT_EDGE_BACK_NAVIGATION,
LEFT_EDGE_BACK_NAVIGATION,
BACK_NAVIGATION_COMPLETE,
HOME_NAVIGATION,
- HOME_NAVIGATION_COMPLETE
+ HOME_NAVIGATION_COMPLETE,
+ OVERVIEW_NAVIGATION,
+ OVERVIEW_NAVIGATION_COMPLETE,
+ ASSISTANT,
+ ASSISTANT_COMPLETE
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index a3881cf..9a8264d 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -68,6 +68,12 @@
case HOME_NAVIGATION:
case HOME_NAVIGATION_COMPLETE:
return new HomeGestureTutorialFragment();
+ case OVERVIEW_NAVIGATION:
+ case OVERVIEW_NAVIGATION_COMPLETE:
+ return new OverviewGestureTutorialFragment();
+ case ASSISTANT:
+ case ASSISTANT_COMPLETE:
+ return new AssistantGestureTutorialFragment();
default:
Log.e(LOG_TAG, "Failed to find an appropriate fragment for " + tutorialType.name());
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 6efdd7b..04f1169 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -164,10 +164,10 @@
getHierarchy(info) /* hierarchy */,
info.getIsWork() /* is_work_profile */,
info.getRank() /* rank */,
- 0 /* fromState */,
- 0 /* toState */,
- null /* edittext */,
- 0 /* cardinality */);
+ info.getFolderIcon().getFromLabelState().getNumber() /* fromState */,
+ info.getFolderIcon().getToLabelState().getNumber() /* toState */,
+ info.getFolderIcon().getLabelInfo() /* edittext */,
+ info.getFolderIcon().getCardinality() /* cardinality */);
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index f5fbf28..0b48a8b 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -39,6 +39,8 @@
import com.android.launcher3.BuildConfig;
import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.utilities.BitmapUtil;
import java.io.File;
import java.io.FileOutputStream;
@@ -59,8 +61,9 @@
*/
public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
Rect screenshotBounds,
- Insets visibleInsets, int taskId) {
- systemUiProxy.handleImageAsScreenshot(screenshot, screenshotBounds, visibleInsets, taskId);
+ Insets visibleInsets, Task.TaskKey task) {
+ systemUiProxy.handleImageBundleAsScreenshot(BitmapUtil.hardwareBitmapToBundle(screenshot),
+ screenshotBounds, visibleInsets, task);
}
/**
diff --git a/res/drawable/gesture_tutorial_ripple.xml b/res/drawable/gesture_tutorial_ripple.xml
index ca45662..782af33 100644
--- a/res/drawable/gesture_tutorial_ripple.xml
+++ b/res/drawable/gesture_tutorial_ripple.xml
@@ -1,6 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple android:color="@color/gesture_tutorial_ripple_color"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@android:id/mask"
- android:drawable="@color/gesture_tutorial_background_color" />
-</ripple>
\ No newline at end of file
+ xmlns:android="http://schemas.android.com/apk/res/android"/>
\ No newline at end of file
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 5691af2..5ed7712 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -135,7 +135,7 @@
<string name="accessibility_close" msgid="2277148124685870734">"Zapri"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Obvestilo je bilo opuščeno"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Osebno"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"Služba"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Delo"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Delovni profil"</string>
<string name="work_profile_edu_personal_apps" msgid="4155536355149317441">"Osebni podatki so ločeni in skriti pred delovnimi aplikacijami"</string>
<string name="work_profile_edu_work_apps" msgid="237051938268703058">"Delovne aplikacije in službeni podatki so vidni skrbniku za IT"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index de8bbd8..35e5678 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -71,9 +71,7 @@
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ina arifa <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g></item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Ukurasa%1$d wa %2$d"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for workspace_scroll_format (8458889198184077399) -->
- <skip />
+ <string name="workspace_scroll_format" msgid="8458889198184077399">"Skrini ya mwanzo %1$d ya %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ukurasa mpya wa skrini ya kwanza"</string>
<string name="folder_opened" msgid="94695026776264709">"Folda imefunguliwa, <xliff:g id="WIDTH">%1$d</xliff:g> kwa <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"Gusa ili ufunge folda"</string>
diff --git a/res/values-v30/styles.xml b/res/values-v30/styles.xml
new file mode 100644
index 0000000..71740a9
--- /dev/null
+++ b/res/values-v30/styles.xml
@@ -0,0 +1,34 @@
+<?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>
+ <!-- Launcher theme -->
+ <style name="BaseLauncherTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:colorEdgeEffect">#FF757575</item>
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="folderTextColor">?attr/workspaceTextColor</item>
+ <item name="android:windowLayoutInDisplayCutoutMode">always</item>
+ <item name="android:enforceStatusBarContrast">false</item>
+ <item name="android:enforceNavigationBarContrast">false</item>
+ </style>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index c4ec7dd..043ad9a 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -38,14 +38,8 @@
<color name="all_apps_bg_hand_fill">#E5E5E5</color>
<color name="all_apps_bg_hand_fill_dark">#9AA0A6</color>
- <color name="gesture_tutorial_background_color">#FFFFFFFF</color>
- <color name="gesture_tutorial_title_color">#FF000000</color>
- <color name="gesture_tutorial_subtitle_color">#99000000</color> <!-- 60% black -->
- <color name="gesture_tutorial_feedback_color">#FF000000</color>
<color name="gesture_tutorial_ripple_color">#A0C2F9</color> <!-- Light Blue -->
<color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
<color name="gesture_tutorial_action_button_label_color">#FFFFFFFF</color>
<color name="gesture_tutorial_primary_color">#1A73E8</color> <!-- Blue -->
-
-
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 26b7205..e470c42 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -81,7 +81,6 @@
<item name="folderFillColor">#CDFFFFFF</item>
<item name="folderIconBorderColor">#FF80868B</item>
<item name="folderTextColor">?attr/workspaceTextColor</item>
-
</style>
<style name="LauncherTheme.Dark" parent="@style/LauncherTheme">
diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties
index c162255..b171712 100644
--- a/robolectric_tests/config/robolectric.properties
+++ b/robolectric_tests/config/robolectric.properties
@@ -13,6 +13,6 @@
com.android.launcher3.shadows.ShadowLooperExecutor \
com.android.launcher3.shadows.ShadowMainThreadInitializedObject \
com.android.launcher3.shadows.ShadowOverrides \
- com.android.launcher3.shadows.ShadowSyncRtSurfaceTransactionApplierCompat \
+ com.android.launcher3.shadows.ShadowSurfaceTransactionApplier \
application=com.android.launcher3.util.LauncherTestApplication
\ No newline at end of file
diff --git a/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
index 59c9480..cca333c 100644
--- a/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
+++ b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
@@ -59,6 +59,17 @@
private HashSet<String> mValidPackages;
private InvariantDeviceProfile mIdp;
+ private final String testPackage1 = "com.android.launcher3.validpackage1";
+ private final String testPackage2 = "com.android.launcher3.validpackage2";
+ private final String testPackage3 = "com.android.launcher3.validpackage3";
+ private final String testPackage4 = "com.android.launcher3.validpackage4";
+ private final String testPackage5 = "com.android.launcher3.validpackage5";
+ private final String testPackage6 = "com.android.launcher3.validpackage6";
+ private final String testPackage7 = "com.android.launcher3.validpackage7";
+ private final String testPackage8 = "com.android.launcher3.validpackage8";
+ private final String testPackage9 = "com.android.launcher3.validpackage9";
+ private final String testPackage10 = "com.android.launcher3.validpackage10";
+
@Before
public void setUp() {
mModelHelper = new LauncherModelHelper();
@@ -67,6 +78,17 @@
mValidPackages = new HashSet<>();
mValidPackages.add(TEST_PACKAGE);
+ mValidPackages.add(testPackage1);
+ mValidPackages.add(testPackage2);
+ mValidPackages.add(testPackage3);
+ mValidPackages.add(testPackage4);
+ mValidPackages.add(testPackage5);
+ mValidPackages.add(testPackage6);
+ mValidPackages.add(testPackage7);
+ mValidPackages.add(testPackage8);
+ mValidPackages.add(testPackage9);
+ mValidPackages.add(testPackage10);
+
mIdp = InvariantDeviceProfile.INSTANCE.get(mContext);
long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
@@ -78,20 +100,6 @@
@Test
public void testMigration() {
- final String testPackage1 = "com.android.launcher3.validpackage1";
- final String testPackage2 = "com.android.launcher3.validpackage2";
- final String testPackage3 = "com.android.launcher3.validpackage3";
- final String testPackage4 = "com.android.launcher3.validpackage4";
- final String testPackage5 = "com.android.launcher3.validpackage5";
- final String testPackage7 = "com.android.launcher3.validpackage7";
-
- mValidPackages.add(testPackage1);
- mValidPackages.add(testPackage2);
- mValidPackages.add(testPackage3);
- mValidPackages.add(testPackage4);
- mValidPackages.add(testPackage5);
- mValidPackages.add(testPackage7);
-
int[] srcHotseatItems = {
mModelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
@@ -100,6 +108,10 @@
mModelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI),
};
mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage5, 5, TMP_CONTENT_URI);
+ mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage6, 6, TMP_CONTENT_URI);
+ mModelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage8, 8, TMP_CONTENT_URI);
+ mModelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage9, 9, TMP_CONTENT_URI);
+ mModelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage10, 10, TMP_CONTENT_URI);
int[] destHotseatItems = {
-1,
@@ -108,21 +120,24 @@
};
mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage7);
- mIdp.numHotseatIcons = 3;
- mIdp.numColumns = 3;
- mIdp.numRows = 3;
+ mIdp.numHotseatIcons = 4;
+ mIdp.numColumns = 4;
+ mIdp.numRows = 4;
GridSizeMigrationTaskV2.DbReader srcReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages, 5);
+ LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages,
+ srcHotseatItems.length);
GridSizeMigrationTaskV2.DbReader destReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages, 3);
+ LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages,
+ mIdp.numHotseatIcons);
GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(mContext, mDb, srcReader,
- destReader, 3, new Point(mIdp.numColumns, mIdp.numRows));
+ destReader, mIdp.numHotseatIcons, new Point(mIdp.numColumns, mIdp.numRows));
task.migrate();
+ // Check hotseat items
Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[]{LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.INTENT},
"container=" + CONTAINER_HOTSEAT, null, null, null);
- assertEquals(c.getCount(), 3);
+ assertEquals(c.getCount(), mIdp.numHotseatIcons);
int screenIndex = c.getColumnIndex(LauncherSettings.Favorites.SCREEN);
int intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
c.moveToNext();
@@ -134,13 +149,17 @@
c.moveToNext();
assertEquals(c.getInt(screenIndex), 2);
assertTrue(c.getString(intentIndex).contains(testPackage3));
+ c.moveToNext();
+ assertEquals(c.getInt(screenIndex), 3);
+ assertTrue(c.getString(intentIndex).contains(testPackage4));
c.close();
+ // Check workspace items
c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[]{LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
LauncherSettings.Favorites.INTENT},
"container=" + CONTAINER_DESKTOP, null, null, null);
- assertEquals(c.getCount(), 2);
+ assertEquals(c.getCount(), 6);
intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
int cellXIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLX);
int cellYIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLY);
@@ -148,7 +167,23 @@
c.moveToNext();
assertTrue(c.getString(intentIndex).contains(testPackage7));
c.moveToNext();
+ assertTrue(c.getString(intentIndex).contains(testPackage6));
+ assertEquals(c.getInt(cellXIndex), 0);
+ assertEquals(c.getInt(cellYIndex), 3);
+ c.moveToNext();
+ assertTrue(c.getString(intentIndex).contains(testPackage10));
+ assertEquals(c.getInt(cellXIndex), 1);
+ assertEquals(c.getInt(cellYIndex), 3);
+ c.moveToNext();
assertTrue(c.getString(intentIndex).contains(testPackage5));
+ assertEquals(c.getInt(cellXIndex), 2);
+ assertEquals(c.getInt(cellYIndex), 3);
+ c.moveToNext();
+ assertTrue(c.getString(intentIndex).contains(testPackage9));
+ assertEquals(c.getInt(cellXIndex), 3);
+ assertEquals(c.getInt(cellYIndex), 3);
+ c.moveToNext();
+ assertTrue(c.getString(intentIndex).contains(testPackage8));
assertEquals(c.getInt(cellXIndex), 0);
assertEquals(c.getInt(cellYIndex), 2);
}
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/ShadowSyncRtSurfaceTransactionApplierCompat.java b/robolectric_tests/src/com/android/launcher3/shadows/ShadowSurfaceTransactionApplier.java
similarity index 83%
rename from robolectric_tests/src/com/android/launcher3/shadows/ShadowSyncRtSurfaceTransactionApplierCompat.java
rename to robolectric_tests/src/com/android/launcher3/shadows/ShadowSurfaceTransactionApplier.java
index 238926c..a9f2f27 100644
--- a/robolectric_tests/src/com/android/launcher3/shadows/ShadowSyncRtSurfaceTransactionApplierCompat.java
+++ b/robolectric_tests/src/com/android/launcher3/shadows/ShadowSurfaceTransactionApplier.java
@@ -26,11 +26,11 @@
import org.robolectric.annotation.RealObject;
/**
- * Shadow for SyncRtSurfaceTransactionApplierCompat to override default functionality
+ * Shadow for SurfaceTransactionApplier to override default functionality
*/
-@Implements(className = "com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat",
+@Implements(className = "com.android.quickstep.util.SurfaceTransactionApplier",
isInAndroidSdk = false)
-public class ShadowSyncRtSurfaceTransactionApplierCompat {
+public class ShadowSurfaceTransactionApplier {
@RealObject
private Object mRealObject;
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 1aa3144..572615f 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -257,4 +257,8 @@
@FloatingViewType int type) {
return getOpenView(activity, type);
}
+
+ public boolean canInterceptEventsInSystemGestureRegion() {
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 72831f4..e3cd0bd 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -538,7 +538,6 @@
mInsets.right + hotseatBarSidePaddingStartPx, mInsets.bottom);
}
} else {
-
// We want the edges of the hotseat to line up with the edges of the workspace, but the
// icons in the hotseat are a different size, and so don't line up perfectly. To account
// for this, we pad the left and right of the hotseat with half of the difference of a
@@ -547,9 +546,11 @@
float hotseatCellWidth = (float) widthPx / inv.numHotseatIcons;
int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2);
mHotseatPadding.set(
- hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx,
+ hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx
+ + mInsets.left,
hotseatBarTopPaddingPx,
- hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx,
+ hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx
+ + mInsets.right,
hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx);
}
return mHotseatPadding;
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 1c157c2..51f3819 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -91,7 +91,6 @@
public void setInsets(Rect insets) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
DeviceProfile grid = mActivity.getDeviceProfile();
- insets = grid.getInsets();
if (grid.isVerticalBarLayout()) {
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 48b97fa..e8b5568 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -411,6 +411,11 @@
Favorites.BACKUP_TABLE_NAME);
return null;
}
+ case LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE: {
+ mOpenHelper.mHotseatRestoreTableExists = tableExists(
+ mOpenHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
+ return null;
+ }
case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: {
final long ts = System.currentTimeMillis();
if (ts - mLastRestoreTimestamp > RESTORE_BACKUP_TABLE_DELAY) {
@@ -609,6 +614,7 @@
private int mMaxItemId = -1;
private int mMaxScreenId = -1;
private boolean mBackupTableExists;
+ private boolean mHotseatRestoreTableExists;
static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) {
return createDatabaseHelper(context, null, forMigration);
@@ -633,6 +639,8 @@
databaseHelper.mBackupTableExists = tableExists(
databaseHelper.getReadableDatabase(), Favorites.BACKUP_TABLE_NAME);
}
+ databaseHelper.mHotseatRestoreTableExists = tableExists(
+ databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
databaseHelper.initIds();
return databaseHelper;
@@ -679,6 +687,10 @@
dropTable(db, Favorites.BACKUP_TABLE_NAME);
mBackupTableExists = false;
}
+ if (mHotseatRestoreTableExists) {
+ dropTable(db, Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
+ mHotseatRestoreTableExists = false;
+ }
}
/**
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 9ac370f..6951ff2 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -1,19 +1,12 @@
package com.android.launcher3;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
-import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_ROOT_VIEW;
import android.annotation.TargetApi;
-import android.app.ActivityManager;
import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
-import android.view.View;
import android.view.ViewDebug;
import android.view.WindowInsets;
@@ -26,16 +19,10 @@
private final Launcher mLauncher;
- private final Paint mOpaquePaint;
-
- @ViewDebug.ExportedProperty(category = "launcher")
- private final Rect mConsumedInsets = new Rect();
-
@ViewDebug.ExportedProperty(category = "launcher")
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
- private View mAlignedView;
private WindowStateListener mWindowStateListener;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mDisallowBackGesture;
@@ -44,55 +31,15 @@
public LauncherRootView(Context context, AttributeSet attrs) {
super(context, attrs);
-
- mOpaquePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mOpaquePaint.setColor(Color.BLACK);
- mOpaquePaint.setStyle(Paint.Style.FILL);
-
mLauncher = Launcher.getLauncher(context);
}
- @Override
- protected void onFinishInflate() {
- if (getChildCount() > 0) {
- // LauncherRootView contains only one child, which should be aligned
- // based on the horizontal insets.
- mAlignedView = getChildAt(0);
- }
- super.onFinishInflate();
- }
-
private void handleSystemWindowInsets(Rect insets) {
- mConsumedInsets.setEmpty();
- boolean drawInsetBar = false;
- if ((insets.right > 0 || insets.left > 0)
- && getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
- mConsumedInsets.left = insets.left;
- mConsumedInsets.right = insets.right;
- insets.set(0, insets.top, 0, insets.bottom);
- drawInsetBar = true;
- }
-
- mLauncher.getSystemUiController().updateUiState(
- UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
-
// Update device profile before notifying th children.
mLauncher.getDeviceProfile().updateInsets(insets);
boolean resetState = !insets.equals(mInsets);
setInsets(insets);
- if (mAlignedView != null) {
- // Apply margins on aligned view to handle consumed insets.
- MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams();
- if (lp.leftMargin != mConsumedInsets.left || lp.rightMargin != mConsumedInsets.right ||
- lp.bottomMargin != mConsumedInsets.bottom) {
- lp.leftMargin = mConsumedInsets.left;
- lp.rightMargin = mConsumedInsets.right;
- lp.topMargin = mConsumedInsets.top;
- lp.bottomMargin = mConsumedInsets.bottom;
- mAlignedView.setLayoutParams(lp);
- }
- }
if (resetState) {
mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
}
@@ -103,12 +50,7 @@
mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
handleSystemWindowInsets(mTempRect);
- if (Utilities.ATLEAST_Q) {
- return insets.inset(mConsumedInsets.left, mConsumedInsets.top,
- mConsumedInsets.right, mConsumedInsets.bottom);
- } else {
- return insets.replaceSystemWindowInsets(mTempRect);
- }
+ return insets;
}
@Override
@@ -125,24 +67,6 @@
super.setInsets(mInsets);
}
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
-
- // If the right inset is opaque, draw a black rectangle to ensure that is stays opaque.
- if (mConsumedInsets.right > 0) {
- int width = getWidth();
- canvas.drawRect(width - mConsumedInsets.right, 0, width, getHeight(), mOpaquePaint);
- }
- if (mConsumedInsets.left > 0) {
- canvas.drawRect(0, 0, mConsumedInsets.left, getHeight(), mOpaquePaint);
- }
- if (mConsumedInsets.bottom > 0) {
- int height = getHeight();
- canvas.drawRect(0, height - mConsumedInsets.bottom, getWidth(), height, mOpaquePaint);
- }
- }
-
public void setWindowStateListener(WindowStateListener listener) {
mWindowStateListener = listener;
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 2cb3910..2a5ee00 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -100,6 +100,11 @@
public static final String BACKUP_TABLE_NAME = "favorites_bakup";
/**
+ * Backup table created when user hotseat is moved to workspace for hybrid hotseat
+ */
+ public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup";
+
+ /**
* Temporary table used specifically for grid migrations during wallpaper preview
*/
public static final String PREVIEW_TABLE_NAME = "favorites_preview";
@@ -333,6 +338,8 @@
public static final String METHOD_REFRESH_BACKUP_TABLE = "refresh_backup_table";
+ public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
+
public static final String METHOD_RESTORE_BACKUP_TABLE = "restore_backup_table";
public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper";
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index a45c96c..0e57f53 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -349,15 +349,15 @@
}
ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+ mlp.leftMargin = insets.left;
+ mlp.rightMargin = insets.right;
+ setLayoutParams(mlp);
+
if (grid.isVerticalBarLayout()) {
- mlp.leftMargin = insets.left;
- mlp.rightMargin = insets.right;
setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
} else {
- mlp.leftMargin = mlp.rightMargin = 0;
setPadding(0, 0, 0, 0);
}
- setLayoutParams(mlp);
InsettableFrameLayout.dispatchInsets(this, insets);
}
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 34bf636..7d5363f 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
+
import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.animation.Interpolator;
@@ -57,6 +59,13 @@
Interpolator interpolator);
/**
+ * Returns true if the QSB should be visible for the given set of visible elements
+ */
+ default boolean isQsbVisible(int visibleElements) {
+ return (visibleElements & ALL_APPS_HEADER) != 0;
+ }
+
+ /**
* Called to control how the search UI result should be handled.
*
* @param isEnabled when {@code true}, the search is all handled inside AOSP
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index e72e1a8..356c52c 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -19,7 +19,6 @@
import static android.view.View.MeasureSpec.getSize;
import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
import static com.android.launcher3.Utilities.prefixTextWithIcon;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
@@ -213,7 +212,7 @@
@Override
public void setContentVisibility(int visibleElements, PropertySetter setter,
Interpolator interpolator) {
- setter.setViewAlpha(this, (visibleElements & ALL_APPS_HEADER) != 0 ? 1 : 0, interpolator);
+ setter.setViewAlpha(this, isQsbVisible(visibleElements) ? 1 : 0, interpolator);
}
@Override
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index e11917b..ea0ff8b 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.anim;
+import static com.android.launcher3.Utilities.boundToRange;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
@@ -30,8 +31,6 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.Utilities;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -54,11 +53,8 @@
* to float (animation-fraction * total duration) to int conversion.
*/
public static AnimatorPlaybackController wrap(AnimatorSet anim, long duration) {
- /**
- * TODO: use {@link AnimatorSet#setCurrentPlayTime(long)} once b/68382377 is fixed.
- */
ArrayList<Holder> childAnims = new ArrayList<>();
- addAnimationHoldersRecur(anim, SpringProperty.DEFAULT, childAnims);
+ addAnimationHoldersRecur(anim, duration, SpringProperty.DEFAULT, childAnims);
return new AnimatorPlaybackController(anim, duration, childAnims);
}
@@ -152,7 +148,7 @@
float scaleInverse = 1 / Math.abs(scale);
float scaledVelocity = velocity * scaleInverse;
- float nextFrameProgress = Utilities.boundToRange(getProgressFraction()
+ float nextFrameProgress = boundToRange(getProgressFraction()
+ scaledVelocity * getSingleFrameMs(context), 0f, 1f);
// Update setters for spring
@@ -176,8 +172,8 @@
springDuration = Math.max(expectedDurationL, springDuration);
float expectedDuration = expectedDurationL;
- h.setter = (a, l) -> a.setCurrentFraction(
- mAnimationPlayer.getCurrentPlayTime() / expectedDuration);
+ h.mapper = (progress, globalEndProgress) ->
+ mAnimationPlayer.getCurrentPlayTime() / expectedDuration;
h.anim.setInterpolator(s::getInterpolatedValue);
}
}
@@ -237,9 +233,9 @@
if (mTargetCancelled) {
return;
}
- long playPos = clampDuration(fraction);
+ float progress = boundToRange(fraction, 0, 1);
for (Holder holder : mChildAnimations) {
- holder.setter.set(holder.anim, playPos);
+ holder.setProgress(progress);
}
}
@@ -361,14 +357,14 @@
}
/**
- * Interface for setting position of value animator
+ * Interface for mapping progress to animation progress
*/
- private interface PositionSetter {
+ private interface ProgressMapper {
- PositionSetter DEFAULT = (anim, playPos) ->
- anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration()));
+ ProgressMapper DEFAULT = (progress, globalEndProgress) ->
+ progress > globalEndProgress ? 1 : (progress / globalEndProgress);
- void set(ValueAnimator anim, long position);
+ float getProgress(float progress, float globalProgress);
}
/**
@@ -382,27 +378,34 @@
public final TimeInterpolator interpolator;
- public PositionSetter setter;
+ public final float globalEndProgress;
- Holder(Animator anim, SpringProperty springProperty) {
+ public ProgressMapper mapper;
+
+ Holder(Animator anim, float globalDuration, SpringProperty springProperty) {
this.anim = (ValueAnimator) anim;
this.springProperty = springProperty;
this.interpolator = this.anim.getInterpolator();
- this.setter = PositionSetter.DEFAULT;
+ this.globalEndProgress = anim.getDuration() / globalDuration;
+ this.mapper = ProgressMapper.DEFAULT;
+ }
+
+ public void setProgress(float progress) {
+ anim.setCurrentFraction(mapper.getProgress(progress, globalEndProgress));
}
public void reset() {
anim.setInterpolator(interpolator);
- setter = PositionSetter.DEFAULT;
+ mapper = ProgressMapper.DEFAULT;
}
}
- static void addAnimationHoldersRecur(
- Animator anim, SpringProperty springProperty, ArrayList<Holder> out) {
+ static void addAnimationHoldersRecur(Animator anim, long globalDuration,
+ SpringProperty springProperty, ArrayList<Holder> out) {
long forceDuration = anim.getDuration();
TimeInterpolator forceInterpolator = anim.getInterpolator();
if (anim instanceof ValueAnimator) {
- out.add(new Holder(anim, springProperty));
+ out.add(new Holder(anim, globalDuration, springProperty));
} else if (anim instanceof AnimatorSet) {
for (Animator child : ((AnimatorSet) anim).getChildAnimations()) {
if (forceDuration > 0) {
@@ -411,7 +414,7 @@
if (forceInterpolator != null) {
child.setInterpolator(forceInterpolator);
}
- addAnimationHoldersRecur(child, springProperty, out);
+ addAnimationHoldersRecur(child, globalDuration, springProperty, out);
}
} else {
throw new RuntimeException("Unknown animation type " + anim);
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 0f04104..afeb341 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -70,7 +70,7 @@
public void add(Animator a, SpringProperty springProperty) {
mAnim.play(a);
- addAnimationHoldersRecur(a, springProperty, mAnimHolders);
+ addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
}
public void finish(boolean isSuccess, int logAction) {
@@ -150,7 +150,7 @@
}
if (mAnimHolders.isEmpty()) {
// Add a dummy animation to that the duration is respected
- add(ValueAnimator.ofFloat(0, 1));
+ add(ValueAnimator.ofFloat(0, 1).setDuration(mDuration));
}
return mAnim;
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 978dd52..118ce0c 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -103,7 +103,7 @@
"Adds localized title and keyword search and ranking");
public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
- "ENABLE_PREDICTION_DISMISS", false, "Allow option to dimiss apps from predicted list");
+ "ENABLE_PREDICTION_DISMISS", true, "Allow option to dimiss apps from predicted list");
public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
"ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 781a910..c4ef381 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -44,6 +44,9 @@
@UiEvent(doc = "Task launched from overview using TAP")
LAUNCHER_TASK_LAUNCH_TAP(339),
+ @UiEvent(doc = "User tapped on notification inside popup context menu.")
+ LAUNCHER_NOTIFICATION_LAUNCH_TAP(516),
+
@UiEvent(doc = "Task launched from overview using SWIPE DOWN")
LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(340),
@@ -97,13 +100,28 @@
+ "the icon onto 'Uninstall' button in the target bar")
LAUNCHER_ITEM_UNINSTALL_CANCELLED(470),
+ @UiEvent(doc = "User tapped or long pressed on the task icon(aka package icon) "
+ + "from overview to open task menu.")
+ LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS(517),
+
@UiEvent(doc = "User opened package specific widgets list by tapping on widgets system "
- + "shortcut within longpress popup window.")
+ + "shortcut inside popup context menu.")
LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP(514),
- @UiEvent(doc = "User opened app info of the package by tapping on appinfo system shortcut "
- + "within longpress popup window.")
- LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP(515);
+ @UiEvent(doc = "User tapped on app info system shortcut.")
+ LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP(515),
+
+ @UiEvent(doc = "User tapped on split screen icon on a task menu.")
+ LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP(518),
+
+ @UiEvent(doc = "User tapped on free form icon on a task menu.")
+ LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP(519),
+
+ @UiEvent(doc = "User tapped on pause app system shortcut.")
+ LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP(521),
+
+ @UiEvent(doc = "User tapped on pin system shortcut.")
+ LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP(522);
// ADD MORE
private final int mId;
diff --git a/src/com/android/launcher3/model/GridBackupTable.java b/src/com/android/launcher3/model/GridBackupTable.java
index 4a1bc4d..acfc339 100644
--- a/src/com/android/launcher3/model/GridBackupTable.java
+++ b/src/com/android/launcher3/model/GridBackupTable.java
@@ -128,6 +128,32 @@
}
/**
+ * Creates a new table and populates with copy of Favorites.TABLE_NAME
+ */
+ public void createCustomBackupTable(String tableName) {
+ long profileId = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
+ Process.myUserHandle());
+ copyTable(mDb, Favorites.TABLE_NAME, tableName, profileId);
+ encodeDBProperties(0);
+ }
+
+ /**
+ *
+ * Restores the contents of a custom table to Favorites.TABLE_NAME
+ */
+
+ public void restoreFromCustomBackupTable(String tableName, boolean dropAfterUse) {
+ if (!tableExists(mDb, tableName)) {
+ return;
+ }
+ long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
+ Process.myUserHandle());
+ copyTable(mDb, tableName, Favorites.TABLE_NAME, userSerial);
+ if (dropAfterUse) {
+ dropTable(mDb, tableName);
+ }
+ }
+ /**
* Copy valid grid entries from one table to another.
*/
private static void copyTable(SQLiteDatabase db, String from, String to, long userSerial) {
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index 4a28218..4bfabb0 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -33,6 +33,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Point;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -55,6 +56,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -226,9 +228,8 @@
if (DEBUG) {
Log.d(TAG, "Migrating " + screenId);
}
- List<DbEntry> entries = mDestReader.loadWorkspaceEntries(screenId);
GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, entries, screenId, mTrgX, mTrgY, mWorkspaceDiff);
+ mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff);
workspaceSolution.find();
if (mWorkspaceDiff.isEmpty()) {
break;
@@ -238,8 +239,7 @@
int screenId = mDestReader.mLastScreenId + 1;
while (!mWorkspaceDiff.isEmpty()) {
GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, new ArrayList<>(), screenId, mTrgX, mTrgY,
- mWorkspaceDiff);
+ mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff);
workspaceSolution.find();
screenId++;
}
@@ -352,8 +352,7 @@
private int mNextStartY;
GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
- Context context, List<DbEntry> placedWorkspaceItems, int screenId, int trgX,
- int trgY, List<DbEntry> itemsToPlace) {
+ Context context, int screenId, int trgX, int trgY, List<DbEntry> itemsToPlace) {
mDb = db;
mSrcReader = srcReader;
mDestReader = destReader;
@@ -364,8 +363,11 @@
mTrgY = trgY;
mNextStartX = 0;
mNextStartY = mTrgY - 1;
- for (DbEntry entry : placedWorkspaceItems) {
- mOccupied.markCells(entry, true);
+ List<DbEntry> existedEntries = mDestReader.mWorkspaceEntriesByScreenId.get(screenId);
+ if (existedEntries != null) {
+ for (DbEntry entry : existedEntries) {
+ mOccupied.markCells(entry, true);
+ }
}
mItemsToPlace = itemsToPlace;
}
@@ -386,6 +388,11 @@
}
}
+ /**
+ * Search for the next possible placement of an icon. (mNextStartX, mNextStartY) serves as
+ * a memoization of last placement, we can start our search for next placement from there
+ * to speed up the search.
+ */
private boolean findPlacement(DbEntry entry) {
for (int y = mNextStartY; y >= 0; y--) {
for (int x = mNextStartX; x < mTrgX; x++) {
@@ -406,6 +413,7 @@
return true;
}
}
+ mNextStartX = 0;
}
return false;
}
@@ -475,6 +483,8 @@
private final ArrayList<DbEntry> mHotseatEntries = new ArrayList<>();
private final ArrayList<DbEntry> mWorkspaceEntries = new ArrayList<>();
+ private final Map<Integer, ArrayList<DbEntry>> mWorkspaceEntriesByScreenId =
+ new ArrayMap<>();
DbReader(SQLiteDatabase db, String tableName, Context context,
HashSet<String> validPackages, int hotseatSize) {
@@ -564,25 +574,6 @@
return loadWorkspaceEntries(c);
}
- protected ArrayList<DbEntry> loadWorkspaceEntries(int screen) {
- Cursor c = queryWorkspace(
- new String[]{
- LauncherSettings.Favorites._ID, // 0
- LauncherSettings.Favorites.ITEM_TYPE, // 1
- LauncherSettings.Favorites.SCREEN, // 2
- LauncherSettings.Favorites.CELLX, // 3
- LauncherSettings.Favorites.CELLY, // 4
- LauncherSettings.Favorites.SPANX, // 5
- LauncherSettings.Favorites.SPANY, // 6
- LauncherSettings.Favorites.INTENT, // 7
- LauncherSettings.Favorites.APPWIDGET_PROVIDER, // 8
- LauncherSettings.Favorites.APPWIDGET_ID}, // 9
- LauncherSettings.Favorites.CONTAINER + " = "
- + LauncherSettings.Favorites.CONTAINER_DESKTOP
- + " AND " + LauncherSettings.Favorites.SCREEN + " = " + screen);
- return loadWorkspaceEntries(c);
- }
-
private ArrayList<DbEntry> loadWorkspaceEntries(Cursor c) {
final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
@@ -660,6 +651,10 @@
continue;
}
mWorkspaceEntries.add(entry);
+ if (!mWorkspaceEntriesByScreenId.containsKey(entry.screenId)) {
+ mWorkspaceEntriesByScreenId.put(entry.screenId, new ArrayList<>());
+ }
+ mWorkspaceEntriesByScreenId.get(entry.screenId).add(entry);
}
removeEntryFromDb(mDb, mTableName, entriesToRemove);
c.close();
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index e5525b2..fa1bdfb 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -16,6 +16,8 @@
package com.android.launcher3.notification;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_LAUNCH_TAP;
+
import android.app.ActivityOptions;
import android.app.Notification;
import android.app.PendingIntent;
@@ -32,6 +34,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.graphics.IconPalette;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.PackageUserKey;
/**
@@ -51,6 +54,7 @@
public final boolean autoCancel;
public final boolean dismissable;
+ private final ItemInfo mItemInfo;
private Drawable mIconDrawable;
private int mIconColor;
private boolean mIsIconLarge;
@@ -58,7 +62,8 @@
/**
* Extracts the data that we need from the StatusBarNotification.
*/
- public NotificationInfo(Context context, StatusBarNotification statusBarNotification) {
+ public NotificationInfo(Context context, StatusBarNotification statusBarNotification,
+ ItemInfo itemInfo) {
packageUserKey = PackageUserKey.fromNotification(statusBarNotification);
notificationKey = statusBarNotification.getKey();
Notification notification = statusBarNotification.getNotification();
@@ -88,6 +93,7 @@
intent = notification.contentIntent;
autoCancel = (notification.flags & Notification.FLAG_AUTO_CANCEL) != 0;
dismissable = (notification.flags & Notification.FLAG_ONGOING_EVENT) == 0;
+ this.mItemInfo = itemInfo;
}
@Override
@@ -101,6 +107,8 @@
try {
intent.send(null, 0, null, null, null, null, activityOptions);
launcher.getUserEventDispatcher().logNotificationLaunch(view, intent);
+ launcher.getStatsLogManager()
+ .log(LAUNCHER_NOTIFICATION_LAUNCH_TAP, mItemInfo.buildProto());
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 18bc55a..5b0c388 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -293,8 +293,8 @@
// gravity to CENTER_HORIZONTAL, but continue below to update y.
} else {
boolean canBeLeftAligned = x + width + insets.left
- < dragLayer.getRight() - insets.right;
- boolean canBeRightAligned = x > dragLayer.getLeft() + insets.left;
+ < dragLayer.getWidth() - insets.right;
+ boolean canBeRightAligned = x > insets.left;
boolean alignmentStillValid = mIsLeftAligned && canBeLeftAligned
|| !mIsLeftAligned && canBeRightAligned;
if (!alignmentStillValid) {
@@ -367,8 +367,10 @@
super.onLayout(changed, l, t, r, b);
// enforce contained is within screen
- ViewGroup dragLayer = getPopupContainer();
- if (getTranslationX() + l < 0 || getTranslationX() + r > dragLayer.getWidth()) {
+ BaseDragLayer dragLayer = getPopupContainer();
+ Rect insets = dragLayer.getInsets();
+ if (getTranslationX() + l < insets.left
+ || getTranslationX() + r > dragLayer.getWidth() - insets.right) {
// If we are still off screen, center horizontally too.
mGravity |= Gravity.CENTER_HORIZONTAL;
}
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 7da86cc..5ed6f2e 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -16,6 +16,8 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
+
import android.content.ComponentName;
import android.content.pm.ShortcutInfo;
import android.os.Handler;
@@ -142,7 +144,7 @@
infos = Collections.emptyList();
} else {
infos = notificationListener.getNotificationsForKeys(notificationKeys).stream()
- .map(sbn -> new NotificationInfo(launcher, sbn))
+ .map(sbn -> new NotificationInfo(launcher, sbn, originalInfo))
.collect(Collectors.toList());
}
uiHandler.post(() -> container.applyNotificationInfos(infos));
@@ -160,6 +162,7 @@
final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, launcher);
cache.getUnbadgedShortcutIcon(si, shortcut);
si.rank = i;
+ si.container = CONTAINER_SHORTCUTS;
final DeepShortcutView view = shortcutViews.get(i);
uiHandler.post(() -> view.applyShortcutInfo(si, shortcut, container));
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 3875d2e..58251e8 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -16,6 +16,7 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.annotation.TargetApi;
@@ -76,6 +77,8 @@
@Override
public void onClick(View view) {
AbstractFloatingView.closeAllOpenViews(mTarget);
+ mTarget.getStatsLogManager()
+ .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP, mItemInfo.buildProto());
final String actionIdentity = mAction.getTitle() + ", "
+ mItemInfo.getTargetComponent().getPackageName();
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 58ed5e8..ea8caf5 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -29,6 +29,7 @@
import com.android.launcher3.widget.WidgetsBottomSheet;
import java.util.List;
+
/**
* Represents a system shortcut for a given app. The shortcut should have a label and icon, and an
* onClickListener that depends on the item that the shortcut services.
@@ -142,8 +143,8 @@
mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.APPINFO_TARGET, view);
// TODO(thiruram): Fix missing container info when item is inside folder.
- mTarget.getStatsLogManager().log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP,
- mItemInfo.buildProto());
+ mTarget.getStatsLogManager()
+ .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP, mItemInfo.buildProto());
}
}
diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
index 5bf9173..b12d04f 100644
--- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
+++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
@@ -237,6 +237,24 @@
return true;
});
sandboxCategory.addPreference(launchHomeTutorialPreference);
+ Preference launchOverviewTutorialPreference = new Preference(context);
+ launchOverviewTutorialPreference.setKey("launchOverviewTutorial");
+ launchOverviewTutorialPreference.setTitle("Launch Overview Tutorial");
+ launchOverviewTutorialPreference.setSummary("Learn how to use the Overview gesture");
+ launchOverviewTutorialPreference.setOnPreferenceClickListener(preference -> {
+ startActivity(launchSandboxIntent.putExtra("tutorial_type", "OVERVIEW_NAVIGATION"));
+ return true;
+ });
+ sandboxCategory.addPreference(launchOverviewTutorialPreference);
+ Preference launchAssistantTutorialPreference = new Preference(context);
+ launchAssistantTutorialPreference.setKey("launchAssistantTutorial");
+ launchAssistantTutorialPreference.setTitle("Launch Assistant Tutorial");
+ launchAssistantTutorialPreference.setSummary("Learn how to use the Assistant gesture");
+ launchAssistantTutorialPreference.setOnPreferenceClickListener(preference -> {
+ startActivity(launchSandboxIntent.putExtra("tutorial_type", "ASSISTANT"));
+ return true;
+ });
+ sandboxCategory.addPreference(launchAssistantTutorialPreference);
}
private String toName(String action) {
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index 1c49867..f90ad3c 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -69,7 +69,8 @@
ANIM_ALL_APPS_FADE,
ANIM_OVERVIEW_SCRIM_FADE,
ANIM_ALL_APPS_HEADER_FADE,
- ANIM_OVERVIEW_MODAL
+ ANIM_OVERVIEW_MODAL,
+ ANIM_DEPTH,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimType {}
@@ -87,8 +88,9 @@
public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
public static final int ANIM_OVERVIEW_MODAL = 13;
+ public static final int ANIM_DEPTH = 14;
- private static final int ANIM_TYPES_COUNT = 14;
+ private static final int ANIM_TYPES_COUNT = 15;
private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 44eae56..519b1b9 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -101,4 +101,5 @@
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
public static final String PAUSE_NOT_DETECTED = "b/139891609";
public static final String OVERIEW_NOT_ALLAPPS = "b/156095088";
+ public static final String NO_SWIPE_TO_HOME = "b/158017601";
}
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index 86995b7..53cc157 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.util;
-import android.text.TextUtils;
import android.view.View;
import android.view.Window;
@@ -33,8 +32,7 @@
public static final int UI_STATE_BASE_WINDOW = 0;
public static final int UI_STATE_ALL_APPS = 1;
public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
- public static final int UI_STATE_ROOT_VIEW = 3;
- public static final int UI_STATE_OVERVIEW = 4;
+ public static final int UI_STATE_OVERVIEW = 3;
public static final int FLAG_LIGHT_NAV = 1 << 0;
public static final int FLAG_DARK_NAV = 1 << 1;
@@ -42,7 +40,7 @@
public static final int FLAG_DARK_STATUS = 1 << 3;
private final Window mWindow;
- private final int[] mStates = new int[5];
+ private final int[] mStates = new int[4];
public SystemUiController(Window window) {
mWindow = window;
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index c37c47c..f54edc2 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -186,11 +186,12 @@
+ ", isEventInLauncher=" + isEventInLauncher(ev)
+ ", topOpenView=" + AbstractFloatingView.getTopOpenView(mActivity));
}
- if (isEventInLauncher(ev)) {
- AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
- if (topView != null && topView.onControllerInterceptTouchEvent(ev)) {
- return topView;
- }
+
+ AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+ if (topView != null
+ && (isEventInLauncher(ev) || topView.canInterceptEventsInSystemGestureRegion())
+ && topView.onControllerInterceptTouchEvent(ev)) {
+ return topView;
}
for (TouchController controller : mControllers) {
diff --git a/src/com/android/launcher3/views/ListenerView.java b/src/com/android/launcher3/views/ListenerView.java
index 575f864..3ef778b 100644
--- a/src/com/android/launcher3/views/ListenerView.java
+++ b/src/com/android/launcher3/views/ListenerView.java
@@ -106,4 +106,9 @@
// We want other views to be able to intercept the touch so we return false here.
return false;
}
+
+ @Override
+ public boolean canInterceptEventsInSystemGestureRegion() {
+ return true;
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index 536b766..68a3ec5 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -24,7 +24,6 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -39,10 +38,8 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.TopRoundedCornerView;
@@ -135,7 +132,7 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthUsed;
if (mInsets.bottom > 0) {
- widthUsed = 0;
+ widthUsed = mInsets.left + mInsets.right;
} else {
Rect padding = mLauncher.getDeviceProfile().workspacePadding;
widthUsed = Math.max(padding.left + padding.right,
@@ -156,7 +153,7 @@
// Content is laid out as center bottom aligned
int contentWidth = mContent.getMeasuredWidth();
- int contentLeft = (width - contentWidth) / 2;
+ int contentLeft = (width - contentWidth - mInsets.left - mInsets.right) / 2 + mInsets.left;
mContent.layout(contentLeft, height - mContent.getMeasuredHeight(),
contentLeft + contentWidth, height);