Home | History | Annotate | Download | only in am
      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.am;
     18 
     19 import android.app.ActivityManager.TaskSnapshot;
     20 import android.app.ITaskStackListener;
     21 import android.app.ActivityManager.TaskDescription;
     22 import android.content.ComponentName;
     23 import android.os.Binder;
     24 import android.os.Handler;
     25 import android.os.Looper;
     26 import android.os.Message;
     27 import android.os.RemoteCallbackList;
     28 import android.os.RemoteException;
     29 
     30 import java.util.ArrayList;
     31 
     32 class TaskChangeNotificationController {
     33     private static final int LOG_STACK_STATE_MSG = 1;
     34     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
     35     private static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
     36     private static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
     37     private static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
     38     private static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
     39     private static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
     40     private static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
     41     private static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
     42     private static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
     43     private static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
     44     private static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
     45     private static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
     46     private static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
     47     private static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
     48     private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
     49     private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
     50     private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
     51 
     52     // Delay in notifying task stack change listeners (in millis)
     53     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
     54 
     55     private final ActivityManagerService mService;
     56     private final ActivityStackSupervisor mStackSupervisor;
     57     private final Handler mHandler;
     58 
     59     // Task stack change listeners in a remote process.
     60     private final RemoteCallbackList<ITaskStackListener> mRemoteTaskStackListeners =
     61             new RemoteCallbackList<>();
     62 
     63     /*
     64      * Task stack change listeners in a local process. Tracked separately so that they can be
     65      * called on the same thread.
     66      */
     67     private final ArrayList<ITaskStackListener> mLocalTaskStackListeners = new ArrayList<>();
     68 
     69     private final TaskStackConsumer mNotifyTaskStackChanged = (l, m) -> {
     70         l.onTaskStackChanged();
     71     };
     72 
     73     private final TaskStackConsumer mNotifyTaskCreated = (l, m) -> {
     74         l.onTaskCreated(m.arg1, (ComponentName) m.obj);
     75     };
     76 
     77     private final TaskStackConsumer mNotifyTaskRemoved = (l, m) -> {
     78         l.onTaskRemoved(m.arg1);
     79     };
     80 
     81     private final TaskStackConsumer mNotifyTaskMovedToFront = (l, m) -> {
     82         l.onTaskMovedToFront(m.arg1);
     83     };
     84 
     85     private final TaskStackConsumer mNotifyTaskDescriptionChanged = (l, m) -> {
     86         l.onTaskDescriptionChanged(m.arg1, (TaskDescription) m.obj);
     87     };
     88 
     89     private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> {
     90         l.onActivityRequestedOrientationChanged(m.arg1, m.arg2);
     91     };
     92 
     93     private final TaskStackConsumer mNotifyTaskRemovalStarted = (l, m) -> {
     94         l.onTaskRemovalStarted(m.arg1);
     95     };
     96 
     97     private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
     98         l.onActivityPinned((String) m.obj /* packageName */, m.sendingUid /* userId */,
     99                 m.arg1 /* taskId */, m.arg2 /* stackId */);
    100     };
    101 
    102     private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> {
    103         l.onActivityUnpinned();
    104     };
    105 
    106     private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> {
    107         l.onPinnedActivityRestartAttempt(m.arg1 != 0);
    108     };
    109 
    110     private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> {
    111         l.onPinnedStackAnimationStarted();
    112     };
    113 
    114     private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> {
    115         l.onPinnedStackAnimationEnded();
    116     };
    117 
    118     private final TaskStackConsumer mNotifyActivityForcedResizable = (l, m) -> {
    119         l.onActivityForcedResizable((String) m.obj, m.arg1, m.arg2);
    120     };
    121 
    122     private final TaskStackConsumer mNotifyActivityDismissingDockedStack = (l, m) -> {
    123         l.onActivityDismissingDockedStack();
    124     };
    125 
    126     private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> {
    127         l.onActivityLaunchOnSecondaryDisplayFailed();
    128     };
    129 
    130     private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> {
    131         l.onTaskProfileLocked(m.arg1, m.arg2);
    132     };
    133 
    134     private final TaskStackConsumer mNotifyTaskSnapshotChanged = (l, m) -> {
    135         l.onTaskSnapshotChanged(m.arg1, (TaskSnapshot) m.obj);
    136     };
    137 
    138     @FunctionalInterface
    139     public interface TaskStackConsumer {
    140         void accept(ITaskStackListener t, Message m) throws RemoteException;
    141     }
    142 
    143     private class MainHandler extends Handler {
    144         public MainHandler(Looper looper) {
    145             super(looper);
    146         }
    147 
    148         @Override
    149         public void handleMessage(Message msg) {
    150             switch (msg.what) {
    151                 case LOG_STACK_STATE_MSG: {
    152                     synchronized (mService) {
    153                         mStackSupervisor.logStackState();
    154                     }
    155                     break;
    156                 }
    157                 case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG:
    158                     forAllRemoteListeners(mNotifyTaskStackChanged, msg);
    159                     break;
    160                 case NOTIFY_TASK_ADDED_LISTENERS_MSG:
    161                     forAllRemoteListeners(mNotifyTaskCreated, msg);
    162                     break;
    163                 case NOTIFY_TASK_REMOVED_LISTENERS_MSG:
    164                     forAllRemoteListeners(mNotifyTaskRemoved, msg);
    165                     break;
    166                 case NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG:
    167                     forAllRemoteListeners(mNotifyTaskMovedToFront, msg);
    168                     break;
    169                 case NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG:
    170                     forAllRemoteListeners(mNotifyTaskDescriptionChanged, msg);
    171                     break;
    172                 case NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS:
    173                     forAllRemoteListeners(mNotifyActivityRequestedOrientationChanged, msg);
    174                     break;
    175                 case NOTIFY_TASK_REMOVAL_STARTED_LISTENERS:
    176                     forAllRemoteListeners(mNotifyTaskRemovalStarted, msg);
    177                     break;
    178                 case NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG:
    179                     forAllRemoteListeners(mNotifyActivityPinned, msg);
    180                     break;
    181                 case NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG:
    182                     forAllRemoteListeners(mNotifyActivityUnpinned, msg);
    183                     break;
    184                 case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG:
    185                     forAllRemoteListeners(mNotifyPinnedActivityRestartAttempt, msg);
    186                     break;
    187                 case NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG:
    188                     forAllRemoteListeners(mNotifyPinnedStackAnimationStarted, msg);
    189                     break;
    190                 case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG:
    191                     forAllRemoteListeners(mNotifyPinnedStackAnimationEnded, msg);
    192                     break;
    193                 case NOTIFY_FORCED_RESIZABLE_MSG:
    194                     forAllRemoteListeners(mNotifyActivityForcedResizable, msg);
    195                     break;
    196                 case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG:
    197                     forAllRemoteListeners(mNotifyActivityDismissingDockedStack, msg);
    198                     break;
    199                 case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG:
    200                     forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
    201                     break;
    202                 case NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG:
    203                     forAllRemoteListeners(mNotifyTaskProfileLocked, msg);
    204                     break;
    205                 case NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG:
    206                     forAllRemoteListeners(mNotifyTaskSnapshotChanged, msg);
    207                     break;
    208             }
    209         }
    210     }
    211 
    212     public TaskChangeNotificationController(ActivityManagerService service,
    213             ActivityStackSupervisor stackSupervisor, Handler handler) {
    214         mService = service;
    215         mStackSupervisor = stackSupervisor;
    216         mHandler = new MainHandler(handler.getLooper());
    217     }
    218 
    219     public void registerTaskStackListener(ITaskStackListener listener) {
    220         synchronized (mService) {
    221             if (listener != null) {
    222                 if (Binder.getCallingPid() == android.os.Process.myPid()) {
    223                     if (!mLocalTaskStackListeners.contains(listener)) {
    224                         mLocalTaskStackListeners.add(listener);
    225                     }
    226                 } else {
    227                     mRemoteTaskStackListeners.register(listener);
    228                 }
    229             }
    230         }
    231     }
    232 
    233     public void unregisterTaskStackListener(ITaskStackListener listener) {
    234         synchronized (mService) {
    235             if (listener != null) {
    236                 if (Binder.getCallingPid() == android.os.Process.myPid()) {
    237                     mLocalTaskStackListeners.remove(listener);
    238                 } else {
    239                     mRemoteTaskStackListeners.unregister(listener);
    240                 }
    241             }
    242         }
    243     }
    244 
    245     private void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
    246         synchronized (mService) {
    247             for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
    248                 try {
    249                     // Make a one-way callback to the listener
    250                     callback.accept(mRemoteTaskStackListeners.getBroadcastItem(i), message);
    251                 } catch (RemoteException e) {
    252                     // Handled by the RemoteCallbackList.
    253                 }
    254             }
    255             mRemoteTaskStackListeners.finishBroadcast();
    256         }
    257     }
    258 
    259     private void forAllLocalListeners(TaskStackConsumer callback, Message message) {
    260         synchronized (mService) {
    261             for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) {
    262                 try {
    263                     callback.accept(mLocalTaskStackListeners.get(i), message);
    264                 } catch (RemoteException e) {
    265                     // Never thrown since this is called locally.
    266                 }
    267             }
    268         }
    269     }
    270 
    271     /** Notifies all listeners when the task stack has changed. */
    272     void notifyTaskStackChanged() {
    273         mHandler.sendEmptyMessage(LOG_STACK_STATE_MSG);
    274         mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
    275         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
    276         forAllLocalListeners(mNotifyTaskStackChanged, msg);
    277         // Only the main task stack change notification requires a delay.
    278         mHandler.sendMessageDelayed(msg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY);
    279     }
    280 
    281     /** Notifies all listeners when an Activity is pinned. */
    282     void notifyActivityPinned(ActivityRecord r) {
    283         mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
    284         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
    285                 r.getTask().taskId, r.getStackId(), r.packageName);
    286         msg.sendingUid = r.userId;
    287         forAllLocalListeners(mNotifyActivityPinned, msg);
    288         msg.sendToTarget();
    289     }
    290 
    291     /** Notifies all listeners when an Activity is unpinned. */
    292     void notifyActivityUnpinned() {
    293         mHandler.removeMessages(NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG);
    294         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG);
    295         forAllLocalListeners(mNotifyActivityUnpinned, msg);
    296         msg.sendToTarget();
    297     }
    298 
    299     /**
    300      * Notifies all listeners when an attempt was made to start an an activity that is already
    301      * running in the pinned stack and the activity was not actually started, but the task is
    302      * either brought to the front or a new Intent is delivered to it.
    303      */
    304     void notifyPinnedActivityRestartAttempt(boolean clearedTask) {
    305         mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
    306         final Message msg =
    307                 mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG,
    308                         clearedTask ? 1 : 0, 0);
    309         forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg);
    310         msg.sendToTarget();
    311     }
    312 
    313     /** Notifies all listeners when the pinned stack animation starts. */
    314     void notifyPinnedStackAnimationStarted() {
    315         mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
    316         final Message msg =
    317                 mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
    318         forAllLocalListeners(mNotifyPinnedStackAnimationStarted, msg);
    319         msg.sendToTarget();
    320     }
    321 
    322     /** Notifies all listeners when the pinned stack animation ends. */
    323     void notifyPinnedStackAnimationEnded() {
    324         mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
    325         final Message msg =
    326                 mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
    327         forAllLocalListeners(mNotifyPinnedStackAnimationEnded, msg);
    328         msg.sendToTarget();
    329     }
    330 
    331     void notifyActivityDismissingDockedStack() {
    332         mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
    333         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
    334         forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
    335         msg.sendToTarget();
    336     }
    337 
    338     void notifyActivityForcedResizable(int taskId, int reason, String packageName) {
    339         mHandler.removeMessages(NOTIFY_FORCED_RESIZABLE_MSG);
    340         final Message msg = mHandler.obtainMessage(NOTIFY_FORCED_RESIZABLE_MSG, taskId, reason,
    341                 packageName);
    342         forAllLocalListeners(mNotifyActivityForcedResizable, msg);
    343         msg.sendToTarget();
    344     }
    345 
    346     void notifyActivityLaunchOnSecondaryDisplayFailed() {
    347         mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
    348         final Message msg = mHandler.obtainMessage(
    349                 NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
    350         forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
    351         msg.sendToTarget();
    352     }
    353 
    354     void notifyTaskCreated(int taskId, ComponentName componentName) {
    355         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_ADDED_LISTENERS_MSG,
    356                 taskId, 0 /* unused */, componentName);
    357         forAllLocalListeners(mNotifyTaskCreated, msg);
    358         msg.sendToTarget();
    359     }
    360 
    361     void notifyTaskRemoved(int taskId) {
    362         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVED_LISTENERS_MSG,
    363                 taskId, 0 /* unused */);
    364         forAllLocalListeners(mNotifyTaskRemoved, msg);
    365         msg.sendToTarget();
    366     }
    367 
    368     void notifyTaskMovedToFront(int taskId) {
    369         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG,
    370                 taskId, 0 /* unused */);
    371         forAllLocalListeners(mNotifyTaskMovedToFront, msg);
    372         msg.sendToTarget();
    373     }
    374 
    375     void notifyTaskDescriptionChanged(int taskId, TaskDescription taskDescription) {
    376         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG,
    377                 taskId, 0 /* unused */, taskDescription);
    378         forAllLocalListeners(mNotifyTaskDescriptionChanged, msg);
    379         msg.sendToTarget();
    380 
    381     }
    382 
    383     void notifyActivityRequestedOrientationChanged(int taskId, int orientation) {
    384         final Message msg = mHandler.obtainMessage(
    385                 NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS, taskId, orientation);
    386         forAllLocalListeners(mNotifyActivityRequestedOrientationChanged, msg);
    387         msg.sendToTarget();
    388     }
    389 
    390     /**
    391      * Notify listeners that the task is about to be finished before its surfaces are removed from
    392      * the window manager. This allows interested parties to perform relevant animations before
    393      * the window disappears.
    394      */
    395     void notifyTaskRemovalStarted(int taskId) {
    396         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskId,
    397                 0 /* unused */);
    398         forAllLocalListeners(mNotifyTaskRemovalStarted, msg);
    399         msg.sendToTarget();
    400 
    401     }
    402 
    403     /**
    404      * Notify listeners that the task has been put in a locked state because one or more of the
    405      * activities inside it belong to a managed profile user that has been locked.
    406      */
    407     void notifyTaskProfileLocked(int taskId, int userId) {
    408         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG, taskId,
    409                 userId);
    410         forAllLocalListeners(mNotifyTaskProfileLocked, msg);
    411         msg.sendToTarget();
    412     }
    413 
    414     /**
    415      * Notify listeners that the snapshot of a task has changed.
    416      */
    417     void notifyTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
    418         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG,
    419                 taskId, 0, snapshot);
    420         forAllLocalListeners(mNotifyTaskSnapshotChanged, msg);
    421         msg.sendToTarget();
    422     }
    423 }
    424