Merge "Fix LauncherInstrumentation for OOP tests from gradle" into tm-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index 7e3ee7d..bc3253f 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -27,6 +27,8 @@
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -52,7 +54,8 @@
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
Context context = app.getContext();
// TODO: remove this
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index 9cd9d85..7a483a8 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -21,6 +21,8 @@
import android.content.ComponentName;
import android.text.TextUtils;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -52,7 +54,8 @@
* workspace.
*/
@Override
- public void execute(LauncherAppState appState, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState appState,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
Set<ComponentKey> widgetsInWorkspace = dataModel.appWidgets.stream().map(
widget -> new ComponentKey(widget.providerName, widget.user)).collect(
Collectors.toSet());
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 9a682c6..7c3281a 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -55,6 +55,7 @@
@Override
public void onClick(View view) {
+ // Initiate splitscreen from the Home screen or Home All Apps
Bitmap bitmap;
Intent intent;
if (mItemInfo instanceof WorkspaceItemInfo) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 49d0873..da6dab1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -270,6 +270,7 @@
@Override
public void onClick(View view) {
+ // Initiate splitscreen from the in-app Taskbar or Taskbar All Apps
Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
LogUtils.getShellShareableInstanceId();
mTarget.getStatsLogManager().logger()
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 2e4e739..8fb7030 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -88,6 +88,11 @@
return;
}
setStateWithAnimationInternal(toState, config, builder);
+ builder.addEndListener(success -> {
+ if (!success) {
+ mRecentsView.reset();
+ }
+ });
}
/**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index f5161aa..f75a404 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -34,6 +34,7 @@
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
@@ -62,6 +63,7 @@
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.RecentsView;
/**
@@ -79,14 +81,6 @@
private static final int PER_PAGE_SCROLL_DURATION = 150;
private static final int MAX_PAGE_SCROLL_DURATION = 750;
- private static final int OVERVIEW_TO_SPLIT_ACTIONS_FADE_START = 0;
- private static final int OVERVIEW_TO_SPLIT_ACTIONS_FADE_END = 83;
-
- private static final float OVERVIEW_TO_SPLIT_ACTIONS_FADE_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ACTIONS_FADE_START / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_ACTIONS_FADE_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ACTIONS_FADE_END / SplitScreenSelectState.ENTER_DURATION;
-
// Due to use of physics, duration may differ between devices so we need to calculate and
// cache the value.
private int mHintToNormalDuration = -1;
@@ -197,9 +191,17 @@
} else if (fromState == NORMAL && toState == ALL_APPS) {
AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
} else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) {
+ SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_ACTIONS_FADE_START_OFFSET,
- OVERVIEW_TO_SPLIT_ACTIONS_FADE_END_OFFSET));
+ timings.getActionsFadeStartOffset(),
+ timings.getActionsFadeEndOffset()));
+ } else if (fromState == NORMAL && toState == OVERVIEW_SPLIT_SELECT) {
+ SplitAnimationTimings timings = SplitAnimationTimings.NORMAL_TO_SPLIT;
+ config.setInterpolator(ANIM_SCRIM_FADE, clampToProgress(LINEAR,
+ timings.getScrimFadeInStartOffset(),
+ timings.getScrimFadeInEndOffset()));
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_0_75);
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_0_75);
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
index 2bc3c3e..430053d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
@@ -19,6 +19,7 @@
import android.content.Context;
import com.android.launcher3.Launcher;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.RecentsView;
/**
@@ -26,10 +27,6 @@
* pinned and user is selecting the second one
*/
public class SplitScreenSelectState extends OverviewState {
- public static final int ENTER_DURATION = 866;
- public static final int EXIT_DURATION = 500;
- // TODO: Add ability to differentiate between Split > Home and Split > Confirmed timings
-
public SplitScreenSelectState(int id) {
super(id);
}
@@ -47,6 +44,8 @@
@Override
public int getTransitionDuration(Context context, boolean isToState) {
- return isToState ? ENTER_DURATION : EXIT_DURATION;
+ return isToState
+ ? SplitAnimationTimings.ENTER_DURATION
+ : SplitAnimationTimings.ABORT_DURATION;
}
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 4e635a7..24bb393 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1140,6 +1140,13 @@
boolean isCancel) {
long duration = MAX_SWIPE_DURATION;
float currentShift = mCurrentShift.value;
+ boolean recentsVisible = mRecentsView != null
+ && (mRecentsView.getWindowVisibility() == View.VISIBLE);
+ if (!recentsVisible) {
+ // We've hit a case where Launcher is been stopped mid-gesture, in this case, force
+ // a LAST_TASK end target
+ isCancel = true;
+ }
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
isFling, isCancel);
// Set the state, but don't notify until the animation completes
@@ -1219,7 +1226,7 @@
// Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
// or resumeLastTask().
- if (mRecentsView != null) {
+ if (recentsVisible) {
ActiveGestureLog.INSTANCE.trackEvent(ActiveGestureErrorDetector.GestureEvent
.SET_ON_PAGE_TRANSITION_END_CALLBACK);
mRecentsView.setOnPageTransitionEndCallback(
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 1e0ceed..19a6c38 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -78,6 +78,11 @@
}
// While animating into recents, update the visible task data as needed
setter.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
+ setter.addEndListener(success -> {
+ if (!success) {
+ mRecentsView.reset();
+ }
+ });
mRecentsView.updateEmptyMessage();
setProperties(toState, config, setter);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 93eb0f1..e32aaee 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -232,11 +232,6 @@
}
@Override
- public void onStateTransitionFailed(RecentsState toState) {
- reset();
- }
-
- @Override
public void onStateTransitionComplete(RecentsState finalState) {
if (finalState == HOME) {
// Clean-up logic that occurs when recents is no longer in use/visible.
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 45c8036..37a28e5 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -336,8 +336,9 @@
appState.getModel().enqueueModelUpdateTask(
new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel,
- AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
FolderInfo folderInfo = dataModel.folders.get(mItemInfo.container);
write(event, applyOverwrites(mItemInfo.buildProto(folderInfo)));
}
diff --git a/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java b/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java
new file mode 100644
index 0000000..1bf5a5d
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the Normal > OverviewSplitSelect animation.
+ */
+public class NormalToSplitTimings extends OverviewToSplitTimings implements SplitAnimationTimings {
+ @Override
+ public Interpolator getStagedRectXInterpolator() { return LINEAR; }
+ @Override
+ public Interpolator getStagedRectScaleXInterpolator() { return LINEAR; }
+ @Override
+ public Interpolator getStagedRectScaleYInterpolator() { return LINEAR; }
+
+ public int getScrimFadeInStart() { return 0; }
+ public int getScrimFadeInEnd() { return 167; }
+
+ public float getScrimFadeInStartOffset() {
+ return (float) getScrimFadeInStart() / getDuration();
+ }
+ public float getScrimFadeInEndOffset() {
+ return (float) getScrimFadeInEnd() / getDuration();
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
new file mode 100644
index 0000000..f44796b
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the Overview > OverviewSplitSelect animation.
+ */
+public class OverviewToSplitTimings implements SplitAnimationTimings {
+ public int getPlaceholderFadeInStart() { return 0; }
+ public int getPlaceholderFadeInEnd() { return 133; }
+ public int getPlaceholderIconFadeInStart() { return 167; }
+ public int getPlaceholderIconFadeInEnd() { return 250; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 417; }
+ public int getGridSlideStart() { return 67; }
+ public int getGridSlideStagger() { return 16; }
+ public int getGridSlideDuration() { return 500; }
+ public int getActionsFadeStart() { return 0; }
+ public int getActionsFadeEnd() { return 83; }
+ public int getIconFadeStart() { return 0; }
+ public int getIconFadeEnd() { return 83; }
+ public int getInstructionsContainerFadeInStart() { return 167; }
+ public int getInstructionsContainerFadeInEnd() { return 250; }
+ public int getInstructionsTextFadeInStart() { return 217; }
+ public int getInstructionsTextFadeInEnd() { return 300; }
+ public int getInstructionsUnfoldStart() { return 167; }
+ public int getInstructionsUnfoldEnd() { return 500; }
+
+ public int getDuration() { return ENTER_DURATION; }
+ public Interpolator getStagedRectXInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectYInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectScaleXInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectScaleYInterpolator() { return DEACCEL_2; }
+
+ public float getGridSlideStartOffset() {
+ return (float) getGridSlideStart() / getDuration();
+ }
+ public float getGridSlideStaggerOffset() {
+ return (float) getGridSlideStagger() / getDuration();
+ }
+ public float getGridSlideDurationOffset() {
+ return (float) getGridSlideDuration() / getDuration();
+ }
+ public float getActionsFadeStartOffset() {
+ return (float) getActionsFadeStart() / getDuration();
+ }
+ public float getActionsFadeEndOffset() {
+ return (float) getActionsFadeEnd() / getDuration();
+ }
+ public float getIconFadeStartOffset() {
+ return (float) getIconFadeStart() / getDuration();
+ }
+ public float getIconFadeEndOffset() {
+ return (float) getIconFadeEnd() / getDuration();
+ }
+ public float getInstructionsContainerFadeInStartOffset() {
+ return (float) getInstructionsContainerFadeInStart() / getDuration();
+ }
+ public float getInstructionsContainerFadeInEndOffset() {
+ return (float) getInstructionsContainerFadeInEnd() / getDuration();
+ }
+ public float getInstructionsTextFadeInStartOffset() {
+ return (float) getInstructionsTextFadeInStart() / getDuration();
+ }
+ public float getInstructionsTextFadeInEndOffset() {
+ return (float) getInstructionsTextFadeInEnd() / getDuration();
+ }
+ public float getInstructionsUnfoldStartOffset() {
+ return (float) getInstructionsUnfoldStart() / getDuration();
+ }
+ public float getInstructionsUnfoldEndOffset() {
+ return (float) getInstructionsUnfoldEnd() / getDuration();
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
new file mode 100644
index 0000000..133be03
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+import android.view.animation.Interpolator;
+
+/**
+ * An interface that supports the centralization of timing information for splitscreen animations.
+ */
+public interface SplitAnimationTimings {
+ int ENTER_DURATION = 866;
+ int ABORT_DURATION = 500;
+ int CONFIRM_DURATION = 383;
+
+ SplitAnimationTimings OVERVIEW_TO_SPLIT = new OverviewToSplitTimings();
+ SplitAnimationTimings NORMAL_TO_SPLIT = new NormalToSplitTimings();
+ SplitAnimationTimings SPLIT_TO_CONFIRM = new SplitToConfirmTimings();
+
+ // Shared methods
+ int getDuration();
+ int getPlaceholderFadeInStart();
+ int getPlaceholderFadeInEnd();
+ int getPlaceholderIconFadeInStart();
+ int getPlaceholderIconFadeInEnd();
+ int getStagedRectSlideStart();
+ int getStagedRectSlideEnd();
+ Interpolator getStagedRectXInterpolator();
+ Interpolator getStagedRectYInterpolator();
+ Interpolator getStagedRectScaleXInterpolator();
+ Interpolator getStagedRectScaleYInterpolator();
+ default float getPlaceholderFadeInStartOffset() {
+ return (float) getPlaceholderFadeInStart() / getDuration();
+ }
+ default float getPlaceholderFadeInEndOffset() {
+ return (float) getPlaceholderFadeInEnd() / getDuration();
+ }
+ default float getPlaceholderIconFadeInStartOffset() {
+ return (float) getPlaceholderIconFadeInStart() / getDuration();
+ }
+ default float getPlaceholderIconFadeInEndOffset() {
+ return (float) getPlaceholderIconFadeInEnd() / getDuration();
+ }
+ default float getStagedRectSlideStartOffset() {
+ return (float) getStagedRectSlideStart() / getDuration();
+ }
+ default float getStagedRectSlideEndOffset() {
+ return (float) getStagedRectSlideEnd() / getDuration();
+ }
+
+ // Defaults for OverviewToSplit
+ default float getGridSlideStartOffset() { return 0; }
+ default float getGridSlideStaggerOffset() { return 0; }
+ default float getGridSlideDurationOffset() { return 0; }
+ default float getActionsFadeStartOffset() { return 0; }
+ default float getActionsFadeEndOffset() { return 0; }
+ default float getIconFadeStartOffset() { return 0; }
+ default float getIconFadeEndOffset() { return 0; }
+ default float getInstructionsContainerFadeInStartOffset() { return 0; }
+ default float getInstructionsContainerFadeInEndOffset() { return 0; }
+ default float getInstructionsTextFadeInStartOffset() { return 0; }
+ default float getInstructionsTextFadeInEndOffset() { return 0; }
+ default float getInstructionsUnfoldStartOffset() { return 0; }
+ default float getInstructionsUnfoldEndOffset() { return 0; }
+
+ // Defaults for NormalToSplit
+ default float getScrimFadeInStartOffset() { return 0; }
+ default float getScrimFadeInEndOffset() { return 0; }
+
+ // Defaults for SplitToConfirm
+ default float getInstructionsFadeStartOffset() { return 0; }
+ default float getInstructionsFadeEndOffset() { return 0; }
+}
+
diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
new file mode 100644
index 0000000..84cfb0b
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the OverviewSplitSelect > confirmed animation.
+ */
+public class SplitToConfirmTimings implements SplitAnimationTimings {
+ public int getPlaceholderFadeInStart() { return 0; }
+ public int getPlaceholderFadeInEnd() { return 133; }
+ public int getPlaceholderIconFadeInStart() { return 167; }
+ public int getPlaceholderIconFadeInEnd() { return 250; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 383; }
+ public int getInstructionsFadeStart() { return 0; }
+ public int getInstructionsFadeEnd() { return 67; }
+
+ public int getDuration() { return CONFIRM_DURATION; }
+ public Interpolator getStagedRectXInterpolator() { return LINEAR; }
+ public Interpolator getStagedRectYInterpolator() { return LINEAR; }
+ public Interpolator getStagedRectScaleXInterpolator() { return LINEAR; }
+ public Interpolator getStagedRectScaleYInterpolator() { return LINEAR; }
+
+ public float getInstructionsFadeStartOffset() {
+ return (float) getInstructionsFadeStart() / getDuration();
+ }
+ public float getInstructionsFadeEndOffset() {
+ return (float) getInstructionsFadeEnd() / getDuration();
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 76552a3..96504af 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -385,4 +385,12 @@
mBanner.setLayerType(View.LAYER_TYPE_HARDWARE, layerPaint);
mBanner.setLayerPaint(layerPaint);
}
+
+ void setBannerVisibility(int visibility) {
+ if (mBanner == null) {
+ return;
+ }
+
+ mBanner.setVisibility(visibility);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index c211d7a..bf88702 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -1,9 +1,6 @@
package com.android.quickstep.views;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
@@ -31,10 +28,10 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.uioverrides.states.SplitScreenSelectState;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.TaskCornerRadius;
import com.android.systemui.shared.system.QuickStepContract;
@@ -44,38 +41,14 @@
* which will have the thumbnail from the provided existing TaskView overlaying the taskview itself.
*
* Can then animate the taskview using
- * {@link #addAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}
+ * {@link #addStagingAnimation(PendingAnimation, RectF, Rect, boolean, boolean)} or
+ * {@link #addConfirmAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}
* giving a starting and ending bounds. Currently this is set to use the split placeholder view,
* but it could be generified.
*
* TODO: Figure out how to copy thumbnail data from existing TaskView to this view.
*/
public class FloatingTaskView extends FrameLayout {
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START = 0;
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END = 133;
- private static final int OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START = 167;
- private static final int OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END = 250;
- private static final int OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START = 0;
- private static final int OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END = 417;
-
- private static final float OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END
- / SplitScreenSelectState.ENTER_DURATION;
public static final FloatProperty<FloatingTaskView> PRIMARY_TRANSLATE_OFFSCREEN =
new FloatProperty<FloatingTaskView>("floatingTaskPrimaryTranslateOffscreen") {
@@ -236,8 +209,37 @@
layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height);
}
- public void addAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds,
- boolean fadeWithThumbnail, boolean isStagedTask) {
+ /**
+ * Animates a FloatingTaskThumbnailView and its overlapping SplitPlaceholderView when a split
+ * is staged.
+ */
+ public void addStagingAnimation(PendingAnimation animation, RectF startingBounds,
+ Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
+ SplitAnimationTimings timings = fadeWithThumbnail
+ ? SplitAnimationTimings.OVERVIEW_TO_SPLIT
+ : SplitAnimationTimings.NORMAL_TO_SPLIT;
+ addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
+ timings);
+ }
+
+ /**
+ * Animates the FloatingTaskThumbnailView and SplitPlaceholderView for the two thumbnails
+ * when a split is confirmed.
+ */
+ public void addConfirmAnimation(PendingAnimation animation, RectF startingBounds,
+ Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
+ addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
+ SplitAnimationTimings.SPLIT_TO_CONFIRM);
+ }
+
+ /**
+ * Sets up and builds a split staging animation.
+ * Called by {@link #addStagingAnimation(PendingAnimation, RectF, Rect, boolean, boolean)} and
+ * {@link #addConfirmAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}.
+ */
+ public void addAnimation(PendingAnimation animation, RectF startingBounds,
+ Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask,
+ SplitAnimationTimings timings) {
mFullscreenParams.setIsStagedTask(isStagedTask);
final BaseDragLayer dragLayer = mActivity.getDragLayer();
int[] dragLayerBounds = new int[2];
@@ -251,49 +253,47 @@
RectF floatingTaskViewBounds = new RectF();
if (fadeWithThumbnail) {
- // This code block runs when animating from Overview > OverviewSplitSelect
- // And for the second thumbnail on confirm
+ // This code block runs for the placeholder view during Overview > OverviewSplitSelect
+ // and for the selected (secondary) thumbnail during OverviewSplitSelect > Confirmed
// FloatingTaskThumbnailView: thumbnail fades out to transparent
animation.setViewAlpha(mThumbnailView, 0, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET));
+ timings.getPlaceholderFadeInStartOffset(),
+ timings.getPlaceholderFadeInEndOffset()));
- // SplitPlaceholderView: gray background fades in at the same time, then new icon fades
- // in
- animation.setViewAlpha(mSplitPlaceholderView, 1, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET));
- animation.setViewAlpha(mSplitPlaceholderView.getIconView(), 1, clampToProgress(
- LINEAR, OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START_OFFSET,
- OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END_OFFSET));
+ // SplitPlaceholderView: gray background fades in at same time, then new icon fades in
+ fadeInSplitPlaceholder(animation, timings);
} else if (isStagedTask) {
- // This code block runs when animating from Normal > OverviewSplitSelect
- // and for the first thumbnail on confirm
+ // This code block runs for the placeholder view during Normal > OverviewSplitSelect
+ // and for the placeholder (primary) thumbnail during OverviewSplitSelect > Confirmed
- // Fade in the placeholder view when split is initiated from homescreen / all apps
+ // Fade in the placeholder view during Normal > OverviewSplitSelect
if (mSplitPlaceholderView.getAlpha() == 0) {
- animation.setViewAlpha(mSplitPlaceholderView, 0.3f, INSTANT);
- animation.setViewAlpha(mSplitPlaceholderView, 1, ACCEL);
+ mSplitPlaceholderView.getIconView().setAlpha(0);
+ fadeInSplitPlaceholder(animation, timings);
}
+
+ // No-op for placeholder during OverviewSplitSelect > Confirmed, alpha should be set
}
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
// SplitPlaceholderView: rectangle translates and stretches to new position
final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration,
- clampToProgress(DEACCEL_2, OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ clampToProgress(timings.getStagedRectXInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration,
- clampToProgress(DEACCEL_2, OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ clampToProgress(timings.getStagedRectYInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0,
- animDuration, clampToProgress(DEACCEL_2,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ animDuration, clampToProgress(timings.getStagedRectScaleXInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0,
- animDuration, clampToProgress(DEACCEL_2,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ animDuration, clampToProgress(timings.getStagedRectScaleYInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
@Override
public void onUpdate(float percent, boolean initOnly) {
// Calculate the icon position.
@@ -305,9 +305,19 @@
update(floatingTaskViewBounds, percent);
}
};
+
transitionAnimator.addUpdateListener(listener);
}
+ void fadeInSplitPlaceholder(PendingAnimation animation, SplitAnimationTimings timings) {
+ animation.setViewAlpha(mSplitPlaceholderView, 1, clampToProgress(LINEAR,
+ timings.getPlaceholderFadeInStartOffset(),
+ timings.getPlaceholderFadeInEndOffset()));
+ animation.setViewAlpha(mSplitPlaceholderView.getIconView(), 1, clampToProgress(LINEAR,
+ timings.getPlaceholderIconFadeInStartOffset(),
+ timings.getPlaceholderIconFadeInEndOffset()));
+ }
+
void drawRoundedRect(Canvas canvas, Paint paint) {
if (mFullscreenParams == null) {
return;
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 44ea0a0..5bc7f18 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -230,11 +230,12 @@
}
@Override
- protected int getChildTaskIndexAtPosition(PointF position) {
- if (isCoordInView(mIconView2, position) || isCoordInView(mSnapshotView2, position)) {
+ protected int getLastSelectedChildTaskIndex() {
+ if (isCoordInView(mIconView2, mLastTouchDownPosition)
+ || isCoordInView(mSnapshotView2, mLastTouchDownPosition)) {
return 1;
}
- return super.getChildTaskIndexAtPosition(position);
+ return super.getLastSelectedChildTaskIndex();
}
private boolean isCoordInView(View v, PointF position) {
@@ -336,9 +337,26 @@
mSnapshotView2.setSplashAlpha(mTaskThumbnailSplashAlpha);
}
+ /**
+ * Sets visibility for thumbnails and associated elements (DWB banners).
+ * IconView is unaffected.
+ *
+ * When setting INVISIBLE, sets the visibility for the last selected child task.
+ * When setting VISIBLE (as a reset), sets the visibility for both tasks.
+ */
@Override
void setThumbnailVisibility(int visibility) {
- super.setThumbnailVisibility(visibility);
- mSnapshotView2.setVisibility(visibility);
+ if (visibility == VISIBLE) {
+ mSnapshotView.setVisibility(visibility);
+ mDigitalWellBeingToast.setBannerVisibility(visibility);
+ mSnapshotView2.setVisibility(visibility);
+ mDigitalWellBeingToast2.setBannerVisibility(visibility);
+ } else if (getLastSelectedChildTaskIndex() == 0) {
+ mSnapshotView.setVisibility(visibility);
+ mDigitalWellBeingToast.setBannerVisibility(visibility);
+ } else {
+ mSnapshotView2.setVisibility(visibility);
+ mDigitalWellBeingToast2.setBannerVisibility(visibility);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 364cf7b..bb8506d 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -120,11 +120,6 @@
}
@Override
- public void onStateTransitionFailed(LauncherState toState) {
- reset();
- }
-
- @Override
public void onStateTransitionComplete(LauncherState finalState) {
if (finalState == NORMAL || finalState == SPRING_LOADED) {
// Clean-up logic that occurs when recents is no longer in use/visible.
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6a94094..b00794f 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -39,7 +39,7 @@
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_85;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
@@ -142,7 +142,6 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.uioverrides.states.SplitScreenSelectState;
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
@@ -175,6 +174,7 @@
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.SurfaceTransactionApplier;
@@ -419,54 +419,6 @@
private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f;
private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f;
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_START = 67;
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_OFFSET = 16;
- private static final int SPRING_DISMISS_TRANSLATION_DURATION = 500;
-
- private static final float INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_OFFSET
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float END_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
- (float) SPRING_DISMISS_TRANSLATION_DURATION
- / SplitScreenSelectState.ENTER_DURATION;
-
- private static final int OVERVIEW_TO_SPLIT_ICON_FADE_START = 0;
- private static final int OVERVIEW_TO_SPLIT_ICON_FADE_END = 83;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START = 167;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END = 250;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START = 217;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END = 300;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START = 167;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END = 500;
-
- private static final float OVERVIEW_TO_SPLIT_ICON_FADE_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ICON_FADE_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_ICON_FADE_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ICON_FADE_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END
- / SplitScreenSelectState.ENTER_DURATION;
-
private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
protected final RecentsOrientedState mOrientationState;
@@ -703,7 +655,7 @@
@Nullable
private TaskView mSplitHiddenTaskView;
@Nullable
- private View mSecondSplitHiddenView;
+ private TaskView mSecondSplitHiddenView;
@Nullable
private SplitBounds mSplitBoundsConfig;
private final Toast mSplitToast = Toast.makeText(getContext(),
@@ -1292,7 +1244,7 @@
protected void onPageEndTransition() {
super.onPageEndTransition();
ActiveGestureLog.INSTANCE.addLog(
- "onPageEndTransition: current page index updated", mCurrentPage);
+ "onPageEndTransition: current page index updated", getNextPage());
if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
}
@@ -2857,28 +2809,30 @@
mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
+ SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
RectF startingTaskRect = new RectF();
safeRemoveDragLayerView(mFirstFloatingTaskView);
if (mSplitHiddenTaskView != null) {
- // Split staging is initiated
+ // Create the split select animation from Overview
mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE);
anim.setViewAlpha(mSplitHiddenTaskView.getIconView(), 0, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_ICON_FADE_START_OFFSET,
- OVERVIEW_TO_SPLIT_ICON_FADE_END_OFFSET));
+ timings.getIconFadeStartOffset(),
+ timings.getIconFadeEndOffset()));
mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
mSplitHiddenTaskView.getThumbnail(),
mSplitHiddenTaskView.getThumbnail().getThumbnail(),
mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
mFirstFloatingTaskView.setAlpha(1);
- mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
+ mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
true /* fadeWithThumbnail */, true /* isStagedTask */);
} else {
+ // Create the split select animation from Home
mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
mSplitSelectSource.view, null /* thumbnail */,
mSplitSelectSource.drawable, startingTaskRect);
mFirstFloatingTaskView.setAlpha(1);
- mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
+ mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
false /* fadeWithThumbnail */, true /* isStagedTask */);
}
@@ -2887,15 +2841,15 @@
mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
mSplitInstructionsView.setAlpha(0);
anim.setViewAlpha(mSplitInstructionsView, 1, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START_OFFSET,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END_OFFSET));
+ timings.getInstructionsContainerFadeInStartOffset(),
+ timings.getInstructionsContainerFadeInEndOffset()));
anim.setViewAlpha(mSplitInstructionsView.getTextView(), 1, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START_OFFSET,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END_OFFSET));
+ timings.getInstructionsTextFadeInStartOffset(),
+ timings.getInstructionsTextFadeInEndOffset()));
anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1,
clampToProgress(EMPHASIZED_DECELERATE,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START_OFFSET,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END_OFFSET));
+ timings.getInstructionsUnfoldStartOffset(),
+ timings.getInstructionsUnfoldEndOffset()));
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
@@ -3184,24 +3138,26 @@
: distanceFromDismissedTask;
// Set timings based on if user is initiating splitscreen on the focused task,
// or splitting/dismissing some other task.
+ SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
float animationStartProgress = isStagingFocusedTask
? Utilities.boundToRange(
- INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- * staggerColumn, 0f, dismissTranslationInterpolationEnd)
+ timings.getGridSlideStartOffset()
+ + (timings.getGridSlideStaggerOffset() * staggerColumn),
+ 0f,
+ dismissTranslationInterpolationEnd)
: Utilities.boundToRange(
INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
* staggerColumn, 0f, dismissTranslationInterpolationEnd);
float animationEndProgress = isStagingFocusedTask
? Utilities.boundToRange(
- INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + END_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- * staggerColumn,
- 0f, dismissTranslationInterpolationEnd)
+ timings.getGridSlideStartOffset()
+ + (timings.getGridSlideStaggerOffset() * staggerColumn)
+ + timings.getGridSlideDurationOffset(),
+ 0f,
+ dismissTranslationInterpolationEnd)
: dismissTranslationInterpolationEnd;
- Interpolator dismissInterpolator = isStagingFocusedTask ? OVERSHOOT_0_85 : LINEAR;
+ Interpolator dismissInterpolator = isStagingFocusedTask ? OVERSHOOT_0_75 : LINEAR;
if (taskView == nextFocusedTaskView) {
// Enlarge the task to be focused next, and translate into focus position.
@@ -4223,9 +4179,9 @@
// TODO(194414938) starting bounds seem slightly off, investigate
Rect firstTaskStartingBounds = new Rect();
Rect firstTaskEndingBounds = mTempRect;
- int duration = mActivity.getStateManager().getState().getTransitionDuration(mActivity,
- false /* isToState */);
- PendingAnimation pendingAnimation = new PendingAnimation(duration);
+ PendingAnimation pendingAnimation =
+ new PendingAnimation(SplitAnimationTimings.CONFIRM_DURATION);
+ SplitAnimationTimings timings = SplitAnimationTimings.SPLIT_TO_CONFIRM;
int halfDividerSize = getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
@@ -4235,7 +4191,7 @@
secondTaskEndingBounds);
mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
- mFirstFloatingTaskView.addAnimation(pendingAnimation,
+ mFirstFloatingTaskView.addConfirmAnimation(pendingAnimation,
new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
false /* fadeWithThumbnail */, true /* isStagedTask */);
@@ -4244,20 +4200,22 @@
thumbnailView, thumbnailView.getThumbnail(),
iconView.getDrawable(), secondTaskStartingBounds);
mSecondFloatingTaskView.setAlpha(1);
- mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
+ mSecondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
+
+ pendingAnimation.setViewAlpha(mSplitInstructionsView, 0, clampToProgress(LINEAR,
+ timings.getInstructionsFadeStartOffset(),
+ timings.getInstructionsFadeEndOffset()));
+
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.launchSplitTasks(
aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
});
- if (containerTaskView.containsMultipleTasks()) {
- // If we are launching from a child task, then only hide the thumbnail itself
- mSecondSplitHiddenView = thumbnailView;
- } else {
- mSecondSplitHiddenView = containerTaskView;
- }
- mSecondSplitHiddenView.setVisibility(INVISIBLE);
+
+ mSecondSplitHiddenView = containerTaskView;
+ mSecondSplitHiddenView.setThumbnailVisibility(INVISIBLE);
+
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "Second tile selected");
@@ -4278,13 +4236,14 @@
mFirstFloatingTaskView = null;
mSecondFloatingTaskView = null;
mSplitInstructionsView = null;
- if (mSecondSplitHiddenView != null) {
- mSecondSplitHiddenView.setVisibility(VISIBLE);
- mSecondSplitHiddenView = null;
- }
mSplitSelectSource = null;
}
+ if (mSecondSplitHiddenView != null) {
+ mSecondSplitHiddenView.setThumbnailVisibility(VISIBLE);
+ mSecondSplitHiddenView = null;
+ }
+
if (mSplitHiddenTaskViewIndex == -1) {
return;
}
@@ -4300,10 +4259,6 @@
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
resetTaskVisuals();
mSplitHiddenTaskViewIndex = -1;
- if (mSplitHiddenTaskView != null) {
- mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE);
- mSplitHiddenTaskView = null;
- }
}
private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index ee8489d..5df03cc 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -387,7 +387,7 @@
private final float[] mIconCenterCoords = new float[2];
- private final PointF mLastTouchDownPosition = new PointF();
+ protected final PointF mLastTouchDownPosition = new PointF();
private boolean mIsClickableAsLiveTile = true;
@@ -584,16 +584,16 @@
* second app. {@code false} otherwise
*/
private boolean confirmSecondSplitSelectApp() {
- int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
+ int index = getLastSelectedChildTaskIndex();
TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
return getRecentsView().confirmSplitSelect(this, container.getTask(),
container.getIconView(), container.getThumbnailView());
}
/**
- * Returns the task under the given position in the local coordinates of this task view.
+ * Returns the task index of the last selected child task (0 or 1).
*/
- protected int getChildTaskIndexAtPosition(PointF position) {
+ protected int getLastSelectedChildTaskIndex() {
return 0;
}
@@ -1516,8 +1516,17 @@
return display != null ? display.getDisplayId() : DEFAULT_DISPLAY;
}
+ /**
+ * Sets visibility for the thumbnail and associated elements (DWB banners and action chips).
+ * IconView is unaffected.
+ */
void setThumbnailVisibility(int visibility) {
- mSnapshotView.setVisibility(visibility);
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ if (child != mIconView) {
+ child.setVisibility(visibility);
+ }
+ }
}
/**
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 709160d..3a58b85 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -85,7 +85,7 @@
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> телефон чалууларды аткарууга уруксаты жок"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Виджет жүктөлбөй жатат"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Виджеттин жөндөөлөрү"</string>
- <string name="gadget_complete_setup_text" msgid="309040266978007925">"Жөндөп бүтүү үчүн таптап коюңуз"</string>
+ <string name="gadget_complete_setup_text" msgid="309040266978007925">"Аягына чейин тууралоо үчүн басып коюңуз"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Бул системдик колдонмо жана аны чечкенге болбойт."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Аталышын түзөтүү"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> өчүрүлгөн"</string>
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index d34f535..83ff084 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -25,12 +25,16 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
+import android.os.Bundle;
+import android.window.OnBackInvokedDispatcher;
import androidx.annotation.IntDef;
import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.AppLauncher;
@@ -172,6 +176,19 @@
}
@Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (Utilities.ATLEAST_T) {
+ getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ () -> {
+ onBackPressed();
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
+ });
+ }
+ }
+
+ @Override
protected void onStart() {
addActivityFlags(ACTIVITY_STATE_STARTED);
super.onStart();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 17fb7eb..5e2187e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -114,7 +114,6 @@
import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
import android.widget.Toast;
-import android.window.OnBackInvokedDispatcher;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
@@ -544,8 +543,6 @@
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
setTitle(R.string.home_screen);
-
- registerOnBackInvokedCallback();
}
protected LauncherOverlayManager getDefaultOverlay() {
@@ -2065,17 +2062,6 @@
mStateManager.getState().onBackPressed(this);
}
- private void registerOnBackInvokedCallback() {
- if (Utilities.ATLEAST_T) {
- getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
- OnBackInvokedDispatcher.PRIORITY_DEFAULT,
- () -> {
- onBackPressed();
- TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
- });
- }
- }
-
protected void onScreenOff() {
// Reset AllApps to its initial state only if we are not in the middle of
// processing a multi-step drop
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 68b7701..20df897 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -33,6 +33,7 @@
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -89,9 +90,11 @@
static final String TAG = "Launcher.Model";
+ @NonNull
private final LauncherAppState mApp;
+ @NonNull
private final Object mLock = new Object();
-
+ @Nullable
private LoaderTask mLoaderTask;
private boolean mIsLoaderTaskRunning;
@@ -107,20 +110,25 @@
}
}
+ @NonNull
private final ArrayList<Callbacks> mCallbacksList = new ArrayList<>(1);
// < only access in worker thread >
+ @NonNull
private final AllAppsList mBgAllAppsList;
/**
* All the static data should be accessed on the background thread, A lock should be acquired
* on this object when accessing any data from this model.
*/
+ @NonNull
private final BgDataModel mBgDataModel = new BgDataModel();
+ @NonNull
private final ModelDelegate mModelDelegate;
// Runnable to check if the shortcuts permission has changed.
+ @NonNull
private final Runnable mDataValidationCheck = new Runnable() {
@Override
public void run() {
@@ -130,14 +138,16 @@
}
};
- LauncherModel(Context context, LauncherAppState app, IconCache iconCache, AppFilter appFilter,
- boolean isPrimaryInstance) {
+ LauncherModel(@NonNull final Context context, @NonNull final LauncherAppState app,
+ @NonNull final IconCache iconCache, @NonNull final AppFilter appFilter,
+ final boolean isPrimaryInstance) {
mApp = app;
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
mModelDelegate = ModelDelegate.newInstance(context, app, mBgAllAppsList, mBgDataModel,
isPrimaryInstance);
}
+ @NonNull
public ModelDelegate getModelDelegate() {
return mModelDelegate;
}
@@ -145,52 +155,57 @@
/**
* Adds the provided items to the workspace.
*/
- public void addAndBindAddedWorkspaceItems(List<Pair<ItemInfo, Object>> itemList) {
+ public void addAndBindAddedWorkspaceItems(
+ @NonNull final List<Pair<ItemInfo, Object>> itemList) {
for (Callbacks cb : getCallbacks()) {
cb.preAddApps();
}
enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList));
}
- public ModelWriter getWriter(boolean hasVerticalHotseat, boolean verifyChanges,
- @Nullable Callbacks owner) {
+ @NonNull
+ public ModelWriter getWriter(final boolean hasVerticalHotseat, final boolean verifyChanges,
+ @Nullable final Callbacks owner) {
return new ModelWriter(mApp.getContext(), this, mBgDataModel,
hasVerticalHotseat, verifyChanges, owner);
}
@Override
- public void onPackageChanged(String packageName, UserHandle user) {
+ public void onPackageChanged(
+ @NonNull final String packageName, @NonNull final UserHandle user) {
int op = PackageUpdatedTask.OP_UPDATE;
enqueueModelUpdateTask(new PackageUpdatedTask(op, user, packageName));
}
@Override
- public void onPackageRemoved(String packageName, UserHandle user) {
+ public void onPackageRemoved(
+ @NonNull final String packageName, @NonNull final UserHandle user) {
onPackagesRemoved(user, packageName);
}
- public void onPackagesRemoved(UserHandle user, String... packages) {
+ public void onPackagesRemoved(
+ @NonNull final UserHandle user, @NonNull final String... packages) {
int op = PackageUpdatedTask.OP_REMOVE;
FileLog.d(TAG, "package removed received " + TextUtils.join(",", packages));
enqueueModelUpdateTask(new PackageUpdatedTask(op, user, packages));
}
@Override
- public void onPackageAdded(String packageName, UserHandle user) {
+ public void onPackageAdded(@NonNull final String packageName, @NonNull final UserHandle user) {
int op = PackageUpdatedTask.OP_ADD;
enqueueModelUpdateTask(new PackageUpdatedTask(op, user, packageName));
}
@Override
- public void onPackagesAvailable(String[] packageNames, UserHandle user,
- boolean replacing) {
+ public void onPackagesAvailable(@NonNull final String[] packageNames,
+ @NonNull final UserHandle user, final boolean replacing) {
enqueueModelUpdateTask(
new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, user, packageNames));
}
@Override
- public void onPackagesUnavailable(String[] packageNames, UserHandle user,
- boolean replacing) {
+ public void onPackagesUnavailable(@NonNull final String[] packageNames,
+ @NonNull final UserHandle user, final boolean replacing) {
if (!replacing) {
enqueueModelUpdateTask(new PackageUpdatedTask(
PackageUpdatedTask.OP_UNAVAILABLE, user, packageNames));
@@ -198,20 +213,22 @@
}
@Override
- public void onPackagesSuspended(String[] packageNames, UserHandle user) {
+ public void onPackagesSuspended(
+ @NonNull final String[] packageNames, @NonNull final UserHandle user) {
enqueueModelUpdateTask(new PackageUpdatedTask(
PackageUpdatedTask.OP_SUSPEND, user, packageNames));
}
@Override
- public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
+ public void onPackagesUnsuspended(
+ @NonNull final String[] packageNames, @NonNull final UserHandle user) {
enqueueModelUpdateTask(new PackageUpdatedTask(
PackageUpdatedTask.OP_UNSUSPEND, user, packageNames));
}
@Override
- public void onPackageLoadingProgressChanged(
- String packageName, UserHandle user, float progress) {
+ public void onPackageLoadingProgressChanged(@NonNull final String packageName,
+ @NonNull final UserHandle user, final float progress) {
if (Utilities.ATLEAST_S) {
enqueueModelUpdateTask(new PackageIncrementalDownloadUpdatedTask(
packageName, user, progress));
@@ -219,8 +236,8 @@
}
@Override
- public void onShortcutsChanged(String packageName, List<ShortcutInfo> shortcuts,
- UserHandle user) {
+ public void onShortcutsChanged(@NonNull final String packageName,
+ @NonNull final List<ShortcutInfo> shortcuts, @NonNull final UserHandle user) {
enqueueModelUpdateTask(new ShortcutsChangedTask(packageName, shortcuts, user, true));
}
@@ -228,7 +245,8 @@
* Called when the icon for an app changes, outside of package event
*/
@WorkerThread
- public void onAppIconChanged(String packageName, UserHandle user) {
+ public void onAppIconChanged(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
// Update the icon for the calendar package
Context context = mApp.getContext();
onPackageChanged(packageName, user);
@@ -256,7 +274,7 @@
MODEL_EXECUTOR.execute(mModelDelegate::destroy);
}
- public void onBroadcastIntent(Intent intent) {
+ public void onBroadcastIntent(@NonNull final Intent intent) {
if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);
final String action = intent.getAction();
if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
@@ -322,7 +340,7 @@
/**
* Removes an existing callback
*/
- public void removeCallbacks(Callbacks callbacks) {
+ public void removeCallbacks(@NonNull final Callbacks callbacks) {
synchronized (mCallbacksList) {
Preconditions.assertUIThread();
if (mCallbacksList.remove(callbacks)) {
@@ -338,7 +356,7 @@
* Adds a callbacks to receive model updates
* @return true if workspace load was performed synchronously
*/
- public boolean addCallbacksAndLoad(Callbacks callbacks) {
+ public boolean addCallbacksAndLoad(@NonNull final Callbacks callbacks) {
synchronized (mLock) {
addCallbacks(callbacks);
return startLoader(new Callbacks[] { callbacks });
@@ -349,7 +367,7 @@
/**
* Adds a callbacks to receive model updates
*/
- public void addCallbacks(Callbacks callbacks) {
+ public void addCallbacks(@NonNull final Callbacks callbacks) {
Preconditions.assertUIThread();
synchronized (mCallbacksList) {
if (TestProtocol.sDebugTracing) {
@@ -370,7 +388,7 @@
return startLoader(new Callbacks[0]);
}
- private boolean startLoader(Callbacks[] newCallbacks) {
+ private boolean startLoader(@NonNull final Callbacks[] newCallbacks) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
ItemInstallQueue.INSTANCE.get(mApp.getContext())
.pauseModelPush(ItemInstallQueue.FLAG_LOADER_RUNNING);
@@ -433,7 +451,7 @@
* Loads the model if not loaded
* @param callback called with the data model upon successful load or null on model thread.
*/
- public void loadAsync(Consumer<BgDataModel> callback) {
+ public void loadAsync(@NonNull final Consumer<BgDataModel> callback) {
synchronized (mLock) {
if (!mModelLoaded && !mIsLoaderTaskRunning) {
startLoader();
@@ -443,11 +461,12 @@
}
@Override
- public void onInstallSessionCreated(final PackageInstallInfo sessionInfo) {
+ public void onInstallSessionCreated(@NonNull final PackageInstallInfo sessionInfo) {
if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
apps.addPromiseApp(app.getContext(), sessionInfo);
bindApplicationsIfNeeded();
}
@@ -456,10 +475,12 @@
}
@Override
- public void onSessionFailure(String packageName, UserHandle user) {
+ public void onSessionFailure(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
final IntSet removedIds = new IntSet();
synchronized (dataModel) {
for (ItemInfo info : dataModel.itemsIdMap) {
@@ -483,7 +504,7 @@
}
@Override
- public void onPackageStateChanged(PackageInstallInfo installInfo) {
+ public void onPackageStateChanged(@NonNull final PackageInstallInfo installInfo) {
enqueueModelUpdateTask(new PackageInstallStateChangedTask(installInfo));
}
@@ -491,7 +512,8 @@
* Updates the icons and label of all pending icons for the provided package name.
*/
@Override
- public void onUpdateSessionDisplay(PackageUserKey key, PackageInstaller.SessionInfo info) {
+ public void onUpdateSessionDisplay(@NonNull final PackageUserKey key,
+ @NonNull final PackageInstaller.SessionInfo info) {
mApp.getIconCache().updateSessionCache(key, info);
HashSet<String> packages = new HashSet<>();
@@ -502,9 +524,10 @@
public class LoaderTransaction implements AutoCloseable {
+ @NonNull
private final LoaderTask mTask;
- private LoaderTransaction(LoaderTask task) throws CancellationException {
+ private LoaderTransaction(@NonNull final LoaderTask task) throws CancellationException {
synchronized (mLock) {
if (mLoaderTask != task) {
throw new CancellationException("Loader already stopped");
@@ -534,7 +557,8 @@
}
}
- public LoaderTransaction beginLoader(LoaderTask task) throws CancellationException {
+ public LoaderTransaction beginLoader(@NonNull final LoaderTask task)
+ throws CancellationException {
return new LoaderTransaction(task);
}
@@ -551,7 +575,8 @@
/**
* Called when the icons for packages have been updated in the icon cache.
*/
- public void onPackageIconsUpdated(HashSet<String> updatedPackages, UserHandle user) {
+ public void onPackageIconsUpdated(@NonNull final HashSet<String> updatedPackages,
+ @NonNull final UserHandle user) {
// If any package icon has changed (app was updated while launcher was dead),
// update the corresponding shortcuts.
enqueueModelUpdateTask(new CacheDataUpdatedTask(
@@ -561,17 +586,19 @@
/**
* Called when the labels for the widgets has updated in the icon cache.
*/
- public void onWidgetLabelsUpdated(HashSet<String> updatedPackages, UserHandle user) {
+ public void onWidgetLabelsUpdated(@NonNull final HashSet<String> updatedPackages,
+ @NonNull final UserHandle user) {
enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user, app);
bindUpdatedWidgets(dataModel);
}
});
}
- public void enqueueModelUpdateTask(ModelUpdateTask task) {
+ public void enqueueModelUpdateTask(@NonNull final ModelUpdateTask task) {
if (mModelDestroyed) {
return;
}
@@ -585,7 +612,7 @@
*/
public interface CallbackTask {
- void execute(Callbacks callbacks);
+ void execute(@NonNull Callbacks callbacks);
}
/**
@@ -596,12 +623,14 @@
/**
* Called before the task is posted to initialize the internal state.
*/
- void init(LauncherAppState app, LauncherModel model,
- BgDataModel dataModel, AllAppsList allAppsList, Executor uiExecutor);
+ void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
+ @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
+ @NonNull Executor uiExecutor);
}
- public void updateAndBindWorkspaceItem(WorkspaceItemInfo si, ShortcutInfo info) {
+ public void updateAndBindWorkspaceItem(@NonNull final WorkspaceItemInfo si,
+ @NonNull final ShortcutInfo info) {
updateAndBindWorkspaceItem(() -> {
si.updateFromDeepShortcutInfo(info, mApp.getContext());
mApp.getIconCache().getShortcutIcon(si, info);
@@ -612,10 +641,12 @@
/**
* Utility method to update a shortcut on the background thread.
*/
- public void updateAndBindWorkspaceItem(final Supplier<WorkspaceItemInfo> itemProvider) {
+ public void updateAndBindWorkspaceItem(
+ @NonNull final Supplier<WorkspaceItemInfo> itemProvider) {
enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
WorkspaceItemInfo info = itemProvider.get();
getModelWriter().updateItemInDatabase(info);
ArrayList<WorkspaceItemInfo> update = new ArrayList<>();
@@ -628,14 +659,16 @@
public void refreshAndBindWidgetsAndShortcuts(@Nullable final PackageUserKey packageUser) {
enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
dataModel.widgetsModel.update(app, packageUser);
bindUpdatedWidgets(dataModel);
}
});
}
- public void dumpState(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ public void dumpState(@Nullable final String prefix, @Nullable final FileDescriptor fd,
+ @NonNull final PrintWriter writer, @NonNull final String[] args) {
if (args.length > 0 && TextUtils.equals(args[0], "--all")) {
writer.println(prefix + "All apps list: size=" + mBgAllAppsList.data.size());
for (AppInfo info : mBgAllAppsList.data) {
@@ -661,6 +694,7 @@
/**
* Returns an array of currently attached callbacks
*/
+ @NonNull
public Callbacks[] getCallbacks() {
synchronized (mCallbacksList) {
return mCallbacksList.toArray(new Callbacks[mCallbacksList.size()]);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 22e8bcf..391de8d 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -228,6 +228,11 @@
public void setStateWithAnimation(LauncherState toState,
StateAnimationConfig config, PendingAnimation builder) {
if (mLauncher.isInState(ALL_APPS) && !ALL_APPS.equals(toState)) {
+ // For atomic animations, we close the keyboard immediately.
+ if (!config.userControlled && !FeatureFlags.ENABLE_KEYBOARD_TRANSITION_SYNC.get()) {
+ mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
+ }
+
builder.addEndListener(success -> {
// Reset pull back progress and alpha after switching states.
ALL_APPS_PULL_BACK_TRANSLATION.set(this, 0f);
@@ -238,7 +243,7 @@
// the keyboard open and then changes their mind and swipes back up, we want the
// keyboard to remain open. However an onCancel signal is sent to the listeners
// (success = false), so we need to check for that.
- if (success) {
+ if (config.userControlled && success) {
mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
}
});
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index d2d7a6c..ab47097 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -22,6 +22,7 @@
import android.os.Handler;
import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
@@ -68,7 +69,8 @@
public void doSearch(String query, SearchCallback<AdapterItem> callback) {
mAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
ArrayList<AdapterItem> result = getTitleMatchResult(apps.data, query);
if (mAddNoResultsMessage && result.isEmpty()) {
result.add(getEmptyMessageAdapterItem(query));
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index d900c90..b55a1e4 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -83,7 +83,7 @@
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
}
- public static final Interpolator OVERSHOOT_0_85 = new OvershootInterpolator(0.85f);
+ public static final Interpolator OVERSHOOT_0_75 = new OvershootInterpolator(0.75f);
public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 5021644..bf59594 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -24,6 +24,7 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
@@ -192,7 +193,8 @@
private class FolderNameWorker extends BaseModelUpdateTask {
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
mFolderInfos = dataModel.folders.clone();
mAppInfos = Arrays.asList(apps.copyData());
}
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 4c0f1ae..0d978e1 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -23,6 +23,9 @@
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherSettings;
@@ -42,6 +45,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Task to add auto-created workspace items.
@@ -50,14 +54,16 @@
private static final String LOG = "AddWorkspaceItemsTask";
+ @NonNull
private final List<Pair<ItemInfo, Object>> mItemList;
+ @NonNull
private final WorkspaceItemSpaceFinder mItemSpaceFinder;
/**
* @param itemList items to add on the workspace
*/
- public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) {
+ public AddWorkspaceItemsTask(@NonNull final List<Pair<ItemInfo, Object>> itemList) {
this(itemList, new WorkspaceItemSpaceFinder());
}
@@ -65,14 +71,15 @@
* @param itemList items to add on the workspace
* @param itemSpaceFinder inject WorkspaceItemSpaceFinder dependency for testing
*/
- public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList,
- WorkspaceItemSpaceFinder itemSpaceFinder) {
+ public AddWorkspaceItemsTask(@NonNull final List<Pair<ItemInfo, Object>> itemList,
+ @NonNull final WorkspaceItemSpaceFinder itemSpaceFinder) {
mItemList = itemList;
mItemSpaceFinder = itemSpaceFinder;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
if (mItemList.isEmpty()) {
return;
}
@@ -98,7 +105,8 @@
}
// b/139663018 Short-circuit this logic if the icon is a system app
- if (PackageManagerHelper.isSystemApp(app.getContext(), item.getIntent())) {
+ if (PackageManagerHelper.isSystemApp(app.getContext(),
+ Objects.requireNonNull(item.getIntent()))) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.MISSING_PROMISE_ICON,
LOG + " Item is a system app.");
@@ -159,7 +167,7 @@
continue;
}
- List<LauncherActivityInfo> activities = launcherApps
+ List<LauncherActivityInfo> activities = Objects.requireNonNull(launcherApps)
.getActivityList(packageName, item.user);
boolean hasActivity = activities != null && !activities.isEmpty();
@@ -218,7 +226,7 @@
if (!addedItemsFinal.isEmpty()) {
scheduleCallbackTask(new CallbackTask() {
@Override
- public void execute(Callbacks callbacks) {
+ public void execute(@NonNull Callbacks callbacks) {
final ArrayList<ItemInfo> addAnimated = new ArrayList<>();
final ArrayList<ItemInfo> addNotAnimated = new ArrayList<>();
if (!addedItemsFinal.isEmpty()) {
@@ -243,7 +251,8 @@
* Returns true if the shortcuts already exists on the workspace. This must be called after
* the workspace has been loaded. We identify a shortcut by its intent.
*/
- protected boolean shortcutExists(BgDataModel dataModel, Intent intent, UserHandle user) {
+ protected boolean shortcutExists(@NonNull final BgDataModel dataModel,
+ @Nullable final Intent intent, @NonNull final UserHandle user) {
final String compPkgName, intentWithPkg, intentWithoutPkg;
if (intent == null) {
// Skip items with null intents
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index 95150dc..6da948c 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -66,7 +66,10 @@
/** The list off all apps. */
public final ArrayList<AppInfo> data = new ArrayList<>(DEFAULT_APPLICATIONS_NUMBER);
+ @NonNull
private IconCache mIconCache;
+
+ @NonNull
private AppFilter mAppFilter;
private boolean mDataChanged = false;
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index 2a6a691..5b6f9f6 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -17,6 +17,7 @@
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
@@ -47,14 +48,17 @@
private static final boolean DEBUG_TASKS = false;
private static final String TAG = "BaseModelUpdateTask";
+ // Nullabilities are explicitly omitted here because these are late-init fields,
+ // They will be non-null after init(), which is always the case in enqueueModelUpdateTask().
private LauncherAppState mApp;
private LauncherModel mModel;
private BgDataModel mDataModel;
private AllAppsList mAllAppsList;
private Executor mUiExecutor;
- public void init(LauncherAppState app, LauncherModel model,
- BgDataModel dataModel, AllAppsList allAppsList, Executor uiExecutor) {
+ public void init(@NonNull final LauncherAppState app, @NonNull final LauncherModel model,
+ @NonNull final BgDataModel dataModel, @NonNull final AllAppsList allAppsList,
+ @NonNull final Executor uiExecutor) {
mApp = app;
mModel = model;
mDataModel = dataModel;
@@ -64,7 +68,7 @@
@Override
public final void run() {
- if (!mModel.isModelLoaded()) {
+ if (!Objects.requireNonNull(mModel).isModelLoaded()) {
if (DEBUG_TASKS) {
Log.d(TAG, "Ignoring model task since loader is pending=" + this);
}
@@ -77,13 +81,13 @@
/**
* Execute the actual task. Called on the worker thread.
*/
- public abstract void execute(
- LauncherAppState app, BgDataModel dataModel, AllAppsList apps);
+ public abstract void execute(@NonNull LauncherAppState app,
+ @NonNull BgDataModel dataModel, @NonNull AllAppsList apps);
/**
* Schedules a {@param task} to be executed on the current callbacks.
*/
- public final void scheduleCallbackTask(final CallbackTask task) {
+ public final void scheduleCallbackTask(@NonNull final CallbackTask task) {
for (final Callbacks cb : mModel.getCallbacks()) {
mUiExecutor.execute(() -> task.execute(cb));
}
@@ -95,7 +99,7 @@
return mModel.getWriter(false /* hasVerticalHotseat */, false /* verifyChanges */, null);
}
- public void bindUpdatedWorkspaceItems(List<WorkspaceItemInfo> allUpdates) {
+ public void bindUpdatedWorkspaceItems(@NonNull final List<WorkspaceItemInfo> allUpdates) {
// Bind workspace items
List<WorkspaceItemInfo> workspaceUpdates = allUpdates.stream()
.filter(info -> info.id != ItemInfo.NO_ID)
@@ -113,18 +117,18 @@
.forEach(this::bindExtraContainerItems);
}
- public void bindExtraContainerItems(FixedContainerItems item) {
+ public void bindExtraContainerItems(@NonNull final FixedContainerItems item) {
FixedContainerItems copy = item.clone();
scheduleCallbackTask(c -> c.bindExtraContainerItems(copy));
}
- public void bindDeepShortcuts(BgDataModel dataModel) {
+ public void bindDeepShortcuts(@NonNull final BgDataModel dataModel) {
final HashMap<ComponentKey, Integer> shortcutMapCopy =
new HashMap<>(dataModel.deepShortcutMap);
scheduleCallbackTask(callbacks -> callbacks.bindDeepShortcutMap(shortcutMapCopy));
}
- public void bindUpdatedWidgets(BgDataModel dataModel) {
+ public void bindUpdatedWidgets(@NonNull final BgDataModel dataModel) {
final ArrayList<WidgetsListBaseEntry> widgets =
dataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());
scheduleCallbackTask(c -> c.bindAllWidgets(widgets));
diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
index f644d49..57fefaa 100644
--- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java
+++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
@@ -18,6 +18,8 @@
import android.content.ComponentName;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.icons.IconCache;
@@ -35,17 +37,23 @@
public static final int OP_SESSION_UPDATE = 2;
private final int mOp;
+
+ @NonNull
private final UserHandle mUser;
+
+ @NonNull
private final HashSet<String> mPackages;
- public CacheDataUpdatedTask(int op, UserHandle user, HashSet<String> packages) {
+ public CacheDataUpdatedTask(final int op, @NonNull final UserHandle user,
+ @NonNull final HashSet<String> packages) {
mOp = op;
mUser = user;
mPackages = packages;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
IconCache iconCache = app.getIconCache();
ArrayList<WorkspaceItemInfo> updatedShortcuts = new ArrayList<>();
@@ -65,7 +73,7 @@
bindApplicationsIfNeeded();
}
- public boolean isValidShortcut(WorkspaceItemInfo si) {
+ public boolean isValidShortcut(@NonNull final WorkspaceItemInfo si) {
switch (mOp) {
case OP_CACHE_UPDATE:
return true;
diff --git a/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java b/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java
index c0dc34a..b9fba9d 100644
--- a/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java
@@ -17,6 +17,8 @@
import android.os.UserHandle;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -31,19 +33,24 @@
*/
public class PackageIncrementalDownloadUpdatedTask extends BaseModelUpdateTask {
+ @NonNull
private final UserHandle mUser;
+
private final int mProgress;
+
+ @NonNull
private final String mPackageName;
- public PackageIncrementalDownloadUpdatedTask(
- String packageName, UserHandle user, float progress) {
+ public PackageIncrementalDownloadUpdatedTask(@NonNull final String packageName,
+ @NonNull final UserHandle user, final float progress) {
mUser = user;
mProgress = 1 - progress > 0.001 ? (int) (100 * progress) : 100;
mPackageName = packageName;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+ public void execute(@NonNull LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList appsList) {
PackageInstallInfo downloadInfo = new PackageInstallInfo(
mPackageName,
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING,
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index b74d0fc..76a87ed 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -18,6 +18,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -33,14 +35,16 @@
*/
public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
+ @NonNull
private final PackageInstallInfo mInstallInfo;
- public PackageInstallStateChangedTask(PackageInstallInfo installInfo) {
+ public PackageInstallStateChangedTask(@NonNull final PackageInstallInfo installInfo) {
mInstallInfo = installInfo;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
if (mInstallInfo.state == PackageInstallInfo.STATUS_INSTALLED) {
try {
// For instant apps we do not get package-add. Use setting events to update
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index a9d272e..3d9d81f 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -29,6 +29,8 @@
import android.os.UserManager;
import android.util.Log;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
@@ -80,17 +82,23 @@
public static final int OP_USER_AVAILABILITY_CHANGE = 7; // user available/unavailable
private final int mOp;
+
+ @NonNull
private final UserHandle mUser;
+
+ @NonNull
private final String[] mPackages;
- public PackageUpdatedTask(int op, UserHandle user, String... packages) {
+ public PackageUpdatedTask(final int op, @NonNull final UserHandle user,
+ @NonNull final String... packages) {
mOp = op;
mUser = user;
mPackages = packages;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList appsList) {
final Context context = app.getContext();
final IconCache iconCache = app.getIconCache();
diff --git a/src/com/android/launcher3/model/ReloadStringCacheTask.java b/src/com/android/launcher3/model/ReloadStringCacheTask.java
index f4d4298..34f7057 100644
--- a/src/com/android/launcher3/model/ReloadStringCacheTask.java
+++ b/src/com/android/launcher3/model/ReloadStringCacheTask.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.model;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
/**
@@ -22,14 +24,17 @@
* {@link android.app.admin.DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED}.
*/
public class ReloadStringCacheTask extends BaseModelUpdateTask {
+
+ @NonNull
private ModelDelegate mModelDelegate;
- public ReloadStringCacheTask(ModelDelegate modelDelegate) {
+ public ReloadStringCacheTask(@NonNull final ModelDelegate modelDelegate) {
mModelDelegate = modelDelegate;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList appsList) {
synchronized (dataModel) {
mModelDelegate.loadStringCache(dataModel.stringCache);
StringCache cloneSC = dataModel.stringCache.clone();
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 1026e0b..a6a04a7 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -19,6 +19,8 @@
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -38,13 +40,20 @@
*/
public class ShortcutsChangedTask extends BaseModelUpdateTask {
+ @NonNull
private final String mPackageName;
+
+ @NonNull
private final List<ShortcutInfo> mShortcuts;
+
+ @NonNull
private final UserHandle mUser;
+
private final boolean mUpdateIdMap;
- public ShortcutsChangedTask(String packageName, List<ShortcutInfo> shortcuts,
- UserHandle user, boolean updateIdMap) {
+ public ShortcutsChangedTask(@NonNull final String packageName,
+ @NonNull final List<ShortcutInfo> shortcuts, @NonNull final UserHandle user,
+ final boolean updateIdMap) {
mPackageName = packageName;
mShortcuts = shortcuts;
mUser = user;
@@ -52,7 +61,8 @@
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
final Context context = app.getContext();
// Find WorkspaceItemInfo's that have changed on the workspace.
ArrayList<WorkspaceItemInfo> matchingWorkspaceItems = new ArrayList<>();
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 1565b19..63ca35b 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -21,6 +21,8 @@
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -40,16 +42,18 @@
*/
public class UserLockStateChangedTask extends BaseModelUpdateTask {
+ @NonNull
private final UserHandle mUser;
private boolean mIsUserUnlocked;
- public UserLockStateChangedTask(UserHandle user, boolean isUserUnlocked) {
+ public UserLockStateChangedTask(@NonNull final UserHandle user, final boolean isUserUnlocked) {
mUser = user;
mIsUserUnlocked = isUserUnlocked;
}
@Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList apps) {
Context context = app.getContext();
HashMap<ShortcutKey, ShortcutInfo> pinnedShortcuts = new HashMap<>();
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index 76a0c4d..e5fb015 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -16,7 +16,6 @@
package com.android.launcher3.model.data;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -220,10 +219,10 @@
/** Creates an intent to that launches the app store at this app's page. */
@Nullable
public Intent getMarketIntent(Context context) {
- ComponentName componentName = getTargetComponent();
+ String targetPackage = getTargetPackage();
- return componentName != null
- ? new PackageManagerHelper(context).getMarketIntent(componentName.getPackageName())
+ return targetPackage != null
+ ? new PackageManagerHelper(context).getMarketIntent(targetPackage)
: null;
}
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 1f16474..59ef320 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -24,7 +24,6 @@
import android.text.TextUtils;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -76,6 +75,7 @@
/**
* The intent used to start the application.
*/
+ @NonNull
public Intent intent;
/**
@@ -148,7 +148,7 @@
}
@Override
- @Nullable
+ @NonNull
public Intent getIntent() {
return intent;
}
@@ -166,7 +166,8 @@
return isPromise() && !hasStatusFlag(FLAG_SUPPORTS_WEB_UI);
}
- public void updateFromDeepShortcutInfo(ShortcutInfo shortcutInfo, Context context) {
+ public void updateFromDeepShortcutInfo(@NonNull final ShortcutInfo shortcutInfo,
+ @NonNull final Context context) {
// {@link ShortcutInfo#getActivity} can change during an update. Recreate the intent
intent = ShortcutKey.makeIntent(shortcutInfo);
title = shortcutInfo.getShortLabel();
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index b695194..16bb868 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -30,6 +30,7 @@
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.WorkerThread;
@@ -51,38 +52,50 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
/**
* Utility class to tracking install sessions
*/
public class InstallSessionHelper {
+ @NonNull
private static final String LOG = "InstallSessionHelper";
// Set<String> of session ids of promise icons that have been added to the home screen
// as FLAG_PROMISE_NEW_INSTALLS.
+ @NonNull
protected static final String PROMISE_ICON_IDS = "promise_icon_ids";
private static final boolean DEBUG = false;
+ @NonNull
public static final MainThreadInitializedObject<InstallSessionHelper> INSTANCE =
new MainThreadInitializedObject<>(InstallSessionHelper::new);
+ @Nullable
private final LauncherApps mLauncherApps;
+
+ @NonNull
private final Context mAppContext;
+ @NonNull
private final PackageInstaller mInstaller;
+
+ @NonNull
private final HashMap<String, Boolean> mSessionVerifiedMap = new HashMap<>();
+ @Nullable
private IntSet mPromiseIconIds;
- public InstallSessionHelper(Context context) {
+ public InstallSessionHelper(@NonNull final Context context) {
mInstaller = context.getPackageManager().getPackageInstaller();
mAppContext = context.getApplicationContext();
mLauncherApps = context.getSystemService(LauncherApps.class);
}
@WorkerThread
+ @NonNull
private IntSet getPromiseIconIds() {
Preconditions.assertWorkerThread();
if (mPromiseIconIds != null) {
@@ -108,6 +121,7 @@
return mPromiseIconIds;
}
+ @NonNull
public HashMap<PackageUserKey, SessionInfo> getActiveSessions() {
HashMap<PackageUserKey, SessionInfo> activePackages = new HashMap<>();
for (SessionInfo info : getAllVerifiedSessions()) {
@@ -117,6 +131,7 @@
return activePackages;
}
+ @Nullable
public SessionInfo getActiveSessionInfo(UserHandle user, String pkg) {
for (SessionInfo info : getAllVerifiedSessions()) {
boolean match = pkg.equals(info.getAppPackageName());
@@ -136,11 +151,13 @@
.apply();
}
- SessionInfo getVerifiedSessionInfo(int sessionId) {
+ @Nullable
+ SessionInfo getVerifiedSessionInfo(final int sessionId) {
return verify(mInstaller.getSessionInfo(sessionId));
}
- private SessionInfo verify(SessionInfo sessionInfo) {
+ @Nullable
+ private SessionInfo verify(@Nullable final SessionInfo sessionInfo) {
if (sessionInfo == null
|| sessionInfo.getInstallerPackageName() == null
|| TextUtils.isEmpty(sessionInfo.getAppPackageName())) {
@@ -167,9 +184,10 @@
return mSessionVerifiedMap.get(pkg) ? sessionInfo : null;
}
+ @NonNull
public List<SessionInfo> getAllVerifiedSessions() {
List<SessionInfo> list = new ArrayList<>(Utilities.ATLEAST_Q
- ? mLauncherApps.getAllPackageInstallerSessions()
+ ? Objects.requireNonNull(mLauncherApps).getAllPackageInstallerSessions()
: mInstaller.getAllSessions());
Iterator<SessionInfo> it = list.iterator();
while (it.hasNext()) {
@@ -201,12 +219,12 @@
}
@WorkerThread
- public boolean promiseIconAddedForId(int sessionId) {
+ public boolean promiseIconAddedForId(final int sessionId) {
return getPromiseIconIds().contains(sessionId);
}
@WorkerThread
- public void removePromiseIconId(int sessionId) {
+ public void removePromiseIconId(final int sessionId) {
if (promiseIconAddedForId(sessionId)) {
getPromiseIconIds().getArray().removeValue(sessionId);
updatePromiseIconPrefs();
@@ -222,7 +240,7 @@
* - A promise icon for the session has not already been created
*/
@WorkerThread
- void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) {
+ void tryQueuePromiseAppIcon(@Nullable final PackageInstaller.SessionInfo sessionInfo) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " tryQueuePromiseAppIcon"
+ ", SessionCommitReceiveEnabled" + SessionCommitReceiver.isEnabled(mAppContext)
@@ -244,7 +262,7 @@
}
}
- public boolean verifySessionInfo(PackageInstaller.SessionInfo sessionInfo) {
+ public boolean verifySessionInfo(@Nullable final PackageInstaller.SessionInfo sessionInfo) {
if (TestProtocol.sDebugTracing) {
boolean appNotInstalled = sessionInfo == null
|| !new PackageManagerHelper(mAppContext)
@@ -267,14 +285,15 @@
sessionInfo.getAppPackageName(), getUserHandle(sessionInfo));
}
- public InstallSessionTracker registerInstallTracker(InstallSessionTracker.Callback callback) {
+ public InstallSessionTracker registerInstallTracker(
+ @Nullable final InstallSessionTracker.Callback callback) {
InstallSessionTracker tracker = new InstallSessionTracker(
this, callback, mInstaller, mLauncherApps);
tracker.register();
return tracker;
}
- public static UserHandle getUserHandle(SessionInfo info) {
+ public static UserHandle getUserHandle(@NonNull final SessionInfo info) {
return Utilities.ATLEAST_Q ? info.getUser() : Process.myUserHandle();
}
}
diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java
index b16aaa2..aeaa320 100644
--- a/src/com/android/launcher3/pm/InstallSessionTracker.java
+++ b/src/com/android/launcher3/pm/InstallSessionTracker.java
@@ -28,12 +28,15 @@
import android.util.Log;
import android.util.SparseArray;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.PackageUserKey;
import java.lang.ref.WeakReference;
+import java.util.Objects;
@WorkerThread
public class InstallSessionTracker extends PackageInstaller.SessionCallback {
@@ -41,14 +44,22 @@
// Lazily initialized
private SparseArray<PackageUserKey> mActiveSessions = null;
+ @NonNull
private final WeakReference<InstallSessionHelper> mWeakHelper;
+
+ @NonNull
private final WeakReference<Callback> mWeakCallback;
+
+ @NonNull
private final PackageInstaller mInstaller;
+
+ @Nullable
private final LauncherApps mLauncherApps;
- InstallSessionTracker(InstallSessionHelper installerCompat, Callback callback,
- PackageInstaller installer, LauncherApps launcherApps) {
+ InstallSessionTracker(@Nullable final InstallSessionHelper installerCompat,
+ @Nullable final Callback callback, @NonNull final PackageInstaller installer,
+ @Nullable LauncherApps launcherApps) {
mWeakHelper = new WeakReference<>(installerCompat);
mWeakCallback = new WeakReference<>(callback);
mInstaller = installer;
@@ -56,7 +67,7 @@
}
@Override
- public void onCreated(int sessionId) {
+ public void onCreated(final int sessionId) {
InstallSessionHelper helper = mWeakHelper.get();
Callback callback = mWeakCallback.get();
if (TestProtocol.sDebugTracing) {
@@ -80,7 +91,7 @@
}
@Override
- public void onFinished(int sessionId, boolean success) {
+ public void onFinished(final int sessionId, final boolean success) {
InstallSessionHelper helper = mWeakHelper.get();
Callback callback = mWeakCallback.get();
if (callback == null || helper == null) {
@@ -108,7 +119,7 @@
}
@Override
- public void onProgressChanged(int sessionId, float progress) {
+ public void onProgressChanged(final int sessionId, final float progress) {
InstallSessionHelper helper = mWeakHelper.get();
Callback callback = mWeakCallback.get();
if (callback == null || helper == null) {
@@ -121,10 +132,10 @@
}
@Override
- public void onActiveChanged(int sessionId, boolean active) { }
+ public void onActiveChanged(final int sessionId, final boolean active) { }
@Override
- public void onBadgingChanged(int sessionId) {
+ public void onBadgingChanged(final int sessionId) {
InstallSessionHelper helper = mWeakHelper.get();
Callback callback = mWeakCallback.get();
if (callback == null || helper == null) {
@@ -136,8 +147,9 @@
}
}
- private SessionInfo pushSessionDisplayToLauncher(
- int sessionId, InstallSessionHelper helper, Callback callback) {
+ @Nullable
+ private SessionInfo pushSessionDisplayToLauncher(final int sessionId,
+ @NonNull final InstallSessionHelper helper, @NonNull final Callback callback) {
SessionInfo session = helper.getVerifiedSessionInfo(sessionId);
if (session != null && session.getAppPackageName() != null) {
PackageUserKey key =
@@ -149,7 +161,9 @@
return null;
}
- private SparseArray<PackageUserKey> getActiveSessionMap(InstallSessionHelper helper) {
+ @NonNull
+ private SparseArray<PackageUserKey> getActiveSessionMap(
+ @NonNull final InstallSessionHelper helper) {
if (mActiveSessions == null) {
mActiveSessions = new SparseArray<>();
helper.getActiveSessions().forEach(
@@ -162,7 +176,8 @@
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
mInstaller.registerSessionCallback(this, MODEL_EXECUTOR.getHandler());
} else {
- mLauncherApps.registerPackageInstallerSessionCallback(MODEL_EXECUTOR, this);
+ Objects.requireNonNull(mLauncherApps).registerPackageInstallerSessionCallback(
+ MODEL_EXECUTOR, this);
}
}
@@ -170,18 +185,18 @@
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
mInstaller.unregisterSessionCallback(this);
} else {
- mLauncherApps.unregisterPackageInstallerSessionCallback(this);
+ Objects.requireNonNull(mLauncherApps).unregisterPackageInstallerSessionCallback(this);
}
}
public interface Callback {
- void onSessionFailure(String packageName, UserHandle user);
+ void onSessionFailure(@NonNull String packageName, @NonNull UserHandle user);
- void onUpdateSessionDisplay(PackageUserKey key, SessionInfo info);
+ void onUpdateSessionDisplay(@NonNull PackageUserKey key, @NonNull SessionInfo info);
- void onPackageStateChanged(PackageInstallInfo info);
+ void onPackageStateChanged(@NonNull PackageInstallInfo info);
- void onInstallSessionCreated(PackageInstallInfo info);
+ void onInstallSessionCreated(@NonNull PackageInstallInfo info);
}
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 54e8e5b..86277a7 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -343,11 +343,6 @@
onStateTransitionEnd(state);
}
- @Override
- public void onAnimationCancel(Animator animation) {
- super.onAnimationCancel(animation);
- onStateTransitionFailed(state);
- }
};
}
@@ -360,12 +355,6 @@
}
}
- private void onStateTransitionFailed(STATE_TYPE state) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- mListeners.get(i).onStateTransitionFailed(state);
- }
- }
-
private void onStateTransitionEnd(STATE_TYPE state) {
// Only change the stable states after the transitions have finished
if (state != mCurrentStableState) {
@@ -600,11 +589,6 @@
default void onStateTransitionStart(STATE_TYPE toState) { }
- /**
- * If the state transition animation fails (e.g. is canceled by the user), this fires.
- */
- default void onStateTransitionFailed(STATE_TYPE toState) { }
-
default void onStateTransitionComplete(STATE_TYPE finalState) { }
}
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index c408904..b94ea07 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -24,12 +24,16 @@
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
+import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Handler;
import android.os.Message;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
@@ -58,6 +62,7 @@
public static final int REQUEST_ROTATE = 1;
public static final int REQUEST_LOCK = 2;
+ @Nullable
private BaseActivity mActivity;
private SharedPreferences mSharedPrefs = null;
private final Handler mRequestOrientationHandler;
@@ -209,8 +214,12 @@
}
}
+ @WorkerThread
private boolean setOrientationAsync(Message msg) {
- mActivity.setRequestedOrientation(msg.what);
+ Activity activity = mActivity;
+ if (activity != null) {
+ activity.setRequestedOrientation(msg.what);
+ }
return true;
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 5fa30bc..b4be061 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -248,13 +248,19 @@
final Launcher launcher = Launcher.getLauncher(context);
if (shortcut.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
&& shortcut.isDisabledVersionLower()) {
+ final Intent marketIntent = shortcut.getMarketIntent(context);
+ // No market intent means no target package for the shortcut, which should be an
+ // issue. Falling back to showing toast messages.
+ if (marketIntent == null) {
+ return false;
+ }
new AlertDialog.Builder(context)
.setTitle(R.string.dialog_update_title)
.setMessage(R.string.dialog_update_message)
.setPositiveButton(R.string.dialog_update, (d, i) -> {
// Direct the user to the play store to update the app
- context.startActivity(shortcut.getMarketIntent(context));
+ context.startActivity(marketIntent);
})
.setNeutralButton(R.string.dialog_remove, (d, i) -> {
// Remove the icon if launcher is successfully initialized
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index f42d304..12e8b54 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -43,6 +43,9 @@
import android.util.Pair;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -54,6 +57,7 @@
import java.net.URISyntaxException;
import java.util.List;
+import java.util.Objects;
/**
* Utility methods using package manager
@@ -62,22 +66,28 @@
private static final String TAG = "PackageManagerHelper";
+ @NonNull
private final Context mContext;
+
+ @NonNull
private final PackageManager mPm;
+
+ @NonNull
private final LauncherApps mLauncherApps;
- public PackageManagerHelper(Context context) {
+ public PackageManagerHelper(@NonNull final Context context) {
mContext = context;
mPm = context.getPackageManager();
- mLauncherApps = context.getSystemService(LauncherApps.class);
+ mLauncherApps = Objects.requireNonNull(context.getSystemService(LauncherApps.class));
}
/**
* Returns true if the app can possibly be on the SDCard. This is just a workaround and doesn't
* guarantee that the app is on SD card.
*/
- public boolean isAppOnSdcard(String packageName, UserHandle user) {
- ApplicationInfo info = getApplicationInfo(
+ public boolean isAppOnSdcard(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
+ final ApplicationInfo info = getApplicationInfo(
packageName, user, PackageManager.MATCH_UNINSTALLED_PACKAGES);
return info != null && (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
}
@@ -86,23 +96,27 @@
* Returns whether the target app is suspended for a given user as per
* {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
*/
- public boolean isAppSuspended(String packageName, UserHandle user) {
- ApplicationInfo info = getApplicationInfo(packageName, user, 0);
+ public boolean isAppSuspended(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
+ final ApplicationInfo info = getApplicationInfo(packageName, user, 0);
return info != null && isAppSuspended(info);
}
/**
* Returns whether the target app is installed for a given user
*/
- public boolean isAppInstalled(String packageName, UserHandle user) {
- ApplicationInfo info = getApplicationInfo(packageName, user, 0);
+ public boolean isAppInstalled(@NonNull final String packageName,
+ @NonNull final UserHandle user) {
+ final ApplicationInfo info = getApplicationInfo(packageName, user, 0);
return info != null;
}
/**
* Returns the application info for the provided package or null
*/
- public ApplicationInfo getApplicationInfo(String packageName, UserHandle user, int flags) {
+ @Nullable
+ public ApplicationInfo getApplicationInfo(@NonNull final String packageName,
+ @NonNull final UserHandle user, final int flags) {
try {
ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 || !info.enabled
@@ -116,7 +130,8 @@
return mPm.isSafeMode();
}
- public Intent getAppLaunchIntent(String pkg, UserHandle user) {
+ @Nullable
+ public Intent getAppLaunchIntent(@Nullable final String pkg, @NonNull final UserHandle user) {
List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(pkg, user);
return activities.isEmpty() ? null :
AppInfo.makeLaunchIntent(activities.get(0));
@@ -251,7 +266,8 @@
return packageFilter;
}
- public static boolean isSystemApp(Context context, Intent intent) {
+ public static boolean isSystemApp(@NonNull final Context context,
+ @NonNull final Intent intent) {
PackageManager pm = context.getPackageManager();
ComponentName cn = intent.getComponent();
String packageName = null;
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 3324959..e7e551f 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -47,6 +47,7 @@
import android.test.mock.MockContentResolver;
import android.util.ArrayMap;
+import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.uiautomator.UiDevice;
@@ -194,8 +195,9 @@
Executor mockExecutor = mock(Executor.class);
model.enqueueModelUpdateTask(new ModelUpdateTask() {
@Override
- public void init(LauncherAppState app, LauncherModel model, BgDataModel dataModel,
- AllAppsList allAppsList, Executor uiExecutor) {
+ public void init(@NonNull final LauncherAppState app,
+ @NonNull final LauncherModel model, @NonNull final BgDataModel dataModel,
+ @NonNull final AllAppsList allAppsList, @NonNull final Executor uiExecutor) {
task.init(app, model, dataModel, allAppsList, mockExecutor);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 4a6aca1..3986df6 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -907,7 +907,14 @@
}
/**
- * Presses nav bar home button.
+ * Goes to home by swiping up in zero-button mode or pressing Home button.
+ * Calling it after another TAPL call is safe because all TAPL methods wait for the animations
+ * to finish.
+ * When calling it after a non-TAPL method, make sure that all animations have already
+ * completed, otherwise it may detect the current state (for example "Application" or "Home")
+ * incorrectly.
+ * The method expects either app or Launcher to be active when it's called. Other states, such
+ * as visible notification shade are not supported.
*
* @return the Workspace object.
*/
@@ -1908,8 +1915,9 @@
/**
* Taps outside container to dismiss.
+ *
* @param container container to be dismissed
- * @param tapRight tap on the right of the container if true, or left otherwise
+ * @param tapRight tap on the right of the container if true, or left otherwise
*/
void touchOutsideContainer(UiObject2 container, boolean tapRight) {
try (LauncherInstrumentation.Closable c = addContextLayer(