Merge "Add start to widget app name layout gravity" into sc-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index fb47b0a..475b5be 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -162,6 +162,7 @@
optional int32 app_widget_id = 3;
optional string package_name = 4; // only populated during snapshot if from workspace
optional string component_name = 5; // only populated during snapshot if from workspace
+ optional int32 widget_features = 6;
}
// Tasks handled by PackageManager
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index de9b361..275dfda 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1260,7 +1260,8 @@
if (launchingFromWidget) {
composeWidgetLaunchAnimator(anim, (LauncherAppWidgetHostView) mV, appTargets,
wallpaperTargets, nonAppTargets);
- // TODO(b/169042867): jank monitoring instrumentation
+ addCujInstrumentation(
+ anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_WIDGET);
} else if (launchingFromRecents) {
composeRecentsLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets,
launcherClosing);
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 67ed5fb..5dcf84c 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.hybridhotseat.HotseatEduController.getSettingsIntent;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED;
@@ -150,7 +151,7 @@
* Shows appropriate hotseat education based on prediction enabled and migration states.
*/
public void showEdu() {
- mLauncher.getStateManager().goToState(NORMAL, true, () -> {
+ mLauncher.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
if (mPredictedItems.isEmpty()) {
// launcher has empty predictions set
Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_disabled,
@@ -165,7 +166,7 @@
.collect(Collectors.toList()));
eduController.showEdu();
}
- });
+ }));
}
/**
@@ -255,8 +256,8 @@
}
}
if (animate) {
- animationSet.addListener(AnimationSuccessListener
- .forRunnable(this::removeOutlineDrawings));
+ animationSet.addListener(
+ forSuccessCallback(this::removeOutlineDrawings));
animationSet.start();
} else {
removeOutlineDrawings();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 0652d48..996d36a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -35,7 +35,7 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.states.StateAnimationConfig;
@@ -78,7 +78,7 @@
mRecentsView.updateEmptyMessage();
} else {
builder.addListener(
- AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
+ AnimatorListeners.forSuccessCallback(mRecentsView::resetTaskVisuals));
}
// Create or dismiss split screen select animations
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index b8caf81..521dd23 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@@ -38,7 +39,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
@@ -199,7 +199,7 @@
.animateWithVelocity(velocity);
} else {
mLauncher.getStateManager().goToState(mEndState, true,
- () -> onSwipeInteractionCompleted(mEndState));
+ forSuccessCallback(() -> onSwipeInteractionCompleted(mEndState)));
}
if (mStartState != mEndState) {
logHomeGesture();
@@ -214,8 +214,7 @@
// Quickly return to the state we came from (we didn't move far).
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(progress, 0);
- anim.addListener(AnimationSuccessListener.forRunnable(
- () -> onSwipeInteractionCompleted(mStartState)));
+ anim.addListener(forSuccessCallback(() -> onSwipeInteractionCompleted(mStartState)));
anim.setDuration(80).start();
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 729e2cb..eb62110 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -172,13 +173,13 @@
}
mNormalToHintOverviewScrimAnimator = null;
mCurrentAnimation.getTarget().addListener(newCancelListener(() ->
- mLauncher.getStateManager().goToState(OVERVIEW, true, () -> {
+ mLauncher.getStateManager().goToState(OVERVIEW, true, forSuccessCallback(() -> {
mOverviewResistYAnim = AnimatorControllerWithResistance
.createRecentsResistanceFromOverviewAnim(mLauncher, null)
.createPlaybackController();
mReachedOverview = true;
maybeSwipeInteractionToOverviewComplete();
- })));
+ }))));
mCurrentAnimation.getTarget().removeListener(mClearStateOnCancelListener);
mCurrentAnimation.dispatchOnCancel();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 0f64abc..62687c5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -418,7 +419,7 @@
targetState.ordinal > mStartState.ordinal
? LAUNCHER_UNKNOWN_SWIPEUP
: LAUNCHER_UNKNOWN_SWIPEDOWN));
- mLauncher.getStateManager().goToState(targetState, false, this::clearState);
+ mLauncher.getStateManager().goToState(targetState, false, forEndCallback(this::clearState));
}
private void cancelAnimations() {
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 2242168..63646d0 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1514,10 +1514,12 @@
if (mIsSwipingPipToHome && mSwipePipToHomeAnimator != null) {
SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome(
mSwipePipToHomeAnimator.getComponentName(),
- mSwipePipToHomeAnimator.getDestinationBounds());
+ mSwipePipToHomeAnimator.getDestinationBounds(),
+ mSwipePipToHomeAnimator.getContentOverlay());
mRecentsAnimationController.setFinishTaskTransaction(
mSwipePipToHomeAnimator.getTaskId(),
- mSwipePipToHomeAnimator.getFinishTransaction());
+ mSwipePipToHomeAnimator.getFinishTransaction(),
+ mSwipePipToHomeAnimator.getContentOverlay());
mIsSwipingPipToHome = false;
}
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 1ca4fd7..5217c3b 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
@@ -197,7 +198,8 @@
closeOverlay();
launcher.getStateManager().goToState(OVERVIEW,
- launcher.getStateManager().shouldAnimateStateChange(), onCompleteCallback);
+ launcher.getStateManager().shouldAnimateStateChange(),
+ onCompleteCallback == null ? null : forEndCallback(onCompleteCallback));
return true;
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 78da311..f2bd916 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
import androidx.annotation.NonNull;
@@ -159,12 +160,15 @@
* that animating Activity to PiP has completed and the associated task surface should be
* updated accordingly. This should be called before `finish`
* @param taskId for which the leash should be updated
- * @param finishTransaction leash operations for the final transform.
+ * @param finishTransaction the transaction to transfer to the task surface control after the
+ * leash is removed
+ * @param overlay the surface control for an overlay being shown above the pip (can be null)
*/
public void setFinishTaskTransaction(int taskId,
- PictureInPictureSurfaceTransaction finishTransaction) {
+ PictureInPictureSurfaceTransaction finishTransaction,
+ SurfaceControl overlay) {
UI_HELPER_EXECUTOR.execute(
- () -> mController.setFinishTaskTransaction(taskId, finishTransaction));
+ () -> mController.setFinishTaskTransaction(taskId, finishTransaction, overlay));
}
/**
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 39d8888..6fb938a 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -33,6 +33,7 @@
import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.SurfaceControl;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -427,10 +428,11 @@
return null;
}
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
+ public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds,
+ SurfaceControl overlay) {
if (mPip != null) {
try {
- mPip.stopSwipePipToHome(componentName, destinationBounds);
+ mPip.stopSwipePipToHome(componentName, destinationBounds, overlay);
} catch (RemoteException e) {
Log.w(TAG, "Failed call stopSwipePipToHome");
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 1aa64fa..66e0400 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -43,7 +43,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.quickstep.AnimatedFloat;
@@ -156,7 +156,7 @@
fadeAnim.setViewAlpha(mFakePreviousTaskView, 0, ACCEL);
}
if (onEndRunnable != null) {
- fadeAnim.addListener(AnimationSuccessListener.forRunnable(onEndRunnable));
+ fadeAnim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
}
AnimatorSet animset = fadeAnim.buildAnim();
animset.setStartDelay(100);
@@ -174,7 +174,7 @@
anim.setViewAlpha(mFakePreviousTaskView, 0, ACCEL);
}
if (onEndRunnable != null) {
- anim.addListener(AnimationSuccessListener.forRunnable(onEndRunnable));
+ anim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
}
}
AnimatorSet animset = anim.buildAnim();
@@ -205,10 +205,10 @@
PendingAnimation fadeAnim = new PendingAnimation(300);
fadeAnim.setViewAlpha(mFakeIconView, 0, ACCEL);
if (onEndRunnable != null) {
- fadeAnim.addListener(AnimationSuccessListener.forRunnable(onEndRunnable));
+ fadeAnim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
}
AnimatorSet animset = fadeAnim.buildAnim();
- rectAnim.addAnimatorListener(AnimationSuccessListener.forRunnable(animset::start));
+ rectAnim.addAnimatorListener(AnimatorListeners.forSuccessCallback(animset::start));
mRunningWindowAnim = RunningWindowAnim.wrap(rectAnim);
}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index e86062c..f9d5c94 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -38,7 +38,7 @@
import androidx.appcompat.content.res.AppCompatResources;
import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.views.ClipIconView;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureAttemptCallback;
@@ -141,7 +141,7 @@
}
void fadeTaskViewAndRun(Runnable r) {
- mFakeTaskView.animate().alpha(0).setListener(AnimationSuccessListener.forRunnable(r));
+ mFakeTaskView.animate().alpha(0).setListener(AnimatorListeners.forSuccessCallback(r));
}
@StringRes
@@ -359,8 +359,8 @@
mContext, getMockLauncherResId()));
mFakeTaskView.setBackground(AppCompatResources.getDrawable(
mContext, getMockAppTaskThumbnailResId()));
- mFakeTaskView.animate().alpha(1).setListener(AnimationSuccessListener.forRunnable(
- () -> mFakeTaskView.animate().cancel()));
+ mFakeTaskView.animate().alpha(1).setListener(
+ AnimatorListeners.forSuccessCallback(() -> mFakeTaskView.animate().cancel()));
mFakePreviousTaskView.setBackground(AppCompatResources.getDrawable(
mContext, getMockPreviousAppTaskThumbnailResId()));
mFakeIconView.setBackground(AppCompatResources.getDrawable(
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 3b26108..719cb0a 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -354,6 +354,10 @@
}
private static int getCardinality(LauncherAtom.ItemInfo info) {
+ // TODO(b/187734511): Implement a unified solution for 1x1 widgets in folders/hotseat.
+ if (info.getItemCase().equals(LauncherAtom.ItemInfo.ItemCase.WIDGET)) {
+ return info.getWidget().getWidgetFeatures();
+ }
switch (info.getContainerInfo().getContainerCase()) {
case PREDICTED_HOTSEAT_CONTAINER:
return info.getContainerInfo().getPredictedHotseatContainer().getCardinality();
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index b5570a7..3631130 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -22,19 +22,24 @@
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.view.View;
import android.window.PictureInPictureSurfaceTransaction;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.util.Themes;
import com.android.systemui.shared.pip.PipSurfaceTransactionHelper;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -79,6 +84,12 @@
private boolean mHasAnimationEnded;
/**
+ * An overlay used to mask changes in content when entering PiP for apps that aren't seamless.
+ */
+ @Nullable
+ private SurfaceControl mContentOverlay;
+
+ /**
* @param taskId Task id associated with this animator, see also {@link #getTaskId()}
* @param componentName Component associated with this animator,
* see also {@link #getComponentName()}
@@ -112,6 +123,33 @@
if (sourceRectHint == null) {
mSourceHintRectInsets = null;
+
+ // Create a new overlay layer
+ SurfaceSession session = new SurfaceSession();
+ mContentOverlay = new SurfaceControl.Builder(session)
+ .setCallsite("SwipePipToHomeAnimator")
+ .setName("PipContentOverlay")
+ .setColorLayer()
+ .build();
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.show(mContentOverlay);
+ t.setLayer(mContentOverlay, Integer.MAX_VALUE);
+ int color = Themes.getColorBackground(view.getContext());
+ float[] bgColor = new float[] {Color.red(color) / 255f, Color.green(color) / 255f,
+ Color.blue(color) / 255f};
+ t.setColor(mContentOverlay, bgColor);
+ t.setAlpha(mContentOverlay, 0f);
+ t.reparent(mContentOverlay, mLeash);
+ t.apply();
+
+ addUpdateListener(valueAnimator -> {
+ float alpha = valueAnimator.getAnimatedFraction() < 0.5f
+ ? 0
+ : Utilities.mapToRange(valueAnimator.getAnimatedFraction(), 0.5f, 1f,
+ 0f, 1f, Interpolators.FAST_OUT_SLOW_IN);
+ t.setAlpha(mContentOverlay, alpha);
+ t.apply();
+ });
} else {
mSourceHintRectInsets = new Rect(sourceRectHint.left - appBounds.left,
sourceRectHint.top - appBounds.top,
@@ -234,6 +272,11 @@
return mDestinationBounds;
}
+ @Nullable
+ public SurfaceControl getContentOverlay() {
+ return mContentOverlay;
+ }
+
/** @return {@link PictureInPictureSurfaceTransaction} for the final leash transaction. */
public PictureInPictureSurfaceTransaction getFinishTransaction() {
// get the final leash operations but do not apply to the leash.
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 396dafb..5bad5e8 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -111,6 +111,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringProperty;
@@ -120,7 +121,6 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DynamicResource;
@@ -1677,7 +1677,7 @@
return;
}
AnimatorSet pa = setRecentsChangedOrientation(true);
- pa.addListener(AnimationSuccessListener.forRunnable(() -> {
+ pa.addListener(AnimatorListeners.forSuccessCallback(() -> {
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
mActivity.getDragLayer().recreateControllers();
updateChildTaskOrientations();
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 5b8d4ce..02888a1 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -335,16 +335,13 @@
public void setOverlayEnabled(boolean overlayEnabled) {
if (mOverlayEnabled != overlayEnabled) {
mOverlayEnabled = overlayEnabled;
- updateOverlay();
- }
- }
- private void updateOverlay() {
- if (mOverlayEnabled) {
- getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
- mPreviewPositionHelper.mIsOrientationChanged);
- } else {
- getTaskOverlay().reset();
+ if (mOverlayEnabled) {
+ getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
+ mPreviewPositionHelper.mIsOrientationChanged);
+ } else {
+ getTaskOverlay().reset();
+ }
}
}
@@ -379,10 +376,6 @@
}
getTaskView().updateCurrentFullscreenParams(mPreviewPositionHelper);
invalidate();
-
- // Update can be called from {@link #onSizeChanged} during layout, post handling of overlay
- // as overlay could modify the views in the overlay as a side effect of its update.
- post(this::updateOverlay);
}
@Override
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index cabbe93..a5038a1 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -17,14 +17,13 @@
package com.android.quickstep;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_POSTSUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.content.Intent;
+import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -38,8 +37,8 @@
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewActions;
import com.android.launcher3.tapl.OverviewTask;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.views.RecentsView;
@@ -95,7 +94,6 @@
@Test
@PortraitLandscape
- @Stability(flavors = LOCAL | UNBUNDLED_POSTSUBMIT) // b/187899876
public void testOverview() throws Exception {
startTestAppsWithCheck();
// mLauncher.pressHome() also tests an important case of pressing home while in background.
@@ -165,7 +163,6 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
- @Stability(flavors = LOCAL | UNBUNDLED_POSTSUBMIT) // b/187899876
public void testOverviewActions() throws Exception {
// Experimenting for b/165029151:
final Overview overview = mLauncher.pressHome().switchToOverview();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7b67807..16ffd7a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1307,8 +1307,15 @@
appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
}
+ if (hostView == null) {
+ // Perform actual inflation because we're live
+ hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
+ }
+
LauncherAppWidgetInfo launcherInfo;
- launcherInfo = new LauncherAppWidgetInfo(appWidgetId, appWidgetInfo.provider);
+ launcherInfo =
+ new LauncherAppWidgetInfo(
+ appWidgetId, appWidgetInfo.provider, appWidgetInfo, hostView);
launcherInfo.spanX = itemInfo.spanX;
launcherInfo.spanY = itemInfo.spanY;
launcherInfo.minSpanX = itemInfo.minSpanX;
@@ -1318,10 +1325,6 @@
getModelWriter().addItemToDatabase(launcherInfo,
itemInfo.container, itemInfo.screenId, itemInfo.cellX, itemInfo.cellY);
- if (hostView == null) {
- // Perform actual inflation because we're live
- hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
- }
hostView.setVisibility(View.VISIBLE);
prepareAppWidget(hostView, launcherInfo);
mWorkspace.addInScreen(hostView, launcherInfo);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 47c67b9..5ba7623 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
@@ -1946,8 +1947,8 @@
}
parent.onDropChild(cell);
- mLauncher.getStateManager().goToState(
- NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
+ mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY,
+ onCompleteRunnable == null ? null : forSuccessCallback(onCompleteRunnable));
mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId)
.log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index c580d47..2b36f19 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -3,6 +3,7 @@
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import android.appwidget.AppWidgetProviderInfo;
@@ -220,30 +221,26 @@
} else if (action == ADD_TO_WORKSPACE) {
final int[] coordinates = new int[2];
final int screenId = findSpaceOnWorkspace(item, coordinates);
- mLauncher.getStateManager().goToState(NORMAL, true, new Runnable() {
+ mLauncher.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
+ if (item instanceof AppInfo) {
+ WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
+ mLauncher.getModelWriter().addItemToDatabase(info,
+ Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
- @Override
- public void run() {
- if (item instanceof AppInfo) {
- WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
- mLauncher.getModelWriter().addItemToDatabase(info,
- Favorites.CONTAINER_DESKTOP,
- screenId, coordinates[0], coordinates[1]);
-
- mLauncher.bindItems(
- Collections.singletonList(info),
- /* forceAnimateIcons= */ true,
- /* focusFirstItemForAccessibility= */ true);
- announceConfirmation(R.string.item_added_to_workspace);
- } else if (item instanceof PendingAddItemInfo) {
- PendingAddItemInfo info = (PendingAddItemInfo) item;
- Workspace workspace = mLauncher.getWorkspace();
- workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
- mLauncher.addPendingItem(info, Favorites.CONTAINER_DESKTOP,
- screenId, coordinates, info.spanX, info.spanY);
- }
+ mLauncher.bindItems(
+ Collections.singletonList(info),
+ /* forceAnimateIcons= */ true,
+ /* focusFirstItemForAccessibility= */ true);
+ announceConfirmation(R.string.item_added_to_workspace);
+ } else if (item instanceof PendingAddItemInfo) {
+ PendingAddItemInfo info = (PendingAddItemInfo) item;
+ Workspace workspace = mLauncher.getWorkspace();
+ workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
+ mLauncher.addPendingItem(info, Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates, info.spanX, info.spanY);
}
- });
+ }));
return true;
} else if (action == MOVE_TO_WORKSPACE) {
Folder folder = Folder.getOpen(mLauncher);
diff --git a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
index 1733e5d..f96afa8 100644
--- a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
@@ -17,6 +17,7 @@
package com.android.launcher3.accessibility;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import android.view.KeyEvent;
import android.view.View;
@@ -67,19 +68,14 @@
final WorkspaceItemInfo info = ((DeepShortcutView) host.getParent()).getFinalInfo();
final int[] coordinates = new int[2];
final int screenId = findSpaceOnWorkspace(item, coordinates);
- Runnable onComplete = new Runnable() {
- @Override
- public void run() {
- mLauncher.getModelWriter().addItemToDatabase(info,
- LauncherSettings.Favorites.CONTAINER_DESKTOP,
- screenId, coordinates[0], coordinates[1]);
- mLauncher.bindItems(Collections.singletonList(info), true);
- AbstractFloatingView.closeAllOpenViews(mLauncher);
- announceConfirmation(R.string.item_added_to_workspace);
- }
- };
-
- mLauncher.getStateManager().goToState(NORMAL, true, onComplete);
+ mLauncher.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
+ mLauncher.getModelWriter().addItemToDatabase(info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
+ mLauncher.bindItems(Collections.singletonList(info), true);
+ AbstractFloatingView.closeAllOpenViews(mLauncher);
+ announceConfirmation(R.string.item_added_to_workspace);
+ }));
return true;
} else if (action == DISMISS_NOTIFICATION) {
if (!(host instanceof NotificationMainView)) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 75f3149..3a61609 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -25,7 +25,7 @@
import static com.android.launcher3.util.SystemUiController.UI_STATE_ALLAPPS;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
+import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.util.FloatProperty;
import android.view.View;
@@ -36,7 +36,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.config.FeatureFlags;
@@ -185,8 +185,8 @@
mScrimView.setDrawingController(shouldProtectHeader ? mAppsView : null);
}
- public AnimatorListenerAdapter getProgressAnimatorListener() {
- return AnimationSuccessListener.forRunnable(this::onProgressAnimationEnd);
+ public AnimatorListener getProgressAnimatorListener() {
+ return AnimatorListeners.forSuccessCallback(this::onProgressAnimationEnd);
}
/**
diff --git a/src/com/android/launcher3/anim/AnimationSuccessListener.java b/src/com/android/launcher3/anim/AnimationSuccessListener.java
index 9905e81..a312070 100644
--- a/src/com/android/launcher3/anim/AnimationSuccessListener.java
+++ b/src/com/android/launcher3/anim/AnimationSuccessListener.java
@@ -40,24 +40,4 @@
public abstract void onAnimationSuccess(Animator animator);
- /**
- * Returns an AnimationSuccessListener which runs the provided action on success
- */
- public static AnimationSuccessListener forRunnable(Runnable r) {
- return new RunnableSuccessListener(r);
- }
-
- private static class RunnableSuccessListener extends AnimationSuccessListener {
-
- private final Runnable mRunnable;
-
- private RunnableSuccessListener(Runnable r) {
- mRunnable = r;
- }
-
- @Override
- public void onAnimationSuccess(Animator animator) {
- mRunnable.run();
- }
- }
}
diff --git a/src/com/android/launcher3/anim/AnimatorListeners.java b/src/com/android/launcher3/anim/AnimatorListeners.java
new file mode 100644
index 0000000..d9046b9
--- /dev/null
+++ b/src/com/android/launcher3/anim/AnimatorListeners.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.anim;
+
+import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+
+import java.util.function.Consumer;
+
+/**
+ * Utility class for creating common {@link AnimatorListener}
+ */
+public class AnimatorListeners {
+
+ /**
+ * Returns an AnimatorListener which executes the callback on successful animation completion
+ */
+ public static AnimatorListener forSuccessCallback(Runnable callback) {
+ return new RunnableSuccessListener(callback);
+ }
+
+ /**
+ * Returns an AnimatorListener which executes the callback on animation completion,
+ * with the boolean representing success
+ */
+ public static AnimatorListener forEndCallback(Consumer<Boolean> callback) {
+ return new EndStateCallbackWrapper(callback);
+ }
+
+ /**
+ * Returns an AnimatorListener which executes the callback on animation completion
+ */
+ public static AnimatorListener forEndCallback(Runnable callback) {
+ return new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ callback.run();
+ }
+ };
+ }
+
+ private static class EndStateCallbackWrapper extends AnimatorListenerAdapter {
+
+ private final Consumer<Boolean> mListener;
+ private boolean mListenerCalled = false;
+
+ EndStateCallbackWrapper(Consumer<Boolean> listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ if (!mListenerCalled) {
+ mListenerCalled = true;
+ mListener.accept(false);
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator anim) {
+ if (!mListenerCalled) {
+ mListenerCalled = true;
+ mListener.accept(anim instanceof ValueAnimator
+ ? ((ValueAnimator) anim).getAnimatedFraction() > SUCCESS_TRANSITION_PROGRESS
+ : true);
+ }
+ }
+ }
+
+ private static class RunnableSuccessListener extends AnimationSuccessListener {
+
+ private final Runnable mRunnable;
+
+ private RunnableSuccessListener(Runnable r) {
+ mRunnable = r;
+ }
+
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ mRunnable.run();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 8057475..01f7de6 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -15,13 +15,11 @@
*/
package com.android.launcher3.anim;
-import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimationHoldersRecur;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
@@ -182,32 +180,6 @@
if (mProgressAnimator == null) {
mProgressAnimator = ValueAnimator.ofFloat(0, 1);
}
- mProgressAnimator.addListener(new EndStateCallbackWrapper(listener));
- }
-
- private static class EndStateCallbackWrapper extends AnimatorListenerAdapter {
-
- private final Consumer<Boolean> mListener;
- private boolean mCalled = false;
-
- EndStateCallbackWrapper(Consumer<Boolean> listener) {
- mListener = listener;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- if (!mCalled) {
- mCalled = true;
- mListener.accept(false);
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mCalled) {
- ValueAnimator anim = (ValueAnimator) animation;
- mListener.accept(anim.getAnimatedFraction() > SUCCESS_TRANSITION_PROGRESS);
- }
- }
+ mProgressAnimator.addListener(AnimatorListeners.forEndCallback(listener));
}
}
diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
index c04b7f0..003b3bd 100644
--- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
@@ -16,9 +16,12 @@
package com.android.launcher3.model.data;
+import static com.android.launcher3.Utilities.ATLEAST_S;
+
import android.appwidget.AppWidgetHostView;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.res.Resources;
import android.os.Process;
import androidx.annotation.Nullable;
@@ -26,7 +29,10 @@
import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.util.ContentWriter;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
/**
* Represents a widget (either instantiated or about to be) in the Launcher.
@@ -81,6 +87,18 @@
public static final int CUSTOM_WIDGET_ID = -100;
/**
+ * Flags for recording all the features that a widget has enabled.
+ * @see widgetFeatures
+ */
+ public static final int FEATURE_RECONFIGURABLE = 1;
+ public static final int FEATURE_OPTIONAL_CONFIGURATION = 1 << 1;
+ public static final int FEATURE_PREVIEW_LAYOUT = 1 << 2;
+ public static final int FEATURE_TARGET_CELL_SIZE = 1 << 3;
+ public static final int FEATURE_MIN_SIZE = 1 << 4;
+ public static final int FEATURE_MAX_SIZE = 1 << 5;
+ public static final int FEATURE_ROUNDED_CORNERS = 1 << 6;
+
+ /**
* Identifier for this widget when talking with
* {@link android.appwidget.AppWidgetManager} for updates.
*/
@@ -113,6 +131,12 @@
*/
public PackageItemInfo pendingItemInfo;
+ /**
+ * Contains a binary representation indicating which widget features are enabled. This value is
+ * -1 if widget features could not be identified.
+ */
+ private int widgetFeatures;
+
private boolean mHasNotifiedInitialWidgetSizeChanged;
public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
@@ -129,11 +153,18 @@
// to indicate that they should be calculated based on the layout and minWidth/minHeight
spanX = -1;
spanY = -1;
+ widgetFeatures = -1;
// We only support app widgets on current user.
user = Process.myUserHandle();
restoreStatus = RESTORE_COMPLETED;
}
+ public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName,
+ LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView) {
+ this(appWidgetId, providerName);
+ widgetFeatures = computeWidgetFeatures(providerInfo, hostView);
+ }
+
/** Used for testing **/
public LauncherAppWidgetInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
@@ -194,4 +225,41 @@
public final boolean hasOptionFlag(int option) {
return (options & option) != 0;
}
+
+ @SuppressWarnings("NewApi")
+ private static int computeWidgetFeatures(
+ LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView) {
+ int widgetFeatures = 0;
+ if (providerInfo.isReconfigurable()) {
+ widgetFeatures |= FEATURE_RECONFIGURABLE;
+ }
+ if (providerInfo.isConfigurationOptional()) {
+ widgetFeatures |= FEATURE_OPTIONAL_CONFIGURATION;
+ }
+ if (ATLEAST_S && providerInfo.previewLayout != Resources.ID_NULL) {
+ widgetFeatures |= FEATURE_PREVIEW_LAYOUT;
+ }
+ if (ATLEAST_S && providerInfo.targetCellWidth > 0 || providerInfo.targetCellHeight > 0) {
+ widgetFeatures |= FEATURE_TARGET_CELL_SIZE;
+ }
+ if (providerInfo.minResizeWidth > 0 || providerInfo.minResizeHeight > 0) {
+ widgetFeatures |= FEATURE_MIN_SIZE;
+ }
+ if (ATLEAST_S && providerInfo.maxResizeWidth > 0 || providerInfo.maxResizeHeight > 0) {
+ widgetFeatures |= FEATURE_MAX_SIZE;
+ }
+ if (hostView instanceof LauncherAppWidgetHostView &&
+ ((LauncherAppWidgetHostView) hostView).hasEnforcedCornerRadius()) {
+ widgetFeatures |= FEATURE_ROUNDED_CORNERS;
+ }
+ return widgetFeatures;
+ }
+
+ @Override
+ public LauncherAtom.ItemInfo buildProto(FolderInfo folderInfo) {
+ LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
+ return info.toBuilder()
+ .setWidget(info.getWidget().toBuilder().setWidgetFeatures(widgetFeatures))
+ .build();
+ }
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 14ef2dc..03b6853 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -129,14 +129,14 @@
}
/**
- * @see #goToState(STATE_TYPE, boolean, Runnable)
+ * @see #goToState(STATE_TYPE, boolean, AnimatorListener)
*/
public void goToState(STATE_TYPE state) {
goToState(state, shouldAnimateStateChange());
}
/**
- * @see #goToState(STATE_TYPE, boolean, Runnable)
+ * @see #goToState(STATE_TYPE, boolean, AnimatorListener)
*/
public void goToState(STATE_TYPE state, boolean animated) {
goToState(state, animated, 0, null);
@@ -149,15 +149,15 @@
* true otherwise
* @paras onCompleteRunnable any action to perform at the end of the transition, of null.
*/
- public void goToState(STATE_TYPE state, boolean animated, Runnable onCompleteRunnable) {
- goToState(state, animated, 0, onCompleteRunnable);
+ public void goToState(STATE_TYPE state, boolean animated, AnimatorListener listener) {
+ goToState(state, animated, 0, listener);
}
/**
* Changes the Launcher state to the provided state after the given delay.
*/
- public void goToState(STATE_TYPE state, long delay, Runnable onCompleteRunnable) {
- goToState(state, true, delay, onCompleteRunnable);
+ public void goToState(STATE_TYPE state, long delay, AnimatorListener listener) {
+ goToState(state, true, delay, listener);
}
/**
@@ -187,21 +187,20 @@
}
}
- private void goToState(STATE_TYPE state, boolean animated, long delay,
- final Runnable onCompleteRunnable) {
+ private void goToState(
+ STATE_TYPE state, boolean animated, long delay, AnimatorListener listener) {
animated &= areAnimatorsEnabled();
if (mActivity.isInState(state)) {
if (mConfig.currentAnimation == null) {
// Run any queued runnable
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
+ if (listener != null) {
+ listener.onAnimationEnd(null);
}
return;
} else if (!mConfig.userControlled && animated && mConfig.targetState == state) {
// We are running the same animation as requested
- if (onCompleteRunnable != null) {
- mConfig.currentAnimation.addListener(
- AnimationSuccessListener.forRunnable(onCompleteRunnable));
+ if (listener != null) {
+ mConfig.currentAnimation.addListener(listener);
}
return;
}
@@ -221,8 +220,8 @@
onStateTransitionEnd(state);
// Run any queued runnable
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
+ if (listener != null) {
+ listener.onAnimationEnd(null);
}
return;
}
@@ -233,16 +232,16 @@
int startChangeId = mConfig.changeId;
mUiHandler.postDelayed(() -> {
if (mConfig.changeId == startChangeId) {
- goToStateAnimated(state, fromState, onCompleteRunnable);
+ goToStateAnimated(state, fromState, listener);
}
}, delay);
} else {
- goToStateAnimated(state, fromState, onCompleteRunnable);
+ goToStateAnimated(state, fromState, listener);
}
}
private void goToStateAnimated(STATE_TYPE state, STATE_TYPE fromState,
- Runnable onCompleteRunnable) {
+ AnimatorListener listener) {
// Since state mBaseState can be reached from multiple states, just assume that the
// transition plays in reverse and use the same duration as previous state.
mConfig.duration = state == mBaseState
@@ -250,8 +249,8 @@
: state.getTransitionDuration(mActivity);
prepareForAtomicAnimation(fromState, state, mConfig);
AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).buildAnim();
- if (onCompleteRunnable != null) {
- animation.addListener(AnimationSuccessListener.forRunnable(onCompleteRunnable));
+ if (listener != null) {
+ animation.addListener(listener);
}
mUiHandler.post(new StartAnimRunnable(animation));
}
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 06cac08..8243dd4 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -92,7 +92,7 @@
return getAttrColor(context, android.R.attr.colorAccent);
}
- /** Returns the floating background color attribute. */
+ /** Returns the background color attribute. */
public static int getColorBackground(Context context) {
return getAttrColor(context, android.R.attr.colorBackground);
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index de511cd..53b5fec 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -149,6 +149,12 @@
return configure != null && (getWidgetFeatures() & WIDGET_FEATURE_RECONFIGURABLE) != 0;
}
+ public boolean isConfigurationOptional() {
+ return ATLEAST_S
+ && isReconfigurable()
+ && (getWidgetFeatures() & WIDGET_FEATURE_CONFIGURATION_OPTIONAL) != 0;
+ }
+
@Override
public final ComponentName getComponent() {
return provider;