| /* |
| * Copyright (C) 2015 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.systemui.recents; |
| |
| import android.app.ActivityManager; |
| import android.app.AlertDialog; |
| import android.app.Dialog; |
| import android.app.DialogFragment; |
| import android.app.FragmentManager; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.content.Intent; |
| import android.content.pm.ActivityInfo; |
| import android.content.pm.ResolveInfo; |
| import android.graphics.Rect; |
| import android.os.Bundle; |
| import android.util.MutableInt; |
| import android.util.SparseArray; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.widget.EditText; |
| import android.widget.Toast; |
| import com.android.systemui.R; |
| import com.android.systemui.recents.misc.SystemServicesProxy; |
| import com.android.systemui.recents.model.RecentsTaskLoader; |
| import com.android.systemui.recents.model.Task; |
| |
| import java.util.List; |
| |
| /** |
| * A helper for the dialogs that show when multistack debugging is on. |
| */ |
| public class RecentsMultiStackDialog extends DialogFragment { |
| |
| static final String TAG = "RecentsMultiStackDialog"; |
| |
| public static final int ADD_STACK_DIALOG = 0; |
| public static final int ADD_STACK_PICK_APP_DIALOG = 1; |
| public static final int REMOVE_STACK_DIALOG = 2; |
| public static final int RESIZE_STACK_DIALOG = 3; |
| public static final int RESIZE_STACK_PICK_STACK_DIALOG = 4; |
| public static final int MOVE_TASK_DIALOG = 5; |
| |
| FragmentManager mFragmentManager; |
| int mCurrentDialogType; |
| MutableInt mTargetStackIndex = new MutableInt(0); |
| Task mTaskToMove; |
| SparseArray<ActivityManager.StackInfo> mStacks; |
| List<ResolveInfo> mLauncherActivities; |
| Rect mAddStackRect; |
| Intent mAddStackIntent; |
| |
| View mAddStackDialogContent; |
| |
| public RecentsMultiStackDialog() {} |
| |
| public RecentsMultiStackDialog(FragmentManager mgr) { |
| mFragmentManager = mgr; |
| } |
| |
| /** Shows the add-stack dialog. */ |
| void showAddStackDialog() { |
| mCurrentDialogType = ADD_STACK_DIALOG; |
| show(mFragmentManager, TAG); |
| } |
| |
| /** Creates a new add-stack dialog. */ |
| private void createAddStackDialog(final Context context, LayoutInflater inflater, |
| AlertDialog.Builder builder, final SystemServicesProxy ssp) { |
| builder.setTitle("Add Stack - Enter new dimensions"); |
| mAddStackDialogContent = |
| inflater.inflate(R.layout.recents_multistack_stack_size_dialog, null, false); |
| Rect windowRect = ssp.getWindowRect(); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_left, windowRect.left); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_top, windowRect.top); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_right, windowRect.right); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_bottom, windowRect.bottom); |
| builder.setView(mAddStackDialogContent); |
| builder.setPositiveButton("Add Stack", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| int left = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_left); |
| int top = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_top); |
| int right = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_right); |
| int bottom = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_bottom); |
| if (bottom <= top || right <= left) { |
| Toast.makeText(context, "Invalid dimensions", Toast.LENGTH_SHORT).show(); |
| dismiss(); |
| return; |
| } |
| |
| // Prompt the user for the app to start |
| dismiss(); |
| mCurrentDialogType = ADD_STACK_PICK_APP_DIALOG; |
| mAddStackRect = new Rect(left, top, right, bottom); |
| show(mFragmentManager, TAG); |
| } |
| }); |
| builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| dismiss(); |
| } |
| }); |
| } |
| |
| /** Creates a new add-stack pick-app dialog. */ |
| private void createAddStackPickAppDialog(final Context context, LayoutInflater inflater, |
| AlertDialog.Builder builder, final SystemServicesProxy ssp) { |
| mLauncherActivities = ssp.getLauncherApps(); |
| mAddStackIntent = null; |
| int activityCount = mLauncherActivities.size(); |
| CharSequence[] activityNames = new CharSequence[activityCount]; |
| for (int i = 0; i < activityCount; i++) { |
| activityNames[i] = ssp.getActivityLabel(mLauncherActivities.get(i).activityInfo); |
| } |
| builder.setTitle("Add Stack - Pick starting app"); |
| builder.setSingleChoiceItems(activityNames, -1, |
| new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| ActivityInfo ai = mLauncherActivities.get(which).activityInfo; |
| mAddStackIntent = new Intent(Intent.ACTION_MAIN); |
| mAddStackIntent.addCategory(Intent.CATEGORY_LAUNCHER); |
| mAddStackIntent.setComponent(new ComponentName(ai.packageName, ai.name)); |
| } |
| }); |
| builder.setPositiveButton("Add Stack", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| // Display 0 = default display |
| ssp.createNewStack(0, mAddStackRect, mAddStackIntent); |
| } |
| }); |
| builder.setNegativeButton("Skip", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| // Display 0 = default display |
| ssp.createNewStack(0, mAddStackRect, null); |
| } |
| }); |
| } |
| |
| /** Shows the resize-stack dialog. */ |
| void showResizeStackDialog() { |
| mCurrentDialogType = RESIZE_STACK_PICK_STACK_DIALOG; |
| show(mFragmentManager, TAG); |
| } |
| |
| /** Creates a new resize-stack pick-stack dialog. */ |
| private void createResizeStackPickStackDialog(final Context context, LayoutInflater inflater, |
| AlertDialog.Builder builder, final SystemServicesProxy ssp) { |
| mStacks = ssp.getAllStackInfos(); |
| mTargetStackIndex.value = -1; |
| CharSequence[] stackNames = getAllStacksDescriptions(mStacks, -1, null); |
| builder.setTitle("Resize Stack - Pick stack"); |
| builder.setSingleChoiceItems(stackNames, mTargetStackIndex.value, |
| new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| mTargetStackIndex.value = which; |
| } |
| }); |
| builder.setPositiveButton("Resize Stack", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| if (mTargetStackIndex.value != -1) { |
| // Prompt the user for the new dimensions |
| dismiss(); |
| mCurrentDialogType = RESIZE_STACK_DIALOG; |
| show(mFragmentManager, TAG); |
| } |
| } |
| }); |
| builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| dismiss(); |
| } |
| }); |
| } |
| |
| /** Creates a new resize-stack dialog. */ |
| private void createResizeStackDialog(final Context context, LayoutInflater inflater, |
| AlertDialog.Builder builder, final SystemServicesProxy ssp) { |
| builder.setTitle("Resize Stack - Enter new dimensions"); |
| final ActivityManager.StackInfo stack = mStacks.valueAt(mTargetStackIndex.value); |
| mAddStackDialogContent = |
| inflater.inflate(R.layout.recents_multistack_stack_size_dialog, null, false); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_left, stack.bounds.left); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_top, stack.bounds.top); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_right, stack.bounds.right); |
| setDimensionInEditText(mAddStackDialogContent, R.id.inset_bottom, stack.bounds.bottom); |
| builder.setView(mAddStackDialogContent); |
| builder.setPositiveButton("Resize Stack", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| int left = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_left); |
| int top = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_top); |
| int right = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_right); |
| int bottom = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_bottom); |
| if (bottom <= top || right <= left) { |
| Toast.makeText(context, "Invalid dimensions", Toast.LENGTH_SHORT).show(); |
| dismiss(); |
| return; |
| } |
| ssp.resizeStack(stack.stackId, new Rect(left, top, right, bottom)); |
| } |
| }); |
| builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| dismiss(); |
| } |
| }); |
| } |
| |
| /** Shows the remove-stack dialog. */ |
| void showRemoveStackDialog() { |
| mCurrentDialogType = REMOVE_STACK_DIALOG; |
| show(mFragmentManager, TAG); |
| } |
| |
| /** Shows the move-task dialog. */ |
| void showMoveTaskDialog(Task task) { |
| mCurrentDialogType = MOVE_TASK_DIALOG; |
| mTaskToMove = task; |
| show(mFragmentManager, TAG); |
| } |
| |
| /** Creates a new move-stack dialog. */ |
| private void createMoveTaskDialog(final Context context, LayoutInflater inflater, |
| AlertDialog.Builder builder, final SystemServicesProxy ssp) { |
| mStacks = ssp.getAllStackInfos(); |
| mTargetStackIndex.value = -1; |
| CharSequence[] stackNames = getAllStacksDescriptions(mStacks, mTaskToMove.key.stackId, |
| mTargetStackIndex); |
| builder.setTitle("Move Task to Stack"); |
| builder.setSingleChoiceItems(stackNames, mTargetStackIndex.value, |
| new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| mTargetStackIndex.value = which; |
| } |
| }); |
| builder.setPositiveButton("Move Task", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| if (mTargetStackIndex.value != -1) { |
| ActivityManager.StackInfo toStack = mStacks.valueAt(mTargetStackIndex.value); |
| if (toStack.stackId != mTaskToMove.key.stackId) { |
| ssp.moveTaskToStack(mTaskToMove.key.id, toStack.stackId, true); |
| mTaskToMove.setStackId(toStack.stackId); |
| } |
| } |
| } |
| }); |
| builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| dismiss(); |
| } |
| }); |
| } |
| |
| /** Helper to get an integer value from an edit text. */ |
| private int getDimensionFromEditText(View container, int id) { |
| String text = ((EditText) container.findViewById(id)).getText().toString(); |
| if (text.trim().length() != 0) { |
| return Integer.parseInt(text.trim()); |
| } |
| return 0; |
| } |
| |
| /** Helper to set an integer value to an edit text. */ |
| private void setDimensionInEditText(View container, int id, int value) { |
| ((EditText) container.findViewById(id)).setText("" + value); |
| } |
| |
| /** Gets a list of all the stacks. */ |
| private CharSequence[] getAllStacksDescriptions(SparseArray<ActivityManager.StackInfo> stacks, |
| int targetStackId, MutableInt indexOfTargetStackId) { |
| int stackCount = stacks.size(); |
| CharSequence[] stackNames = new CharSequence[stackCount]; |
| for (int i = 0; i < stackCount; i++) { |
| ActivityManager.StackInfo stack = stacks.valueAt(i); |
| Rect b = stack.bounds; |
| String desc = "Stack " + stack.stackId + " / " + |
| "" + (stack.taskIds.length > 0 ? stack.taskIds.length : "No") + " tasks\n" + |
| "(" + b.left + ", " + b.top + ")-(" + b.right + ", " + b.bottom + ")\n"; |
| stackNames[i] = desc; |
| if (targetStackId != -1 && stack.stackId == targetStackId) { |
| indexOfTargetStackId.value = i; |
| } |
| } |
| return stackNames; |
| } |
| |
| @Override |
| public Dialog onCreateDialog(Bundle args) { |
| final Context context = this.getActivity(); |
| final SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy(); |
| LayoutInflater inflater = getActivity().getLayoutInflater(); |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| switch(mCurrentDialogType) { |
| case ADD_STACK_DIALOG: |
| createAddStackDialog(context, inflater, builder, ssp); |
| break; |
| case ADD_STACK_PICK_APP_DIALOG: |
| createAddStackPickAppDialog(context, inflater, builder, ssp); |
| break; |
| case MOVE_TASK_DIALOG: |
| createMoveTaskDialog(context, inflater, builder, ssp); |
| break; |
| case RESIZE_STACK_PICK_STACK_DIALOG: |
| createResizeStackPickStackDialog(context, inflater, builder, ssp); |
| break; |
| case RESIZE_STACK_DIALOG: |
| createResizeStackDialog(context, inflater, builder, ssp); |
| break; |
| } |
| return builder.create(); |
| } |
| } |