Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import android.app.ActivityManager.TaskDescription;
     20 import android.app.ActivityManager.TaskSnapshot;
     21 import android.content.res.Configuration;
     22 import android.graphics.Rect;
     23 import android.os.Handler;
     24 import android.os.Looper;
     25 import android.os.Message;
     26 import android.util.EventLog;
     27 import android.util.Slog;
     28 import com.android.internal.annotations.VisibleForTesting;
     29 
     30 import java.lang.ref.WeakReference;
     31 
     32 import static com.android.server.EventLogTags.WM_TASK_CREATED;
     33 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
     34 import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
     35 import static com.android.server.wm.WindowContainer.POSITION_TOP;
     36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
     37 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     38 
     39 /**
     40  * Controller for the task container. This is created by activity manager to link task records to
     41  * the task container they use in window manager.
     42  *
     43  * Test class: {@link TaskWindowContainerControllerTests}
     44  */
     45 public class TaskWindowContainerController
     46         extends WindowContainerController<Task, TaskWindowContainerListener> {
     47 
     48     private final int mTaskId;
     49     private final H mHandler;
     50 
     51     public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
     52             StackWindowController stackController, int userId, Rect bounds,
     53             Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
     54             boolean homeTask, boolean toTop, boolean showForAllUsers,
     55             TaskDescription taskDescription) {
     56         this(taskId, listener, stackController, userId, bounds, overrideConfig, resizeMode,
     57                 supportsPictureInPicture, homeTask, toTop, showForAllUsers, taskDescription,
     58                 WindowManagerService.getInstance());
     59     }
     60 
     61     public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
     62             StackWindowController stackController, int userId, Rect bounds,
     63             Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
     64             boolean homeTask, boolean toTop, boolean showForAllUsers,
     65             TaskDescription taskDescription, WindowManagerService service) {
     66         super(listener, service);
     67         mTaskId = taskId;
     68         mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
     69 
     70         synchronized(mWindowMap) {
     71             if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
     72                     + " stack=" + stackController + " bounds=" + bounds);
     73 
     74             final TaskStack stack = stackController.mContainer;
     75             if (stack == null) {
     76                 throw new IllegalArgumentException("TaskWindowContainerController: invalid stack="
     77                         + stackController);
     78             }
     79             EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
     80             final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
     81                     supportsPictureInPicture, homeTask, taskDescription);
     82             final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
     83             stack.addTask(task, position, showForAllUsers, true /* moveParents */);
     84         }
     85     }
     86 
     87     @VisibleForTesting
     88     Task createTask(int taskId, TaskStack stack, int userId, Rect bounds,
     89             Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
     90             boolean homeTask, TaskDescription taskDescription) {
     91         return new Task(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
     92                 supportsPictureInPicture, homeTask, taskDescription, this);
     93     }
     94 
     95     @Override
     96     public void removeContainer() {
     97         synchronized(mWindowMap) {
     98             if (mContainer == null) {
     99                 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
    100                 return;
    101             }
    102             mContainer.removeIfPossible();
    103             super.removeContainer();
    104         }
    105     }
    106 
    107     public void positionChildAt(AppWindowContainerController childController, int position) {
    108         synchronized(mService.mWindowMap) {
    109             final AppWindowToken aToken = childController.mContainer;
    110             if (aToken == null) {
    111                 Slog.w(TAG_WM,
    112                         "Attempted to position of non-existing app : " + childController);
    113                 return;
    114             }
    115 
    116             final Task task = mContainer;
    117             if (task == null) {
    118                 throw new IllegalArgumentException("positionChildAt: invalid task=" + this);
    119             }
    120             task.positionChildAt(position, aToken, false /* includeParents */);
    121         }
    122     }
    123 
    124     public void reparent(StackWindowController stackController, int position, boolean moveParents) {
    125         synchronized (mWindowMap) {
    126             if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
    127                     + " to stack=" + stackController + " at " + position);
    128             if (mContainer == null) {
    129                 if (DEBUG_STACK) Slog.i(TAG_WM,
    130                         "reparent: could not find taskId=" + mTaskId);
    131                 return;
    132             }
    133             final TaskStack stack = stackController.mContainer;
    134             if (stack == null) {
    135                 throw new IllegalArgumentException("reparent: could not find stack="
    136                         + stackController);
    137             }
    138             mContainer.reparent(stack, position, moveParents);
    139             mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
    140         }
    141     }
    142 
    143     public void setResizeable(int resizeMode) {
    144         synchronized (mWindowMap) {
    145             if (mContainer != null) {
    146                 mContainer.setResizeable(resizeMode);
    147             }
    148         }
    149     }
    150 
    151     public void resize(Rect bounds, Configuration overrideConfig, boolean relayout,
    152             boolean forced) {
    153         synchronized (mWindowMap) {
    154             if (mContainer == null) {
    155                 throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
    156             }
    157 
    158             if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) {
    159                 mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
    160             }
    161         }
    162     }
    163 
    164     public void getBounds(Rect bounds) {
    165         synchronized (mWindowMap) {
    166             if (mContainer != null) {
    167                 mContainer.getBounds(bounds);
    168                 return;
    169             }
    170             bounds.setEmpty();
    171         }
    172     }
    173 
    174     /**
    175      * Puts this task into docked drag resizing mode. See {@link DragResizeMode}.
    176      *
    177      * @param resizing Whether to put the task into drag resize mode.
    178      */
    179     public void setTaskDockedResizing(boolean resizing) {
    180         synchronized (mWindowMap) {
    181             if (mContainer == null) {
    182                 Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
    183                 return;
    184             }
    185             mContainer.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
    186         }
    187     }
    188 
    189     public void cancelWindowTransition() {
    190         synchronized (mWindowMap) {
    191             if (mContainer == null) {
    192                 Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
    193                 return;
    194             }
    195             mContainer.cancelTaskWindowTransition();
    196         }
    197     }
    198 
    199     public void cancelThumbnailTransition() {
    200         synchronized (mWindowMap) {
    201             if (mContainer == null) {
    202                 Slog.w(TAG_WM, "cancelThumbnailTransition: taskId " + mTaskId + " not found.");
    203                 return;
    204             }
    205             mContainer.cancelTaskThumbnailTransition();
    206         }
    207     }
    208 
    209     public void setTaskDescription(TaskDescription taskDescription) {
    210         synchronized (mWindowMap) {
    211             if (mContainer == null) {
    212                 Slog.w(TAG_WM, "setTaskDescription: taskId " + mTaskId + " not found.");
    213                 return;
    214             }
    215             mContainer.setTaskDescription(taskDescription);
    216         }
    217     }
    218 
    219     void reportSnapshotChanged(TaskSnapshot snapshot) {
    220         mHandler.obtainMessage(H.REPORT_SNAPSHOT_CHANGED, snapshot).sendToTarget();
    221     }
    222 
    223     void requestResize(Rect bounds, int resizeMode) {
    224         mHandler.obtainMessage(H.REQUEST_RESIZE, resizeMode, 0, bounds).sendToTarget();
    225     }
    226 
    227     @Override
    228     public String toString() {
    229         return "{TaskWindowContainerController taskId=" + mTaskId + "}";
    230     }
    231 
    232     private static final class H extends Handler {
    233 
    234         static final int REPORT_SNAPSHOT_CHANGED = 0;
    235         static final int REQUEST_RESIZE = 1;
    236 
    237         private final WeakReference<TaskWindowContainerController> mController;
    238 
    239         H(WeakReference<TaskWindowContainerController> controller, Looper looper) {
    240             super(looper);
    241             mController = controller;
    242         }
    243 
    244         @Override
    245         public void handleMessage(Message msg) {
    246             final TaskWindowContainerController controller = mController.get();
    247             final TaskWindowContainerListener listener = (controller != null)
    248                     ? controller.mListener : null;
    249             if (listener == null) {
    250                 return;
    251             }
    252             switch (msg.what) {
    253                 case REPORT_SNAPSHOT_CHANGED:
    254                     listener.onSnapshotChanged((TaskSnapshot) msg.obj);
    255                     break;
    256                 case REQUEST_RESIZE:
    257                     listener.requestResize((Rect) msg.obj, msg.arg1);
    258                     break;
    259             }
    260         }
    261     }
    262 }
    263