/** Launches the task that Recents was launched from, if possible */
  public boolean launchPreviousTask() {
    // Get the first stack view
    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
      View child = getChildAt(i);
      if (child != mSearchBar) {
        TaskStackView stackView = (TaskStackView) child;
        TaskStack stack = stackView.mStack;
        ArrayList<Task> tasks = stack.getTasks();

        // Find the launch task in the stack
        if (!tasks.isEmpty()) {
          int taskCount = tasks.size();
          for (int j = 0; j < taskCount; j++) {
            if (tasks.get(j).isLaunchTarget) {
              Task task = tasks.get(j);
              TaskView tv = stackView.getChildViewForTask(task);
              onTaskViewClicked(stackView, tv, stack, task, false);
              return true;
            }
          }
        }
      }
    }
    return false;
  }
Example #2
0
  /** Launches the task that Recents was launched from, if possible */
  public boolean launchPreviousTask() {
    Log.d(TAG, "launchPreviousTask: ");
    // Get the first stack view
    List<TaskStackView> stackViews = getTaskStackViews();
    int stackCount = stackViews.size();
    for (int i = 0; i < stackCount; i++) {
      TaskStackView stackView = stackViews.get(i);
      TaskStack stack = stackView.getStack();
      ArrayList<Task> tasks = stack.getTasks();

      // Find the launch task in the stack
      if (!tasks.isEmpty()) {
        int taskCount = tasks.size();
        for (int j = 0; j < taskCount; j++) {
          if (tasks.get(j).isLaunchTarget) {
            Task task = tasks.get(j);
            TaskView tv = stackView.getChildViewForTask(task);
            onTaskViewClicked(stackView, tv, stack, task, false);
            return true;
          }
        }
      }
    }
    return false;
  }
  /** Returns the transition rect for the given task id. */
  TaskViewTransform getThumbnailTransitionTransform(
      TaskStack stack, TaskStackView stackView, int runningTaskId, Task runningTaskOut) {
    // Find the running task in the TaskStack
    Task task = null;
    ArrayList<Task> tasks = stack.getTasks();
    if (runningTaskId != -1) {
      // Otherwise, try and find the task with the
      int taskCount = tasks.size();
      for (int i = taskCount - 1; i >= 0; i--) {
        Task t = tasks.get(i);
        if (t.key.id == runningTaskId) {
          task = t;
          runningTaskOut.copyFrom(t);
          break;
        }
      }
    }
    if (task == null) {
      // If no task is specified or we can not find the task just use the front most one
      task = tasks.get(tasks.size() - 1);
      runningTaskOut.copyFrom(task);
    }

    // Get the transform for the running task
    stackView.getScroller().setStackScrollToInitialState();
    mTmpTransform =
        stackView
            .getStackAlgorithm()
            .getStackTransform(task, stackView.getScroller().getStackScroll(), mTmpTransform, null);
    return mTmpTransform;
  }
  /** Dismisses the focused task. */
  public void dismissFocusedTask() {
    // Return early if there is no focused task index
    if (mFocusedTaskIndex < 0) return;

    Task t = mStack.getTasks().get(mFocusedTaskIndex);
    TaskView tv = getChildViewForTask(t);
    tv.dismissTask();
  }
  /** Updates the min and max virtual scroll bounds */
  void updateMinMaxScroll(
      boolean boundScrollToNewMinMax, boolean launchedWithAltTab, boolean launchedFromHome) {
    // Compute the min and max scroll values
    mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks(), launchedWithAltTab, launchedFromHome);

    // Debug logging
    if (boundScrollToNewMinMax) {
      mStackScroller.boundScroll();
    }
  }
Example #6
0
 /** Gets the next task in the stack - or if the last - the top task */
 public Task getNextTaskOrTopTask(Task taskToSearch) {
   Log.d(TAG, "getNextTaskOrTopTask: ");
   Task returnTask = null;
   boolean found = false;
   List<TaskStackView> stackViews = getTaskStackViews();
   int stackCount = stackViews.size();
   for (int i = stackCount - 1; i >= 0; --i) {
     TaskStack stack = stackViews.get(i).getStack();
     ArrayList<Task> taskList = stack.getTasks();
     // Iterate the stack views and try and find the focused task
     for (int j = taskList.size() - 1; j >= 0; --j) {
       Task task = taskList.get(j);
       // Return the next task in the line.
       if (found) return task;
       // Remember the first possible task as the top task.
       if (returnTask == null) returnTask = task;
       if (task == taskToSearch) found = true;
     }
   }
   return returnTask;
 }
  /** Focuses the task at the specified index in the stack */
  void focusTask(int taskIndex, boolean scrollToNewPosition) {
    // Return early if the task is already focused
    if (taskIndex == mFocusedTaskIndex) return;

    if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
      mFocusedTaskIndex = taskIndex;

      // Focus the view if possible, otherwise, focus the view after we scroll into position
      Task t = mStack.getTasks().get(taskIndex);
      TaskView tv = getChildViewForTask(t);
      Runnable postScrollRunnable = null;
      if (tv != null) {
        tv.setFocusedTask();
      } else {
        postScrollRunnable =
            new Runnable() {
              @Override
              public void run() {
                Task t = mStack.getTasks().get(mFocusedTaskIndex);
                TaskView tv = getChildViewForTask(t);
                if (tv != null) {
                  tv.setFocusedTask();
                }
              }
            };
      }

      // Scroll the view into position (just center it in the curve)
      if (scrollToNewPosition) {
        float newScroll = mLayoutAlgorithm.getStackScrollForTask(t) - 0.5f;
        newScroll = mStackScroller.getBoundedStackScroll(newScroll);
        mStackScroller.animateScroll(
            mStackScroller.getStackScroll(), newScroll, postScrollRunnable);
      } else {
        if (postScrollRunnable != null) {
          postScrollRunnable.run();
        }
      }
    }
  }
 @Override
 public void onTaskViewDismissed(TaskView tv) {
   Task task = tv.getTask();
   int taskIndex = mStack.indexOfTask(task);
   boolean taskWasFocused = tv.isFocusedTask();
   // Announce for accessibility
   tv.announceForAccessibility(
       getContext()
           .getString(R.string.accessibility_recents_item_dismissed, tv.getTask().activityLabel));
   // Remove the task from the view
   mStack.removeTask(task);
   // If the dismissed task was focused, then we should focus the next task in front
   if (taskWasFocused) {
     ArrayList<Task> tasks = mStack.getTasks();
     int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex);
     if (nextTaskIndex >= 0) {
       Task nextTask = tasks.get(nextTaskIndex);
       TaskView nextTv = getChildViewForTask(nextTask);
       nextTv.setFocusedTask();
     }
   }
 }
 /** ** RecentsPackageMonitor.PackageCallbacks Implementation *** */
 @Override
 public void onComponentRemoved(HashSet<ComponentName> cns) {
   // For other tasks, just remove them directly if they no longer exist
   ArrayList<Task> tasks = mStack.getTasks();
   for (int i = tasks.size() - 1; i >= 0; i--) {
     final Task t = tasks.get(i);
     if (cns.contains(t.key.baseIntent.getComponent())) {
       TaskView tv = getChildViewForTask(t);
       if (tv != null) {
         // For visible children, defer removing the task until after the animation
         tv.startDeleteTaskAnimation(
             new Runnable() {
               @Override
               public void run() {
                 mStack.removeTask(t);
               }
             });
       } else {
         // Otherwise, remove the task from the stack immediately
         mStack.removeTask(t);
       }
     }
   }
 }
  /** Synchronizes the views with the model */
  boolean synchronizeStackViewsWithModel() {
    if (mStackViewsDirty) {
      RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
      SystemServicesProxy ssp = loader.getSystemServicesProxy();

      // Get all the task transforms
      ArrayList<Task> tasks = mStack.getTasks();
      float stackScroll = mStackScroller.getStackScroll();
      int[] visibleRange = mTmpVisibleRange;
      boolean isValidVisibleRange =
          updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
      if (mDebugOverlay != null) {
        mDebugOverlay.setText("vis[" + visibleRange[1] + "-" + visibleRange[0] + "]");
      }

      // Return all the invisible children to the pool
      mTmpTaskViewMap.clear();
      int childCount = getChildCount();
      for (int i = childCount - 1; i >= 0; i--) {
        TaskView tv = (TaskView) getChildAt(i);
        Task task = tv.getTask();
        int taskIndex = mStack.indexOfTask(task);
        if (visibleRange[1] <= taskIndex && taskIndex <= visibleRange[0]) {
          mTmpTaskViewMap.put(task, tv);
        } else {
          mViewPool.returnViewToPool(tv);
        }
      }

      // Pick up all the newly visible children and update all the existing children
      for (int i = visibleRange[0]; isValidVisibleRange && i >= visibleRange[1]; i--) {
        Task task = tasks.get(i);
        TaskViewTransform transform = mCurrentTaskTransforms.get(i);
        TaskView tv = mTmpTaskViewMap.get(task);
        int taskIndex = mStack.indexOfTask(task);

        if (tv == null) {
          tv = mViewPool.pickUpViewFromPool(task, task);

          if (mStackViewsAnimationDuration > 0) {
            // For items in the list, put them in start animating them from the
            // approriate ends of the list where they are expected to appear
            if (Float.compare(transform.p, 0f) <= 0) {
              mLayoutAlgorithm.getStackTransform(0f, 0f, mTmpTransform, null);
            } else {
              mLayoutAlgorithm.getStackTransform(1f, 0f, mTmpTransform, null);
            }
            tv.updateViewPropertiesToTaskTransform(mTmpTransform, 0);
          }
        }

        // Animate the task into place
        tv.updateViewPropertiesToTaskTransform(
            mCurrentTaskTransforms.get(taskIndex),
            mStackViewsAnimationDuration,
            mRequestUpdateClippingListener);

        // Request accessibility focus on the next view if we removed the task
        // that previously held accessibility focus
        childCount = getChildCount();
        if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
          TaskView atv = (TaskView) getChildAt(childCount - 1);
          int indexOfTask = mStack.indexOfTask(atv.getTask());
          if (mPrevAccessibilityFocusedIndex != indexOfTask) {
            tv.requestAccessibilityFocus();
            mPrevAccessibilityFocusedIndex = indexOfTask;
          }
        }
      }

      // Reset the request-synchronize params
      mStackViewsAnimationDuration = 0;
      mStackViewsDirty = false;
      mStackViewsClipDirty = true;
      return true;
    }
    return false;
  }
  void showRelativeAffiliatedTask(boolean showNextTask) {
    // Return early if there is no focused stack
    int focusedStackId = mSystemServicesProxy.getFocusedStack();
    TaskStack focusedStack = null;
    RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
    RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
    loader.preloadTasks(plan, true /* isTopTaskHome */);
    if (mConfig.multiStackEnabled) {
      if (focusedStackId < 0) return;
      focusedStack = plan.getTaskStack(focusedStackId);
    } else {
      focusedStack = plan.getAllTaskStacks().get(0);
    }

    // Return early if there are no tasks in the focused stack
    if (focusedStack == null || focusedStack.getTaskCount() == 0) return;

    ActivityManager.RunningTaskInfo runningTask = mSystemServicesProxy.getTopMostTask();
    // Return early if there is no running task (can't determine affiliated tasks in this case)
    if (runningTask == null) return;
    // Return early if the running task is in the home stack (optimization)
    if (mSystemServicesProxy.isInHomeStack(runningTask.id)) return;

    // Find the task in the recents list
    ArrayList<Task> tasks = focusedStack.getTasks();
    Task toTask = null;
    ActivityOptions launchOpts = null;
    int taskCount = tasks.size();
    int numAffiliatedTasks = 0;
    for (int i = 0; i < taskCount; i++) {
      Task task = tasks.get(i);
      if (task.key.id == runningTask.id) {
        TaskGrouping group = task.group;
        Task.TaskKey toTaskKey;
        if (showNextTask) {
          toTaskKey = group.getNextTaskInGroup(task);
          launchOpts =
              ActivityOptions.makeCustomAnimation(
                  mContext,
                  R.anim.recents_launch_next_affiliated_task_target,
                  R.anim.recents_launch_next_affiliated_task_source);
        } else {
          toTaskKey = group.getPrevTaskInGroup(task);
          launchOpts =
              ActivityOptions.makeCustomAnimation(
                  mContext,
                  R.anim.recents_launch_prev_affiliated_task_target,
                  R.anim.recents_launch_prev_affiliated_task_source);
        }
        if (toTaskKey != null) {
          toTask = focusedStack.findTaskWithId(toTaskKey.id);
        }
        numAffiliatedTasks = group.getTaskCount();
        break;
      }
    }

    // Return early if there is no next task
    if (toTask == null) {
      if (numAffiliatedTasks > 1) {
        if (showNextTask) {
          mSystemServicesProxy.startInPlaceAnimationOnFrontMostApplication(
              ActivityOptions.makeCustomInPlaceAnimation(
                  mContext, R.anim.recents_launch_next_affiliated_task_bounce));
        } else {
          mSystemServicesProxy.startInPlaceAnimationOnFrontMostApplication(
              ActivityOptions.makeCustomInPlaceAnimation(
                  mContext, R.anim.recents_launch_prev_affiliated_task_bounce));
        }
      }
      return;
    }

    // Keep track of actually launched affiliated tasks
    MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1);

    // Launch the task
    if (toTask.isActive) {
      // Bring an active task to the foreground
      mSystemServicesProxy.moveTaskToFront(toTask.key.id, launchOpts);
    } else {
      mSystemServicesProxy.startActivityFromRecents(
          mContext, toTask.key.id, toTask.activityLabel, launchOpts);
    }
  }