Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9c77aee authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Fixing crash with multiple touch pointers"

parents cde7086b 4c71aefc
Loading
Loading
Loading
Loading
+62 −12
Original line number Diff line number Diff line
@@ -29,45 +29,73 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.UserHandle;
import android.util.LruCache;
import android.util.Pair;
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;


/** A bitmap load queue */
class TaskResourceLoadQueue {
    ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>();
    ConcurrentHashMap<Task.TaskKey, Boolean> mForceLoadSet =
            new ConcurrentHashMap<Task.TaskKey, Boolean>();

    Task nextTask() {
        Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [TaskResourceLoadQueue|nextTask]");
        return mQueue.poll();
    }
    static final Boolean sFalse = new Boolean(false);

    void addTask(Task t) {
    /** Adds a new task to the load queue */
    void addTask(Task t, boolean forceLoad) {
        Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [TaskResourceLoadQueue|addTask]");
        if (!mQueue.contains(t)) {
            mQueue.add(t);
        }
        if (forceLoad) {
            mForceLoadSet.put(t.key, new Boolean(true));
        }
        synchronized(this) {
            notifyAll();
        }
    }

    /**
     * Retrieves the next task from the load queue, as well as whether we want that task to be
     * force reloaded.
     */
    Pair<Task, Boolean> nextTask() {
        Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [TaskResourceLoadQueue|nextTask]");
        Task task = mQueue.poll();
        Boolean forceLoadTask = null;
        if (task != null) {
            forceLoadTask = mForceLoadSet.remove(task.key);
        }
        if (forceLoadTask == null) {
            forceLoadTask = sFalse;
        }
        return new Pair<Task, Boolean>(task, forceLoadTask);
    }

    /** Removes a task from the load queue */
    void removeTask(Task t) {
        Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [TaskResourceLoadQueue|removeTask]");
        mQueue.remove(t);
        mForceLoadSet.remove(t.key);
    }

    /** Clears all the tasks from the load queue */
    void clearTasks() {
        Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [TaskResourceLoadQueue|clearTasks]");
        mQueue.clear();
        mForceLoadSet.clear();
    }

    /** Returns whether the load queue is empty */
    boolean isEmpty() {
        return mQueue.isEmpty();
    }
@@ -147,16 +175,19 @@ class TaskResourceLoader implements Runnable {
                }
            } else {
                // Load the next item from the queue
                final Task t = mLoadQueue.nextTask();
                Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
                final Task t = nextTaskData.first;
                final boolean forceLoadTask = nextTaskData.second;
                if (t != null) {
                    try {
                        Drawable loadIcon = mIconCache.get(t.key);
                        Bitmap loadThumbnail = mThumbnailCache.get(t.key);
                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
                                "  [TaskResourceLoader|load]",
                                t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail);
                                t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
                                        " forceLoad: " + forceLoadTask);
                        // Load the icon
                        if (loadIcon == null) {
                        if (loadIcon == null || forceLoadTask) {
                            PackageManager pm = mContext.getPackageManager();
                            ActivityInfo info = pm.getActivityInfo(t.key.intent.getComponent(),
                                    PackageManager.GET_META_DATA);
@@ -172,7 +203,7 @@ class TaskResourceLoader implements Runnable {
                            }
                        }
                        // Load the thumbnail
                        if (loadThumbnail == null) {
                        if (loadThumbnail == null || forceLoadTask) {
                            ActivityManager am = (ActivityManager)
                                    mContext.getSystemService(Context.ACTIVITY_SERVICE);
                            Bitmap thumbnail = am.getTaskTopThumbnail(t.key.id);
@@ -197,7 +228,7 @@ class TaskResourceLoader implements Runnable {
                            mMainThreadHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    t.notifyTaskDataLoaded(newThumbnail, newIcon);
                                    t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
                                }
                            });
                        }
@@ -329,9 +360,11 @@ public class RecentsTaskLoader {
    /** Reload the set of recent tasks */
    SpaceNode reload(Context context, int preloadCount) {
        Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
        ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
        TaskStack stack = new TaskStack(context);
        SpaceNode root = new SpaceNode(context);
        root.setStack(stack);

        try {
            long t1 = System.currentTimeMillis();

@@ -387,6 +420,12 @@ public class RecentsTaskLoader {
                    // Load the icon (if possible and not the foremost task, from the cache)
                    if (!isForemostTask) {
                        task.icon = mIconCache.get(task.key);

                        if (task.icon != null) {
                            // Even though we get things from the cache, we should update them if
                            // they've changed in the bg
                            tasksToForceLoad.add(task);
                        }
                    }
                    if (task.icon == null) {
                        task.icon = info.loadIcon(pm);
@@ -400,6 +439,12 @@ public class RecentsTaskLoader {
                    // Load the thumbnail (if possible and not the foremost task, from the cache)
                    if (!isForemostTask) {
                        task.thumbnail = mThumbnailCache.get(task.key);

                        if (task.thumbnail != null) {
                            // Even though we get things from the cache, we should update them if
                            // they've changed in the bg
                            tasksToForceLoad.add(task);
                        }
                    }
                    if (task.thumbnail == null) {
                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
@@ -451,6 +496,11 @@ public class RecentsTaskLoader {
        // Start the task loader
        mLoader.start(context);

        // Add all the tasks that we are force/re-loading
        for (Task t : tasksToForceLoad) {
            mLoadQueue.addTask(t, true);
        }

        return root;
    }

@@ -473,9 +523,9 @@ public class RecentsTaskLoader {
            requiresLoad = true;
        }
        if (requiresLoad) {
            mLoadQueue.addTask(t);
            mLoadQueue.addTask(t, false);
        }
        t.notifyTaskDataLoaded(thumbnail, icon);
        t.notifyTaskDataLoaded(thumbnail, icon, false);
    }

    /** Releases the task resource data back into the pool. */
+3 −3
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ public class Task {
    /* Task callbacks */
    public interface TaskCallbacks {
        /* Notifies when a task has been bound */
        public void onTaskDataLoaded();
        public void onTaskDataLoaded(boolean reloadingTaskData);
        /* Notifies when a task has been unbound */
        public void onTaskDataUnloaded();
    }
@@ -84,11 +84,11 @@ public class Task {
    }

    /** Notifies the callback listeners that this task has been loaded */
    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable icon) {
    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable icon, boolean reloadingTaskData) {
        this.icon = icon;
        this.thumbnail = thumbnail;
        if (mCb != null) {
            mCb.onTaskDataLoaded();
            mCb.onTaskDataLoaded(reloadingTaskData);
        }
    }

+20 −4
Original line number Diff line number Diff line
@@ -881,6 +881,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                }
                break;
            }
            case MotionEvent.ACTION_POINTER_DOWN: {
                final int index = ev.getActionIndex();
                mActivePointerId = ev.getPointerId(index);
                mLastMotionX = (int) ev.getX(index);
                mLastMotionY = (int) ev.getY(index);
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                if (mActivePointerId == INACTIVE_POINTER_ID) break;

@@ -957,6 +964,19 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                recycleVelocityTracker();
                break;
            }
            case MotionEvent.ACTION_POINTER_UP: {
                int pointerIndex = ev.getActionIndex();
                int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    // Select a new active pointer id and reset the motion state
                    final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                    mLastMotionX = (int) ev.getX(newPointerIndex);
                    mLastMotionY = (int) ev.getY(newPointerIndex);
                    mVelocityTracker.clear();
                }
                break;
            }
            case MotionEvent.ACTION_CANCEL: {
                if (mIsScrolling) {
                    // Disable HW layers
@@ -1006,10 +1026,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
        Task task = tv.getTask();
        Activity activity = (Activity) mSv.getContext();

        // We have to disable the listener to ensure that we
        // don't hit this again
        tv.animate().setListener(null);

        // Remove the task from the view
        mSv.mStack.removeTask(task);

+8 −18
Original line number Diff line number Diff line
@@ -65,10 +65,7 @@ class TaskThumbnailView extends ImageView {

            setImageBitmap(t.thumbnail);
            if (animate) {
                setAlpha(0f);
                animate().alpha(1f)
                        .setDuration(Constants.Values.TaskView.Animation.TaskDataUpdatedFadeDuration)
                        .start();
                // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
            }
        }
    }
@@ -143,10 +140,7 @@ class TaskIconView extends ImageView {
        if (t.icon != null) {
            setImageDrawable(t.icon);
            if (animate) {
                setAlpha(0f);
                animate().alpha(1f)
                        .setDuration(Constants.Values.TaskView.Animation.TaskDataUpdatedFadeDuration)
                        .start();
                // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
            }
        }
    }
@@ -311,6 +305,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
                    .translationY(0)
                    .setStartDelay(235)
                    .setDuration(Constants.Values.TaskView.Animation.TaskIconOnEnterDuration)
                    .withLayer()
                    .start();
        }
    }
@@ -333,13 +328,8 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
                .setStartDelay(0)
                .setDuration(Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration)
                .setInterpolator(new DecelerateInterpolator())
                .setListener(
                    new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            r.run();
                        }
                    })
                .withLayer()
                .withEndAction(r)
                .start();
        }
    }
@@ -379,10 +369,10 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
    }

    @Override
    public void onTaskDataLoaded() {
    public void onTaskDataLoaded(boolean reloadingTaskData) {
        // Bind each of the views to the new task data
        mThumbnailView.rebindToTask(mTask, false);
        mIconView.rebindToTask(mTask, false);
        mThumbnailView.rebindToTask(mTask, reloadingTaskData);
        mIconView.rebindToTask(mTask, reloadingTaskData);
    }

    @Override
+1 −0
Original line number Diff line number Diff line
@@ -757,6 +757,7 @@ public abstract class BaseStatusBar extends SystemUI implements

    protected void toggleRecentsActivity() {
        if (mRecents != null) {
            sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
            mRecents.toggleRecents(mDisplay, mLayoutDirection, getStatusBarView());
        }
    }