blob: 368687d9fd64ce4f6e34afd44356bb34b6b06e24 [file] [log] [blame]
Keun-young Park4727da32016-05-31 10:00:51 -07001/*
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 */
16package com.android.car;
17
Yao, Yuxingd525de12019-05-06 15:11:48 -070018import static com.android.car.pm.CarPackageManagerService.BLOCKING_INTENT_EXTRA_DISPLAY_ID;
19
Sudheer Shankaa4f49aa2016-11-10 16:39:13 -080020import android.app.ActivityManager;
Keun-young Park4727da32016-05-31 10:00:51 -070021import android.app.ActivityManager.StackInfo;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080022import android.app.ActivityOptions;
Keun-young Park4727da32016-05-31 10:00:51 -070023import android.app.IActivityManager;
24import android.app.IProcessObserver;
Yorke Leec1265de2016-10-27 11:25:25 -070025import android.app.TaskStackListener;
Keun-young Park4727da32016-05-31 10:00:51 -070026import android.content.ComponentName;
27import android.content.Context;
28import android.content.Intent;
29import android.os.Handler;
30import android.os.HandlerThread;
31import android.os.Looper;
32import android.os.Message;
33import android.os.RemoteException;
34import android.os.UserHandle;
Yao Chened8609e2016-10-07 09:49:13 -070035import android.util.ArrayMap;
Keun-young Park4727da32016-05-31 10:00:51 -070036import android.util.ArraySet;
37import android.util.Log;
38import android.util.Pair;
39import android.util.SparseArray;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080040import android.view.Display;
Keun-young Park4727da32016-05-31 10:00:51 -070041
Yuncheol Heo8b5ab802020-04-09 12:13:44 -070042import com.android.internal.annotations.GuardedBy;
43
Keun-young Park4727da32016-05-31 10:00:51 -070044import java.io.PrintWriter;
45import java.util.Arrays;
Keun-young Park4727da32016-05-31 10:00:51 -070046import java.util.LinkedList;
47import java.util.List;
48import java.util.Map;
Yao Chened8609e2016-10-07 09:49:13 -070049import java.util.Objects;
Keun-young Park4727da32016-05-31 10:00:51 -070050import java.util.Set;
51
52/**
53 * Service to monitor AMS for new Activity or Service launching.
54 */
55public class SystemActivityMonitoringService implements CarServiceBase {
56
57 /**
58 * Container to hold info on top task in an Activity stack
59 */
60 public static class TopTaskInfoContainer {
61 public final ComponentName topActivity;
62 public final int taskId;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080063 public final int displayId;
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -080064 public final int position;
Keun-young Park4727da32016-05-31 10:00:51 -070065 public final StackInfo stackInfo;
66
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -080067 private TopTaskInfoContainer(ComponentName topActivity, int taskId,
68 int displayId, int position, StackInfo stackInfo) {
Keun-young Park4727da32016-05-31 10:00:51 -070069 this.topActivity = topActivity;
70 this.taskId = taskId;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080071 this.displayId = displayId;
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -080072 this.position = position;
Keun-young Park4727da32016-05-31 10:00:51 -070073 this.stackInfo = stackInfo;
74 }
75
Yao Chened8609e2016-10-07 09:49:13 -070076 public boolean isMatching(TopTaskInfoContainer taskInfo) {
77 return taskInfo != null
78 && Objects.equals(this.topActivity, taskInfo.topActivity)
79 && this.taskId == taskInfo.taskId
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080080 && this.displayId == taskInfo.displayId
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -080081 && this.position == taskInfo.position
Yao Chened8609e2016-10-07 09:49:13 -070082 && this.stackInfo.userId == taskInfo.stackInfo.userId;
Keun-young Park4727da32016-05-31 10:00:51 -070083 }
84
85 @Override
86 public String toString() {
87 return String.format(
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -080088 "TaskInfoContainer [topActivity=%s, taskId=%d, stackId=%d, userId=%d, "
89 + "displayId=%d, position=%d",
90 topActivity, taskId, stackInfo.stackId, stackInfo.userId, displayId, position);
Keun-young Park4727da32016-05-31 10:00:51 -070091 }
92 }
93
94 public interface ActivityLaunchListener {
95 /**
96 * Notify launch of activity.
97 * @param topTask Task information for what is currently launched.
98 */
99 void onActivityLaunch(TopTaskInfoContainer topTask);
100 }
101
Michal Palczewski7684dbb2018-11-13 18:36:06 -0800102 private static final int INVALID_STACK_ID = -1;
Keun-young Park4727da32016-05-31 10:00:51 -0700103 private final Context mContext;
104 private final IActivityManager mAm;
105 private final ProcessObserver mProcessObserver;
106 private final TaskListener mTaskListener;
107
108 private final HandlerThread mMonitorHandlerThread;
109 private final ActivityMonitorHandler mHandler;
110
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700111 private final Object mLock = new Object();
112
Yao, Yuxingd525de12019-05-06 15:11:48 -0700113 /** K: display id, V: top task */
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700114 @GuardedBy("mLock")
Keun-young Park4727da32016-05-31 10:00:51 -0700115 private final SparseArray<TopTaskInfoContainer> mTopTasks = new SparseArray<>();
116 /** K: uid, V : list of pid */
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700117 @GuardedBy("mLock")
Yao Chened8609e2016-10-07 09:49:13 -0700118 private final Map<Integer, Set<Integer>> mForegroundUidPids = new ArrayMap<>();
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700119 @GuardedBy("mLock")
Keun-young Park4727da32016-05-31 10:00:51 -0700120 private ActivityLaunchListener mActivityLaunchListener;
121
122 public SystemActivityMonitoringService(Context context) {
123 mContext = context;
124 mMonitorHandlerThread = new HandlerThread(CarLog.TAG_AM);
125 mMonitorHandlerThread.start();
126 mHandler = new ActivityMonitorHandler(mMonitorHandlerThread.getLooper());
127 mProcessObserver = new ProcessObserver();
128 mTaskListener = new TaskListener();
Sudheer Shankaa4f49aa2016-11-10 16:39:13 -0800129 mAm = ActivityManager.getService();
Keun-young Park4727da32016-05-31 10:00:51 -0700130 // Monitoring both listeners are necessary as there are cases where one listener cannot
131 // monitor activity change.
132 try {
133 mAm.registerProcessObserver(mProcessObserver);
134 mAm.registerTaskStackListener(mTaskListener);
135 } catch (RemoteException e) {
136 Log.e(CarLog.TAG_AM, "cannot register activity monitoring", e);
137 throw new RuntimeException(e);
138 }
139 updateTasks();
140 }
141
142 @Override
143 public void init() {
144 }
145
146 @Override
147 public void release() {
148 }
149
150 @Override
151 public void dump(PrintWriter writer) {
152 writer.println("*SystemActivityMonitoringService*");
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800153 writer.println(" Top Tasks per display:");
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700154 synchronized (mLock) {
Keun-young Park4727da32016-05-31 10:00:51 -0700155 for (int i = 0; i < mTopTasks.size(); i++) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800156 int displayId = mTopTasks.keyAt(i);
Keun-young Park4727da32016-05-31 10:00:51 -0700157 TopTaskInfoContainer info = mTopTasks.valueAt(i);
158 if (info != null) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800159 writer.println("display id " + displayId + ": " + info);
Keun-young Park4727da32016-05-31 10:00:51 -0700160 }
161 }
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800162 writer.println(" Foreground uid-pids:");
Keun-young Park4727da32016-05-31 10:00:51 -0700163 for (Integer key : mForegroundUidPids.keySet()) {
164 Set<Integer> pids = mForegroundUidPids.get(key);
165 if (pids == null) {
166 continue;
167 }
168 writer.println("uid:" + key + ", pids:" + Arrays.toString(pids.toArray()));
169 }
Keun-young Park4727da32016-05-31 10:00:51 -0700170 }
171 }
172
173 /**
174 * Block the current task: Launch new activity with given Intent and finish the current task.
175 * @param currentTask task to finish
176 * @param newActivityIntent Intent for new Activity
177 */
178 public void blockActivity(TopTaskInfoContainer currentTask, Intent newActivityIntent) {
179 mHandler.requestBlockActivity(currentTask, newActivityIntent);
180 }
181
182 public List<TopTaskInfoContainer> getTopTasks() {
183 LinkedList<TopTaskInfoContainer> tasks = new LinkedList<>();
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700184 synchronized (mLock) {
Keun-young Park4727da32016-05-31 10:00:51 -0700185 for (int i = 0; i < mTopTasks.size(); i++) {
Yao, Yuxing2646cff2019-04-23 17:01:26 -0700186 TopTaskInfoContainer topTask = mTopTasks.valueAt(i);
187 if (topTask == null) {
188 Log.e(CarLog.TAG_AM, "Top tasks contains null. Full content is: "
189 + mTopTasks.toString());
190 continue;
191 }
192 tasks.add(topTask);
Keun-young Park4727da32016-05-31 10:00:51 -0700193 }
194 }
195 return tasks;
196 }
197
198 public boolean isInForeground(int pid, int uid) {
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700199 synchronized (mLock) {
Keun-young Park4727da32016-05-31 10:00:51 -0700200 Set<Integer> pids = mForegroundUidPids.get(uid);
201 if (pids == null) {
202 return false;
203 }
204 if (pids.contains(pid)) {
205 return true;
206 }
207 }
208 return false;
209 }
210
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700211 /**
212 * Attempts to restart a task.
213 *
214 * <p>Restarts a task by sending an empty intent with flag
215 * {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} to its root activity. If the task does not exist,
216 * do nothing.
217 *
218 * @param taskId id of task to be restarted.
219 */
220 public void restartTask(int taskId) {
221 String rootActivityName = null;
222 int userId = 0;
223 try {
224 findRootActivityName:
225 for (StackInfo info : mAm.getAllStackInfos()) {
226 for (int i = 0; i < info.taskIds.length; i++) {
227 if (info.taskIds[i] == taskId) {
228 rootActivityName = info.taskNames[i];
229 userId = info.userId;
230 if (Log.isLoggable(CarLog.TAG_AM, Log.DEBUG)) {
231 Log.d(CarLog.TAG_AM, "Root activity is " + rootActivityName);
232 Log.d(CarLog.TAG_AM, "User id is " + userId);
233 }
234 // Break out of nested loop.
235 break findRootActivityName;
236 }
237 }
238 }
239 } catch (RemoteException e) {
240 Log.e(CarLog.TAG_AM, "Could not get stack info", e);
241 return;
242 }
243
244 if (rootActivityName == null) {
245 Log.e(CarLog.TAG_AM, "Could not find root activity with task id " + taskId);
246 return;
247 }
248
249 Intent rootActivityIntent = new Intent();
250 rootActivityIntent.setComponent(ComponentName.unflattenFromString(rootActivityName));
251 // Clear the task the root activity is running in and start it in a new task.
252 // Effectively restart root activity.
253 rootActivityIntent.addFlags(
254 Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
255
256 if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
257 Log.i(CarLog.TAG_AM, "restarting root activity with user id " + userId);
258 }
259 mContext.startActivityAsUser(rootActivityIntent, new UserHandle(userId));
260 }
261
Keun-young Park4727da32016-05-31 10:00:51 -0700262 public void registerActivityLaunchListener(ActivityLaunchListener listener) {
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700263 synchronized (mLock) {
Keun-young Park4727da32016-05-31 10:00:51 -0700264 mActivityLaunchListener = listener;
265 }
266 }
267
268 private void updateTasks() {
269 List<StackInfo> infos;
270 try {
271 infos = mAm.getAllStackInfos();
272 } catch (RemoteException e) {
273 Log.e(CarLog.TAG_AM, "cannot getTasks", e);
274 return;
275 }
tadvana3b9ed202019-07-17 19:21:28 -0700276
277 if (infos == null) {
278 return;
279 }
280
Michal Palczewski7684dbb2018-11-13 18:36:06 -0800281 int focusedStackId = INVALID_STACK_ID;
Keun-young Park4727da32016-05-31 10:00:51 -0700282 try {
Wale Ogunwale9a000b92017-09-26 11:05:02 -0700283 // TODO(b/66955160): Someone on the Auto-team should probably re-work the code in the
284 // synchronized block below based on this new API.
285 final StackInfo focusedStackInfo = mAm.getFocusedStackInfo();
286 if (focusedStackInfo != null) {
287 focusedStackId = focusedStackInfo.stackId;
288 }
Keun-young Park4727da32016-05-31 10:00:51 -0700289 } catch (RemoteException e) {
290 Log.e(CarLog.TAG_AM, "cannot getFocusedStackId", e);
291 return;
292 }
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800293
294 SparseArray<TopTaskInfoContainer> topTasks = new SparseArray<>();
Keun-young Park4727da32016-05-31 10:00:51 -0700295 ActivityLaunchListener listener;
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700296 synchronized (mLock) {
297 mTopTasks.clear();
Keun-young Park4727da32016-05-31 10:00:51 -0700298 listener = mActivityLaunchListener;
Yao, Yuxingf4ed5282019-04-09 13:37:59 -0700299
Keun-young Park4727da32016-05-31 10:00:51 -0700300 for (StackInfo info : infos) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800301 int displayId = info.displayId;
Keun-young Park4727da32016-05-31 10:00:51 -0700302 if (info.taskNames.length == 0 || !info.visible) { // empty stack or not shown
Keun-young Park4727da32016-05-31 10:00:51 -0700303 continue;
304 }
Yao Chened8609e2016-10-07 09:49:13 -0700305 TopTaskInfoContainer newTopTaskInfo = new TopTaskInfoContainer(
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800306 info.topActivity, info.taskIds[info.taskIds.length - 1],
307 info.displayId, info.position, info);
308 TopTaskInfoContainer currentTopTaskInfo = topTasks.get(displayId);
Yao Chened8609e2016-10-07 09:49:13 -0700309
Keun-young Park4727da32016-05-31 10:00:51 -0700310 if (currentTopTaskInfo == null ||
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800311 newTopTaskInfo.position > currentTopTaskInfo.position) {
312 topTasks.put(displayId, newTopTaskInfo);
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700313 if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Yao, Yuxingf4ed5282019-04-09 13:37:59 -0700314 Log.i(CarLog.TAG_AM, "Updating top task to: " + newTopTaskInfo);
Keun-young Park4727da32016-05-31 10:00:51 -0700315 }
316 }
317 }
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800318 // Assuming displays remains the same.
319 for (int i = 0; i < topTasks.size(); i++) {
Yao, Yuxing2646cff2019-04-23 17:01:26 -0700320 TopTaskInfoContainer topTask = topTasks.valueAt(i);
Yao, Yuxingf4ed5282019-04-09 13:37:59 -0700321
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800322 int displayId = topTasks.keyAt(i);
Yao, Yuxingf4ed5282019-04-09 13:37:59 -0700323 mTopTasks.put(displayId, topTask);
Michal Palczewski7684dbb2018-11-13 18:36:06 -0800324 }
Keun-young Park4727da32016-05-31 10:00:51 -0700325 }
326 if (listener != null) {
Yao, Yuxingf4ed5282019-04-09 13:37:59 -0700327 for (int i = 0; i < topTasks.size(); i++) {
328 TopTaskInfoContainer topTask = topTasks.valueAt(i);
329
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700330 if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Yao, Yuxingf4ed5282019-04-09 13:37:59 -0700331 Log.i(CarLog.TAG_AM, "Notifying about top task: " + topTask.toString());
Keun-young Park4727da32016-05-31 10:00:51 -0700332 }
333 listener.onActivityLaunch(topTask);
334 }
335 }
336 }
337
338 public StackInfo getFocusedStackForTopActivity(ComponentName activity) {
Keun-young Park4727da32016-05-31 10:00:51 -0700339 StackInfo focusedStack;
340 try {
Wale Ogunwale9a000b92017-09-26 11:05:02 -0700341 focusedStack = mAm.getFocusedStackInfo();
Keun-young Park4727da32016-05-31 10:00:51 -0700342 } catch (RemoteException e) {
343 Log.e(CarLog.TAG_AM, "cannot getFocusedStackId", e);
344 return null;
345 }
346 if (focusedStack.taskNames.length == 0) { // nothing in focused stack
347 return null;
348 }
349 ComponentName topActivity = ComponentName.unflattenFromString(
350 focusedStack.taskNames[focusedStack.taskNames.length - 1]);
351 if (topActivity.equals(activity)) {
352 return focusedStack;
353 } else {
354 return null;
355 }
356 }
357
358 private void handleForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700359 synchronized (mLock) {
Keun-young Park4727da32016-05-31 10:00:51 -0700360 if (foregroundActivities) {
361 Set<Integer> pids = mForegroundUidPids.get(uid);
362 if (pids == null) {
363 pids = new ArraySet<Integer>();
364 mForegroundUidPids.put(uid, pids);
365 }
366 pids.add(pid);
367 } else {
368 doHandlePidGoneLocked(pid, uid);
369 }
370 }
371 }
372
373 private void handleProcessDied(int pid, int uid) {
Yuncheol Heo8b5ab802020-04-09 12:13:44 -0700374 synchronized (mLock) {
Keun-young Park4727da32016-05-31 10:00:51 -0700375 doHandlePidGoneLocked(pid, uid);
376 }
377 }
378
379 private void doHandlePidGoneLocked(int pid, int uid) {
380 Set<Integer> pids = mForegroundUidPids.get(uid);
381 if (pids != null) {
382 pids.remove(pid);
383 if (pids.isEmpty()) {
384 mForegroundUidPids.remove(uid);
385 }
386 }
387 }
388
Ram Periathiruvadiffcdb842018-04-16 17:17:39 -0700389 /**
390 * block the current task with the provided new activity.
391 */
Keun-young Park4727da32016-05-31 10:00:51 -0700392 private void handleBlockActivity(TopTaskInfoContainer currentTask, Intent newActivityIntent) {
Yao, Yuxingd525de12019-05-06 15:11:48 -0700393 int displayId = newActivityIntent.getIntExtra(BLOCKING_INTENT_EXTRA_DISPLAY_ID,
394 Display.DEFAULT_DISPLAY);
395 if (Log.isLoggable(CarLog.TAG_AM, Log.DEBUG)) {
396 Log.d(CarLog.TAG_AM, "Launching blocking activity on display: " + displayId);
397 }
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -0800398
Yao, Yuxingd525de12019-05-06 15:11:48 -0700399 ActivityOptions options = ActivityOptions.makeBasic();
400 options.setLaunchDisplayId(displayId);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -0800401 mContext.startActivityAsUser(newActivityIntent, options.toBundle(),
Keun-young Park4727da32016-05-31 10:00:51 -0700402 new UserHandle(currentTask.stackInfo.userId));
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700403 // Now make stack with new activity focused.
Keun-young Park4727da32016-05-31 10:00:51 -0700404 findTaskAndGrantFocus(newActivityIntent.getComponent());
Keun-young Park4727da32016-05-31 10:00:51 -0700405 }
406
407 private void findTaskAndGrantFocus(ComponentName activity) {
408 List<StackInfo> infos;
409 try {
410 infos = mAm.getAllStackInfos();
411 } catch (RemoteException e) {
412 Log.e(CarLog.TAG_AM, "cannot getTasks", e);
413 return;
414 }
415 for (StackInfo info : infos) {
416 if (info.taskNames.length == 0) {
417 continue;
418 }
419 ComponentName topActivity = ComponentName.unflattenFromString(
420 info.taskNames[info.taskNames.length - 1]);
421 if (activity.equals(topActivity)) {
422 try {
423 mAm.setFocusedStack(info.stackId);
424 } catch (RemoteException e) {
425 Log.e(CarLog.TAG_AM, "cannot setFocusedStack to stack:" + info.stackId, e);
426 }
427 return;
428 }
429 }
430 Log.i(CarLog.TAG_AM, "cannot give focus, cannot find Activity:" + activity);
431 }
432
433 private class ProcessObserver extends IProcessObserver.Stub {
434 @Override
435 public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700436 if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Keun-young Park4727da32016-05-31 10:00:51 -0700437 Log.i(CarLog.TAG_AM,
438 String.format("onForegroundActivitiesChanged uid %d pid %d fg %b",
439 uid, pid, foregroundActivities));
440 }
441 mHandler.requestForegroundActivitiesChanged(pid, uid, foregroundActivities);
442 }
443
444 @Override
Narayan Kamath4291a192019-03-15 18:49:29 +0000445 public void onForegroundServicesChanged(int pid, int uid, int fgServiceTypes) {
446 }
447
448 @Override
Keun-young Park4727da32016-05-31 10:00:51 -0700449 public void onProcessDied(int pid, int uid) {
450 mHandler.requestProcessDied(pid, uid);
451 }
452 }
453
Yorke Leec1265de2016-10-27 11:25:25 -0700454 private class TaskListener extends TaskStackListener {
Keun-young Park4727da32016-05-31 10:00:51 -0700455 @Override
456 public void onTaskStackChanged() {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700457 if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Keun-young Park4727da32016-05-31 10:00:51 -0700458 Log.i(CarLog.TAG_AM, "onTaskStackChanged");
459 }
460 mHandler.requestUpdatingTask();
461 }
Keun-young Park4727da32016-05-31 10:00:51 -0700462 }
463
464 private class ActivityMonitorHandler extends Handler {
465 private static final int MSG_UPDATE_TASKS = 0;
466 private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 1;
467 private static final int MSG_PROCESS_DIED = 2;
468 private static final int MSG_BLOCK_ACTIVITY = 3;
469
470 private ActivityMonitorHandler(Looper looper) {
471 super(looper);
472 }
473
474 private void requestUpdatingTask() {
475 Message msg = obtainMessage(MSG_UPDATE_TASKS);
476 sendMessage(msg);
477 }
478
479 private void requestForegroundActivitiesChanged(int pid, int uid,
480 boolean foregroundActivities) {
481 Message msg = obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED, pid, uid,
482 Boolean.valueOf(foregroundActivities));
483 sendMessage(msg);
484 }
485
486 private void requestProcessDied(int pid, int uid) {
487 Message msg = obtainMessage(MSG_PROCESS_DIED, pid, uid);
488 sendMessage(msg);
489 }
490
491 private void requestBlockActivity(TopTaskInfoContainer currentTask,
492 Intent newActivityIntent) {
493 Message msg = obtainMessage(MSG_BLOCK_ACTIVITY,
494 new Pair<TopTaskInfoContainer, Intent>(currentTask, newActivityIntent));
495 sendMessage(msg);
496 }
497
498 @Override
499 public void handleMessage(Message msg) {
500 switch (msg.what) {
501 case MSG_UPDATE_TASKS:
502 updateTasks();
503 break;
504 case MSG_FOREGROUND_ACTIVITIES_CHANGED:
505 handleForegroundActivitiesChanged(msg.arg1, msg.arg2, (Boolean) msg.obj);
506 updateTasks();
507 break;
508 case MSG_PROCESS_DIED:
509 handleProcessDied(msg.arg1, msg.arg2);
510 break;
511 case MSG_BLOCK_ACTIVITY:
512 Pair<TopTaskInfoContainer, Intent> pair =
513 (Pair<TopTaskInfoContainer, Intent>) msg.obj;
514 handleBlockActivity(pair.first, pair.second);
515 break;
516 }
517 }
518 }
519}