Home | History | Annotate | Download | only in system
      1 /*
      2  * Copyright (C) 2017 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.systemui.shared.system;
     18 
     19 import android.app.ActivityManager.TaskSnapshot;
     20 import android.app.IActivityManager;
     21 import android.app.TaskStackListener;
     22 import android.content.ComponentName;
     23 import android.os.Handler;
     24 import android.os.Looper;
     25 import android.os.Message;
     26 import android.os.RemoteException;
     27 import android.os.Trace;
     28 import android.util.Log;
     29 
     30 import com.android.systemui.shared.recents.model.ThumbnailData;
     31 
     32 import java.util.ArrayList;
     33 import java.util.List;
     34 
     35 /**
     36  * Tracks all the task stack listeners
     37  */
     38 public class TaskStackChangeListeners extends TaskStackListener {
     39 
     40     private static final String TAG = TaskStackChangeListeners.class.getSimpleName();
     41 
     42     /**
     43      * List of {@link TaskStackChangeListener} registered from {@link #addListener}.
     44      */
     45     private final List<TaskStackChangeListener> mTaskStackListeners = new ArrayList<>();
     46     private final List<TaskStackChangeListener> mTmpListeners = new ArrayList<>();
     47 
     48     private final Handler mHandler;
     49     private boolean mRegistered;
     50 
     51     public TaskStackChangeListeners(Looper looper) {
     52         mHandler = new H(looper);
     53     }
     54 
     55     public void addListener(IActivityManager am, TaskStackChangeListener listener) {
     56         mTaskStackListeners.add(listener);
     57         if (!mRegistered) {
     58             // Register mTaskStackListener to IActivityManager only once if needed.
     59             try {
     60                 am.registerTaskStackListener(this);
     61                 mRegistered = true;
     62             } catch (Exception e) {
     63                 Log.w(TAG, "Failed to call registerTaskStackListener", e);
     64             }
     65         }
     66     }
     67 
     68     public void removeListener(TaskStackChangeListener listener) {
     69         mTaskStackListeners.remove(listener);
     70     }
     71 
     72     @Override
     73     public void onTaskStackChanged() throws RemoteException {
     74         // Call the task changed callback for the non-ui thread listeners first
     75         synchronized (mTaskStackListeners) {
     76             mTmpListeners.clear();
     77             mTmpListeners.addAll(mTaskStackListeners);
     78         }
     79         for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
     80             mTmpListeners.get(i).onTaskStackChangedBackground();
     81         }
     82 
     83         mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
     84         mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
     85     }
     86 
     87     @Override
     88     public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
     89             throws RemoteException {
     90         mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
     91         mHandler.obtainMessage(H.ON_ACTIVITY_PINNED,
     92                 new PinnedActivityInfo(packageName, userId, taskId, stackId)).sendToTarget();
     93     }
     94 
     95     @Override
     96     public void onActivityUnpinned() throws RemoteException {
     97         mHandler.removeMessages(H.ON_ACTIVITY_UNPINNED);
     98         mHandler.sendEmptyMessage(H.ON_ACTIVITY_UNPINNED);
     99     }
    100 
    101     @Override
    102     public void onPinnedActivityRestartAttempt(boolean clearedTask)
    103             throws RemoteException{
    104         mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
    105         mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, clearedTask ? 1 : 0, 0)
    106                 .sendToTarget();
    107     }
    108 
    109     @Override
    110     public void onPinnedStackAnimationStarted() throws RemoteException {
    111         mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_STARTED);
    112         mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_STARTED);
    113     }
    114 
    115     @Override
    116     public void onPinnedStackAnimationEnded() throws RemoteException {
    117         mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
    118         mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
    119     }
    120 
    121     @Override
    122     public void onActivityForcedResizable(String packageName, int taskId, int reason)
    123             throws RemoteException {
    124         mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
    125                 .sendToTarget();
    126     }
    127 
    128     @Override
    129     public void onActivityDismissingDockedStack() throws RemoteException {
    130         mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK);
    131     }
    132 
    133     @Override
    134     public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
    135         mHandler.sendEmptyMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED);
    136     }
    137 
    138     @Override
    139     public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
    140         mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
    141     }
    142 
    143     @Override
    144     public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
    145         mHandler.obtainMessage(H.ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
    146     }
    147 
    148     @Override
    149     public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
    150         mHandler.obtainMessage(H.ON_TASK_CREATED, taskId, 0, componentName).sendToTarget();
    151     }
    152 
    153     @Override
    154     public void onTaskRemoved(int taskId) throws RemoteException {
    155         mHandler.obtainMessage(H.ON_TASK_REMOVED, taskId, 0).sendToTarget();
    156     }
    157 
    158     @Override
    159     public void onTaskMovedToFront(int taskId) throws RemoteException {
    160         mHandler.obtainMessage(H.ON_TASK_MOVED_TO_FRONT, taskId, 0).sendToTarget();
    161     }
    162 
    163     @Override
    164     public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation)
    165             throws RemoteException {
    166         mHandler.obtainMessage(H.ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE, taskId,
    167                 requestedOrientation).sendToTarget();
    168     }
    169 
    170     private final class H extends Handler {
    171         private static final int ON_TASK_STACK_CHANGED = 1;
    172         private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
    173         private static final int ON_ACTIVITY_PINNED = 3;
    174         private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 4;
    175         private static final int ON_PINNED_STACK_ANIMATION_ENDED = 5;
    176         private static final int ON_ACTIVITY_FORCED_RESIZABLE = 6;
    177         private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 7;
    178         private static final int ON_TASK_PROFILE_LOCKED = 8;
    179         private static final int ON_PINNED_STACK_ANIMATION_STARTED = 9;
    180         private static final int ON_ACTIVITY_UNPINNED = 10;
    181         private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED = 11;
    182         private static final int ON_TASK_CREATED = 12;
    183         private static final int ON_TASK_REMOVED = 13;
    184         private static final int ON_TASK_MOVED_TO_FRONT = 14;
    185         private static final int ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE = 15;
    186 
    187 
    188         public H(Looper looper) {
    189             super(looper);
    190         }
    191 
    192         @Override
    193         public void handleMessage(Message msg) {
    194             synchronized (mTaskStackListeners) {
    195                 switch (msg.what) {
    196                     case ON_TASK_STACK_CHANGED: {
    197                         Trace.beginSection("onTaskStackChanged");
    198                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    199                             mTaskStackListeners.get(i).onTaskStackChanged();
    200                         }
    201                         Trace.endSection();
    202                         break;
    203                     }
    204                     case ON_TASK_SNAPSHOT_CHANGED: {
    205                         Trace.beginSection("onTaskSnapshotChanged");
    206                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    207                             mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
    208                                     new ThumbnailData((TaskSnapshot) msg.obj));
    209                         }
    210                         Trace.endSection();
    211                         break;
    212                     }
    213                     case ON_ACTIVITY_PINNED: {
    214                         final PinnedActivityInfo info = (PinnedActivityInfo) msg.obj;
    215                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    216                             mTaskStackListeners.get(i).onActivityPinned(
    217                                     info.mPackageName, info.mUserId, info.mTaskId, info.mStackId);
    218                         }
    219                         break;
    220                     }
    221                     case ON_ACTIVITY_UNPINNED: {
    222                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    223                             mTaskStackListeners.get(i).onActivityUnpinned();
    224                         }
    225                         break;
    226                     }
    227                     case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
    228                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    229                             mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(
    230                                     msg.arg1 != 0);
    231                         }
    232                         break;
    233                     }
    234                     case ON_PINNED_STACK_ANIMATION_STARTED: {
    235                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    236                             mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
    237                         }
    238                         break;
    239                     }
    240                     case ON_PINNED_STACK_ANIMATION_ENDED: {
    241                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    242                             mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
    243                         }
    244                         break;
    245                     }
    246                     case ON_ACTIVITY_FORCED_RESIZABLE: {
    247                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    248                             mTaskStackListeners.get(i).onActivityForcedResizable(
    249                                     (String) msg.obj, msg.arg1, msg.arg2);
    250                         }
    251                         break;
    252                     }
    253                     case ON_ACTIVITY_DISMISSING_DOCKED_STACK: {
    254                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    255                             mTaskStackListeners.get(i).onActivityDismissingDockedStack();
    256                         }
    257                         break;
    258                     }
    259                     case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
    260                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    261                             mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
    262                         }
    263                         break;
    264                     }
    265                     case ON_TASK_PROFILE_LOCKED: {
    266                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    267                             mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
    268                         }
    269                         break;
    270                     }
    271                     case ON_TASK_CREATED: {
    272                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    273                             mTaskStackListeners.get(i).onTaskCreated(msg.arg1,
    274                                     (ComponentName) msg.obj);
    275                         }
    276                         break;
    277                     }
    278                     case ON_TASK_REMOVED: {
    279                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    280                             mTaskStackListeners.get(i).onTaskRemoved(msg.arg1);
    281                         }
    282                         break;
    283                     }
    284                     case ON_TASK_MOVED_TO_FRONT: {
    285                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    286                             mTaskStackListeners.get(i).onTaskMovedToFront(msg.arg1);
    287                         }
    288                         break;
    289                     }
    290                     case ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE: {
    291                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
    292                             mTaskStackListeners.get(i).onActivityRequestedOrientationChanged(
    293                                     msg.arg1, msg.arg2);
    294                         }
    295                         break;
    296                     }
    297                 }
    298             }
    299         }
    300     }
    301 
    302     private static class PinnedActivityInfo {
    303         final String mPackageName;
    304         final int mUserId;
    305         final int mTaskId;
    306         final int mStackId;
    307 
    308         PinnedActivityInfo(String packageName, int userId, int taskId, int stackId) {
    309             mPackageName = packageName;
    310             mUserId = userId;
    311             mTaskId = taskId;
    312             mStackId = stackId;
    313         }
    314     }
    315 }
    316