summaryrefslogtreecommitdiffstats
path: root/quickstep/src/com/android/quickstep/TaskUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'quickstep/src/com/android/quickstep/TaskUtils.java')
-rw-r--r--quickstep/src/com/android/quickstep/TaskUtils.java172
1 files changed, 171 insertions, 1 deletions
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index 5bf1d07db..2b0c98f93 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -16,25 +16,49 @@
package com.android.quickstep;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
+import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
+import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
+
+import android.animation.ValueAnimator;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.graphics.RectF;
import android.os.UserHandle;
import android.util.Log;
+import android.view.Surface;
+import android.view.View;
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.ComponentKey;
+import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+import java.util.List;
/**
* Contains helpful methods for retrieving data from {@link Task}s.
- * TODO: remove this once we switch to getting the icon and label from IconCache.
*/
public class TaskUtils {
private static final String TAG = "TaskUtils";
+ /**
+ * TODO: remove this once we switch to getting the icon and label from IconCache.
+ */
public static CharSequence getTitle(Context context, Task task) {
LauncherAppsCompat launcherAppsCompat = LauncherAppsCompat.getInstance(context);
UserManagerCompat userManagerCompat = UserManagerCompat.getInstance(context);
@@ -53,4 +77,150 @@ public class TaskUtils {
public static ComponentKey getComponentKeyForTask(Task.TaskKey taskKey) {
return new ComponentKey(taskKey.getComponent(), UserHandle.of(taskKey.userId));
}
+
+
+ /**
+ * Try to find a TaskView that corresponds with the component of the launched view.
+ *
+ * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation.
+ * Otherwise, we will assume we are using a normal app transition, but it's possible that the
+ * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView.
+ */
+ public static TaskView findTaskViewToLaunch(
+ BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) {
+ if (v instanceof TaskView) {
+ return (TaskView) v;
+ }
+ RecentsView recentsView = activity.getOverviewPanel();
+
+ // It's possible that the launched view can still be resolved to a visible task view, check
+ // the task id of the opening task and see if we can find a match.
+ if (v.getTag() instanceof ItemInfo) {
+ ItemInfo itemInfo = (ItemInfo) v.getTag();
+ ComponentName componentName = itemInfo.getTargetComponent();
+ int userId = itemInfo.user.getIdentifier();
+ if (componentName != null) {
+ for (int i = 0; i < recentsView.getChildCount(); i++) {
+ TaskView taskView = recentsView.getPageAt(i);
+ if (recentsView.isTaskViewVisible(taskView)) {
+ Task.TaskKey key = taskView.getTask().key;
+ if (componentName.equals(key.getComponent()) && userId == key.userId) {
+ return taskView;
+ }
+ }
+ }
+ }
+ }
+
+ if (targets == null) {
+ return null;
+ }
+ // Resolve the opening task id
+ int openingTaskId = -1;
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == MODE_OPENING) {
+ openingTaskId = target.taskId;
+ break;
+ }
+ }
+
+ // If there is no opening task id, fall back to the normal app icon launch animation
+ if (openingTaskId == -1) {
+ return null;
+ }
+
+ // If the opening task id is not currently visible in overview, then fall back to normal app
+ // icon launch animation
+ TaskView taskView = recentsView.getTaskView(openingTaskId);
+ if (taskView == null || !recentsView.isTaskViewVisible(taskView)) {
+ return null;
+ }
+ return taskView;
+ }
+
+ /**
+ * @return Animator that controls the window of the opening targets for the recents launch
+ * animation.
+ */
+ public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
+ RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) {
+ final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
+ appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
+ appAnimator.addUpdateListener(new MultiValueUpdateListener() {
+
+ // Defer fading out the view until after the app window gets faded in
+ final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR);
+ final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR);
+
+ final RemoteAnimationTargetSet mTargetSet;
+
+ final RectF mThumbnailRect;
+ private Surface mSurface;
+ private long mFrameNumber;
+
+ {
+ mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING);
+ inOutHelper.setTaskTransformCallback((t, app) -> {
+ t.setAlpha(app.leash, mTaskAlpha.value);
+
+ if (!skipViewChanges) {
+ t.deferTransactionUntil(app.leash, mSurface, mFrameNumber);
+ }
+ });
+
+ inOutHelper.prepareAnimation(true /* isOpening */);
+ inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(),
+ mTargetSet.apps.length == 0 ? null : mTargetSet.apps[0]);
+
+ mThumbnailRect = new RectF(inOutHelper.getTargetRect());
+ mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY());
+ Utilities.scaleRectFAboutCenter(mThumbnailRect, 1 / v.getScaleX());
+ }
+
+ @Override
+ public void onUpdate(float percent) {
+ mSurface = getSurface(v);
+ mFrameNumber = mSurface != null ? getNextFrameNumber(mSurface) : -1;
+ if (mFrameNumber == -1) {
+ // Booo, not cool! Our surface got destroyed, so no reason to animate anything.
+ Log.w(TAG, "Failed to animate, surface got destroyed.");
+ return;
+ }
+
+ RectF taskBounds = inOutHelper.applyTransform(mTargetSet, 1 - percent);
+ if (!skipViewChanges) {
+ float scale = taskBounds.width() / mThumbnailRect.width();
+ v.setScaleX(scale);
+ v.setScaleY(scale);
+ v.setTranslationX(taskBounds.centerX() - mThumbnailRect.centerX());
+ v.setTranslationY(taskBounds.centerY() - mThumbnailRect.centerY());
+ v.setAlpha(mViewAlpha.value);
+ }
+ }
+ });
+ return appAnimator;
+ }
+
+ public static boolean taskIsATargetWithMode(RemoteAnimationTargetCompat[] targets,
+ int taskId, int mode) {
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == mode && target.taskId == taskId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean checkCurrentOrManagedUserId(int currentUserId, Context context) {
+ if (currentUserId == UserHandle.myUserId()) {
+ return true;
+ }
+ List<UserHandle> allUsers = UserManagerCompat.getInstance(context).getUserProfiles();
+ for (int i = allUsers.size() - 1; i >= 0; i--) {
+ if (currentUserId == allUsers.get(i).getIdentifier()) {
+ return true;
+ }
+ }
+ return false;
+ }
}