blob: 87ed2521d74e228528bb3bd345bf88c673e741db [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 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
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.app.IActivityWatcher;
39import android.app.IApplicationThread;
40import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IServiceConnection;
42import android.app.IThumbnailReceiver;
43import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070044import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.PendingIntent;
46import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070047import android.app.Service;
Christopher Tate181fafa2009-05-14 11:12:14 -070048import android.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020049import android.content.ActivityNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.ComponentName;
51import android.content.ContentResolver;
52import android.content.Context;
53import android.content.Intent;
54import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070055import android.content.IIntentReceiver;
56import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070057import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.pm.ActivityInfo;
59import android.content.pm.ApplicationInfo;
60import android.content.pm.ConfigurationInfo;
61import android.content.pm.IPackageDataObserver;
62import android.content.pm.IPackageManager;
63import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080064import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070066import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.ProviderInfo;
68import android.content.pm.ResolveInfo;
69import android.content.pm.ServiceInfo;
70import android.content.res.Configuration;
71import android.graphics.Bitmap;
72import android.net.Uri;
73import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080074import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080075import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070076import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080077import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080079import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.FileUtils;
81import android.os.Handler;
82import android.os.IBinder;
83import android.os.IPermissionController;
84import android.os.Looper;
85import android.os.Message;
86import android.os.Parcel;
87import android.os.ParcelFileDescriptor;
88import android.os.PowerManager;
89import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070090import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import android.os.RemoteException;
92import android.os.ServiceManager;
93import android.os.SystemClock;
94import android.os.SystemProperties;
95import android.provider.Checkin;
96import android.provider.Settings;
97import android.text.TextUtils;
98import android.util.Config;
99import android.util.EventLog;
100import android.util.Log;
101import android.util.PrintWriterPrinter;
102import android.util.SparseArray;
103import android.view.Gravity;
104import android.view.LayoutInflater;
105import android.view.View;
106import android.view.WindowManager;
107import android.view.WindowManagerPolicy;
108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.io.File;
110import java.io.FileDescriptor;
111import java.io.FileInputStream;
112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.io.PrintWriter;
115import java.lang.IllegalStateException;
116import java.lang.ref.WeakReference;
117import java.util.ArrayList;
118import java.util.HashMap;
119import java.util.HashSet;
120import java.util.Iterator;
121import java.util.List;
122import java.util.Locale;
123import java.util.Map;
124
125public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
126 static final String TAG = "ActivityManager";
127 static final boolean DEBUG = false;
128 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
129 static final boolean DEBUG_SWITCH = localLOGV || false;
130 static final boolean DEBUG_TASKS = localLOGV || false;
131 static final boolean DEBUG_PAUSE = localLOGV || false;
132 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
133 static final boolean DEBUG_TRANSITION = localLOGV || false;
134 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700135 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final boolean DEBUG_SERVICE = localLOGV || false;
137 static final boolean DEBUG_VISBILITY = localLOGV || false;
138 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700139 static final boolean DEBUG_PROVIDER = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700141 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700142 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700143 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 static final boolean VALIDATE_TOKENS = false;
145 static final boolean SHOW_ACTIVITY_START_TIME = true;
146
147 // Control over CPU and battery monitoring.
148 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
149 static final boolean MONITOR_CPU_USAGE = true;
150 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
151 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
152 static final boolean MONITOR_THREAD_CPU_USAGE = false;
153
Dianne Hackborn1655be42009-05-08 14:29:01 -0700154 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700155 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 private static final String SYSTEM_SECURE = "ro.secure";
158
159 // This is the maximum number of application processes we would like
160 // to have running. Due to the asynchronous nature of things, we can
161 // temporarily go beyond this limit.
162 static final int MAX_PROCESSES = 2;
163
164 // Set to false to leave processes running indefinitely, relying on
165 // the kernel killing them as resources are required.
166 static final boolean ENFORCE_PROCESS_LIMIT = false;
167
168 // This is the maximum number of activities that we would like to have
169 // running at a given time.
170 static final int MAX_ACTIVITIES = 20;
171
172 // Maximum number of recent tasks that we can remember.
173 static final int MAX_RECENT_TASKS = 20;
174
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700175 // Amount of time after a call to stopAppSwitches() during which we will
176 // prevent further untrusted switches from happening.
177 static final long APP_SWITCH_DELAY_TIME = 5*1000;
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 // How long until we reset a task when the user returns to it. Currently
180 // 30 minutes.
181 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
182
183 // Set to true to disable the icon that is shown while a new activity
184 // is being started.
185 static final boolean SHOW_APP_STARTING_ICON = true;
186
187 // How long we wait until giving up on the last activity to pause. This
188 // is short because it directly impacts the responsiveness of starting the
189 // next activity.
190 static final int PAUSE_TIMEOUT = 500;
191
192 /**
193 * How long we can hold the launch wake lock before giving up.
194 */
195 static final int LAUNCH_TIMEOUT = 10*1000;
196
197 // How long we wait for a launched process to attach to the activity manager
198 // before we decide it's never going to come up for real.
199 static final int PROC_START_TIMEOUT = 10*1000;
200
201 // How long we wait until giving up on the last activity telling us it
202 // is idle.
203 static final int IDLE_TIMEOUT = 10*1000;
204
205 // How long to wait after going idle before forcing apps to GC.
206 static final int GC_TIMEOUT = 5*1000;
207
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700208 // The minimum amount of time between successive GC requests for a process.
209 static final int GC_MIN_INTERVAL = 60*1000;
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // How long we wait until giving up on an activity telling us it has
212 // finished destroying itself.
213 static final int DESTROY_TIMEOUT = 10*1000;
214
215 // How long we allow a receiver to run before giving up on it.
216 static final int BROADCAST_TIMEOUT = 10*1000;
217
218 // How long we wait for a service to finish executing.
219 static final int SERVICE_TIMEOUT = 20*1000;
220
221 // How long a service needs to be running until restarting its process
222 // is no longer considered to be a relaunch of the service.
223 static final int SERVICE_RESTART_DURATION = 5*1000;
224
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700225 // How long a service needs to be running until it will start back at
226 // SERVICE_RESTART_DURATION after being killed.
227 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
228
229 // Multiplying factor to increase restart duration time by, for each time
230 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
231 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
232
233 // The minimum amount of time between restarting services that we allow.
234 // That is, when multiple services are restarting, we won't allow each
235 // to restart less than this amount of time from the last one.
236 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 // Maximum amount of time for there to be no activity on a service before
239 // we consider it non-essential and allow its process to go on the
240 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700241 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242
243 // How long we wait until we timeout on key dispatching.
244 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
245
246 // The minimum time we allow between crashes, for us to consider this
247 // application to be bad and stop and its services and reject broadcasts.
248 static final int MIN_CRASH_INTERVAL = 60*1000;
249
250 // How long we wait until we timeout on key dispatching during instrumentation.
251 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
252
253 // OOM adjustments for processes in various states:
254
255 // This is a process without anything currently running in it. Definitely
256 // the first to go! Value set in system/rootdir/init.rc on startup.
257 // This value is initalized in the constructor, careful when refering to
258 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800259 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
261 // This is a process only hosting activities that are not visible,
262 // so it can be killed without any disruption. Value set in
263 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 static int HIDDEN_APP_MIN_ADJ;
266
The Android Open Source Project4df24232009-03-05 14:34:35 -0800267 // This is a process holding the home application -- we want to try
268 // avoiding killing it, even if it would normally be in the background,
269 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800271
Christopher Tate6fa95972009-06-05 18:43:55 -0700272 // This is a process currently hosting a backup operation. Killing it
273 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 // This is a process holding a secondary server -- killing it will not
277 // have much of an impact as far as the user is concerned. Value set in
278 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280
281 // This is a process only hosting activities that are visible to the
282 // user, so we'd prefer they don't disappear. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // This is the process running the current foreground app. We'd really
287 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800288 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
290 // This is a process running a core server, such as telephony. Definitely
291 // don't want to kill it, but doing so is not completely fatal.
292 static final int CORE_SERVER_ADJ = -12;
293
294 // The system process runs at the default adjustment.
295 static final int SYSTEM_ADJ = -16;
296
297 // Memory pages are 4K.
298 static final int PAGE_SIZE = 4*1024;
299
Jacek Surazski82a73df2009-06-17 14:33:18 +0200300 // System property defining error report receiver for system apps
301 static final String SYSTEM_APPS_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.system.apps";
302
303 // System property defining default error report receiver
304 static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int EMPTY_APP_MEM;
308 static final int HIDDEN_APP_MEM;
309 static final int HOME_APP_MEM;
310 static final int BACKUP_APP_MEM;
311 static final int SECONDARY_SERVER_MEM;
312 static final int VISIBLE_APP_MEM;
313 static final int FOREGROUND_APP_MEM;
314
315 // The minimum number of hidden apps we want to be able to keep around,
316 // without empty apps being able to push them out of memory.
317 static final int MIN_HIDDEN_APPS = 2;
318
319 // We put empty content processes after any hidden processes that have
320 // been idle for less than 30 seconds.
321 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
322
323 // We put empty content processes after any hidden processes that have
324 // been idle for less than 60 seconds.
325 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
326
327 static {
328 // These values are set in system/rootdir/init.rc on startup.
329 FOREGROUND_APP_ADJ =
330 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
331 VISIBLE_APP_ADJ =
332 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
333 SECONDARY_SERVER_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
335 BACKUP_APP_ADJ =
336 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
337 HOME_APP_ADJ =
338 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
339 HIDDEN_APP_MIN_ADJ =
340 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
341 EMPTY_APP_ADJ =
342 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
343 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
344 FOREGROUND_APP_MEM =
345 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
346 VISIBLE_APP_MEM =
347 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
348 SECONDARY_SERVER_MEM =
349 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
350 BACKUP_APP_MEM =
351 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
352 HOME_APP_MEM =
353 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
354 HIDDEN_APP_MEM =
355 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
356 EMPTY_APP_MEM =
357 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359
Dan Egnor42471dd2010-01-07 17:25:22 -0800360 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
362 static final String[] EMPTY_STRING_ARRAY = new String[0];
363
364 enum ActivityState {
365 INITIALIZING,
366 RESUMED,
367 PAUSING,
368 PAUSED,
369 STOPPING,
370 STOPPED,
371 FINISHING,
372 DESTROYING,
373 DESTROYED
374 }
375
376 /**
377 * The back history of all previous (and possibly still
378 * running) activities. It contains HistoryRecord objects.
379 */
380 final ArrayList mHistory = new ArrayList();
381
382 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700383 * Description of a request to start a new activity, which has been held
384 * due to app switches being disabled.
385 */
386 class PendingActivityLaunch {
387 HistoryRecord r;
388 HistoryRecord sourceRecord;
389 Uri[] grantedUriPermissions;
390 int grantedMode;
391 boolean onlyIfNeeded;
392 }
393
394 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
395 = new ArrayList<PendingActivityLaunch>();
396
397 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 * List of all active broadcasts that are to be executed immediately
399 * (without waiting for another broadcast to finish). Currently this only
400 * contains broadcasts to registered receivers, to avoid spinning up
401 * a bunch of processes to execute IntentReceiver components.
402 */
403 final ArrayList<BroadcastRecord> mParallelBroadcasts
404 = new ArrayList<BroadcastRecord>();
405
406 /**
407 * List of all active broadcasts that are to be executed one at a time.
408 * The object at the top of the list is the currently activity broadcasts;
409 * those after it are waiting for the top to finish..
410 */
411 final ArrayList<BroadcastRecord> mOrderedBroadcasts
412 = new ArrayList<BroadcastRecord>();
413
414 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800415 * Historical data of past broadcasts, for debugging.
416 */
417 static final int MAX_BROADCAST_HISTORY = 100;
418 final BroadcastRecord[] mBroadcastHistory
419 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
420
421 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 * Set when we current have a BROADCAST_INTENT_MSG in flight.
423 */
424 boolean mBroadcastsScheduled = false;
425
426 /**
427 * Set to indicate whether to issue an onUserLeaving callback when a
428 * newly launched activity is being brought in front of us.
429 */
430 boolean mUserLeaving = false;
431
432 /**
433 * When we are in the process of pausing an activity, before starting the
434 * next one, this variable holds the activity that is currently being paused.
435 */
436 HistoryRecord mPausingActivity = null;
437
438 /**
439 * Current activity that is resumed, or null if there is none.
440 */
441 HistoryRecord mResumedActivity = null;
442
443 /**
444 * Activity we have told the window manager to have key focus.
445 */
446 HistoryRecord mFocusedActivity = null;
447
448 /**
449 * This is the last activity that we put into the paused state. This is
450 * used to determine if we need to do an activity transition while sleeping,
451 * when we normally hold the top activity paused.
452 */
453 HistoryRecord mLastPausedActivity = null;
454
455 /**
456 * List of activities that are waiting for a new activity
457 * to become visible before completing whatever operation they are
458 * supposed to do.
459 */
460 final ArrayList mWaitingVisibleActivities = new ArrayList();
461
462 /**
463 * List of activities that are ready to be stopped, but waiting
464 * for the next activity to settle down before doing so. It contains
465 * HistoryRecord objects.
466 */
467 final ArrayList<HistoryRecord> mStoppingActivities
468 = new ArrayList<HistoryRecord>();
469
470 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700471 * Animations that for the current transition have requested not to
472 * be considered for the transition animation.
473 */
474 final ArrayList<HistoryRecord> mNoAnimActivities
475 = new ArrayList<HistoryRecord>();
476
477 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 * List of intents that were used to start the most recent tasks.
479 */
480 final ArrayList<TaskRecord> mRecentTasks
481 = new ArrayList<TaskRecord>();
482
483 /**
484 * List of activities that are ready to be finished, but waiting
485 * for the previous activity to settle down before doing so. It contains
486 * HistoryRecord objects.
487 */
488 final ArrayList mFinishingActivities = new ArrayList();
489
490 /**
491 * All of the applications we currently have running organized by name.
492 * The keys are strings of the application package name (as
493 * returned by the package manager), and the keys are ApplicationRecord
494 * objects.
495 */
496 final ProcessMap<ProcessRecord> mProcessNames
497 = new ProcessMap<ProcessRecord>();
498
499 /**
500 * The last time that various processes have crashed.
501 */
502 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
503
504 /**
505 * Set of applications that we consider to be bad, and will reject
506 * incoming broadcasts from (which the user has no control over).
507 * Processes are added to this set when they have crashed twice within
508 * a minimum amount of time; they are removed from it when they are
509 * later restarted (hopefully due to some user action). The value is the
510 * time it was added to the list.
511 */
512 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
513
514 /**
515 * All of the processes we currently have running organized by pid.
516 * The keys are the pid running the application.
517 *
518 * <p>NOTE: This object is protected by its own lock, NOT the global
519 * activity manager lock!
520 */
521 final SparseArray<ProcessRecord> mPidsSelfLocked
522 = new SparseArray<ProcessRecord>();
523
524 /**
525 * All of the processes that have been forced to be foreground. The key
526 * is the pid of the caller who requested it (we hold a death
527 * link on it).
528 */
529 abstract class ForegroundToken implements IBinder.DeathRecipient {
530 int pid;
531 IBinder token;
532 }
533 final SparseArray<ForegroundToken> mForegroundProcesses
534 = new SparseArray<ForegroundToken>();
535
536 /**
537 * List of records for processes that someone had tried to start before the
538 * system was ready. We don't start them at that point, but ensure they
539 * are started by the time booting is complete.
540 */
541 final ArrayList<ProcessRecord> mProcessesOnHold
542 = new ArrayList<ProcessRecord>();
543
544 /**
545 * List of records for processes that we have started and are waiting
546 * for them to call back. This is really only needed when running in
547 * single processes mode, in which case we do not have a unique pid for
548 * each process.
549 */
550 final ArrayList<ProcessRecord> mStartingProcesses
551 = new ArrayList<ProcessRecord>();
552
553 /**
554 * List of persistent applications that are in the process
555 * of being started.
556 */
557 final ArrayList<ProcessRecord> mPersistentStartingProcesses
558 = new ArrayList<ProcessRecord>();
559
560 /**
561 * Processes that are being forcibly torn down.
562 */
563 final ArrayList<ProcessRecord> mRemovedProcesses
564 = new ArrayList<ProcessRecord>();
565
566 /**
567 * List of running applications, sorted by recent usage.
568 * The first entry in the list is the least recently used.
569 * It contains ApplicationRecord objects. This list does NOT include
570 * any persistent application records (since we never want to exit them).
571 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800572 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 = new ArrayList<ProcessRecord>();
574
575 /**
576 * List of processes that should gc as soon as things are idle.
577 */
578 final ArrayList<ProcessRecord> mProcessesToGc
579 = new ArrayList<ProcessRecord>();
580
581 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800582 * This is the process holding what we currently consider to be
583 * the "home" activity.
584 */
585 private ProcessRecord mHomeProcess;
586
587 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 * List of running activities, sorted by recent usage.
589 * The first entry in the list is the least recently used.
590 * It contains HistoryRecord objects.
591 */
592 private final ArrayList mLRUActivities = new ArrayList();
593
594 /**
595 * Set of PendingResultRecord objects that are currently active.
596 */
597 final HashSet mPendingResultRecords = new HashSet();
598
599 /**
600 * Set of IntentSenderRecord objects that are currently active.
601 */
602 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
603 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
604
605 /**
606 * Intent broadcast that we have tried to start, but are
607 * waiting for its application's process to be created. We only
608 * need one (instead of a list) because we always process broadcasts
609 * one at a time, so no others can be started while waiting for this
610 * one.
611 */
612 BroadcastRecord mPendingBroadcast = null;
613
614 /**
615 * Keeps track of all IIntentReceivers that have been registered for
616 * broadcasts. Hash keys are the receiver IBinder, hash value is
617 * a ReceiverList.
618 */
619 final HashMap mRegisteredReceivers = new HashMap();
620
621 /**
622 * Resolver for broadcast intents to registered receivers.
623 * Holds BroadcastFilter (subclass of IntentFilter).
624 */
625 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
626 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
627 @Override
628 protected boolean allowFilterResult(
629 BroadcastFilter filter, List<BroadcastFilter> dest) {
630 IBinder target = filter.receiverList.receiver.asBinder();
631 for (int i=dest.size()-1; i>=0; i--) {
632 if (dest.get(i).receiverList.receiver.asBinder() == target) {
633 return false;
634 }
635 }
636 return true;
637 }
638 };
639
640 /**
641 * State of all active sticky broadcasts. Keys are the action of the
642 * sticky Intent, values are an ArrayList of all broadcasted intents with
643 * that action (which should usually be one).
644 */
645 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
646 new HashMap<String, ArrayList<Intent>>();
647
648 /**
649 * All currently running services.
650 */
651 final HashMap<ComponentName, ServiceRecord> mServices =
652 new HashMap<ComponentName, ServiceRecord>();
653
654 /**
655 * All currently running services indexed by the Intent used to start them.
656 */
657 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
658 new HashMap<Intent.FilterComparison, ServiceRecord>();
659
660 /**
661 * All currently bound service connections. Keys are the IBinder of
662 * the client's IServiceConnection.
663 */
664 final HashMap<IBinder, ConnectionRecord> mServiceConnections
665 = new HashMap<IBinder, ConnectionRecord>();
666
667 /**
668 * List of services that we have been asked to start,
669 * but haven't yet been able to. It is used to hold start requests
670 * while waiting for their corresponding application thread to get
671 * going.
672 */
673 final ArrayList<ServiceRecord> mPendingServices
674 = new ArrayList<ServiceRecord>();
675
676 /**
677 * List of services that are scheduled to restart following a crash.
678 */
679 final ArrayList<ServiceRecord> mRestartingServices
680 = new ArrayList<ServiceRecord>();
681
682 /**
683 * List of services that are in the process of being stopped.
684 */
685 final ArrayList<ServiceRecord> mStoppingServices
686 = new ArrayList<ServiceRecord>();
687
688 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700689 * Backup/restore process management
690 */
691 String mBackupAppName = null;
692 BackupRecord mBackupTarget = null;
693
694 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 * List of PendingThumbnailsRecord objects of clients who are still
696 * waiting to receive all of the thumbnails for a task.
697 */
698 final ArrayList mPendingThumbnails = new ArrayList();
699
700 /**
701 * List of HistoryRecord objects that have been finished and must
702 * still report back to a pending thumbnail receiver.
703 */
704 final ArrayList mCancelledThumbnails = new ArrayList();
705
706 /**
707 * All of the currently running global content providers. Keys are a
708 * string containing the provider name and values are a
709 * ContentProviderRecord object containing the data about it. Note
710 * that a single provider may be published under multiple names, so
711 * there may be multiple entries here for a single one in mProvidersByClass.
712 */
713 final HashMap mProvidersByName = new HashMap();
714
715 /**
716 * All of the currently running global content providers. Keys are a
717 * string containing the provider's implementation class and values are a
718 * ContentProviderRecord object containing the data about it.
719 */
720 final HashMap mProvidersByClass = new HashMap();
721
722 /**
723 * List of content providers who have clients waiting for them. The
724 * application is currently being launched and the provider will be
725 * removed from this list once it is published.
726 */
727 final ArrayList mLaunchingProviders = new ArrayList();
728
729 /**
730 * Global set of specific Uri permissions that have been granted.
731 */
732 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
733 = new SparseArray<HashMap<Uri, UriPermission>>();
734
735 /**
736 * Thread-local storage used to carry caller permissions over through
737 * indirect content-provider access.
738 * @see #ActivityManagerService.openContentUri()
739 */
740 private class Identity {
741 public int pid;
742 public int uid;
743
744 Identity(int _pid, int _uid) {
745 pid = _pid;
746 uid = _uid;
747 }
748 }
749 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
750
751 /**
752 * All information we have collected about the runtime performance of
753 * any user id that can impact battery performance.
754 */
755 final BatteryStatsService mBatteryStatsService;
756
757 /**
758 * information about component usage
759 */
760 final UsageStatsService mUsageStatsService;
761
762 /**
763 * Current configuration information. HistoryRecord objects are given
764 * a reference to this object to indicate which configuration they are
765 * currently running in, so this object must be kept immutable.
766 */
767 Configuration mConfiguration = new Configuration();
768
769 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700770 * Hardware-reported OpenGLES version.
771 */
772 final int GL_ES_VERSION;
773
774 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 * List of initialization arguments to pass to all processes when binding applications to them.
776 * For example, references to the commonly used services.
777 */
778 HashMap<String, IBinder> mAppBindArgs;
779
780 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700781 * Temporary to avoid allocations. Protected by main lock.
782 */
783 final StringBuilder mStringBuilder = new StringBuilder(256);
784
785 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 * Used to control how we initialize the service.
787 */
788 boolean mStartRunning = false;
789 ComponentName mTopComponent;
790 String mTopAction;
791 String mTopData;
792 boolean mSystemReady = false;
793 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700794 boolean mWaitingUpdate = false;
795 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796
797 Context mContext;
798
799 int mFactoryTest;
800
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700801 boolean mCheckedForSetup;
802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700804 * The time at which we will allow normal application switches again,
805 * after a call to {@link #stopAppSwitches()}.
806 */
807 long mAppSwitchesAllowedTime;
808
809 /**
810 * This is set to true after the first switch after mAppSwitchesAllowedTime
811 * is set; any switches after that will clear the time.
812 */
813 boolean mDidAppSwitch;
814
815 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 * Set while we are wanting to sleep, to prevent any
817 * activities from being started/resumed.
818 */
819 boolean mSleeping = false;
820
821 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700822 * Set if we are shutting down the system, similar to sleeping.
823 */
824 boolean mShuttingDown = false;
825
826 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 * Set when the system is going to sleep, until we have
828 * successfully paused the current activity and released our wake lock.
829 * At that point the system is allowed to actually sleep.
830 */
831 PowerManager.WakeLock mGoingToSleep;
832
833 /**
834 * We don't want to allow the device to go to sleep while in the process
835 * of launching an activity. This is primarily to allow alarm intent
836 * receivers to launch an activity and get that to run before the device
837 * goes back to sleep.
838 */
839 PowerManager.WakeLock mLaunchingActivity;
840
841 /**
842 * Task identifier that activities are currently being started
843 * in. Incremented each time a new task is created.
844 * todo: Replace this with a TokenSpace class that generates non-repeating
845 * integers that won't wrap.
846 */
847 int mCurTask = 1;
848
849 /**
850 * Current sequence id for oom_adj computation traversal.
851 */
852 int mAdjSeq = 0;
853
854 /**
855 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
856 * is set, indicating the user wants processes started in such a way
857 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
858 * running in each process (thus no pre-initialized process, etc).
859 */
860 boolean mSimpleProcessManagement = false;
861
862 /**
863 * System monitoring: number of processes that died since the last
864 * N procs were started.
865 */
866 int[] mProcDeaths = new int[20];
867
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700868 /**
869 * This is set if we had to do a delayed dexopt of an app before launching
870 * it, to increasing the ANR timeouts in that case.
871 */
872 boolean mDidDexOpt;
873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 String mDebugApp = null;
875 boolean mWaitForDebugger = false;
876 boolean mDebugTransient = false;
877 String mOrigDebugApp = null;
878 boolean mOrigWaitForDebugger = false;
879 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700880 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700882 final RemoteCallbackList<IActivityWatcher> mWatchers
883 = new RemoteCallbackList<IActivityWatcher>();
884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 /**
886 * Callback of last caller to {@link #requestPss}.
887 */
888 Runnable mRequestPssCallback;
889
890 /**
891 * Remaining processes for which we are waiting results from the last
892 * call to {@link #requestPss}.
893 */
894 final ArrayList<ProcessRecord> mRequestPssList
895 = new ArrayList<ProcessRecord>();
896
897 /**
898 * Runtime statistics collection thread. This object's lock is used to
899 * protect all related state.
900 */
901 final Thread mProcessStatsThread;
902
903 /**
904 * Used to collect process stats when showing not responding dialog.
905 * Protected by mProcessStatsThread.
906 */
907 final ProcessStats mProcessStats = new ProcessStats(
908 MONITOR_THREAD_CPU_USAGE);
909 long mLastCpuTime = 0;
910 long mLastWriteTime = 0;
911
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700912 long mInitialStartTime = 0;
913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 /**
915 * Set to true after the system has finished booting.
916 */
917 boolean mBooted = false;
918
919 int mProcessLimit = 0;
920
921 WindowManagerService mWindowManager;
922
923 static ActivityManagerService mSelf;
924 static ActivityThread mSystemThread;
925
926 private final class AppDeathRecipient implements IBinder.DeathRecipient {
927 final ProcessRecord mApp;
928 final int mPid;
929 final IApplicationThread mAppThread;
930
931 AppDeathRecipient(ProcessRecord app, int pid,
932 IApplicationThread thread) {
933 if (localLOGV) Log.v(
934 TAG, "New death recipient " + this
935 + " for thread " + thread.asBinder());
936 mApp = app;
937 mPid = pid;
938 mAppThread = thread;
939 }
940
941 public void binderDied() {
942 if (localLOGV) Log.v(
943 TAG, "Death received in " + this
944 + " for thread " + mAppThread.asBinder());
945 removeRequestedPss(mApp);
946 synchronized(ActivityManagerService.this) {
947 appDiedLocked(mApp, mPid, mAppThread);
948 }
949 }
950 }
951
952 static final int SHOW_ERROR_MSG = 1;
953 static final int SHOW_NOT_RESPONDING_MSG = 2;
954 static final int SHOW_FACTORY_ERROR_MSG = 3;
955 static final int UPDATE_CONFIGURATION_MSG = 4;
956 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
957 static final int WAIT_FOR_DEBUGGER_MSG = 6;
958 static final int BROADCAST_INTENT_MSG = 7;
959 static final int BROADCAST_TIMEOUT_MSG = 8;
960 static final int PAUSE_TIMEOUT_MSG = 9;
961 static final int IDLE_TIMEOUT_MSG = 10;
962 static final int IDLE_NOW_MSG = 11;
963 static final int SERVICE_TIMEOUT_MSG = 12;
964 static final int UPDATE_TIME_ZONE = 13;
965 static final int SHOW_UID_ERROR_MSG = 14;
966 static final int IM_FEELING_LUCKY_MSG = 15;
967 static final int LAUNCH_TIMEOUT_MSG = 16;
968 static final int DESTROY_TIMEOUT_MSG = 17;
969 static final int SERVICE_ERROR_MSG = 18;
970 static final int RESUME_TOP_ACTIVITY_MSG = 19;
971 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700972 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700973 static final int KILL_APPLICATION_MSG = 22;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974
975 AlertDialog mUidAlert;
976
977 final Handler mHandler = new Handler() {
978 //public Handler() {
979 // if (localLOGV) Log.v(TAG, "Handler started!");
980 //}
981
982 public void handleMessage(Message msg) {
983 switch (msg.what) {
984 case SHOW_ERROR_MSG: {
985 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 synchronized (ActivityManagerService.this) {
987 ProcessRecord proc = (ProcessRecord)data.get("app");
988 if (proc != null && proc.crashDialog != null) {
989 Log.e(TAG, "App already has crash dialog: " + proc);
990 return;
991 }
992 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700993 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800994 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 d.show();
996 proc.crashDialog = d;
997 } else {
998 // The device is asleep, so just pretend that the user
999 // saw a crash dialog and hit "force quit".
1000 res.set(0);
1001 }
1002 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001003
1004 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 } break;
1006 case SHOW_NOT_RESPONDING_MSG: {
1007 synchronized (ActivityManagerService.this) {
1008 HashMap data = (HashMap) msg.obj;
1009 ProcessRecord proc = (ProcessRecord)data.get("app");
1010 if (proc != null && proc.anrDialog != null) {
1011 Log.e(TAG, "App already has anr dialog: " + proc);
1012 return;
1013 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001014
1015 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1016 null, null, 0, null, null, null,
1017 false, false, MY_PID, Process.SYSTEM_UID);
1018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1020 mContext, proc, (HistoryRecord)data.get("activity"));
1021 d.show();
1022 proc.anrDialog = d;
1023 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001024
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001025 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 } break;
1027 case SHOW_FACTORY_ERROR_MSG: {
1028 Dialog d = new FactoryErrorDialog(
1029 mContext, msg.getData().getCharSequence("msg"));
1030 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001031 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 } break;
1033 case UPDATE_CONFIGURATION_MSG: {
1034 final ContentResolver resolver = mContext.getContentResolver();
1035 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1036 } break;
1037 case GC_BACKGROUND_PROCESSES_MSG: {
1038 synchronized (ActivityManagerService.this) {
1039 performAppGcsIfAppropriateLocked();
1040 }
1041 } break;
1042 case WAIT_FOR_DEBUGGER_MSG: {
1043 synchronized (ActivityManagerService.this) {
1044 ProcessRecord app = (ProcessRecord)msg.obj;
1045 if (msg.arg1 != 0) {
1046 if (!app.waitedForDebugger) {
1047 Dialog d = new AppWaitingForDebuggerDialog(
1048 ActivityManagerService.this,
1049 mContext, app);
1050 app.waitDialog = d;
1051 app.waitedForDebugger = true;
1052 d.show();
1053 }
1054 } else {
1055 if (app.waitDialog != null) {
1056 app.waitDialog.dismiss();
1057 app.waitDialog = null;
1058 }
1059 }
1060 }
1061 } break;
1062 case BROADCAST_INTENT_MSG: {
1063 if (DEBUG_BROADCAST) Log.v(
1064 TAG, "Received BROADCAST_INTENT_MSG");
1065 processNextBroadcast(true);
1066 } break;
1067 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001068 if (mDidDexOpt) {
1069 mDidDexOpt = false;
1070 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1071 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1072 return;
1073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 broadcastTimeout();
1075 } break;
1076 case PAUSE_TIMEOUT_MSG: {
1077 IBinder token = (IBinder)msg.obj;
1078 // We don't at this point know if the activity is fullscreen,
1079 // so we need to be conservative and assume it isn't.
1080 Log.w(TAG, "Activity pause timeout for " + token);
1081 activityPaused(token, null, true);
1082 } break;
1083 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001084 if (mDidDexOpt) {
1085 mDidDexOpt = false;
1086 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1087 nmsg.obj = msg.obj;
1088 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1089 return;
1090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 // We don't at this point know if the activity is fullscreen,
1092 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001093 IBinder token = (IBinder)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 Log.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001095 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 } break;
1097 case DESTROY_TIMEOUT_MSG: {
1098 IBinder token = (IBinder)msg.obj;
1099 // We don't at this point know if the activity is fullscreen,
1100 // so we need to be conservative and assume it isn't.
1101 Log.w(TAG, "Activity destroy timeout for " + token);
1102 activityDestroyed(token);
1103 } break;
1104 case IDLE_NOW_MSG: {
1105 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001106 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 } break;
1108 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001109 if (mDidDexOpt) {
1110 mDidDexOpt = false;
1111 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1112 nmsg.obj = msg.obj;
1113 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1114 return;
1115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 serviceTimeout((ProcessRecord)msg.obj);
1117 } break;
1118 case UPDATE_TIME_ZONE: {
1119 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001120 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1121 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 if (r.thread != null) {
1123 try {
1124 r.thread.updateTimeZone();
1125 } catch (RemoteException ex) {
1126 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
1127 }
1128 }
1129 }
1130 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001131 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 case SHOW_UID_ERROR_MSG: {
1133 // XXX This is a temporary dialog, no need to localize.
1134 AlertDialog d = new BaseErrorDialog(mContext);
1135 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1136 d.setCancelable(false);
1137 d.setTitle("System UIDs Inconsistent");
1138 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1139 d.setButton("I'm Feeling Lucky",
1140 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1141 mUidAlert = d;
1142 d.show();
1143 } break;
1144 case IM_FEELING_LUCKY_MSG: {
1145 if (mUidAlert != null) {
1146 mUidAlert.dismiss();
1147 mUidAlert = null;
1148 }
1149 } break;
1150 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001151 if (mDidDexOpt) {
1152 mDidDexOpt = false;
1153 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1154 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1155 return;
1156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 synchronized (ActivityManagerService.this) {
1158 if (mLaunchingActivity.isHeld()) {
1159 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1160 mLaunchingActivity.release();
1161 }
1162 }
1163 } break;
1164 case SERVICE_ERROR_MSG: {
1165 ServiceRecord srv = (ServiceRecord)msg.obj;
1166 // This needs to be *un*synchronized to avoid deadlock.
1167 Checkin.logEvent(mContext.getContentResolver(),
1168 Checkin.Events.Tag.SYSTEM_SERVICE_LOOPING,
1169 srv.name.toShortString());
1170 } break;
1171 case RESUME_TOP_ACTIVITY_MSG: {
1172 synchronized (ActivityManagerService.this) {
1173 resumeTopActivityLocked(null);
1174 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001175 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001177 if (mDidDexOpt) {
1178 mDidDexOpt = false;
1179 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1180 nmsg.obj = msg.obj;
1181 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1182 return;
1183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 ProcessRecord app = (ProcessRecord)msg.obj;
1185 synchronized (ActivityManagerService.this) {
1186 processStartTimedOutLocked(app);
1187 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001188 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001189 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1190 synchronized (ActivityManagerService.this) {
1191 doPendingActivityLaunchesLocked(true);
1192 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001193 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001194 case KILL_APPLICATION_MSG: {
1195 synchronized (ActivityManagerService.this) {
1196 int uid = msg.arg1;
1197 boolean restart = (msg.arg2 == 1);
1198 String pkg = (String) msg.obj;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08001199 forceStopPackageLocked(pkg, uid, restart, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 }
1201 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 }
1203 }
1204 };
1205
1206 public static void setSystemProcess() {
1207 try {
1208 ActivityManagerService m = mSelf;
1209
1210 ServiceManager.addService("activity", m);
1211 ServiceManager.addService("meminfo", new MemBinder(m));
1212 if (MONITOR_CPU_USAGE) {
1213 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 ServiceManager.addService("permission", new PermissionController(m));
1216
1217 ApplicationInfo info =
1218 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001219 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001220 mSystemThread.installSystemApplicationInfo(info);
1221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 synchronized (mSelf) {
1223 ProcessRecord app = mSelf.newProcessRecordLocked(
1224 mSystemThread.getApplicationThread(), info,
1225 info.processName);
1226 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001227 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 app.maxAdj = SYSTEM_ADJ;
1229 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1230 synchronized (mSelf.mPidsSelfLocked) {
1231 mSelf.mPidsSelfLocked.put(app.pid, app);
1232 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001233 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 }
1235 } catch (PackageManager.NameNotFoundException e) {
1236 throw new RuntimeException(
1237 "Unable to find android system package", e);
1238 }
1239 }
1240
1241 public void setWindowManager(WindowManagerService wm) {
1242 mWindowManager = wm;
1243 }
1244
1245 public static final Context main(int factoryTest) {
1246 AThread thr = new AThread();
1247 thr.start();
1248
1249 synchronized (thr) {
1250 while (thr.mService == null) {
1251 try {
1252 thr.wait();
1253 } catch (InterruptedException e) {
1254 }
1255 }
1256 }
1257
1258 ActivityManagerService m = thr.mService;
1259 mSelf = m;
1260 ActivityThread at = ActivityThread.systemMain();
1261 mSystemThread = at;
1262 Context context = at.getSystemContext();
1263 m.mContext = context;
1264 m.mFactoryTest = factoryTest;
1265 PowerManager pm =
1266 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1267 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1268 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1269 m.mLaunchingActivity.setReferenceCounted(false);
1270
1271 m.mBatteryStatsService.publish(context);
1272 m.mUsageStatsService.publish(context);
1273
1274 synchronized (thr) {
1275 thr.mReady = true;
1276 thr.notifyAll();
1277 }
1278
1279 m.startRunning(null, null, null, null);
1280
1281 return context;
1282 }
1283
1284 public static ActivityManagerService self() {
1285 return mSelf;
1286 }
1287
1288 static class AThread extends Thread {
1289 ActivityManagerService mService;
1290 boolean mReady = false;
1291
1292 public AThread() {
1293 super("ActivityManager");
1294 }
1295
1296 public void run() {
1297 Looper.prepare();
1298
1299 android.os.Process.setThreadPriority(
1300 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1301
1302 ActivityManagerService m = new ActivityManagerService();
1303
1304 synchronized (this) {
1305 mService = m;
1306 notifyAll();
1307 }
1308
1309 synchronized (this) {
1310 while (!mReady) {
1311 try {
1312 wait();
1313 } catch (InterruptedException e) {
1314 }
1315 }
1316 }
1317
1318 Looper.loop();
1319 }
1320 }
1321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 static class MemBinder extends Binder {
1323 ActivityManagerService mActivityManagerService;
1324 MemBinder(ActivityManagerService activityManagerService) {
1325 mActivityManagerService = activityManagerService;
1326 }
1327
1328 @Override
1329 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1330 ActivityManagerService service = mActivityManagerService;
1331 ArrayList<ProcessRecord> procs;
1332 synchronized (mActivityManagerService) {
1333 if (args != null && args.length > 0
1334 && args[0].charAt(0) != '-') {
1335 procs = new ArrayList<ProcessRecord>();
1336 int pid = -1;
1337 try {
1338 pid = Integer.parseInt(args[0]);
1339 } catch (NumberFormatException e) {
1340
1341 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001342 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1343 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 if (proc.pid == pid) {
1345 procs.add(proc);
1346 } else if (proc.processName.equals(args[0])) {
1347 procs.add(proc);
1348 }
1349 }
1350 if (procs.size() <= 0) {
1351 pw.println("No process found for: " + args[0]);
1352 return;
1353 }
1354 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001355 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 }
1357 }
1358 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1359 }
1360 }
1361
1362 static class CpuBinder extends Binder {
1363 ActivityManagerService mActivityManagerService;
1364 CpuBinder(ActivityManagerService activityManagerService) {
1365 mActivityManagerService = activityManagerService;
1366 }
1367
1368 @Override
1369 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1370 synchronized (mActivityManagerService.mProcessStatsThread) {
1371 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1372 }
1373 }
1374 }
1375
1376 private ActivityManagerService() {
1377 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1378 if (v != null && Integer.getInteger(v) != 0) {
1379 mSimpleProcessManagement = true;
1380 }
1381 v = System.getenv("ANDROID_DEBUG_APP");
1382 if (v != null) {
1383 mSimpleProcessManagement = true;
1384 }
1385
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001386 Log.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
1387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 File dataDir = Environment.getDataDirectory();
1389 File systemDir = new File(dataDir, "system");
1390 systemDir.mkdirs();
1391 mBatteryStatsService = new BatteryStatsService(new File(
1392 systemDir, "batterystats.bin").toString());
1393 mBatteryStatsService.getActiveStatistics().readLocked();
1394 mBatteryStatsService.getActiveStatistics().writeLocked();
1395
1396 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001397 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398
Jack Palevichb90d28c2009-07-22 15:35:24 -07001399 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1400 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 mConfiguration.makeDefault();
1403 mProcessStats.init();
1404
1405 // Add ourself to the Watchdog monitors.
1406 Watchdog.getInstance().addMonitor(this);
1407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 mProcessStatsThread = new Thread("ProcessStats") {
1409 public void run() {
1410 while (true) {
1411 try {
1412 try {
1413 synchronized(this) {
1414 final long now = SystemClock.uptimeMillis();
1415 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1416 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
1417 //Log.i(TAG, "Cpu delay=" + nextCpuDelay
1418 // + ", write delay=" + nextWriteDelay);
1419 if (nextWriteDelay < nextCpuDelay) {
1420 nextCpuDelay = nextWriteDelay;
1421 }
1422 if (nextCpuDelay > 0) {
1423 this.wait(nextCpuDelay);
1424 }
1425 }
1426 } catch (InterruptedException e) {
1427 }
1428
1429 updateCpuStatsNow();
1430 } catch (Exception e) {
1431 Log.e(TAG, "Unexpected exception collecting process stats", e);
1432 }
1433 }
1434 }
1435 };
1436 mProcessStatsThread.start();
1437 }
1438
1439 @Override
1440 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1441 throws RemoteException {
1442 try {
1443 return super.onTransact(code, data, reply, flags);
1444 } catch (RuntimeException e) {
1445 // The activity manager only throws security exceptions, so let's
1446 // log all others.
1447 if (!(e instanceof SecurityException)) {
1448 Log.e(TAG, "Activity Manager Crash", e);
1449 }
1450 throw e;
1451 }
1452 }
1453
1454 void updateCpuStats() {
1455 synchronized (mProcessStatsThread) {
1456 final long now = SystemClock.uptimeMillis();
1457 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1458 mProcessStatsThread.notify();
1459 }
1460 }
1461 }
1462
1463 void updateCpuStatsNow() {
1464 synchronized (mProcessStatsThread) {
1465 final long now = SystemClock.uptimeMillis();
1466 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 if (MONITOR_CPU_USAGE &&
1469 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1470 mLastCpuTime = now;
1471 haveNewCpuStats = true;
1472 mProcessStats.update();
1473 //Log.i(TAG, mProcessStats.printCurrentState());
1474 //Log.i(TAG, "Total CPU usage: "
1475 // + mProcessStats.getTotalCpuPercent() + "%");
1476
1477 // Log the cpu usage if the property is set.
1478 if ("true".equals(SystemProperties.get("events.cpu"))) {
1479 int user = mProcessStats.getLastUserTime();
1480 int system = mProcessStats.getLastSystemTime();
1481 int iowait = mProcessStats.getLastIoWaitTime();
1482 int irq = mProcessStats.getLastIrqTime();
1483 int softIrq = mProcessStats.getLastSoftIrqTime();
1484 int idle = mProcessStats.getLastIdleTime();
1485
1486 int total = user + system + iowait + irq + softIrq + idle;
1487 if (total == 0) total = 1;
1488
Doug Zongker2bec3d42009-12-04 12:52:44 -08001489 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 ((user+system+iowait+irq+softIrq) * 100) / total,
1491 (user * 100) / total,
1492 (system * 100) / total,
1493 (iowait * 100) / total,
1494 (irq * 100) / total,
1495 (softIrq * 100) / total);
1496 }
1497 }
1498
Amith Yamasanie43530a2009-08-21 13:11:37 -07001499 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001500 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001501 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 synchronized(mPidsSelfLocked) {
1503 if (haveNewCpuStats) {
1504 if (mBatteryStatsService.isOnBattery()) {
1505 final int N = mProcessStats.countWorkingStats();
1506 for (int i=0; i<N; i++) {
1507 ProcessStats.Stats st
1508 = mProcessStats.getWorkingStats(i);
1509 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1510 if (pr != null) {
1511 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1512 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001513 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001514 } else {
1515 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001516 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001517 if (ps != null) {
1518 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001519 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 }
1522 }
1523 }
1524 }
1525 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1528 mLastWriteTime = now;
1529 mBatteryStatsService.getActiveStatistics().writeLocked();
1530 }
1531 }
1532 }
1533 }
1534
1535 /**
1536 * Initialize the application bind args. These are passed to each
1537 * process when the bindApplication() IPC is sent to the process. They're
1538 * lazily setup to make sure the services are running when they're asked for.
1539 */
1540 private HashMap<String, IBinder> getCommonServicesLocked() {
1541 if (mAppBindArgs == null) {
1542 mAppBindArgs = new HashMap<String, IBinder>();
1543
1544 // Setup the application init args
1545 mAppBindArgs.put("package", ServiceManager.getService("package"));
1546 mAppBindArgs.put("window", ServiceManager.getService("window"));
1547 mAppBindArgs.put(Context.ALARM_SERVICE,
1548 ServiceManager.getService(Context.ALARM_SERVICE));
1549 }
1550 return mAppBindArgs;
1551 }
1552
1553 private final void setFocusedActivityLocked(HistoryRecord r) {
1554 if (mFocusedActivity != r) {
1555 mFocusedActivity = r;
1556 mWindowManager.setFocusedApp(r, true);
1557 }
1558 }
1559
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001560 private final void updateLruProcessLocked(ProcessRecord app,
1561 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001563 int lrui = mLruProcesses.indexOf(app);
1564 if (lrui >= 0) mLruProcesses.remove(lrui);
1565
1566 int i = mLruProcesses.size()-1;
1567 int skipTop = 0;
1568
1569 // compute the new weight for this process.
1570 if (updateActivityTime) {
1571 app.lastActivityTime = SystemClock.uptimeMillis();
1572 }
1573 if (app.activities.size() > 0) {
1574 // If this process has activities, we more strongly want to keep
1575 // it around.
1576 app.lruWeight = app.lastActivityTime;
1577 } else if (app.pubProviders.size() > 0) {
1578 // If this process contains content providers, we want to keep
1579 // it a little more strongly.
1580 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1581 // Also don't let it kick out the first few "real" hidden processes.
1582 skipTop = MIN_HIDDEN_APPS;
1583 } else {
1584 // If this process doesn't have activities, we less strongly
1585 // want to keep it around, and generally want to avoid getting
1586 // in front of any very recently used activities.
1587 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1588 // Also don't let it kick out the first few "real" hidden processes.
1589 skipTop = MIN_HIDDEN_APPS;
1590 }
1591 while (i >= 0) {
1592 ProcessRecord p = mLruProcesses.get(i);
1593 // If this app shouldn't be in front of the first N background
1594 // apps, then skip over that many that are currently hidden.
1595 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1596 skipTop--;
1597 }
1598 if (p.lruWeight <= app.lruWeight){
1599 mLruProcesses.add(i+1, app);
1600 break;
1601 }
1602 i--;
1603 }
1604 if (i < 0) {
1605 mLruProcesses.add(0, app);
1606 }
1607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 //Log.i(TAG, "Putting proc to front: " + app.processName);
1609 if (oomAdj) {
1610 updateOomAdjLocked();
1611 }
1612 }
1613
1614 private final boolean updateLRUListLocked(HistoryRecord r) {
1615 final boolean hadit = mLRUActivities.remove(r);
1616 mLRUActivities.add(r);
1617 return hadit;
1618 }
1619
1620 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1621 int i = mHistory.size()-1;
1622 while (i >= 0) {
1623 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1624 if (!r.finishing && r != notTop) {
1625 return r;
1626 }
1627 i--;
1628 }
1629 return null;
1630 }
1631
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001632 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1633 int i = mHistory.size()-1;
1634 while (i >= 0) {
1635 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1636 if (!r.finishing && !r.delayedResume && r != notTop) {
1637 return r;
1638 }
1639 i--;
1640 }
1641 return null;
1642 }
1643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 /**
1645 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001646 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 *
1648 * @param token If non-null, any history records matching this token will be skipped.
1649 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1650 *
1651 * @return Returns the HistoryRecord of the next activity on the stack.
1652 */
1653 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1654 int i = mHistory.size()-1;
1655 while (i >= 0) {
1656 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1657 // Note: the taskId check depends on real taskId fields being non-zero
1658 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1659 return r;
1660 }
1661 i--;
1662 }
1663 return null;
1664 }
1665
1666 private final ProcessRecord getProcessRecordLocked(
1667 String processName, int uid) {
1668 if (uid == Process.SYSTEM_UID) {
1669 // The system gets to run in any process. If there are multiple
1670 // processes with the same uid, just pick the first (this
1671 // should never happen).
1672 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1673 processName);
1674 return procs != null ? procs.valueAt(0) : null;
1675 }
1676 ProcessRecord proc = mProcessNames.get(processName, uid);
1677 return proc;
1678 }
1679
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001680 private void ensurePackageDexOpt(String packageName) {
1681 IPackageManager pm = ActivityThread.getPackageManager();
1682 try {
1683 if (pm.performDexOpt(packageName)) {
1684 mDidDexOpt = true;
1685 }
1686 } catch (RemoteException e) {
1687 }
1688 }
1689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 private boolean isNextTransitionForward() {
1691 int transit = mWindowManager.getPendingAppTransition();
1692 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1693 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1694 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1695 }
1696
1697 private final boolean realStartActivityLocked(HistoryRecord r,
1698 ProcessRecord app, boolean andResume, boolean checkConfig)
1699 throws RemoteException {
1700
1701 r.startFreezingScreenLocked(app, 0);
1702 mWindowManager.setAppVisibility(r, true);
1703
1704 // Have the window manager re-evaluate the orientation of
1705 // the screen based on the new activity order. Note that
1706 // as a result of this, it can call back into the activity
1707 // manager with a new orientation. We don't care about that,
1708 // because the activity is not currently running so we are
1709 // just restarting it anyway.
1710 if (checkConfig) {
1711 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001712 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 r.mayFreezeScreenLocked(app) ? r : null);
1714 updateConfigurationLocked(config, r);
1715 }
1716
1717 r.app = app;
1718
1719 if (localLOGV) Log.v(TAG, "Launching: " + r);
1720
1721 int idx = app.activities.indexOf(r);
1722 if (idx < 0) {
1723 app.activities.add(r);
1724 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001725 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726
1727 try {
1728 if (app.thread == null) {
1729 throw new RemoteException();
1730 }
1731 List<ResultInfo> results = null;
1732 List<Intent> newIntents = null;
1733 if (andResume) {
1734 results = r.results;
1735 newIntents = r.newIntents;
1736 }
1737 if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
1738 + " icicle=" + r.icicle
1739 + " with results=" + results + " newIntents=" + newIntents
1740 + " andResume=" + andResume);
1741 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001742 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 System.identityHashCode(r),
1744 r.task.taskId, r.shortComponentName);
1745 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001746 if (r.isHomeActivity) {
1747 mHomeProcess = app;
1748 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001749 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001751 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 r.info, r.icicle, results, newIntents, !andResume,
1753 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 } catch (RemoteException e) {
1755 if (r.launchFailed) {
1756 // This is the second time we failed -- finish activity
1757 // and give up.
1758 Log.e(TAG, "Second failure launching "
1759 + r.intent.getComponent().flattenToShortString()
1760 + ", giving up", e);
1761 appDiedLocked(app, app.pid, app.thread);
1762 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1763 "2nd-crash");
1764 return false;
1765 }
1766
1767 // This is the first time we failed -- restart process and
1768 // retry.
1769 app.activities.remove(r);
1770 throw e;
1771 }
1772
1773 r.launchFailed = false;
1774 if (updateLRUListLocked(r)) {
1775 Log.w(TAG, "Activity " + r
1776 + " being launched, but already in LRU list");
1777 }
1778
1779 if (andResume) {
1780 // As part of the process of launching, ActivityThread also performs
1781 // a resume.
1782 r.state = ActivityState.RESUMED;
1783 r.icicle = null;
1784 r.haveState = false;
1785 r.stopped = false;
1786 mResumedActivity = r;
1787 r.task.touchActiveTime();
1788 completeResumeLocked(r);
1789 pauseIfSleepingLocked();
1790 } else {
1791 // This activity is not starting in the resumed state... which
1792 // should look like we asked it to pause+stop (but remain visible),
1793 // and it has done so and reported back the current icicle and
1794 // other state.
1795 r.state = ActivityState.STOPPED;
1796 r.stopped = true;
1797 }
1798
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001799 // Launch the new version setup screen if needed. We do this -after-
1800 // launching the initial activity (that is, home), so that it can have
1801 // a chance to initialize itself while in the background, making the
1802 // switch back to it faster and look better.
1803 startSetupActivityLocked();
1804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 return true;
1806 }
1807
1808 private final void startSpecificActivityLocked(HistoryRecord r,
1809 boolean andResume, boolean checkConfig) {
1810 // Is this activity's application already running?
1811 ProcessRecord app = getProcessRecordLocked(r.processName,
1812 r.info.applicationInfo.uid);
1813
1814 if (r.startTime == 0) {
1815 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001816 if (mInitialStartTime == 0) {
1817 mInitialStartTime = r.startTime;
1818 }
1819 } else if (mInitialStartTime == 0) {
1820 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 }
1822
1823 if (app != null && app.thread != null) {
1824 try {
1825 realStartActivityLocked(r, app, andResume, checkConfig);
1826 return;
1827 } catch (RemoteException e) {
1828 Log.w(TAG, "Exception when starting activity "
1829 + r.intent.getComponent().flattenToShortString(), e);
1830 }
1831
1832 // If a dead object exception was thrown -- fall through to
1833 // restart the application.
1834 }
1835
1836 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001837 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 }
1839
1840 private final ProcessRecord startProcessLocked(String processName,
1841 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001842 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1844 // We don't have to do anything more if:
1845 // (1) There is an existing application record; and
1846 // (2) The caller doesn't think it is dead, OR there is no thread
1847 // object attached to it so we know it couldn't have crashed; and
1848 // (3) There is a pid assigned to it, so it is either starting or
1849 // already running.
1850 if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
1851 + " app=" + app + " knownToBeDead=" + knownToBeDead
1852 + " thread=" + (app != null ? app.thread : null)
1853 + " pid=" + (app != null ? app.pid : -1));
1854 if (app != null &&
1855 (!knownToBeDead || app.thread == null) && app.pid > 0) {
1856 return app;
1857 }
1858
1859 String hostingNameStr = hostingName != null
1860 ? hostingName.flattenToShortString() : null;
1861
1862 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1863 // If we are in the background, then check to see if this process
1864 // is bad. If so, we will just silently fail.
1865 if (mBadProcesses.get(info.processName, info.uid) != null) {
1866 return null;
1867 }
1868 } else {
1869 // When the user is explicitly starting a process, then clear its
1870 // crash count so that we won't make it bad until they see at
1871 // least one crash dialog again, and make the process good again
1872 // if it had been bad.
1873 mProcessCrashTimes.remove(info.processName, info.uid);
1874 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001875 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 info.processName);
1877 mBadProcesses.remove(info.processName, info.uid);
1878 if (app != null) {
1879 app.bad = false;
1880 }
1881 }
1882 }
1883
1884 if (app == null) {
1885 app = newProcessRecordLocked(null, info, processName);
1886 mProcessNames.put(processName, info.uid, app);
1887 } else {
1888 // If this is a new package in the process, add the package to the list
1889 app.addPackage(info.packageName);
1890 }
1891
1892 // If the system is not ready yet, then hold off on starting this
1893 // process until it is.
1894 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001895 && !isAllowedWhileBooting(info)
1896 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 if (!mProcessesOnHold.contains(app)) {
1898 mProcessesOnHold.add(app);
1899 }
1900 return app;
1901 }
1902
1903 startProcessLocked(app, hostingType, hostingNameStr);
1904 return (app.pid != 0) ? app : null;
1905 }
1906
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001907 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1908 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1909 }
1910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 private final void startProcessLocked(ProcessRecord app,
1912 String hostingType, String hostingNameStr) {
1913 if (app.pid > 0 && app.pid != MY_PID) {
1914 synchronized (mPidsSelfLocked) {
1915 mPidsSelfLocked.remove(app.pid);
1916 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1917 }
1918 app.pid = 0;
1919 }
1920
1921 mProcessesOnHold.remove(app);
1922
1923 updateCpuStats();
1924
1925 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1926 mProcDeaths[0] = 0;
1927
1928 try {
1929 int uid = app.info.uid;
1930 int[] gids = null;
1931 try {
1932 gids = mContext.getPackageManager().getPackageGids(
1933 app.info.packageName);
1934 } catch (PackageManager.NameNotFoundException e) {
1935 Log.w(TAG, "Unable to retrieve gids", e);
1936 }
1937 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1938 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1939 && mTopComponent != null
1940 && app.processName.equals(mTopComponent.getPackageName())) {
1941 uid = 0;
1942 }
1943 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1944 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1945 uid = 0;
1946 }
1947 }
1948 int debugFlags = 0;
1949 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1950 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1951 }
Ben Cheng23085b72010-02-08 16:06:32 -08001952 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0) {
1953 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1956 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1957 }
1958 if ("1".equals(SystemProperties.get("debug.assert"))) {
1959 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1960 }
1961 int pid = Process.start("android.app.ActivityThread",
1962 mSimpleProcessManagement ? app.processName : null, uid, uid,
1963 gids, debugFlags, null);
1964 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1965 synchronized (bs) {
1966 if (bs.isOnBattery()) {
1967 app.batteryStats.incStartsLocked();
1968 }
1969 }
1970
Doug Zongker2bec3d42009-12-04 12:52:44 -08001971 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 app.processName, hostingType,
1973 hostingNameStr != null ? hostingNameStr : "");
1974
1975 if (app.persistent) {
1976 Watchdog.getInstance().processStarted(app, app.processName, pid);
1977 }
1978
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001979 StringBuilder buf = mStringBuilder;
1980 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 buf.append("Start proc ");
1982 buf.append(app.processName);
1983 buf.append(" for ");
1984 buf.append(hostingType);
1985 if (hostingNameStr != null) {
1986 buf.append(" ");
1987 buf.append(hostingNameStr);
1988 }
1989 buf.append(": pid=");
1990 buf.append(pid);
1991 buf.append(" uid=");
1992 buf.append(uid);
1993 buf.append(" gids={");
1994 if (gids != null) {
1995 for (int gi=0; gi<gids.length; gi++) {
1996 if (gi != 0) buf.append(", ");
1997 buf.append(gids[gi]);
1998
1999 }
2000 }
2001 buf.append("}");
2002 Log.i(TAG, buf.toString());
2003 if (pid == 0 || pid == MY_PID) {
2004 // Processes are being emulated with threads.
2005 app.pid = MY_PID;
2006 app.removed = false;
2007 mStartingProcesses.add(app);
2008 } else if (pid > 0) {
2009 app.pid = pid;
2010 app.removed = false;
2011 synchronized (mPidsSelfLocked) {
2012 this.mPidsSelfLocked.put(pid, app);
2013 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2014 msg.obj = app;
2015 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2016 }
2017 } else {
2018 app.pid = 0;
2019 RuntimeException e = new RuntimeException(
2020 "Failure starting process " + app.processName
2021 + ": returned pid=" + pid);
2022 Log.e(TAG, e.getMessage(), e);
2023 }
2024 } catch (RuntimeException e) {
2025 // XXX do better error recovery.
2026 app.pid = 0;
2027 Log.e(TAG, "Failure starting process " + app.processName, e);
2028 }
2029 }
2030
2031 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2032 if (mPausingActivity != null) {
2033 RuntimeException e = new RuntimeException();
2034 Log.e(TAG, "Trying to pause when pause is already pending for "
2035 + mPausingActivity, e);
2036 }
2037 HistoryRecord prev = mResumedActivity;
2038 if (prev == null) {
2039 RuntimeException e = new RuntimeException();
2040 Log.e(TAG, "Trying to pause when nothing is resumed", e);
2041 resumeTopActivityLocked(null);
2042 return;
2043 }
2044 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
2045 mResumedActivity = null;
2046 mPausingActivity = prev;
2047 mLastPausedActivity = prev;
2048 prev.state = ActivityState.PAUSING;
2049 prev.task.touchActiveTime();
2050
2051 updateCpuStats();
2052
2053 if (prev.app != null && prev.app.thread != null) {
2054 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
2055 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002056 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 System.identityHashCode(prev),
2058 prev.shortComponentName);
2059 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2060 prev.configChangeFlags);
2061 updateUsageStats(prev, false);
2062 } catch (Exception e) {
2063 // Ignore exception, if process died other code will cleanup.
2064 Log.w(TAG, "Exception thrown during pause", e);
2065 mPausingActivity = null;
2066 mLastPausedActivity = null;
2067 }
2068 } else {
2069 mPausingActivity = null;
2070 mLastPausedActivity = null;
2071 }
2072
2073 // If we are not going to sleep, we want to ensure the device is
2074 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002075 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 mLaunchingActivity.acquire();
2077 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2078 // To be safe, don't allow the wake lock to be held for too long.
2079 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2080 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2081 }
2082 }
2083
2084
2085 if (mPausingActivity != null) {
2086 // Have the window manager pause its key dispatching until the new
2087 // activity has started. If we're pausing the activity just because
2088 // the screen is being turned off and the UI is sleeping, don't interrupt
2089 // key dispatch; the same activity will pick it up again on wakeup.
2090 if (!uiSleeping) {
2091 prev.pauseKeyDispatchingLocked();
2092 } else {
2093 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
2094 }
2095
2096 // Schedule a pause timeout in case the app doesn't respond.
2097 // We don't give it much time because this directly impacts the
2098 // responsiveness seen by the user.
2099 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2100 msg.obj = prev;
2101 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
2102 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
2103 } else {
2104 // This activity failed to schedule the
2105 // pause, so just treat it as being paused now.
2106 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
2107 resumeTopActivityLocked(null);
2108 }
2109 }
2110
2111 private final void completePauseLocked() {
2112 HistoryRecord prev = mPausingActivity;
2113 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
2114
2115 if (prev != null) {
2116 if (prev.finishing) {
2117 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
2118 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2119 } else if (prev.app != null) {
2120 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
2121 if (prev.waitingVisible) {
2122 prev.waitingVisible = false;
2123 mWaitingVisibleActivities.remove(prev);
2124 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
2125 TAG, "Complete pause, no longer waiting: " + prev);
2126 }
2127 if (prev.configDestroy) {
2128 // The previous is being paused because the configuration
2129 // is changing, which means it is actually stopping...
2130 // To juggle the fact that we are also starting a new
2131 // instance right now, we need to first completely stop
2132 // the current instance before starting the new one.
2133 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
2134 destroyActivityLocked(prev, true);
2135 } else {
2136 mStoppingActivities.add(prev);
2137 if (mStoppingActivities.size() > 3) {
2138 // If we already have a few activities waiting to stop,
2139 // then give up on things going idle and start clearing
2140 // them out.
2141 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
2142 Message msg = Message.obtain();
2143 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2144 mHandler.sendMessage(msg);
2145 }
2146 }
2147 } else {
2148 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
2149 prev = null;
2150 }
2151 mPausingActivity = null;
2152 }
2153
Dianne Hackborn55280a92009-05-07 15:53:46 -07002154 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 resumeTopActivityLocked(prev);
2156 } else {
2157 if (mGoingToSleep.isHeld()) {
2158 mGoingToSleep.release();
2159 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002160 if (mShuttingDown) {
2161 notifyAll();
2162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 }
2164
2165 if (prev != null) {
2166 prev.resumeKeyDispatchingLocked();
2167 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002168
2169 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2170 long diff = 0;
2171 synchronized (mProcessStatsThread) {
2172 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2173 }
2174 if (diff > 0) {
2175 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2176 synchronized (bsi) {
2177 BatteryStatsImpl.Uid.Proc ps =
2178 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2179 prev.info.packageName);
2180 if (ps != null) {
2181 ps.addForegroundTimeLocked(diff);
2182 }
2183 }
2184 }
2185 }
2186 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 }
2188
2189 /**
2190 * Once we know that we have asked an application to put an activity in
2191 * the resumed state (either by launching it or explicitly telling it),
2192 * this function updates the rest of our state to match that fact.
2193 */
2194 private final void completeResumeLocked(HistoryRecord next) {
2195 next.idle = false;
2196 next.results = null;
2197 next.newIntents = null;
2198
2199 // schedule an idle timeout in case the app doesn't do it for us.
2200 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2201 msg.obj = next;
2202 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2203
2204 if (false) {
2205 // The activity was never told to pause, so just keep
2206 // things going as-is. To maintain our own state,
2207 // we need to emulate it coming back and saying it is
2208 // idle.
2209 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2210 msg.obj = next;
2211 mHandler.sendMessage(msg);
2212 }
2213
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002214 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 next.thumbnail = null;
2217 setFocusedActivityLocked(next);
2218 next.resumeKeyDispatchingLocked();
2219 ensureActivitiesVisibleLocked(null, 0);
2220 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002221 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002222
2223 // Mark the point when the activity is resuming
2224 // TODO: To be more accurate, the mark should be before the onCreate,
2225 // not after the onResume. But for subsequent starts, onResume is fine.
2226 if (next.app != null) {
2227 synchronized (mProcessStatsThread) {
2228 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2229 }
2230 } else {
2231 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 }
2234
2235 /**
2236 * Make sure that all activities that need to be visible (that is, they
2237 * currently can be seen by the user) actually are.
2238 */
2239 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2240 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2241 if (DEBUG_VISBILITY) Log.v(
2242 TAG, "ensureActivitiesVisible behind " + top
2243 + " configChanges=0x" + Integer.toHexString(configChanges));
2244
2245 // If the top activity is not fullscreen, then we need to
2246 // make sure any activities under it are now visible.
2247 final int count = mHistory.size();
2248 int i = count-1;
2249 while (mHistory.get(i) != top) {
2250 i--;
2251 }
2252 HistoryRecord r;
2253 boolean behindFullscreen = false;
2254 for (; i>=0; i--) {
2255 r = (HistoryRecord)mHistory.get(i);
2256 if (DEBUG_VISBILITY) Log.v(
2257 TAG, "Make visible? " + r + " finishing=" + r.finishing
2258 + " state=" + r.state);
2259 if (r.finishing) {
2260 continue;
2261 }
2262
2263 final boolean doThisProcess = onlyThisProcess == null
2264 || onlyThisProcess.equals(r.processName);
2265
2266 // First: if this is not the current activity being started, make
2267 // sure it matches the current configuration.
2268 if (r != starting && doThisProcess) {
2269 ensureActivityConfigurationLocked(r, 0);
2270 }
2271
2272 if (r.app == null || r.app.thread == null) {
2273 if (onlyThisProcess == null
2274 || onlyThisProcess.equals(r.processName)) {
2275 // This activity needs to be visible, but isn't even
2276 // running... get it started, but don't resume it
2277 // at this point.
2278 if (DEBUG_VISBILITY) Log.v(
2279 TAG, "Start and freeze screen for " + r);
2280 if (r != starting) {
2281 r.startFreezingScreenLocked(r.app, configChanges);
2282 }
2283 if (!r.visible) {
2284 if (DEBUG_VISBILITY) Log.v(
2285 TAG, "Starting and making visible: " + r);
2286 mWindowManager.setAppVisibility(r, true);
2287 }
2288 if (r != starting) {
2289 startSpecificActivityLocked(r, false, false);
2290 }
2291 }
2292
2293 } else if (r.visible) {
2294 // If this activity is already visible, then there is nothing
2295 // else to do here.
2296 if (DEBUG_VISBILITY) Log.v(
2297 TAG, "Skipping: already visible at " + r);
2298 r.stopFreezingScreenLocked(false);
2299
2300 } else if (onlyThisProcess == null) {
2301 // This activity is not currently visible, but is running.
2302 // Tell it to become visible.
2303 r.visible = true;
2304 if (r.state != ActivityState.RESUMED && r != starting) {
2305 // If this activity is paused, tell it
2306 // to now show its window.
2307 if (DEBUG_VISBILITY) Log.v(
2308 TAG, "Making visible and scheduling visibility: " + r);
2309 try {
2310 mWindowManager.setAppVisibility(r, true);
2311 r.app.thread.scheduleWindowVisibility(r, true);
2312 r.stopFreezingScreenLocked(false);
2313 } catch (Exception e) {
2314 // Just skip on any failure; we'll make it
2315 // visible when it next restarts.
2316 Log.w(TAG, "Exception thrown making visibile: "
2317 + r.intent.getComponent(), e);
2318 }
2319 }
2320 }
2321
2322 // Aggregate current change flags.
2323 configChanges |= r.configChangeFlags;
2324
2325 if (r.fullscreen) {
2326 // At this point, nothing else needs to be shown
2327 if (DEBUG_VISBILITY) Log.v(
2328 TAG, "Stopping: fullscreen at " + r);
2329 behindFullscreen = true;
2330 i--;
2331 break;
2332 }
2333 }
2334
2335 // Now for any activities that aren't visible to the user, make
2336 // sure they no longer are keeping the screen frozen.
2337 while (i >= 0) {
2338 r = (HistoryRecord)mHistory.get(i);
2339 if (DEBUG_VISBILITY) Log.v(
2340 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2341 + " state=" + r.state
2342 + " behindFullscreen=" + behindFullscreen);
2343 if (!r.finishing) {
2344 if (behindFullscreen) {
2345 if (r.visible) {
2346 if (DEBUG_VISBILITY) Log.v(
2347 TAG, "Making invisible: " + r);
2348 r.visible = false;
2349 try {
2350 mWindowManager.setAppVisibility(r, false);
2351 if ((r.state == ActivityState.STOPPING
2352 || r.state == ActivityState.STOPPED)
2353 && r.app != null && r.app.thread != null) {
2354 if (DEBUG_VISBILITY) Log.v(
2355 TAG, "Scheduling invisibility: " + r);
2356 r.app.thread.scheduleWindowVisibility(r, false);
2357 }
2358 } catch (Exception e) {
2359 // Just skip on any failure; we'll make it
2360 // visible when it next restarts.
2361 Log.w(TAG, "Exception thrown making hidden: "
2362 + r.intent.getComponent(), e);
2363 }
2364 } else {
2365 if (DEBUG_VISBILITY) Log.v(
2366 TAG, "Already invisible: " + r);
2367 }
2368 } else if (r.fullscreen) {
2369 if (DEBUG_VISBILITY) Log.v(
2370 TAG, "Now behindFullscreen: " + r);
2371 behindFullscreen = true;
2372 }
2373 }
2374 i--;
2375 }
2376 }
2377
2378 /**
2379 * Version of ensureActivitiesVisible that can easily be called anywhere.
2380 */
2381 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2382 int configChanges) {
2383 HistoryRecord r = topRunningActivityLocked(null);
2384 if (r != null) {
2385 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2386 }
2387 }
2388
2389 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2390 if (resumed) {
2391 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2392 } else {
2393 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2394 }
2395 }
2396
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002397 private boolean startHomeActivityLocked() {
2398 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2399 && mTopAction == null) {
2400 // We are running in factory test mode, but unable to find
2401 // the factory test app, so just sit around displaying the
2402 // error message and don't try to start anything.
2403 return false;
2404 }
2405 Intent intent = new Intent(
2406 mTopAction,
2407 mTopData != null ? Uri.parse(mTopData) : null);
2408 intent.setComponent(mTopComponent);
2409 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2410 intent.addCategory(Intent.CATEGORY_HOME);
2411 }
2412 ActivityInfo aInfo =
2413 intent.resolveActivityInfo(mContext.getPackageManager(),
2414 STOCK_PM_FLAGS);
2415 if (aInfo != null) {
2416 intent.setComponent(new ComponentName(
2417 aInfo.applicationInfo.packageName, aInfo.name));
2418 // Don't do this if the home app is currently being
2419 // instrumented.
2420 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2421 aInfo.applicationInfo.uid);
2422 if (app == null || app.instrumentationClass == null) {
2423 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2424 startActivityLocked(null, intent, null, null, 0, aInfo,
2425 null, null, 0, 0, 0, false, false);
2426 }
2427 }
2428
2429
2430 return true;
2431 }
2432
2433 /**
2434 * Starts the "new version setup screen" if appropriate.
2435 */
2436 private void startSetupActivityLocked() {
2437 // Only do this once per boot.
2438 if (mCheckedForSetup) {
2439 return;
2440 }
2441
2442 // We will show this screen if the current one is a different
2443 // version than the last one shown, and we are not running in
2444 // low-level factory test mode.
2445 final ContentResolver resolver = mContext.getContentResolver();
2446 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2447 Settings.Secure.getInt(resolver,
2448 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2449 mCheckedForSetup = true;
2450
2451 // See if we should be showing the platform update setup UI.
2452 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2453 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2454 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2455
2456 // We don't allow third party apps to replace this.
2457 ResolveInfo ri = null;
2458 for (int i=0; ris != null && i<ris.size(); i++) {
2459 if ((ris.get(i).activityInfo.applicationInfo.flags
2460 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2461 ri = ris.get(i);
2462 break;
2463 }
2464 }
2465
2466 if (ri != null) {
2467 String vers = ri.activityInfo.metaData != null
2468 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2469 : null;
2470 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2471 vers = ri.activityInfo.applicationInfo.metaData.getString(
2472 Intent.METADATA_SETUP_VERSION);
2473 }
2474 String lastVers = Settings.Secure.getString(
2475 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2476 if (vers != null && !vers.equals(lastVers)) {
2477 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2478 intent.setComponent(new ComponentName(
2479 ri.activityInfo.packageName, ri.activityInfo.name));
2480 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2481 null, null, 0, 0, 0, false, false);
2482 }
2483 }
2484 }
2485 }
2486
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002487 private void reportResumedActivityLocked(HistoryRecord r) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002488 //Log.i(TAG, "**** REPORT RESUME: " + r);
2489
2490 final int identHash = System.identityHashCode(r);
2491 updateUsageStats(r, true);
2492
2493 int i = mWatchers.beginBroadcast();
2494 while (i > 0) {
2495 i--;
2496 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2497 if (w != null) {
2498 try {
2499 w.activityResuming(identHash);
2500 } catch (RemoteException e) {
2501 }
2502 }
2503 }
2504 mWatchers.finishBroadcast();
2505 }
2506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 /**
2508 * Ensure that the top activity in the stack is resumed.
2509 *
2510 * @param prev The previously resumed activity, for when in the process
2511 * of pausing; can be null to call from elsewhere.
2512 *
2513 * @return Returns true if something is being resumed, or false if
2514 * nothing happened.
2515 */
2516 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2517 // Find the first activity that is not finishing.
2518 HistoryRecord next = topRunningActivityLocked(null);
2519
2520 // Remember how we'll process this pause/resume situation, and ensure
2521 // that the state is reset however we wind up proceeding.
2522 final boolean userLeaving = mUserLeaving;
2523 mUserLeaving = false;
2524
2525 if (next == null) {
2526 // There are no more activities! Let's just start up the
2527 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002528 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 }
2530
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002531 next.delayedResume = false;
2532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 // If the top activity is the resumed one, nothing to do.
2534 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2535 // Make sure we have executed any pending transitions, since there
2536 // should be nothing left to do at this point.
2537 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002538 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 return false;
2540 }
2541
2542 // If we are sleeping, and there is no resumed activity, and the top
2543 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002544 if ((mSleeping || mShuttingDown)
2545 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 // Make sure we have executed any pending transitions, since there
2547 // should be nothing left to do at this point.
2548 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002549 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 return false;
2551 }
2552
2553 // The activity may be waiting for stop, but that is no longer
2554 // appropriate for it.
2555 mStoppingActivities.remove(next);
2556 mWaitingVisibleActivities.remove(next);
2557
2558 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2559
2560 // If we are currently pausing an activity, then don't do anything
2561 // until that is done.
2562 if (mPausingActivity != null) {
2563 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2564 return false;
2565 }
2566
2567 // We need to start pausing the current activity so the top one
2568 // can be resumed...
2569 if (mResumedActivity != null) {
2570 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2571 startPausingLocked(userLeaving, false);
2572 return true;
2573 }
2574
2575 if (prev != null && prev != next) {
2576 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2577 prev.waitingVisible = true;
2578 mWaitingVisibleActivities.add(prev);
2579 if (DEBUG_SWITCH) Log.v(
2580 TAG, "Resuming top, waiting visible to hide: " + prev);
2581 } else {
2582 // The next activity is already visible, so hide the previous
2583 // activity's windows right now so we can show the new one ASAP.
2584 // We only do this if the previous is finishing, which should mean
2585 // it is on top of the one being resumed so hiding it quickly
2586 // is good. Otherwise, we want to do the normal route of allowing
2587 // the resumed activity to be shown so we can decide if the
2588 // previous should actually be hidden depending on whether the
2589 // new one is found to be full-screen or not.
2590 if (prev.finishing) {
2591 mWindowManager.setAppVisibility(prev, false);
2592 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2593 + prev + ", waitingVisible="
2594 + (prev != null ? prev.waitingVisible : null)
2595 + ", nowVisible=" + next.nowVisible);
2596 } else {
2597 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2598 + prev + ", waitingVisible="
2599 + (prev != null ? prev.waitingVisible : null)
2600 + ", nowVisible=" + next.nowVisible);
2601 }
2602 }
2603 }
2604
2605 // We are starting up the next activity, so tell the window manager
2606 // that the previous one will be hidden soon. This way it can know
2607 // to ignore it when computing the desired screen orientation.
2608 if (prev != null) {
2609 if (prev.finishing) {
2610 if (DEBUG_TRANSITION) Log.v(TAG,
2611 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002612 if (mNoAnimActivities.contains(prev)) {
2613 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2614 } else {
2615 mWindowManager.prepareAppTransition(prev.task == next.task
2616 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2617 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 mWindowManager.setAppWillBeHidden(prev);
2620 mWindowManager.setAppVisibility(prev, false);
2621 } else {
2622 if (DEBUG_TRANSITION) Log.v(TAG,
2623 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002624 if (mNoAnimActivities.contains(next)) {
2625 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2626 } else {
2627 mWindowManager.prepareAppTransition(prev.task == next.task
2628 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2629 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 }
2632 if (false) {
2633 mWindowManager.setAppWillBeHidden(prev);
2634 mWindowManager.setAppVisibility(prev, false);
2635 }
2636 } else if (mHistory.size() > 1) {
2637 if (DEBUG_TRANSITION) Log.v(TAG,
2638 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002639 if (mNoAnimActivities.contains(next)) {
2640 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2641 } else {
2642 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 }
2645
2646 if (next.app != null && next.app.thread != null) {
2647 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2648
2649 // This activity is now becoming visible.
2650 mWindowManager.setAppVisibility(next, true);
2651
2652 HistoryRecord lastResumedActivity = mResumedActivity;
2653 ActivityState lastState = next.state;
2654
2655 updateCpuStats();
2656
2657 next.state = ActivityState.RESUMED;
2658 mResumedActivity = next;
2659 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002660 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 updateLRUListLocked(next);
2662
2663 // Have the window manager re-evaluate the orientation of
2664 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002665 boolean updated;
2666 synchronized (this) {
2667 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2668 mConfiguration,
2669 next.mayFreezeScreenLocked(next.app) ? next : null);
2670 if (config != null) {
2671 /*
2672 * Explicitly restore the locale to the one from the
2673 * old configuration, since the one that comes back from
2674 * the window manager has the default (boot) locale.
2675 *
2676 * It looks like previously the locale picker only worked
2677 * by coincidence: usually it would do its setting of
2678 * the locale after the activity transition, so it didn't
2679 * matter that this lost it. With the synchronized
2680 * block now keeping them from happening at the same time,
2681 * this one always would happen second and undo what the
2682 * locale picker had just done.
2683 */
2684 config.locale = mConfiguration.locale;
2685 next.frozenBeforeDestroy = true;
2686 }
2687 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002689 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 // The configuration update wasn't able to keep the existing
2691 // instance of the activity, and instead started a new one.
2692 // We should be all done, but let's just make sure our activity
2693 // is still at the top and schedule another run if something
2694 // weird happened.
2695 HistoryRecord nextNext = topRunningActivityLocked(null);
2696 if (DEBUG_SWITCH) Log.i(TAG,
2697 "Activity config changed during resume: " + next
2698 + ", new next: " + nextNext);
2699 if (nextNext != next) {
2700 // Do over!
2701 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2702 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002703 setFocusedActivityLocked(next);
2704 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002706 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 return true;
2708 }
2709
2710 try {
2711 // Deliver all pending results.
2712 ArrayList a = next.results;
2713 if (a != null) {
2714 final int N = a.size();
2715 if (!next.finishing && N > 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002716 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 TAG, "Delivering results to " + next
2718 + ": " + a);
2719 next.app.thread.scheduleSendResult(next, a);
2720 }
2721 }
2722
2723 if (next.newIntents != null) {
2724 next.app.thread.scheduleNewIntent(next.newIntents, next);
2725 }
2726
Doug Zongker2bec3d42009-12-04 12:52:44 -08002727 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 System.identityHashCode(next),
2729 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730
2731 next.app.thread.scheduleResumeActivity(next,
2732 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 pauseIfSleepingLocked();
2735
2736 } catch (Exception e) {
2737 // Whoops, need to restart this activity!
2738 next.state = lastState;
2739 mResumedActivity = lastResumedActivity;
Dianne Hackborn03abb812010-01-04 18:43:19 -08002740 Log.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 if (!next.hasBeenLaunched) {
2742 next.hasBeenLaunched = true;
2743 } else {
2744 if (SHOW_APP_STARTING_ICON) {
2745 mWindowManager.setAppStartingWindow(
2746 next, next.packageName, next.theme,
2747 next.nonLocalizedLabel,
2748 next.labelRes, next.icon, null, true);
2749 }
2750 }
2751 startSpecificActivityLocked(next, true, false);
2752 return true;
2753 }
2754
2755 // From this point on, if something goes wrong there is no way
2756 // to recover the activity.
2757 try {
2758 next.visible = true;
2759 completeResumeLocked(next);
2760 } catch (Exception e) {
2761 // If any exception gets thrown, toss away this
2762 // activity and try the next one.
2763 Log.w(TAG, "Exception thrown during resume of " + next, e);
2764 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2765 "resume-exception");
2766 return true;
2767 }
2768
2769 // Didn't need to use the icicle, and it is now out of date.
2770 next.icicle = null;
2771 next.haveState = false;
2772 next.stopped = false;
2773
2774 } else {
2775 // Whoops, need to restart this activity!
2776 if (!next.hasBeenLaunched) {
2777 next.hasBeenLaunched = true;
2778 } else {
2779 if (SHOW_APP_STARTING_ICON) {
2780 mWindowManager.setAppStartingWindow(
2781 next, next.packageName, next.theme,
2782 next.nonLocalizedLabel,
2783 next.labelRes, next.icon, null, true);
2784 }
2785 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2786 }
2787 startSpecificActivityLocked(next, true, true);
2788 }
2789
2790 return true;
2791 }
2792
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002793 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2794 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 final int NH = mHistory.size();
2796
2797 int addPos = -1;
2798
2799 if (!newTask) {
2800 // If starting in an existing task, find where that is...
2801 HistoryRecord next = null;
2802 boolean startIt = true;
2803 for (int i = NH-1; i >= 0; i--) {
2804 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2805 if (p.finishing) {
2806 continue;
2807 }
2808 if (p.task == r.task) {
2809 // Here it is! Now, if this is not yet visible to the
2810 // user, then just add it without starting; it will
2811 // get started when the user navigates back to it.
2812 addPos = i+1;
2813 if (!startIt) {
2814 mHistory.add(addPos, r);
2815 r.inHistory = true;
2816 r.task.numActivities++;
2817 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2818 r.info.screenOrientation, r.fullscreen);
2819 if (VALIDATE_TOKENS) {
2820 mWindowManager.validateAppTokens(mHistory);
2821 }
2822 return;
2823 }
2824 break;
2825 }
2826 if (p.fullscreen) {
2827 startIt = false;
2828 }
2829 next = p;
2830 }
2831 }
2832
2833 // Place a new activity at top of stack, so it is next to interact
2834 // with the user.
2835 if (addPos < 0) {
2836 addPos = mHistory.size();
2837 }
2838
2839 // If we are not placing the new activity frontmost, we do not want
2840 // to deliver the onUserLeaving callback to the actual frontmost
2841 // activity
2842 if (addPos < NH) {
2843 mUserLeaving = false;
2844 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2845 }
2846
2847 // Slot the activity into the history stack and proceed
2848 mHistory.add(addPos, r);
2849 r.inHistory = true;
2850 r.frontOfTask = newTask;
2851 r.task.numActivities++;
2852 if (NH > 0) {
2853 // We want to show the starting preview window if we are
2854 // switching to a new task, or the next activity's process is
2855 // not currently running.
2856 boolean showStartingIcon = newTask;
2857 ProcessRecord proc = r.app;
2858 if (proc == null) {
2859 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2860 }
2861 if (proc == null || proc.thread == null) {
2862 showStartingIcon = true;
2863 }
2864 if (DEBUG_TRANSITION) Log.v(TAG,
2865 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002866 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2867 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2868 mNoAnimActivities.add(r);
2869 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2870 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2871 mNoAnimActivities.remove(r);
2872 } else {
2873 mWindowManager.prepareAppTransition(newTask
2874 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2875 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2876 mNoAnimActivities.remove(r);
2877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 mWindowManager.addAppToken(
2879 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2880 boolean doShow = true;
2881 if (newTask) {
2882 // Even though this activity is starting fresh, we still need
2883 // to reset it to make sure we apply affinities to move any
2884 // existing activities from other tasks in to it.
2885 // If the caller has requested that the target task be
2886 // reset, then do so.
2887 if ((r.intent.getFlags()
2888 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2889 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002890 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 }
2892 }
2893 if (SHOW_APP_STARTING_ICON && doShow) {
2894 // Figure out if we are transitioning from another activity that is
2895 // "has the same starting icon" as the next one. This allows the
2896 // window manager to keep the previous window it had previously
2897 // created, if it still had one.
2898 HistoryRecord prev = mResumedActivity;
2899 if (prev != null) {
2900 // We don't want to reuse the previous starting preview if:
2901 // (1) The current activity is in a different task.
2902 if (prev.task != r.task) prev = null;
2903 // (2) The current activity is already displayed.
2904 else if (prev.nowVisible) prev = null;
2905 }
2906 mWindowManager.setAppStartingWindow(
2907 r, r.packageName, r.theme, r.nonLocalizedLabel,
2908 r.labelRes, r.icon, prev, showStartingIcon);
2909 }
2910 } else {
2911 // If this is the first activity, don't do any fancy animations,
2912 // because there is nothing for it to animate on top of.
2913 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2914 r.info.screenOrientation, r.fullscreen);
2915 }
2916 if (VALIDATE_TOKENS) {
2917 mWindowManager.validateAppTokens(mHistory);
2918 }
2919
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002920 if (doResume) {
2921 resumeTopActivityLocked(null);
2922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 }
2924
2925 /**
2926 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002927 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2928 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 * an instance of that activity in the stack and, if found, finish all
2930 * activities on top of it and return the instance.
2931 *
2932 * @param newR Description of the new activity being started.
2933 * @return Returns the old activity that should be continue to be used,
2934 * or null if none was found.
2935 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002936 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002937 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002939
2940 // First find the requested task.
2941 while (i > 0) {
2942 i--;
2943 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2944 if (r.task.taskId == taskId) {
2945 i++;
2946 break;
2947 }
2948 }
2949
2950 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 while (i > 0) {
2952 i--;
2953 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2954 if (r.finishing) {
2955 continue;
2956 }
2957 if (r.task.taskId != taskId) {
2958 return null;
2959 }
2960 if (r.realActivity.equals(newR.realActivity)) {
2961 // Here it is! Now finish everything in front...
2962 HistoryRecord ret = r;
2963 if (doClear) {
2964 while (i < (mHistory.size()-1)) {
2965 i++;
2966 r = (HistoryRecord)mHistory.get(i);
2967 if (r.finishing) {
2968 continue;
2969 }
2970 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2971 null, "clear")) {
2972 i--;
2973 }
2974 }
2975 }
2976
2977 // Finally, if this is a normal launch mode (that is, not
2978 // expecting onNewIntent()), then we will finish the current
2979 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002980 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2981 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002983 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 if (index >= 0) {
2985 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2986 null, "clear");
2987 }
2988 return null;
2989 }
2990 }
2991
2992 return ret;
2993 }
2994 }
2995
2996 return null;
2997 }
2998
2999 /**
3000 * Find the activity in the history stack within the given task. Returns
3001 * the index within the history at which it's found, or < 0 if not found.
3002 */
3003 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3004 int i = mHistory.size();
3005 while (i > 0) {
3006 i--;
3007 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3008 if (candidate.task.taskId != task) {
3009 break;
3010 }
3011 if (candidate.realActivity.equals(r.realActivity)) {
3012 return i;
3013 }
3014 }
3015
3016 return -1;
3017 }
3018
3019 /**
3020 * Reorder the history stack so that the activity at the given index is
3021 * brought to the front.
3022 */
3023 private final HistoryRecord moveActivityToFrontLocked(int where) {
3024 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3025 int top = mHistory.size();
3026 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3027 mHistory.add(top, newTop);
3028 oldTop.frontOfTask = false;
3029 newTop.frontOfTask = true;
3030 return newTop;
3031 }
3032
3033 /**
3034 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3035 * method will be called at the proper time.
3036 */
3037 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3038 boolean sent = false;
3039 if (r.state == ActivityState.RESUMED
3040 && r.app != null && r.app.thread != null) {
3041 try {
3042 ArrayList<Intent> ar = new ArrayList<Intent>();
3043 ar.add(new Intent(intent));
3044 r.app.thread.scheduleNewIntent(ar, r);
3045 sent = true;
3046 } catch (Exception e) {
3047 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
3048 }
3049 }
3050 if (!sent) {
3051 r.addNewIntentLocked(new Intent(intent));
3052 }
3053 }
3054
3055 private final void logStartActivity(int tag, HistoryRecord r,
3056 TaskRecord task) {
3057 EventLog.writeEvent(tag,
3058 System.identityHashCode(r), task.taskId,
3059 r.shortComponentName, r.intent.getAction(),
3060 r.intent.getType(), r.intent.getDataString(),
3061 r.intent.getFlags());
3062 }
3063
3064 private final int startActivityLocked(IApplicationThread caller,
3065 Intent intent, String resolvedType,
3066 Uri[] grantedUriPermissions,
3067 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3068 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003069 int callingPid, int callingUid, boolean onlyIfNeeded,
3070 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003071 Log.i(TAG, "Starting activity: " + intent);
3072
3073 HistoryRecord sourceRecord = null;
3074 HistoryRecord resultRecord = null;
3075 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003076 int index = indexOfTokenLocked(resultTo);
The Android Open Source Project10592532009-03-18 17:39:46 -07003077 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3079 if (index >= 0) {
3080 sourceRecord = (HistoryRecord)mHistory.get(index);
3081 if (requestCode >= 0 && !sourceRecord.finishing) {
3082 resultRecord = sourceRecord;
3083 }
3084 }
3085 }
3086
3087 int launchFlags = intent.getFlags();
3088
3089 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3090 && sourceRecord != null) {
3091 // Transfer the result target from the source activity to the new
3092 // one being started, including any failures.
3093 if (requestCode >= 0) {
3094 return START_FORWARD_AND_REQUEST_CONFLICT;
3095 }
3096 resultRecord = sourceRecord.resultTo;
3097 resultWho = sourceRecord.resultWho;
3098 requestCode = sourceRecord.requestCode;
3099 sourceRecord.resultTo = null;
3100 if (resultRecord != null) {
3101 resultRecord.removeResultsLocked(
3102 sourceRecord, resultWho, requestCode);
3103 }
3104 }
3105
3106 int err = START_SUCCESS;
3107
3108 if (intent.getComponent() == null) {
3109 // We couldn't find a class that can handle the given Intent.
3110 // That's the end of that!
3111 err = START_INTENT_NOT_RESOLVED;
3112 }
3113
3114 if (err == START_SUCCESS && aInfo == null) {
3115 // We couldn't find the specific class specified in the Intent.
3116 // Also the end of the line.
3117 err = START_CLASS_NOT_FOUND;
3118 }
3119
3120 ProcessRecord callerApp = null;
3121 if (err == START_SUCCESS && caller != null) {
3122 callerApp = getRecordForAppLocked(caller);
3123 if (callerApp != null) {
3124 callingPid = callerApp.pid;
3125 callingUid = callerApp.info.uid;
3126 } else {
3127 Log.w(TAG, "Unable to find app for caller " + caller
3128 + " (pid=" + callingPid + ") when starting: "
3129 + intent.toString());
3130 err = START_PERMISSION_DENIED;
3131 }
3132 }
3133
3134 if (err != START_SUCCESS) {
3135 if (resultRecord != null) {
3136 sendActivityResultLocked(-1,
3137 resultRecord, resultWho, requestCode,
3138 Activity.RESULT_CANCELED, null);
3139 }
3140 return err;
3141 }
3142
3143 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3144 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3145 if (perm != PackageManager.PERMISSION_GRANTED) {
3146 if (resultRecord != null) {
3147 sendActivityResultLocked(-1,
3148 resultRecord, resultWho, requestCode,
3149 Activity.RESULT_CANCELED, null);
3150 }
3151 String msg = "Permission Denial: starting " + intent.toString()
3152 + " from " + callerApp + " (pid=" + callingPid
3153 + ", uid=" + callingUid + ")"
3154 + " requires " + aInfo.permission;
3155 Log.w(TAG, msg);
3156 throw new SecurityException(msg);
3157 }
3158
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003159 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 boolean abort = false;
3161 try {
3162 // The Intent we give to the watcher has the extra data
3163 // stripped off, since it can contain private information.
3164 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003165 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 aInfo.applicationInfo.packageName);
3167 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003168 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 }
3170
3171 if (abort) {
3172 if (resultRecord != null) {
3173 sendActivityResultLocked(-1,
3174 resultRecord, resultWho, requestCode,
3175 Activity.RESULT_CANCELED, null);
3176 }
3177 // We pretend to the caller that it was really started, but
3178 // they will just get a cancel result.
3179 return START_SUCCESS;
3180 }
3181 }
3182
3183 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3184 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003185 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003187 if (mResumedActivity == null
3188 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3189 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3190 PendingActivityLaunch pal = new PendingActivityLaunch();
3191 pal.r = r;
3192 pal.sourceRecord = sourceRecord;
3193 pal.grantedUriPermissions = grantedUriPermissions;
3194 pal.grantedMode = grantedMode;
3195 pal.onlyIfNeeded = onlyIfNeeded;
3196 mPendingActivityLaunches.add(pal);
3197 return START_SWITCHES_CANCELED;
3198 }
3199 }
3200
3201 if (mDidAppSwitch) {
3202 // This is the second allowed switch since we stopped switches,
3203 // so now just generally allow switches. Use case: user presses
3204 // home (switches disabled, switch to home, mDidAppSwitch now true);
3205 // user taps a home icon (coming from home so allowed, we hit here
3206 // and now allow anyone to switch again).
3207 mAppSwitchesAllowedTime = 0;
3208 } else {
3209 mDidAppSwitch = true;
3210 }
3211
3212 doPendingActivityLaunchesLocked(false);
3213
3214 return startActivityUncheckedLocked(r, sourceRecord,
3215 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3216 }
3217
3218 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3219 final int N = mPendingActivityLaunches.size();
3220 if (N <= 0) {
3221 return;
3222 }
3223 for (int i=0; i<N; i++) {
3224 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3225 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3226 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3227 doResume && i == (N-1));
3228 }
3229 mPendingActivityLaunches.clear();
3230 }
3231
3232 private final int startActivityUncheckedLocked(HistoryRecord r,
3233 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3234 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3235 final Intent intent = r.intent;
3236 final int callingUid = r.launchedFromUid;
3237
3238 int launchFlags = intent.getFlags();
3239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 // We'll invoke onUserLeaving before onPause only if the launching
3241 // activity did not explicitly state that this is an automated launch.
3242 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
3243 if (DEBUG_USER_LEAVING) Log.v(TAG,
3244 "startActivity() => mUserLeaving=" + mUserLeaving);
3245
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003246 // If the caller has asked not to resume at this point, we make note
3247 // of this in the record so that we can skip it when trying to find
3248 // the top running activity.
3249 if (!doResume) {
3250 r.delayedResume = true;
3251 }
3252
3253 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3254 != 0 ? r : null;
3255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 // If the onlyIfNeeded flag is set, then we can do this if the activity
3257 // being launched is the same as the one making the call... or, as
3258 // a special case, if we do not know the caller then we count the
3259 // current top activity as the caller.
3260 if (onlyIfNeeded) {
3261 HistoryRecord checkedCaller = sourceRecord;
3262 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003263 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 }
3265 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3266 // Caller is not the same as launcher, so always needed.
3267 onlyIfNeeded = false;
3268 }
3269 }
3270
3271 if (grantedUriPermissions != null && callingUid > 0) {
3272 for (int i=0; i<grantedUriPermissions.length; i++) {
3273 grantUriPermissionLocked(callingUid, r.packageName,
3274 grantedUriPermissions[i], grantedMode, r);
3275 }
3276 }
3277
3278 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3279 intent, r);
3280
3281 if (sourceRecord == null) {
3282 // This activity is not being started from another... in this
3283 // case we -always- start a new task.
3284 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
3285 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
3286 + intent);
3287 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3288 }
3289 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3290 // The original activity who is starting us is running as a single
3291 // instance... this new activity it is starting must go on its
3292 // own task.
3293 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3294 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3295 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3296 // The activity being started is a single instance... it always
3297 // gets launched into its own task.
3298 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3299 }
3300
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003301 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 // For whatever reason this activity is being launched into a new
3303 // task... yet the caller has requested a result back. Well, that
3304 // is pretty messed up, so instead immediately send back a cancel
3305 // and let the new task continue launched as normal without a
3306 // dependency on its originator.
3307 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3308 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003309 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 Activity.RESULT_CANCELED, null);
3311 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 }
3313
3314 boolean addingToTask = false;
3315 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3316 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3317 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3318 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3319 // If bring to front is requested, and no result is requested, and
3320 // we can find a task that was started with this same
3321 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003322 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 // See if there is a task to bring to the front. If this is
3324 // a SINGLE_INSTANCE activity, there can be one and only one
3325 // instance of it in the history, and it is always in its own
3326 // unique task, so we do a special search.
3327 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3328 ? findTaskLocked(intent, r.info)
3329 : findActivityLocked(intent, r.info);
3330 if (taskTop != null) {
3331 if (taskTop.task.intent == null) {
3332 // This task was started because of movement of
3333 // the activity based on affinity... now that we
3334 // are actually launching it, we can assign the
3335 // base intent.
3336 taskTop.task.setIntent(intent, r.info);
3337 }
3338 // If the target task is not in the front, then we need
3339 // to bring it to the front... except... well, with
3340 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3341 // to have the same behavior as if a new instance was
3342 // being started, which means not bringing it to the front
3343 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003344 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 if (curTop.task != taskTop.task) {
3346 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3347 boolean callerAtFront = sourceRecord == null
3348 || curTop.task == sourceRecord.task;
3349 if (callerAtFront) {
3350 // We really do want to push this one into the
3351 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003352 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 }
3354 }
3355 // If the caller has requested that the target task be
3356 // reset, then do so.
3357 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3358 taskTop = resetTaskIfNeededLocked(taskTop, r);
3359 }
3360 if (onlyIfNeeded) {
3361 // We don't need to start a new activity, and
3362 // the client said not to do anything if that
3363 // is the case, so this is it! And for paranoia, make
3364 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003365 if (doResume) {
3366 resumeTopActivityLocked(null);
3367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 return START_RETURN_INTENT_TO_CALLER;
3369 }
3370 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3371 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3372 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3373 // In this situation we want to remove all activities
3374 // from the task up to the one being started. In most
3375 // cases this means we are resetting the task to its
3376 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003377 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003378 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 if (top != null) {
3380 if (top.frontOfTask) {
3381 // Activity aliases may mean we use different
3382 // intents for the top activity, so make sure
3383 // the task now has the identity of the new
3384 // intent.
3385 top.task.setIntent(r.intent, r.info);
3386 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003387 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 deliverNewIntentLocked(top, r.intent);
3389 } else {
3390 // A special case: we need to
3391 // start the activity because it is not currently
3392 // running, and the caller has asked to clear the
3393 // current task to have this activity at the top.
3394 addingToTask = true;
3395 // Now pretend like this activity is being started
3396 // by the top of its task, so it is put in the
3397 // right place.
3398 sourceRecord = taskTop;
3399 }
3400 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3401 // In this case the top activity on the task is the
3402 // same as the one being launched, so we take that
3403 // as a request to bring the task to the foreground.
3404 // If the top activity in the task is the root
3405 // activity, deliver this new intent to it if it
3406 // desires.
3407 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3408 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003409 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 if (taskTop.frontOfTask) {
3411 taskTop.task.setIntent(r.intent, r.info);
3412 }
3413 deliverNewIntentLocked(taskTop, r.intent);
3414 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3415 // In this case we are launching the root activity
3416 // of the task, but with a different intent. We
3417 // should start a new instance on top.
3418 addingToTask = true;
3419 sourceRecord = taskTop;
3420 }
3421 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3422 // In this case an activity is being launched in to an
3423 // existing task, without resetting that task. This
3424 // is typically the situation of launching an activity
3425 // from a notification or shortcut. We want to place
3426 // the new activity on top of the current task.
3427 addingToTask = true;
3428 sourceRecord = taskTop;
3429 } else if (!taskTop.task.rootWasReset) {
3430 // In this case we are launching in to an existing task
3431 // that has not yet been started from its front door.
3432 // The current task has been brought to the front.
3433 // Ideally, we'd probably like to place this new task
3434 // at the bottom of its stack, but that's a little hard
3435 // to do with the current organization of the code so
3436 // for now we'll just drop it.
3437 taskTop.task.setIntent(r.intent, r.info);
3438 }
3439 if (!addingToTask) {
3440 // We didn't do anything... but it was needed (a.k.a., client
3441 // don't use that intent!) And for paranoia, make
3442 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003443 if (doResume) {
3444 resumeTopActivityLocked(null);
3445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 return START_TASK_TO_FRONT;
3447 }
3448 }
3449 }
3450 }
3451
3452 //String uri = r.intent.toURI();
3453 //Intent intent2 = new Intent(uri);
3454 //Log.i(TAG, "Given intent: " + r.intent);
3455 //Log.i(TAG, "URI is: " + uri);
3456 //Log.i(TAG, "To intent: " + intent2);
3457
3458 if (r.packageName != null) {
3459 // If the activity being launched is the same as the one currently
3460 // at the top, then we need to check if it should only be launched
3461 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003462 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3463 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 if (top.realActivity.equals(r.realActivity)) {
3465 if (top.app != null && top.app.thread != null) {
3466 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3467 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3468 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003469 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 // For paranoia, make sure we have correctly
3471 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003472 if (doResume) {
3473 resumeTopActivityLocked(null);
3474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 if (onlyIfNeeded) {
3476 // We don't need to start a new activity, and
3477 // the client said not to do anything if that
3478 // is the case, so this is it!
3479 return START_RETURN_INTENT_TO_CALLER;
3480 }
3481 deliverNewIntentLocked(top, r.intent);
3482 return START_DELIVERED_TO_TOP;
3483 }
3484 }
3485 }
3486 }
3487
3488 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003489 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003491 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 Activity.RESULT_CANCELED, null);
3493 }
3494 return START_CLASS_NOT_FOUND;
3495 }
3496
3497 boolean newTask = false;
3498
3499 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003500 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3502 // todo: should do better management of integers.
3503 mCurTask++;
3504 if (mCurTask <= 0) {
3505 mCurTask = 1;
3506 }
3507 r.task = new TaskRecord(mCurTask, r.info, intent,
3508 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3509 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3510 + " in new task " + r.task);
3511 newTask = true;
3512 addRecentTask(r.task);
3513
3514 } else if (sourceRecord != null) {
3515 if (!addingToTask &&
3516 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3517 // In this case, we are adding the activity to an existing
3518 // task, but the caller has asked to clear that task if the
3519 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003520 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003521 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003523 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 deliverNewIntentLocked(top, r.intent);
3525 // For paranoia, make sure we have correctly
3526 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003527 if (doResume) {
3528 resumeTopActivityLocked(null);
3529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 return START_DELIVERED_TO_TOP;
3531 }
3532 } else if (!addingToTask &&
3533 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3534 // In this case, we are launching an activity in our own task
3535 // that may already be running somewhere in the history, and
3536 // we want to shuffle it to the front of the stack if so.
3537 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3538 if (where >= 0) {
3539 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003540 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003541 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003542 if (doResume) {
3543 resumeTopActivityLocked(null);
3544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 return START_DELIVERED_TO_TOP;
3546 }
3547 }
3548 // An existing activity is starting this new activity, so we want
3549 // to keep the new one in the same task as the one that is starting
3550 // it.
3551 r.task = sourceRecord.task;
3552 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3553 + " in existing task " + r.task);
3554
3555 } else {
3556 // This not being started from an existing activity, and not part
3557 // of a new task... just put it in the top task, though these days
3558 // this case should never happen.
3559 final int N = mHistory.size();
3560 HistoryRecord prev =
3561 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3562 r.task = prev != null
3563 ? prev.task
3564 : new TaskRecord(mCurTask, r.info, intent,
3565 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3566 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3567 + " in new guessed " + r.task);
3568 }
3569 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003570 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003572 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003573 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 return START_SUCCESS;
3575 }
3576
3577 public final int startActivity(IApplicationThread caller,
3578 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3579 int grantedMode, IBinder resultTo,
3580 String resultWho, int requestCode, boolean onlyIfNeeded,
3581 boolean debug) {
3582 // Refuse possible leaked file descriptors
3583 if (intent != null && intent.hasFileDescriptors()) {
3584 throw new IllegalArgumentException("File descriptors passed in Intent");
3585 }
3586
The Android Open Source Project4df24232009-03-05 14:34:35 -08003587 final boolean componentSpecified = intent.getComponent() != null;
3588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 // Don't modify the client's object!
3590 intent = new Intent(intent);
3591
3592 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 ActivityInfo aInfo;
3594 try {
3595 ResolveInfo rInfo =
3596 ActivityThread.getPackageManager().resolveIntent(
3597 intent, resolvedType,
3598 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003599 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 aInfo = rInfo != null ? rInfo.activityInfo : null;
3601 } catch (RemoteException e) {
3602 aInfo = null;
3603 }
3604
3605 if (aInfo != null) {
3606 // Store the found target back into the intent, because now that
3607 // we have it we never want to do this again. For example, if the
3608 // user navigates back to this point in the history, we should
3609 // always restart the exact same activity.
3610 intent.setComponent(new ComponentName(
3611 aInfo.applicationInfo.packageName, aInfo.name));
3612
3613 // Don't debug things in the system process
3614 if (debug) {
3615 if (!aInfo.processName.equals("system")) {
3616 setDebugApp(aInfo.processName, true, false);
3617 }
3618 }
3619 }
3620
3621 synchronized(this) {
3622 final long origId = Binder.clearCallingIdentity();
3623 int res = startActivityLocked(caller, intent, resolvedType,
3624 grantedUriPermissions, grantedMode, aInfo,
3625 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003626 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 Binder.restoreCallingIdentity(origId);
3628 return res;
3629 }
3630 }
3631
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003632 public int startActivityIntentSender(IApplicationThread caller,
3633 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003634 IBinder resultTo, String resultWho, int requestCode,
3635 int flagsMask, int flagsValues) {
3636 // Refuse possible leaked file descriptors
3637 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3638 throw new IllegalArgumentException("File descriptors passed in Intent");
3639 }
3640
3641 IIntentSender sender = intent.getTarget();
3642 if (!(sender instanceof PendingIntentRecord)) {
3643 throw new IllegalArgumentException("Bad PendingIntent object");
3644 }
3645
3646 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003647
3648 synchronized (this) {
3649 // If this is coming from the currently resumed activity, it is
3650 // effectively saying that app switches are allowed at this point.
3651 if (mResumedActivity != null
3652 && mResumedActivity.info.applicationInfo.uid ==
3653 Binder.getCallingUid()) {
3654 mAppSwitchesAllowedTime = 0;
3655 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003656 }
3657
3658 return pir.sendInner(0, fillInIntent, resolvedType,
3659 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3660 }
3661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 public boolean startNextMatchingActivity(IBinder callingActivity,
3663 Intent intent) {
3664 // Refuse possible leaked file descriptors
3665 if (intent != null && intent.hasFileDescriptors() == true) {
3666 throw new IllegalArgumentException("File descriptors passed in Intent");
3667 }
3668
3669 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003670 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 if (index < 0) {
3672 return false;
3673 }
3674 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3675 if (r.app == null || r.app.thread == null) {
3676 // The caller is not running... d'oh!
3677 return false;
3678 }
3679 intent = new Intent(intent);
3680 // The caller is not allowed to change the data.
3681 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3682 // And we are resetting to find the next component...
3683 intent.setComponent(null);
3684
3685 ActivityInfo aInfo = null;
3686 try {
3687 List<ResolveInfo> resolves =
3688 ActivityThread.getPackageManager().queryIntentActivities(
3689 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003690 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691
3692 // Look for the original activity in the list...
3693 final int N = resolves != null ? resolves.size() : 0;
3694 for (int i=0; i<N; i++) {
3695 ResolveInfo rInfo = resolves.get(i);
3696 if (rInfo.activityInfo.packageName.equals(r.packageName)
3697 && rInfo.activityInfo.name.equals(r.info.name)) {
3698 // We found the current one... the next matching is
3699 // after it.
3700 i++;
3701 if (i<N) {
3702 aInfo = resolves.get(i).activityInfo;
3703 }
3704 break;
3705 }
3706 }
3707 } catch (RemoteException e) {
3708 }
3709
3710 if (aInfo == null) {
3711 // Nobody who is next!
3712 return false;
3713 }
3714
3715 intent.setComponent(new ComponentName(
3716 aInfo.applicationInfo.packageName, aInfo.name));
3717 intent.setFlags(intent.getFlags()&~(
3718 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3719 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3720 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3721 Intent.FLAG_ACTIVITY_NEW_TASK));
3722
3723 // Okay now we need to start the new activity, replacing the
3724 // currently running activity. This is a little tricky because
3725 // we want to start the new one as if the current one is finished,
3726 // but not finish the current one first so that there is no flicker.
3727 // And thus...
3728 final boolean wasFinishing = r.finishing;
3729 r.finishing = true;
3730
3731 // Propagate reply information over to the new activity.
3732 final HistoryRecord resultTo = r.resultTo;
3733 final String resultWho = r.resultWho;
3734 final int requestCode = r.requestCode;
3735 r.resultTo = null;
3736 if (resultTo != null) {
3737 resultTo.removeResultsLocked(r, resultWho, requestCode);
3738 }
3739
3740 final long origId = Binder.clearCallingIdentity();
3741 // XXX we are not dealing with propagating grantedUriPermissions...
3742 // those are not yet exposed to user code, so there is no need.
3743 int res = startActivityLocked(r.app.thread, intent,
3744 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003745 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 Binder.restoreCallingIdentity(origId);
3747
3748 r.finishing = wasFinishing;
3749 if (res != START_SUCCESS) {
3750 return false;
3751 }
3752 return true;
3753 }
3754 }
3755
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003756 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 Intent intent, String resolvedType, IBinder resultTo,
3758 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003759
3760 // This is so super not safe, that only the system (or okay root)
3761 // can do it.
3762 final int callingUid = Binder.getCallingUid();
3763 if (callingUid != 0 && callingUid != Process.myUid()) {
3764 throw new SecurityException(
3765 "startActivityInPackage only available to the system");
3766 }
3767
The Android Open Source Project4df24232009-03-05 14:34:35 -08003768 final boolean componentSpecified = intent.getComponent() != null;
3769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003770 // Don't modify the client's object!
3771 intent = new Intent(intent);
3772
3773 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 ActivityInfo aInfo;
3775 try {
3776 ResolveInfo rInfo =
3777 ActivityThread.getPackageManager().resolveIntent(
3778 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003779 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 aInfo = rInfo != null ? rInfo.activityInfo : null;
3781 } catch (RemoteException e) {
3782 aInfo = null;
3783 }
3784
3785 if (aInfo != null) {
3786 // Store the found target back into the intent, because now that
3787 // we have it we never want to do this again. For example, if the
3788 // user navigates back to this point in the history, we should
3789 // always restart the exact same activity.
3790 intent.setComponent(new ComponentName(
3791 aInfo.applicationInfo.packageName, aInfo.name));
3792 }
3793
3794 synchronized(this) {
3795 return startActivityLocked(null, intent, resolvedType,
3796 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003797 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
3799 }
3800
3801 private final void addRecentTask(TaskRecord task) {
3802 // Remove any existing entries that are the same kind of task.
3803 int N = mRecentTasks.size();
3804 for (int i=0; i<N; i++) {
3805 TaskRecord tr = mRecentTasks.get(i);
3806 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3807 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3808 mRecentTasks.remove(i);
3809 i--;
3810 N--;
3811 if (task.intent == null) {
3812 // If the new recent task we are adding is not fully
3813 // specified, then replace it with the existing recent task.
3814 task = tr;
3815 }
3816 }
3817 }
3818 if (N >= MAX_RECENT_TASKS) {
3819 mRecentTasks.remove(N-1);
3820 }
3821 mRecentTasks.add(0, task);
3822 }
3823
3824 public void setRequestedOrientation(IBinder token,
3825 int requestedOrientation) {
3826 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003827 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 if (index < 0) {
3829 return;
3830 }
3831 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3832 final long origId = Binder.clearCallingIdentity();
3833 mWindowManager.setAppOrientation(r, requestedOrientation);
3834 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003835 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 r.mayFreezeScreenLocked(r.app) ? r : null);
3837 if (config != null) {
3838 r.frozenBeforeDestroy = true;
3839 if (!updateConfigurationLocked(config, r)) {
3840 resumeTopActivityLocked(null);
3841 }
3842 }
3843 Binder.restoreCallingIdentity(origId);
3844 }
3845 }
3846
3847 public int getRequestedOrientation(IBinder token) {
3848 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003849 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 if (index < 0) {
3851 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3852 }
3853 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3854 return mWindowManager.getAppOrientation(r);
3855 }
3856 }
3857
3858 private final void stopActivityLocked(HistoryRecord r) {
3859 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3860 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3861 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3862 if (!r.finishing) {
3863 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3864 "no-history");
3865 }
3866 } else if (r.app != null && r.app.thread != null) {
3867 if (mFocusedActivity == r) {
3868 setFocusedActivityLocked(topRunningActivityLocked(null));
3869 }
3870 r.resumeKeyDispatchingLocked();
3871 try {
3872 r.stopped = false;
3873 r.state = ActivityState.STOPPING;
3874 if (DEBUG_VISBILITY) Log.v(
3875 TAG, "Stopping visible=" + r.visible + " for " + r);
3876 if (!r.visible) {
3877 mWindowManager.setAppVisibility(r, false);
3878 }
3879 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3880 } catch (Exception e) {
3881 // Maybe just ignore exceptions here... if the process
3882 // has crashed, our death notification will clean things
3883 // up.
3884 Log.w(TAG, "Exception thrown during pause", e);
3885 // Just in case, assume it to be stopped.
3886 r.stopped = true;
3887 r.state = ActivityState.STOPPED;
3888 if (r.configDestroy) {
3889 destroyActivityLocked(r, true);
3890 }
3891 }
3892 }
3893 }
3894
3895 /**
3896 * @return Returns true if the activity is being finished, false if for
3897 * some reason it is being left as-is.
3898 */
3899 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3900 Intent resultData, String reason) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003901 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003902 TAG, "Finishing activity: token=" + token
3903 + ", result=" + resultCode + ", data=" + resultData);
3904
Dianne Hackborn75b03852009-06-12 15:43:26 -07003905 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 if (index < 0) {
3907 return false;
3908 }
3909 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3910
3911 // Is this the last activity left?
3912 boolean lastActivity = true;
3913 for (int i=mHistory.size()-1; i>=0; i--) {
3914 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3915 if (!p.finishing && p != r) {
3916 lastActivity = false;
3917 break;
3918 }
3919 }
3920
3921 // If this is the last activity, but it is the home activity, then
3922 // just don't finish it.
3923 if (lastActivity) {
3924 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3925 return false;
3926 }
3927 }
3928
3929 finishActivityLocked(r, index, resultCode, resultData, reason);
3930 return true;
3931 }
3932
3933 /**
3934 * @return Returns true if this activity has been removed from the history
3935 * list, or false if it is still in the list and will be removed later.
3936 */
3937 private final boolean finishActivityLocked(HistoryRecord r, int index,
3938 int resultCode, Intent resultData, String reason) {
3939 if (r.finishing) {
3940 Log.w(TAG, "Duplicate finish request for " + r);
3941 return false;
3942 }
3943
3944 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08003945 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946 System.identityHashCode(r),
3947 r.task.taskId, r.shortComponentName, reason);
3948 r.task.numActivities--;
3949 if (r.frontOfTask && index < (mHistory.size()-1)) {
3950 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3951 if (next.task == r.task) {
3952 next.frontOfTask = true;
3953 }
3954 }
3955
3956 r.pauseKeyDispatchingLocked();
3957 if (mFocusedActivity == r) {
3958 setFocusedActivityLocked(topRunningActivityLocked(null));
3959 }
3960
3961 // send the result
3962 HistoryRecord resultTo = r.resultTo;
3963 if (resultTo != null) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003964 if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
3965 + " who=" + r.resultWho + " req=" + r.requestCode
3966 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 if (r.info.applicationInfo.uid > 0) {
3968 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3969 r.packageName, resultData, r);
3970 }
3971 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3972 resultData);
3973 r.resultTo = null;
3974 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003975 else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976
3977 // Make sure this HistoryRecord is not holding on to other resources,
3978 // because clients have remote IPC references to this object so we
3979 // can't assume that will go away and want to avoid circular IPC refs.
3980 r.results = null;
3981 r.pendingResults = null;
3982 r.newIntents = null;
3983 r.icicle = null;
3984
3985 if (mPendingThumbnails.size() > 0) {
3986 // There are clients waiting to receive thumbnails so, in case
3987 // this is an activity that someone is waiting for, add it
3988 // to the pending list so we can correctly update the clients.
3989 mCancelledThumbnails.add(r);
3990 }
3991
3992 if (mResumedActivity == r) {
3993 boolean endTask = index <= 0
3994 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3995 if (DEBUG_TRANSITION) Log.v(TAG,
3996 "Prepare close transition: finishing " + r);
3997 mWindowManager.prepareAppTransition(endTask
3998 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3999 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4000
4001 // Tell window manager to prepare for this one to be removed.
4002 mWindowManager.setAppVisibility(r, false);
4003
4004 if (mPausingActivity == null) {
4005 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
4006 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
4007 startPausingLocked(false, false);
4008 }
4009
4010 } else if (r.state != ActivityState.PAUSING) {
4011 // If the activity is PAUSING, we will complete the finish once
4012 // it is done pausing; else we can just directly finish it here.
4013 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
4014 return finishCurrentActivityLocked(r, index,
4015 FINISH_AFTER_PAUSE) == null;
4016 } else {
4017 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
4018 }
4019
4020 return false;
4021 }
4022
4023 private static final int FINISH_IMMEDIATELY = 0;
4024 private static final int FINISH_AFTER_PAUSE = 1;
4025 private static final int FINISH_AFTER_VISIBLE = 2;
4026
4027 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4028 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004029 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 if (index < 0) {
4031 return null;
4032 }
4033
4034 return finishCurrentActivityLocked(r, index, mode);
4035 }
4036
4037 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4038 int index, int mode) {
4039 // First things first: if this activity is currently visible,
4040 // and the resumed activity is not yet visible, then hold off on
4041 // finishing until the resumed one becomes visible.
4042 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4043 if (!mStoppingActivities.contains(r)) {
4044 mStoppingActivities.add(r);
4045 if (mStoppingActivities.size() > 3) {
4046 // If we already have a few activities waiting to stop,
4047 // then give up on things going idle and start clearing
4048 // them out.
4049 Message msg = Message.obtain();
4050 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4051 mHandler.sendMessage(msg);
4052 }
4053 }
4054 r.state = ActivityState.STOPPING;
4055 updateOomAdjLocked();
4056 return r;
4057 }
4058
4059 // make sure the record is cleaned out of other places.
4060 mStoppingActivities.remove(r);
4061 mWaitingVisibleActivities.remove(r);
4062 if (mResumedActivity == r) {
4063 mResumedActivity = null;
4064 }
4065 final ActivityState prevState = r.state;
4066 r.state = ActivityState.FINISHING;
4067
4068 if (mode == FINISH_IMMEDIATELY
4069 || prevState == ActivityState.STOPPED
4070 || prevState == ActivityState.INITIALIZING) {
4071 // If this activity is already stopped, we can just finish
4072 // it right now.
4073 return destroyActivityLocked(r, true) ? null : r;
4074 } else {
4075 // Need to go through the full pause cycle to get this
4076 // activity into the stopped state and then finish it.
4077 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
4078 mFinishingActivities.add(r);
4079 resumeTopActivityLocked(null);
4080 }
4081 return r;
4082 }
4083
4084 /**
4085 * This is the internal entry point for handling Activity.finish().
4086 *
4087 * @param token The Binder token referencing the Activity we want to finish.
4088 * @param resultCode Result code, if any, from this Activity.
4089 * @param resultData Result data (Intent), if any, from this Activity.
4090 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004091 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 */
4093 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4094 // Refuse possible leaked file descriptors
4095 if (resultData != null && resultData.hasFileDescriptors() == true) {
4096 throw new IllegalArgumentException("File descriptors passed in Intent");
4097 }
4098
4099 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004100 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 // Find the first activity that is not finishing.
4102 HistoryRecord next = topRunningActivityLocked(token, 0);
4103 if (next != null) {
4104 // ask watcher if this is allowed
4105 boolean resumeOK = true;
4106 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004107 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004109 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 }
4111
4112 if (!resumeOK) {
4113 return false;
4114 }
4115 }
4116 }
4117 final long origId = Binder.clearCallingIdentity();
4118 boolean res = requestFinishActivityLocked(token, resultCode,
4119 resultData, "app-request");
4120 Binder.restoreCallingIdentity(origId);
4121 return res;
4122 }
4123 }
4124
4125 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4126 String resultWho, int requestCode, int resultCode, Intent data) {
4127
4128 if (callingUid > 0) {
4129 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4130 data, r);
4131 }
4132
The Android Open Source Project10592532009-03-18 17:39:46 -07004133 if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
4134 + " : who=" + resultWho + " req=" + requestCode
4135 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4137 try {
4138 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4139 list.add(new ResultInfo(resultWho, requestCode,
4140 resultCode, data));
4141 r.app.thread.scheduleSendResult(r, list);
4142 return;
4143 } catch (Exception e) {
4144 Log.w(TAG, "Exception thrown sending result to " + r, e);
4145 }
4146 }
4147
4148 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4149 }
4150
4151 public final void finishSubActivity(IBinder token, String resultWho,
4152 int requestCode) {
4153 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004154 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 if (index < 0) {
4156 return;
4157 }
4158 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4159
4160 final long origId = Binder.clearCallingIdentity();
4161
4162 int i;
4163 for (i=mHistory.size()-1; i>=0; i--) {
4164 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4165 if (r.resultTo == self && r.requestCode == requestCode) {
4166 if ((r.resultWho == null && resultWho == null) ||
4167 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4168 finishActivityLocked(r, i,
4169 Activity.RESULT_CANCELED, null, "request-sub");
4170 }
4171 }
4172 }
4173
4174 Binder.restoreCallingIdentity(origId);
4175 }
4176 }
4177
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004178 public void overridePendingTransition(IBinder token, String packageName,
4179 int enterAnim, int exitAnim) {
4180 synchronized(this) {
4181 int index = indexOfTokenLocked(token);
4182 if (index < 0) {
4183 return;
4184 }
4185 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4186
4187 final long origId = Binder.clearCallingIdentity();
4188
4189 if (self.state == ActivityState.RESUMED
4190 || self.state == ActivityState.PAUSING) {
4191 mWindowManager.overridePendingAppTransition(packageName,
4192 enterAnim, exitAnim);
4193 }
4194
4195 Binder.restoreCallingIdentity(origId);
4196 }
4197 }
4198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 /**
4200 * Perform clean-up of service connections in an activity record.
4201 */
4202 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4203 // Throw away any services that have been bound by this activity.
4204 if (r.connections != null) {
4205 Iterator<ConnectionRecord> it = r.connections.iterator();
4206 while (it.hasNext()) {
4207 ConnectionRecord c = it.next();
4208 removeConnectionLocked(c, null, r);
4209 }
4210 r.connections = null;
4211 }
4212 }
4213
4214 /**
4215 * Perform the common clean-up of an activity record. This is called both
4216 * as part of destroyActivityLocked() (when destroying the client-side
4217 * representation) and cleaning things up as a result of its hosting
4218 * processing going away, in which case there is no remaining client-side
4219 * state to destroy so only the cleanup here is needed.
4220 */
4221 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4222 if (mResumedActivity == r) {
4223 mResumedActivity = null;
4224 }
4225 if (mFocusedActivity == r) {
4226 mFocusedActivity = null;
4227 }
4228
4229 r.configDestroy = false;
4230 r.frozenBeforeDestroy = false;
4231
4232 // Make sure this record is no longer in the pending finishes list.
4233 // This could happen, for example, if we are trimming activities
4234 // down to the max limit while they are still waiting to finish.
4235 mFinishingActivities.remove(r);
4236 mWaitingVisibleActivities.remove(r);
4237
4238 // Remove any pending results.
4239 if (r.finishing && r.pendingResults != null) {
4240 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4241 PendingIntentRecord rec = apr.get();
4242 if (rec != null) {
4243 cancelIntentSenderLocked(rec, false);
4244 }
4245 }
4246 r.pendingResults = null;
4247 }
4248
4249 if (cleanServices) {
4250 cleanUpActivityServicesLocked(r);
4251 }
4252
4253 if (mPendingThumbnails.size() > 0) {
4254 // There are clients waiting to receive thumbnails so, in case
4255 // this is an activity that someone is waiting for, add it
4256 // to the pending list so we can correctly update the clients.
4257 mCancelledThumbnails.add(r);
4258 }
4259
4260 // Get rid of any pending idle timeouts.
4261 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4262 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4263 }
4264
4265 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4266 if (r.state != ActivityState.DESTROYED) {
4267 mHistory.remove(r);
4268 r.inHistory = false;
4269 r.state = ActivityState.DESTROYED;
4270 mWindowManager.removeAppToken(r);
4271 if (VALIDATE_TOKENS) {
4272 mWindowManager.validateAppTokens(mHistory);
4273 }
4274 cleanUpActivityServicesLocked(r);
4275 removeActivityUriPermissionsLocked(r);
4276 }
4277 }
4278
4279 /**
4280 * Destroy the current CLIENT SIDE instance of an activity. This may be
4281 * called both when actually finishing an activity, or when performing
4282 * a configuration switch where we destroy the current client-side object
4283 * but then create a new client-side object for this same HistoryRecord.
4284 */
4285 private final boolean destroyActivityLocked(HistoryRecord r,
4286 boolean removeFromApp) {
4287 if (DEBUG_SWITCH) Log.v(
4288 TAG, "Removing activity: token=" + r
4289 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004290 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 System.identityHashCode(r),
4292 r.task.taskId, r.shortComponentName);
4293
4294 boolean removedFromHistory = false;
4295
4296 cleanUpActivityLocked(r, false);
4297
Dianne Hackborn03abb812010-01-04 18:43:19 -08004298 final boolean hadApp = r.app != null;
4299
4300 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 if (removeFromApp) {
4302 int idx = r.app.activities.indexOf(r);
4303 if (idx >= 0) {
4304 r.app.activities.remove(idx);
4305 }
4306 if (r.persistent) {
4307 decPersistentCountLocked(r.app);
4308 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004309 if (r.app.activities.size() == 0) {
4310 // No longer have activities, so update location in
4311 // LRU list.
4312 updateLruProcessLocked(r.app, true, false);
4313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 }
4315
4316 boolean skipDestroy = false;
4317
4318 try {
4319 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
4320 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4321 r.configChangeFlags);
4322 } catch (Exception e) {
4323 // We can just ignore exceptions here... if the process
4324 // has crashed, our death notification will clean things
4325 // up.
4326 //Log.w(TAG, "Exception thrown during finish", e);
4327 if (r.finishing) {
4328 removeActivityFromHistoryLocked(r);
4329 removedFromHistory = true;
4330 skipDestroy = true;
4331 }
4332 }
4333
4334 r.app = null;
4335 r.nowVisible = false;
4336
4337 if (r.finishing && !skipDestroy) {
4338 r.state = ActivityState.DESTROYING;
4339 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4340 msg.obj = r;
4341 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4342 } else {
4343 r.state = ActivityState.DESTROYED;
4344 }
4345 } else {
4346 // remove this record from the history.
4347 if (r.finishing) {
4348 removeActivityFromHistoryLocked(r);
4349 removedFromHistory = true;
4350 } else {
4351 r.state = ActivityState.DESTROYED;
4352 }
4353 }
4354
4355 r.configChangeFlags = 0;
4356
Dianne Hackborn03abb812010-01-04 18:43:19 -08004357 if (!mLRUActivities.remove(r) && hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4359 }
4360
4361 return removedFromHistory;
4362 }
4363
Dianne Hackborn03abb812010-01-04 18:43:19 -08004364 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 int i = list.size();
4366 if (localLOGV) Log.v(
4367 TAG, "Removing app " + app + " from list " + list
4368 + " with " + i + " entries");
4369 while (i > 0) {
4370 i--;
4371 HistoryRecord r = (HistoryRecord)list.get(i);
4372 if (localLOGV) Log.v(
4373 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4374 if (r.app == app) {
4375 if (localLOGV) Log.v(TAG, "Removing this entry!");
4376 list.remove(i);
4377 }
4378 }
4379 }
4380
4381 /**
4382 * Main function for removing an existing process from the activity manager
4383 * as a result of that process going away. Clears out all connections
4384 * to the process.
4385 */
4386 private final void handleAppDiedLocked(ProcessRecord app,
4387 boolean restarting) {
4388 cleanUpApplicationRecordLocked(app, restarting, -1);
4389 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004390 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 }
4392
4393 // Just in case...
4394 if (mPausingActivity != null && mPausingActivity.app == app) {
4395 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
4396 mPausingActivity = null;
4397 }
4398 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4399 mLastPausedActivity = null;
4400 }
4401
4402 // Remove this application's activities from active lists.
4403 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4404 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4405 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4406 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4407
4408 boolean atTop = true;
4409 boolean hasVisibleActivities = false;
4410
4411 // Clean out the history list.
4412 int i = mHistory.size();
4413 if (localLOGV) Log.v(
4414 TAG, "Removing app " + app + " from history with " + i + " entries");
4415 while (i > 0) {
4416 i--;
4417 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4418 if (localLOGV) Log.v(
4419 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4420 if (r.app == app) {
4421 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4422 if (localLOGV) Log.v(
4423 TAG, "Removing this entry! frozen=" + r.haveState
4424 + " finishing=" + r.finishing);
4425 mHistory.remove(i);
4426
4427 r.inHistory = false;
4428 mWindowManager.removeAppToken(r);
4429 if (VALIDATE_TOKENS) {
4430 mWindowManager.validateAppTokens(mHistory);
4431 }
4432 removeActivityUriPermissionsLocked(r);
4433
4434 } else {
4435 // We have the current state for this activity, so
4436 // it can be restarted later when needed.
4437 if (localLOGV) Log.v(
4438 TAG, "Keeping entry, setting app to null");
4439 if (r.visible) {
4440 hasVisibleActivities = true;
4441 }
4442 r.app = null;
4443 r.nowVisible = false;
4444 if (!r.haveState) {
4445 r.icicle = null;
4446 }
4447 }
4448
4449 cleanUpActivityLocked(r, true);
4450 r.state = ActivityState.STOPPED;
4451 }
4452 atTop = false;
4453 }
4454
4455 app.activities.clear();
4456
4457 if (app.instrumentationClass != null) {
4458 Log.w(TAG, "Crash of app " + app.processName
4459 + " running instrumentation " + app.instrumentationClass);
4460 Bundle info = new Bundle();
4461 info.putString("shortMsg", "Process crashed.");
4462 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4463 }
4464
4465 if (!restarting) {
4466 if (!resumeTopActivityLocked(null)) {
4467 // If there was nothing to resume, and we are not already
4468 // restarting this process, but there is a visible activity that
4469 // is hosted by the process... then make sure all visible
4470 // activities are running, taking care of restarting this
4471 // process.
4472 if (hasVisibleActivities) {
4473 ensureActivitiesVisibleLocked(null, 0);
4474 }
4475 }
4476 }
4477 }
4478
4479 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4480 IBinder threadBinder = thread.asBinder();
4481
4482 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004483 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4484 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4486 return i;
4487 }
4488 }
4489 return -1;
4490 }
4491
4492 private final ProcessRecord getRecordForAppLocked(
4493 IApplicationThread thread) {
4494 if (thread == null) {
4495 return null;
4496 }
4497
4498 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004499 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 }
4501
4502 private final void appDiedLocked(ProcessRecord app, int pid,
4503 IApplicationThread thread) {
4504
4505 mProcDeaths[0]++;
4506
4507 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4508 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4509 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004510 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 if (localLOGV) Log.v(
4512 TAG, "Dying app: " + app + ", pid: " + pid
4513 + ", thread: " + thread.asBinder());
4514 boolean doLowMem = app.instrumentationClass == null;
4515 handleAppDiedLocked(app, false);
4516
4517 if (doLowMem) {
4518 // If there are no longer any background processes running,
4519 // and the app that died was not running instrumentation,
4520 // then tell everyone we are now low on memory.
4521 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004522 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4523 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4525 haveBg = true;
4526 break;
4527 }
4528 }
4529
4530 if (!haveBg) {
4531 Log.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004532 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004533 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004534 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4535 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004536 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004537 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4538 // The low memory report is overriding any current
4539 // state for a GC request. Make sure to do
4540 // visible/foreground processes first.
4541 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4542 rec.lastRequestedGc = 0;
4543 } else {
4544 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004546 rec.reportLowMemory = true;
4547 rec.lastLowMemory = now;
4548 mProcessesToGc.remove(rec);
4549 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 }
4551 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004552 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004553 }
4554 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004555 } else if (DEBUG_PROCESSES) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 Log.d(TAG, "Received spurious death notification for thread "
4557 + thread.asBinder());
4558 }
4559 }
4560
Dan Egnor42471dd2010-01-07 17:25:22 -08004561 /**
4562 * If a stack trace dump file is configured, dump process stack traces.
4563 * @param pids of dalvik VM processes to dump stack traces for
4564 * @return file containing stack traces, or null if no dump file is configured
4565 */
4566 private static File dumpStackTraces(ArrayList<Integer> pids) {
4567 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4568 if (tracesPath == null || tracesPath.length() == 0) {
4569 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004571
4572 File tracesFile = new File(tracesPath);
4573 try {
4574 File tracesDir = tracesFile.getParentFile();
4575 if (!tracesDir.exists()) tracesFile.mkdirs();
4576 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4577
4578 if (tracesFile.exists()) tracesFile.delete();
4579 tracesFile.createNewFile();
4580 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4581 } catch (IOException e) {
4582 Log.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
4583 return null;
4584 }
4585
4586 // Use a FileObserver to detect when traces finish writing.
4587 // The order of traces is considered important to maintain for legibility.
4588 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4589 public synchronized void onEvent(int event, String path) { notify(); }
4590 };
4591
4592 try {
4593 observer.startWatching();
4594 int num = pids.size();
4595 for (int i = 0; i < num; i++) {
4596 synchronized (observer) {
4597 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4598 observer.wait(200); // Wait for write-close, give up after 200msec
4599 }
4600 }
4601 } catch (InterruptedException e) {
4602 Log.wtf(TAG, e);
4603 } finally {
4604 observer.stopWatching();
4605 }
4606
4607 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 }
4609
Dan Egnor42471dd2010-01-07 17:25:22 -08004610 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4611 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 if (app.notResponding || app.crashing) {
4613 return;
4614 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004617 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4618 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619
Dan Egnor42471dd2010-01-07 17:25:22 -08004620 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4621 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4622 pids.add(app.pid);
4623
4624 int parentPid = app.pid;
4625 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4626 if (parentPid != app.pid) pids.add(parentPid);
4627
4628 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4629
4630 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4631 ProcessRecord r = mLruProcesses.get(i);
4632 if (r != null && r.thread != null) {
4633 int pid = r.pid;
4634 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 }
4636 }
4637
Dan Egnor42471dd2010-01-07 17:25:22 -08004638 File tracesFile = dumpStackTraces(pids);
4639
4640 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004641 StringBuilder info = mStringBuilder;
4642 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004643 info.append("ANR in ").append(app.processName);
4644 if (activity != null && activity.shortComponentName != null) {
4645 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 if (annotation != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004648 info.append("\nReason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004650 if (parent != null && parent != activity) {
4651 info.append("\nParent: ").append(parent.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653
Dan Egnor42471dd2010-01-07 17:25:22 -08004654 String cpuInfo = null;
4655 if (MONITOR_CPU_USAGE) {
4656 updateCpuStatsNow();
4657 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4658 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 }
4660
Dan Egnor42471dd2010-01-07 17:25:22 -08004661 Log.e(TAG, info.toString());
4662 if (tracesFile == null) {
4663 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4664 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4665 }
4666
4667 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4668
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004669 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004671 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4672 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004674 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4675 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 }
4677 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004678 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 }
4680 }
4681
Dan Egnor42471dd2010-01-07 17:25:22 -08004682 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4683 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4684 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4685 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4686 Process.killProcess(app.pid);
4687 return;
4688 }
4689
4690 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 makeAppNotRespondingLocked(app,
4692 activity != null ? activity.shortComponentName : null,
4693 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004694 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004695
4696 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 Message msg = Message.obtain();
4698 HashMap map = new HashMap();
4699 msg.what = SHOW_NOT_RESPONDING_MSG;
4700 msg.obj = map;
4701 map.put("app", app);
4702 if (activity != null) {
4703 map.put("activity", activity);
4704 }
4705
4706 mHandler.sendMessage(msg);
4707 return;
4708 }
4709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 private final void decPersistentCountLocked(ProcessRecord app)
4711 {
4712 app.persistentActivities--;
4713 if (app.persistentActivities > 0) {
4714 // Still more of 'em...
4715 return;
4716 }
4717 if (app.persistent) {
4718 // Ah, but the application itself is persistent. Whatever!
4719 return;
4720 }
4721
4722 // App is no longer persistent... make sure it and the ones
4723 // following it in the LRU list have the correc oom_adj.
4724 updateOomAdjLocked();
4725 }
4726
4727 public void setPersistent(IBinder token, boolean isPersistent) {
4728 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4729 != PackageManager.PERMISSION_GRANTED) {
4730 String msg = "Permission Denial: setPersistent() from pid="
4731 + Binder.getCallingPid()
4732 + ", uid=" + Binder.getCallingUid()
4733 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4734 Log.w(TAG, msg);
4735 throw new SecurityException(msg);
4736 }
4737
4738 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004739 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 if (index < 0) {
4741 return;
4742 }
4743 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4744 ProcessRecord app = r.app;
4745
4746 if (localLOGV) Log.v(
4747 TAG, "Setting persistence " + isPersistent + ": " + r);
4748
4749 if (isPersistent) {
4750 if (r.persistent) {
4751 // Okay okay, I heard you already!
4752 if (localLOGV) Log.v(TAG, "Already persistent!");
4753 return;
4754 }
4755 r.persistent = true;
4756 app.persistentActivities++;
4757 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4758 if (app.persistentActivities > 1) {
4759 // We aren't the first...
4760 if (localLOGV) Log.v(TAG, "Not the first!");
4761 return;
4762 }
4763 if (app.persistent) {
4764 // This would be redundant.
4765 if (localLOGV) Log.v(TAG, "App is persistent!");
4766 return;
4767 }
4768
4769 // App is now persistent... make sure it and the ones
4770 // following it now have the correct oom_adj.
4771 final long origId = Binder.clearCallingIdentity();
4772 updateOomAdjLocked();
4773 Binder.restoreCallingIdentity(origId);
4774
4775 } else {
4776 if (!r.persistent) {
4777 // Okay okay, I heard you already!
4778 return;
4779 }
4780 r.persistent = false;
4781 final long origId = Binder.clearCallingIdentity();
4782 decPersistentCountLocked(app);
4783 Binder.restoreCallingIdentity(origId);
4784
4785 }
4786 }
4787 }
4788
4789 public boolean clearApplicationUserData(final String packageName,
4790 final IPackageDataObserver observer) {
4791 int uid = Binder.getCallingUid();
4792 int pid = Binder.getCallingPid();
4793 long callingId = Binder.clearCallingIdentity();
4794 try {
4795 IPackageManager pm = ActivityThread.getPackageManager();
4796 int pkgUid = -1;
4797 synchronized(this) {
4798 try {
4799 pkgUid = pm.getPackageUid(packageName);
4800 } catch (RemoteException e) {
4801 }
4802 if (pkgUid == -1) {
4803 Log.w(TAG, "Invalid packageName:" + packageName);
4804 return false;
4805 }
4806 if (uid == pkgUid || checkComponentPermission(
4807 android.Manifest.permission.CLEAR_APP_USER_DATA,
4808 pid, uid, -1)
4809 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004810 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 } else {
4812 throw new SecurityException(pid+" does not have permission:"+
4813 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4814 "for process:"+packageName);
4815 }
4816 }
4817
4818 try {
4819 //clear application user data
4820 pm.clearApplicationUserData(packageName, observer);
4821 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4822 Uri.fromParts("package", packageName, null));
4823 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4824 broadcastIntentLocked(null, null, intent,
4825 null, null, 0, null, null, null,
4826 false, false, MY_PID, Process.SYSTEM_UID);
4827 } catch (RemoteException e) {
4828 }
4829 } finally {
4830 Binder.restoreCallingIdentity(callingId);
4831 }
4832 return true;
4833 }
4834
Dianne Hackborn03abb812010-01-04 18:43:19 -08004835 public void killBackgroundProcesses(final String packageName) {
4836 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4837 != PackageManager.PERMISSION_GRANTED &&
4838 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4839 != PackageManager.PERMISSION_GRANTED) {
4840 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 + Binder.getCallingPid()
4842 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004843 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 Log.w(TAG, msg);
4845 throw new SecurityException(msg);
4846 }
4847
4848 long callingId = Binder.clearCallingIdentity();
4849 try {
4850 IPackageManager pm = ActivityThread.getPackageManager();
4851 int pkgUid = -1;
4852 synchronized(this) {
4853 try {
4854 pkgUid = pm.getPackageUid(packageName);
4855 } catch (RemoteException e) {
4856 }
4857 if (pkgUid == -1) {
4858 Log.w(TAG, "Invalid packageName: " + packageName);
4859 return;
4860 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004861 killPackageProcessesLocked(packageName, pkgUid,
4862 SECONDARY_SERVER_ADJ, false);
4863 }
4864 } finally {
4865 Binder.restoreCallingIdentity(callingId);
4866 }
4867 }
4868
4869 public void forceStopPackage(final String packageName) {
4870 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4871 != PackageManager.PERMISSION_GRANTED) {
4872 String msg = "Permission Denial: forceStopPackage() from pid="
4873 + Binder.getCallingPid()
4874 + ", uid=" + Binder.getCallingUid()
4875 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4876 Log.w(TAG, msg);
4877 throw new SecurityException(msg);
4878 }
4879
4880 long callingId = Binder.clearCallingIdentity();
4881 try {
4882 IPackageManager pm = ActivityThread.getPackageManager();
4883 int pkgUid = -1;
4884 synchronized(this) {
4885 try {
4886 pkgUid = pm.getPackageUid(packageName);
4887 } catch (RemoteException e) {
4888 }
4889 if (pkgUid == -1) {
4890 Log.w(TAG, "Invalid packageName: " + packageName);
4891 return;
4892 }
4893 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 }
4895 } finally {
4896 Binder.restoreCallingIdentity(callingId);
4897 }
4898 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004899
4900 /*
4901 * The pkg name and uid have to be specified.
4902 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4903 */
4904 public void killApplicationWithUid(String pkg, int uid) {
4905 if (pkg == null) {
4906 return;
4907 }
4908 // Make sure the uid is valid.
4909 if (uid < 0) {
4910 Log.w(TAG, "Invalid uid specified for pkg : " + pkg);
4911 return;
4912 }
4913 int callerUid = Binder.getCallingUid();
4914 // Only the system server can kill an application
4915 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004916 // Post an aysnc message to kill the application
4917 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4918 msg.arg1 = uid;
4919 msg.arg2 = 0;
4920 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004921 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004922 } else {
4923 throw new SecurityException(callerUid + " cannot kill pkg: " +
4924 pkg);
4925 }
4926 }
4927
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004928 public void closeSystemDialogs(String reason) {
4929 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
4930 if (reason != null) {
4931 intent.putExtra("reason", reason);
4932 }
4933
4934 final int uid = Binder.getCallingUid();
4935 final long origId = Binder.clearCallingIdentity();
4936 synchronized (this) {
4937 int i = mWatchers.beginBroadcast();
4938 while (i > 0) {
4939 i--;
4940 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4941 if (w != null) {
4942 try {
4943 w.closingSystemDialogs(reason);
4944 } catch (RemoteException e) {
4945 }
4946 }
4947 }
4948 mWatchers.finishBroadcast();
4949
Dianne Hackbornffa42482009-09-23 22:20:11 -07004950 mWindowManager.closeSystemDialogs(reason);
4951
4952 for (i=mHistory.size()-1; i>=0; i--) {
4953 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4954 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4955 finishActivityLocked(r, i,
4956 Activity.RESULT_CANCELED, null, "close-sys");
4957 }
4958 }
4959
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004960 broadcastIntentLocked(null, null, intent, null,
4961 null, 0, null, null, null, false, false, -1, uid);
4962 }
4963 Binder.restoreCallingIdentity(origId);
4964 }
4965
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004966 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004967 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004968 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4969 for (int i=pids.length-1; i>=0; i--) {
4970 infos[i] = new Debug.MemoryInfo();
4971 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004972 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004973 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004974 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004975
4976 public void killApplicationProcess(String processName, int uid) {
4977 if (processName == null) {
4978 return;
4979 }
4980
4981 int callerUid = Binder.getCallingUid();
4982 // Only the system server can kill an application
4983 if (callerUid == Process.SYSTEM_UID) {
4984 synchronized (this) {
4985 ProcessRecord app = getProcessRecordLocked(processName, uid);
4986 if (app != null) {
4987 try {
4988 app.thread.scheduleSuicide();
4989 } catch (RemoteException e) {
4990 // If the other end already died, then our work here is done.
4991 }
4992 } else {
4993 Log.w(TAG, "Process/uid not found attempting kill of "
4994 + processName + " / " + uid);
4995 }
4996 }
4997 } else {
4998 throw new SecurityException(callerUid + " cannot kill app process: " +
4999 processName);
5000 }
5001 }
5002
Dianne Hackborn03abb812010-01-04 18:43:19 -08005003 private void forceStopPackageLocked(final String packageName, int uid) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005004 forceStopPackageLocked(packageName, uid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5006 Uri.fromParts("package", packageName, null));
5007 intent.putExtra(Intent.EXTRA_UID, uid);
5008 broadcastIntentLocked(null, null, intent,
5009 null, null, 0, null, null, null,
5010 false, false, MY_PID, Process.SYSTEM_UID);
5011 }
5012
Dianne Hackborn03abb812010-01-04 18:43:19 -08005013 private final void killPackageProcessesLocked(String packageName, int uid,
5014 int minOomAdj, boolean callerWillRestart) {
5015 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016
Dianne Hackborn03abb812010-01-04 18:43:19 -08005017 // Remove all processes this package may have touched: all with the
5018 // same UID (except for the system or root user), and all whose name
5019 // matches the package name.
5020 final String procNamePrefix = packageName + ":";
5021 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5022 final int NA = apps.size();
5023 for (int ia=0; ia<NA; ia++) {
5024 ProcessRecord app = apps.valueAt(ia);
5025 if (app.removed) {
5026 procs.add(app);
5027 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5028 || app.processName.equals(packageName)
5029 || app.processName.startsWith(procNamePrefix)) {
5030 if (app.setAdj >= minOomAdj) {
5031 app.removed = true;
5032 procs.add(app);
5033 }
5034 }
5035 }
5036 }
5037
5038 int N = procs.size();
5039 for (int i=0; i<N; i++) {
5040 removeProcessLocked(procs.get(i), callerWillRestart);
5041 }
5042 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005043
Dianne Hackborn03abb812010-01-04 18:43:19 -08005044 private final void forceStopPackageLocked(String name, int uid,
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005045 boolean callerWillRestart, boolean purgeCache) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 int i, N;
5047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 if (uid < 0) {
5049 try {
5050 uid = ActivityThread.getPackageManager().getPackageUid(name);
5051 } catch (RemoteException e) {
5052 }
5053 }
5054
Dianne Hackborn03abb812010-01-04 18:43:19 -08005055 Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
5056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5058 while (badApps.hasNext()) {
5059 SparseArray<Long> ba = badApps.next();
5060 if (ba.get(uid) != null) {
5061 badApps.remove();
5062 }
5063 }
5064
Dianne Hackborn03abb812010-01-04 18:43:19 -08005065 killPackageProcessesLocked(name, uid, -100, callerWillRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066
5067 for (i=mHistory.size()-1; i>=0; i--) {
5068 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5069 if (r.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005070 Log.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 if (r.app != null) {
5072 r.app.removed = true;
5073 }
5074 r.app = null;
5075 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5076 }
5077 }
5078
5079 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5080 for (ServiceRecord service : mServices.values()) {
5081 if (service.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005082 Log.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 if (service.app != null) {
5084 service.app.removed = true;
5085 }
5086 service.app = null;
5087 services.add(service);
5088 }
5089 }
5090
5091 N = services.size();
5092 for (i=0; i<N; i++) {
5093 bringDownServiceLocked(services.get(i), true);
5094 }
5095
5096 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005097 if (purgeCache) {
5098 AttributeCache ac = AttributeCache.instance();
5099 if (ac != null) {
5100 ac.removePackage(name);
5101 }
5102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 }
5104
5105 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5106 final String name = app.processName;
5107 final int uid = app.info.uid;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005108 if (DEBUG_PROCESSES) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 TAG, "Force removing process " + app + " (" + name
5110 + "/" + uid + ")");
5111
5112 mProcessNames.remove(name, uid);
5113 boolean needRestart = false;
5114 if (app.pid > 0 && app.pid != MY_PID) {
5115 int pid = app.pid;
5116 synchronized (mPidsSelfLocked) {
5117 mPidsSelfLocked.remove(pid);
5118 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5119 }
5120 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005121 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 Process.killProcess(pid);
5123
5124 if (app.persistent) {
5125 if (!callerWillRestart) {
5126 addAppLocked(app.info);
5127 } else {
5128 needRestart = true;
5129 }
5130 }
5131 } else {
5132 mRemovedProcesses.add(app);
5133 }
5134
5135 return needRestart;
5136 }
5137
5138 private final void processStartTimedOutLocked(ProcessRecord app) {
5139 final int pid = app.pid;
5140 boolean gone = false;
5141 synchronized (mPidsSelfLocked) {
5142 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5143 if (knownApp != null && knownApp.thread == null) {
5144 mPidsSelfLocked.remove(pid);
5145 gone = true;
5146 }
5147 }
5148
5149 if (gone) {
5150 Log.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005151 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005152 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005154 // Take care of any launching providers waiting for this process.
5155 checkAppInLaunchingProvidersLocked(app, true);
5156 // Take care of any services that are waiting for the process.
5157 for (int i=0; i<mPendingServices.size(); i++) {
5158 ServiceRecord sr = mPendingServices.get(i);
5159 if (app.info.uid == sr.appInfo.uid
5160 && app.processName.equals(sr.processName)) {
5161 Log.w(TAG, "Forcing bringing down service: " + sr);
5162 mPendingServices.remove(i);
5163 i--;
5164 bringDownServiceLocked(sr, true);
5165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005167 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005168 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
5169 Log.w(TAG, "Unattached app died before backup, skipping");
5170 try {
5171 IBackupManager bm = IBackupManager.Stub.asInterface(
5172 ServiceManager.getService(Context.BACKUP_SERVICE));
5173 bm.agentDisconnected(app.info.packageName);
5174 } catch (RemoteException e) {
5175 // Can't happen; the backup manager is local
5176 }
5177 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005178 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
5179 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
5180 mPendingBroadcast = null;
5181 scheduleBroadcastsLocked();
5182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005183 } else {
5184 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
5185 }
5186 }
5187
5188 private final boolean attachApplicationLocked(IApplicationThread thread,
5189 int pid) {
5190
5191 // Find the application record that is being attached... either via
5192 // the pid if we are running in multiple processes, or just pull the
5193 // next app record if we are emulating process with anonymous threads.
5194 ProcessRecord app;
5195 if (pid != MY_PID && pid >= 0) {
5196 synchronized (mPidsSelfLocked) {
5197 app = mPidsSelfLocked.get(pid);
5198 }
5199 } else if (mStartingProcesses.size() > 0) {
5200 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005201 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 } else {
5203 app = null;
5204 }
5205
5206 if (app == null) {
5207 Log.w(TAG, "No pending application record for pid " + pid
5208 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005209 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 if (pid > 0 && pid != MY_PID) {
5211 Process.killProcess(pid);
5212 } else {
5213 try {
5214 thread.scheduleExit();
5215 } catch (Exception e) {
5216 // Ignore exceptions.
5217 }
5218 }
5219 return false;
5220 }
5221
5222 // If this application record is still attached to a previous
5223 // process, clean it up now.
5224 if (app.thread != null) {
5225 handleAppDiedLocked(app, true);
5226 }
5227
5228 // Tell the process all about itself.
5229
5230 if (localLOGV) Log.v(
5231 TAG, "Binding process pid " + pid + " to record " + app);
5232
5233 String processName = app.processName;
5234 try {
5235 thread.asBinder().linkToDeath(new AppDeathRecipient(
5236 app, pid, thread), 0);
5237 } catch (RemoteException e) {
5238 app.resetPackageList();
5239 startProcessLocked(app, "link fail", processName);
5240 return false;
5241 }
5242
Doug Zongker2bec3d42009-12-04 12:52:44 -08005243 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244
5245 app.thread = thread;
5246 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005247 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5248 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 app.forcingToForeground = null;
5250 app.foregroundServices = false;
5251 app.debugging = false;
5252
5253 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5254
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005255 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5256 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005258 if (!normalMode) {
5259 Log.i(TAG, "Launching preboot mode app: " + app);
5260 }
5261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005262 if (localLOGV) Log.v(
5263 TAG, "New app record " + app
5264 + " thread=" + thread.asBinder() + " pid=" + pid);
5265 try {
5266 int testMode = IApplicationThread.DEBUG_OFF;
5267 if (mDebugApp != null && mDebugApp.equals(processName)) {
5268 testMode = mWaitForDebugger
5269 ? IApplicationThread.DEBUG_WAIT
5270 : IApplicationThread.DEBUG_ON;
5271 app.debugging = true;
5272 if (mDebugTransient) {
5273 mDebugApp = mOrigDebugApp;
5274 mWaitForDebugger = mOrigWaitForDebugger;
5275 }
5276 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005277
Christopher Tate181fafa2009-05-14 11:12:14 -07005278 // If the app is being launched for restore or full backup, set it up specially
5279 boolean isRestrictedBackupMode = false;
5280 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5281 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5282 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5283 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005284
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005285 ensurePackageDexOpt(app.instrumentationInfo != null
5286 ? app.instrumentationInfo.packageName
5287 : app.info.packageName);
5288 if (app.instrumentationClass != null) {
5289 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005290 }
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005291 if (DEBUG_CONFIGURATION) Log.v(TAG, "Binding proc "
5292 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005293 thread.bindApplication(processName, app.instrumentationInfo != null
5294 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 app.instrumentationClass, app.instrumentationProfileFile,
5296 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005297 isRestrictedBackupMode || !normalMode,
5298 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005299 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005300 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 } catch (Exception e) {
5302 // todo: Yikes! What should we do? For now we will try to
5303 // start another process, but that could easily get us in
5304 // an infinite loop of restarting processes...
5305 Log.w(TAG, "Exception thrown during bind!", e);
5306
5307 app.resetPackageList();
5308 startProcessLocked(app, "bind fail", processName);
5309 return false;
5310 }
5311
5312 // Remove this record from the list of starting applications.
5313 mPersistentStartingProcesses.remove(app);
5314 mProcessesOnHold.remove(app);
5315
5316 boolean badApp = false;
5317 boolean didSomething = false;
5318
5319 // See if the top visible activity is waiting to run in this process...
5320 HistoryRecord hr = topRunningActivityLocked(null);
5321 if (hr != null) {
5322 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5323 && processName.equals(hr.processName)) {
5324 try {
5325 if (realStartActivityLocked(hr, app, true, true)) {
5326 didSomething = true;
5327 }
5328 } catch (Exception e) {
5329 Log.w(TAG, "Exception in new application when starting activity "
5330 + hr.intent.getComponent().flattenToShortString(), e);
5331 badApp = true;
5332 }
5333 } else {
5334 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5335 }
5336 }
5337
5338 // Find any services that should be running in this process...
5339 if (!badApp && mPendingServices.size() > 0) {
5340 ServiceRecord sr = null;
5341 try {
5342 for (int i=0; i<mPendingServices.size(); i++) {
5343 sr = mPendingServices.get(i);
5344 if (app.info.uid != sr.appInfo.uid
5345 || !processName.equals(sr.processName)) {
5346 continue;
5347 }
5348
5349 mPendingServices.remove(i);
5350 i--;
5351 realStartServiceLocked(sr, app);
5352 didSomething = true;
5353 }
5354 } catch (Exception e) {
5355 Log.w(TAG, "Exception in new application when starting service "
5356 + sr.shortName, e);
5357 badApp = true;
5358 }
5359 }
5360
5361 // Check if the next broadcast receiver is in this process...
5362 BroadcastRecord br = mPendingBroadcast;
5363 if (!badApp && br != null && br.curApp == app) {
5364 try {
5365 mPendingBroadcast = null;
5366 processCurBroadcastLocked(br, app);
5367 didSomething = true;
5368 } catch (Exception e) {
5369 Log.w(TAG, "Exception in new application when starting receiver "
5370 + br.curComponent.flattenToShortString(), e);
5371 badApp = true;
5372 logBroadcastReceiverDiscard(br);
5373 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5374 br.resultExtras, br.resultAbort, true);
5375 scheduleBroadcastsLocked();
5376 }
5377 }
5378
Christopher Tate181fafa2009-05-14 11:12:14 -07005379 // Check whether the next backup agent is in this process...
5380 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
5381 if (DEBUG_BACKUP) Log.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005382 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005383 try {
5384 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5385 } catch (Exception e) {
5386 Log.w(TAG, "Exception scheduling backup agent creation: ");
5387 e.printStackTrace();
5388 }
5389 }
5390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 if (badApp) {
5392 // todo: Also need to kill application to deal with all
5393 // kinds of exceptions.
5394 handleAppDiedLocked(app, false);
5395 return false;
5396 }
5397
5398 if (!didSomething) {
5399 updateOomAdjLocked();
5400 }
5401
5402 return true;
5403 }
5404
5405 public final void attachApplication(IApplicationThread thread) {
5406 synchronized (this) {
5407 int callingPid = Binder.getCallingPid();
5408 final long origId = Binder.clearCallingIdentity();
5409 attachApplicationLocked(thread, callingPid);
5410 Binder.restoreCallingIdentity(origId);
5411 }
5412 }
5413
Dianne Hackborne88846e2009-09-30 21:34:25 -07005414 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005415 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005416 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 Binder.restoreCallingIdentity(origId);
5418 }
5419
5420 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5421 boolean remove) {
5422 int N = mStoppingActivities.size();
5423 if (N <= 0) return null;
5424
5425 ArrayList<HistoryRecord> stops = null;
5426
5427 final boolean nowVisible = mResumedActivity != null
5428 && mResumedActivity.nowVisible
5429 && !mResumedActivity.waitingVisible;
5430 for (int i=0; i<N; i++) {
5431 HistoryRecord s = mStoppingActivities.get(i);
5432 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
5433 + nowVisible + " waitingVisible=" + s.waitingVisible
5434 + " finishing=" + s.finishing);
5435 if (s.waitingVisible && nowVisible) {
5436 mWaitingVisibleActivities.remove(s);
5437 s.waitingVisible = false;
5438 if (s.finishing) {
5439 // If this activity is finishing, it is sitting on top of
5440 // everyone else but we now know it is no longer needed...
5441 // so get rid of it. Otherwise, we need to go through the
5442 // normal flow and hide it once we determine that it is
5443 // hidden by the activities in front of it.
5444 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
5445 mWindowManager.setAppVisibility(s, false);
5446 }
5447 }
5448 if (!s.waitingVisible && remove) {
5449 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
5450 if (stops == null) {
5451 stops = new ArrayList<HistoryRecord>();
5452 }
5453 stops.add(s);
5454 mStoppingActivities.remove(i);
5455 N--;
5456 i--;
5457 }
5458 }
5459
5460 return stops;
5461 }
5462
5463 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005464 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005465 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 mWindowManager.enableScreenAfterBoot();
5467 }
5468
Dianne Hackborne88846e2009-09-30 21:34:25 -07005469 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5470 Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
5472
5473 ArrayList<HistoryRecord> stops = null;
5474 ArrayList<HistoryRecord> finishes = null;
5475 ArrayList<HistoryRecord> thumbnails = null;
5476 int NS = 0;
5477 int NF = 0;
5478 int NT = 0;
5479 IApplicationThread sendThumbnail = null;
5480 boolean booting = false;
5481 boolean enableScreen = false;
5482
5483 synchronized (this) {
5484 if (token != null) {
5485 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5486 }
5487
5488 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005489 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 if (index >= 0) {
5491 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5492
Dianne Hackborne88846e2009-09-30 21:34:25 -07005493 // This is a hack to semi-deal with a race condition
5494 // in the client where it can be constructed with a
5495 // newer configuration from when we asked it to launch.
5496 // We'll update with whatever configuration it now says
5497 // it used to launch.
5498 if (config != null) {
5499 r.configuration = config;
5500 }
5501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 // No longer need to keep the device awake.
5503 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5504 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5505 mLaunchingActivity.release();
5506 }
5507
5508 // We are now idle. If someone is waiting for a thumbnail from
5509 // us, we can now deliver.
5510 r.idle = true;
5511 scheduleAppGcsLocked();
5512 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5513 sendThumbnail = r.app.thread;
5514 r.thumbnailNeeded = false;
5515 }
5516
5517 // If this activity is fullscreen, set up to hide those under it.
5518
5519 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
5520 ensureActivitiesVisibleLocked(null, 0);
5521
5522 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
5523 if (!mBooted && !fromTimeout) {
5524 mBooted = true;
5525 enableScreen = true;
5526 }
5527 }
5528
5529 // Atomically retrieve all of the other things to do.
5530 stops = processStoppingActivitiesLocked(true);
5531 NS = stops != null ? stops.size() : 0;
5532 if ((NF=mFinishingActivities.size()) > 0) {
5533 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5534 mFinishingActivities.clear();
5535 }
5536 if ((NT=mCancelledThumbnails.size()) > 0) {
5537 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5538 mCancelledThumbnails.clear();
5539 }
5540
5541 booting = mBooting;
5542 mBooting = false;
5543 }
5544
5545 int i;
5546
5547 // Send thumbnail if requested.
5548 if (sendThumbnail != null) {
5549 try {
5550 sendThumbnail.requestThumbnail(token);
5551 } catch (Exception e) {
5552 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5553 sendPendingThumbnail(null, token, null, null, true);
5554 }
5555 }
5556
5557 // Stop any activities that are scheduled to do so but have been
5558 // waiting for the next one to start.
5559 for (i=0; i<NS; i++) {
5560 HistoryRecord r = (HistoryRecord)stops.get(i);
5561 synchronized (this) {
5562 if (r.finishing) {
5563 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5564 } else {
5565 stopActivityLocked(r);
5566 }
5567 }
5568 }
5569
5570 // Finish any activities that are scheduled to do so but have been
5571 // waiting for the next one to start.
5572 for (i=0; i<NF; i++) {
5573 HistoryRecord r = (HistoryRecord)finishes.get(i);
5574 synchronized (this) {
5575 destroyActivityLocked(r, true);
5576 }
5577 }
5578
5579 // Report back to any thumbnail receivers.
5580 for (i=0; i<NT; i++) {
5581 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5582 sendPendingThumbnail(r, null, null, null, true);
5583 }
5584
5585 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005586 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 }
5588
5589 trimApplications();
5590 //dump();
5591 //mWindowManager.dump();
5592
5593 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 enableScreenAfterBoot();
5595 }
5596 }
5597
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005598 final void finishBooting() {
5599 // Ensure that any processes we had put on hold are now started
5600 // up.
5601 final int NP = mProcessesOnHold.size();
5602 if (NP > 0) {
5603 ArrayList<ProcessRecord> procs =
5604 new ArrayList<ProcessRecord>(mProcessesOnHold);
5605 for (int ip=0; ip<NP; ip++) {
5606 this.startProcessLocked(procs.get(ip), "on-hold", null);
5607 }
5608 }
5609 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5610 // Tell anyone interested that we are done booting!
5611 synchronized (this) {
5612 broadcastIntentLocked(null, null,
5613 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5614 null, null, 0, null, null,
5615 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5616 false, false, MY_PID, Process.SYSTEM_UID);
5617 }
5618 }
5619 }
5620
5621 final void ensureBootCompleted() {
5622 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005623 boolean enableScreen;
5624 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005625 booting = mBooting;
5626 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005627 enableScreen = !mBooted;
5628 mBooted = true;
5629 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005630
5631 if (booting) {
5632 finishBooting();
5633 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005634
5635 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005636 enableScreenAfterBoot();
5637 }
5638 }
5639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 public final void activityPaused(IBinder token, Bundle icicle) {
5641 // Refuse possible leaked file descriptors
5642 if (icicle != null && icicle.hasFileDescriptors()) {
5643 throw new IllegalArgumentException("File descriptors passed in Bundle");
5644 }
5645
5646 final long origId = Binder.clearCallingIdentity();
5647 activityPaused(token, icicle, false);
5648 Binder.restoreCallingIdentity(origId);
5649 }
5650
5651 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
5652 if (DEBUG_PAUSE) Log.v(
5653 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5654 + ", timeout=" + timeout);
5655
5656 HistoryRecord r = null;
5657
5658 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005659 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005660 if (index >= 0) {
5661 r = (HistoryRecord)mHistory.get(index);
5662 if (!timeout) {
5663 r.icicle = icicle;
5664 r.haveState = true;
5665 }
5666 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5667 if (mPausingActivity == r) {
5668 r.state = ActivityState.PAUSED;
5669 completePauseLocked();
5670 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005671 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 System.identityHashCode(r), r.shortComponentName,
5673 mPausingActivity != null
5674 ? mPausingActivity.shortComponentName : "(none)");
5675 }
5676 }
5677 }
5678 }
5679
5680 public final void activityStopped(IBinder token, Bitmap thumbnail,
5681 CharSequence description) {
5682 if (localLOGV) Log.v(
5683 TAG, "Activity stopped: token=" + token);
5684
5685 HistoryRecord r = null;
5686
5687 final long origId = Binder.clearCallingIdentity();
5688
5689 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005690 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 if (index >= 0) {
5692 r = (HistoryRecord)mHistory.get(index);
5693 r.thumbnail = thumbnail;
5694 r.description = description;
5695 r.stopped = true;
5696 r.state = ActivityState.STOPPED;
5697 if (!r.finishing) {
5698 if (r.configDestroy) {
5699 destroyActivityLocked(r, true);
5700 resumeTopActivityLocked(null);
5701 }
5702 }
5703 }
5704 }
5705
5706 if (r != null) {
5707 sendPendingThumbnail(r, null, null, null, false);
5708 }
5709
5710 trimApplications();
5711
5712 Binder.restoreCallingIdentity(origId);
5713 }
5714
5715 public final void activityDestroyed(IBinder token) {
5716 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
5717 synchronized (this) {
5718 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5719
Dianne Hackborn75b03852009-06-12 15:43:26 -07005720 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 if (index >= 0) {
5722 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5723 if (r.state == ActivityState.DESTROYING) {
5724 final long origId = Binder.clearCallingIdentity();
5725 removeActivityFromHistoryLocked(r);
5726 Binder.restoreCallingIdentity(origId);
5727 }
5728 }
5729 }
5730 }
5731
5732 public String getCallingPackage(IBinder token) {
5733 synchronized (this) {
5734 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005735 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005736 }
5737 }
5738
5739 public ComponentName getCallingActivity(IBinder token) {
5740 synchronized (this) {
5741 HistoryRecord r = getCallingRecordLocked(token);
5742 return r != null ? r.intent.getComponent() : null;
5743 }
5744 }
5745
5746 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005747 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005748 if (index >= 0) {
5749 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5750 if (r != null) {
5751 return r.resultTo;
5752 }
5753 }
5754 return null;
5755 }
5756
5757 public ComponentName getActivityClassForToken(IBinder token) {
5758 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005759 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 if (index >= 0) {
5761 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5762 return r.intent.getComponent();
5763 }
5764 return null;
5765 }
5766 }
5767
5768 public String getPackageForToken(IBinder token) {
5769 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005770 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 if (index >= 0) {
5772 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5773 return r.packageName;
5774 }
5775 return null;
5776 }
5777 }
5778
5779 public IIntentSender getIntentSender(int type,
5780 String packageName, IBinder token, String resultWho,
5781 int requestCode, Intent intent, String resolvedType, int flags) {
5782 // Refuse possible leaked file descriptors
5783 if (intent != null && intent.hasFileDescriptors() == true) {
5784 throw new IllegalArgumentException("File descriptors passed in Intent");
5785 }
5786
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005787 if (type == INTENT_SENDER_BROADCAST) {
5788 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5789 throw new IllegalArgumentException(
5790 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5791 }
5792 }
5793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 synchronized(this) {
5795 int callingUid = Binder.getCallingUid();
5796 try {
5797 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5798 Process.supportsProcesses()) {
5799 int uid = ActivityThread.getPackageManager()
5800 .getPackageUid(packageName);
5801 if (uid != Binder.getCallingUid()) {
5802 String msg = "Permission Denial: getIntentSender() from pid="
5803 + Binder.getCallingPid()
5804 + ", uid=" + Binder.getCallingUid()
5805 + ", (need uid=" + uid + ")"
5806 + " is not allowed to send as package " + packageName;
5807 Log.w(TAG, msg);
5808 throw new SecurityException(msg);
5809 }
5810 }
5811 } catch (RemoteException e) {
5812 throw new SecurityException(e);
5813 }
5814 HistoryRecord activity = null;
5815 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005816 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005817 if (index < 0) {
5818 return null;
5819 }
5820 activity = (HistoryRecord)mHistory.get(index);
5821 if (activity.finishing) {
5822 return null;
5823 }
5824 }
5825
5826 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5827 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5828 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5829 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5830 |PendingIntent.FLAG_UPDATE_CURRENT);
5831
5832 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5833 type, packageName, activity, resultWho,
5834 requestCode, intent, resolvedType, flags);
5835 WeakReference<PendingIntentRecord> ref;
5836 ref = mIntentSenderRecords.get(key);
5837 PendingIntentRecord rec = ref != null ? ref.get() : null;
5838 if (rec != null) {
5839 if (!cancelCurrent) {
5840 if (updateCurrent) {
5841 rec.key.requestIntent.replaceExtras(intent);
5842 }
5843 return rec;
5844 }
5845 rec.canceled = true;
5846 mIntentSenderRecords.remove(key);
5847 }
5848 if (noCreate) {
5849 return rec;
5850 }
5851 rec = new PendingIntentRecord(this, key, callingUid);
5852 mIntentSenderRecords.put(key, rec.ref);
5853 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5854 if (activity.pendingResults == null) {
5855 activity.pendingResults
5856 = new HashSet<WeakReference<PendingIntentRecord>>();
5857 }
5858 activity.pendingResults.add(rec.ref);
5859 }
5860 return rec;
5861 }
5862 }
5863
5864 public void cancelIntentSender(IIntentSender sender) {
5865 if (!(sender instanceof PendingIntentRecord)) {
5866 return;
5867 }
5868 synchronized(this) {
5869 PendingIntentRecord rec = (PendingIntentRecord)sender;
5870 try {
5871 int uid = ActivityThread.getPackageManager()
5872 .getPackageUid(rec.key.packageName);
5873 if (uid != Binder.getCallingUid()) {
5874 String msg = "Permission Denial: cancelIntentSender() from pid="
5875 + Binder.getCallingPid()
5876 + ", uid=" + Binder.getCallingUid()
5877 + " is not allowed to cancel packges "
5878 + rec.key.packageName;
5879 Log.w(TAG, msg);
5880 throw new SecurityException(msg);
5881 }
5882 } catch (RemoteException e) {
5883 throw new SecurityException(e);
5884 }
5885 cancelIntentSenderLocked(rec, true);
5886 }
5887 }
5888
5889 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5890 rec.canceled = true;
5891 mIntentSenderRecords.remove(rec.key);
5892 if (cleanActivity && rec.key.activity != null) {
5893 rec.key.activity.pendingResults.remove(rec.ref);
5894 }
5895 }
5896
5897 public String getPackageForIntentSender(IIntentSender pendingResult) {
5898 if (!(pendingResult instanceof PendingIntentRecord)) {
5899 return null;
5900 }
5901 synchronized(this) {
5902 try {
5903 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5904 return res.key.packageName;
5905 } catch (ClassCastException e) {
5906 }
5907 }
5908 return null;
5909 }
5910
5911 public void setProcessLimit(int max) {
5912 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5913 "setProcessLimit()");
5914 mProcessLimit = max;
5915 }
5916
5917 public int getProcessLimit() {
5918 return mProcessLimit;
5919 }
5920
5921 void foregroundTokenDied(ForegroundToken token) {
5922 synchronized (ActivityManagerService.this) {
5923 synchronized (mPidsSelfLocked) {
5924 ForegroundToken cur
5925 = mForegroundProcesses.get(token.pid);
5926 if (cur != token) {
5927 return;
5928 }
5929 mForegroundProcesses.remove(token.pid);
5930 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5931 if (pr == null) {
5932 return;
5933 }
5934 pr.forcingToForeground = null;
5935 pr.foregroundServices = false;
5936 }
5937 updateOomAdjLocked();
5938 }
5939 }
5940
5941 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5942 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5943 "setProcessForeground()");
5944 synchronized(this) {
5945 boolean changed = false;
5946
5947 synchronized (mPidsSelfLocked) {
5948 ProcessRecord pr = mPidsSelfLocked.get(pid);
5949 if (pr == null) {
5950 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5951 return;
5952 }
5953 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5954 if (oldToken != null) {
5955 oldToken.token.unlinkToDeath(oldToken, 0);
5956 mForegroundProcesses.remove(pid);
5957 pr.forcingToForeground = null;
5958 changed = true;
5959 }
5960 if (isForeground && token != null) {
5961 ForegroundToken newToken = new ForegroundToken() {
5962 public void binderDied() {
5963 foregroundTokenDied(this);
5964 }
5965 };
5966 newToken.pid = pid;
5967 newToken.token = token;
5968 try {
5969 token.linkToDeath(newToken, 0);
5970 mForegroundProcesses.put(pid, newToken);
5971 pr.forcingToForeground = token;
5972 changed = true;
5973 } catch (RemoteException e) {
5974 // If the process died while doing this, we will later
5975 // do the cleanup with the process death link.
5976 }
5977 }
5978 }
5979
5980 if (changed) {
5981 updateOomAdjLocked();
5982 }
5983 }
5984 }
5985
5986 // =========================================================
5987 // PERMISSIONS
5988 // =========================================================
5989
5990 static class PermissionController extends IPermissionController.Stub {
5991 ActivityManagerService mActivityManagerService;
5992 PermissionController(ActivityManagerService activityManagerService) {
5993 mActivityManagerService = activityManagerService;
5994 }
5995
5996 public boolean checkPermission(String permission, int pid, int uid) {
5997 return mActivityManagerService.checkPermission(permission, pid,
5998 uid) == PackageManager.PERMISSION_GRANTED;
5999 }
6000 }
6001
6002 /**
6003 * This can be called with or without the global lock held.
6004 */
6005 int checkComponentPermission(String permission, int pid, int uid,
6006 int reqUid) {
6007 // We might be performing an operation on behalf of an indirect binder
6008 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6009 // client identity accordingly before proceeding.
6010 Identity tlsIdentity = sCallerIdentity.get();
6011 if (tlsIdentity != null) {
6012 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
6013 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6014 uid = tlsIdentity.uid;
6015 pid = tlsIdentity.pid;
6016 }
6017
6018 // Root, system server and our own process get to do everything.
6019 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6020 !Process.supportsProcesses()) {
6021 return PackageManager.PERMISSION_GRANTED;
6022 }
6023 // If the target requires a specific UID, always fail for others.
6024 if (reqUid >= 0 && uid != reqUid) {
root0369a7c2009-03-23 15:20:47 +01006025 Log.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006026 return PackageManager.PERMISSION_DENIED;
6027 }
6028 if (permission == null) {
6029 return PackageManager.PERMISSION_GRANTED;
6030 }
6031 try {
6032 return ActivityThread.getPackageManager()
6033 .checkUidPermission(permission, uid);
6034 } catch (RemoteException e) {
6035 // Should never happen, but if it does... deny!
6036 Log.e(TAG, "PackageManager is dead?!?", e);
6037 }
6038 return PackageManager.PERMISSION_DENIED;
6039 }
6040
6041 /**
6042 * As the only public entry point for permissions checking, this method
6043 * can enforce the semantic that requesting a check on a null global
6044 * permission is automatically denied. (Internally a null permission
6045 * string is used when calling {@link #checkComponentPermission} in cases
6046 * when only uid-based security is needed.)
6047 *
6048 * This can be called with or without the global lock held.
6049 */
6050 public int checkPermission(String permission, int pid, int uid) {
6051 if (permission == null) {
6052 return PackageManager.PERMISSION_DENIED;
6053 }
6054 return checkComponentPermission(permission, pid, uid, -1);
6055 }
6056
6057 /**
6058 * Binder IPC calls go through the public entry point.
6059 * This can be called with or without the global lock held.
6060 */
6061 int checkCallingPermission(String permission) {
6062 return checkPermission(permission,
6063 Binder.getCallingPid(),
6064 Binder.getCallingUid());
6065 }
6066
6067 /**
6068 * This can be called with or without the global lock held.
6069 */
6070 void enforceCallingPermission(String permission, String func) {
6071 if (checkCallingPermission(permission)
6072 == PackageManager.PERMISSION_GRANTED) {
6073 return;
6074 }
6075
6076 String msg = "Permission Denial: " + func + " from pid="
6077 + Binder.getCallingPid()
6078 + ", uid=" + Binder.getCallingUid()
6079 + " requires " + permission;
6080 Log.w(TAG, msg);
6081 throw new SecurityException(msg);
6082 }
6083
6084 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6085 ProviderInfo pi, int uid, int modeFlags) {
6086 try {
6087 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6088 if ((pi.readPermission != null) &&
6089 (pm.checkUidPermission(pi.readPermission, uid)
6090 != PackageManager.PERMISSION_GRANTED)) {
6091 return false;
6092 }
6093 }
6094 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6095 if ((pi.writePermission != null) &&
6096 (pm.checkUidPermission(pi.writePermission, uid)
6097 != PackageManager.PERMISSION_GRANTED)) {
6098 return false;
6099 }
6100 }
6101 return true;
6102 } catch (RemoteException e) {
6103 return false;
6104 }
6105 }
6106
6107 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6108 int modeFlags) {
6109 // Root gets to do everything.
6110 if (uid == 0 || !Process.supportsProcesses()) {
6111 return true;
6112 }
6113 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6114 if (perms == null) return false;
6115 UriPermission perm = perms.get(uri);
6116 if (perm == null) return false;
6117 return (modeFlags&perm.modeFlags) == modeFlags;
6118 }
6119
6120 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6121 // Another redirected-binder-call permissions check as in
6122 // {@link checkComponentPermission}.
6123 Identity tlsIdentity = sCallerIdentity.get();
6124 if (tlsIdentity != null) {
6125 uid = tlsIdentity.uid;
6126 pid = tlsIdentity.pid;
6127 }
6128
6129 // Our own process gets to do everything.
6130 if (pid == MY_PID) {
6131 return PackageManager.PERMISSION_GRANTED;
6132 }
6133 synchronized(this) {
6134 return checkUriPermissionLocked(uri, uid, modeFlags)
6135 ? PackageManager.PERMISSION_GRANTED
6136 : PackageManager.PERMISSION_DENIED;
6137 }
6138 }
6139
6140 private void grantUriPermissionLocked(int callingUid,
6141 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6142 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6143 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6144 if (modeFlags == 0) {
6145 return;
6146 }
6147
6148 final IPackageManager pm = ActivityThread.getPackageManager();
6149
6150 // If this is not a content: uri, we can't do anything with it.
6151 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
6152 return;
6153 }
6154
6155 String name = uri.getAuthority();
6156 ProviderInfo pi = null;
6157 ContentProviderRecord cpr
6158 = (ContentProviderRecord)mProvidersByName.get(name);
6159 if (cpr != null) {
6160 pi = cpr.info;
6161 } else {
6162 try {
6163 pi = pm.resolveContentProvider(name,
6164 PackageManager.GET_URI_PERMISSION_PATTERNS);
6165 } catch (RemoteException ex) {
6166 }
6167 }
6168 if (pi == null) {
6169 Log.w(TAG, "No content provider found for: " + name);
6170 return;
6171 }
6172
6173 int targetUid;
6174 try {
6175 targetUid = pm.getPackageUid(targetPkg);
6176 if (targetUid < 0) {
6177 return;
6178 }
6179 } catch (RemoteException ex) {
6180 return;
6181 }
6182
6183 // First... does the target actually need this permission?
6184 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6185 // No need to grant the target this permission.
6186 return;
6187 }
6188
6189 // Second... maybe someone else has already granted the
6190 // permission?
6191 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
6192 // No need to grant the target this permission.
6193 return;
6194 }
6195
6196 // Third... is the provider allowing granting of URI permissions?
6197 if (!pi.grantUriPermissions) {
6198 throw new SecurityException("Provider " + pi.packageName
6199 + "/" + pi.name
6200 + " does not allow granting of Uri permissions (uri "
6201 + uri + ")");
6202 }
6203 if (pi.uriPermissionPatterns != null) {
6204 final int N = pi.uriPermissionPatterns.length;
6205 boolean allowed = false;
6206 for (int i=0; i<N; i++) {
6207 if (pi.uriPermissionPatterns[i] != null
6208 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6209 allowed = true;
6210 break;
6211 }
6212 }
6213 if (!allowed) {
6214 throw new SecurityException("Provider " + pi.packageName
6215 + "/" + pi.name
6216 + " does not allow granting of permission to path of Uri "
6217 + uri);
6218 }
6219 }
6220
6221 // Fourth... does the caller itself have permission to access
6222 // this uri?
6223 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6224 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6225 throw new SecurityException("Uid " + callingUid
6226 + " does not have permission to uri " + uri);
6227 }
6228 }
6229
6230 // Okay! So here we are: the caller has the assumed permission
6231 // to the uri, and the target doesn't. Let's now give this to
6232 // the target.
6233
6234 HashMap<Uri, UriPermission> targetUris
6235 = mGrantedUriPermissions.get(targetUid);
6236 if (targetUris == null) {
6237 targetUris = new HashMap<Uri, UriPermission>();
6238 mGrantedUriPermissions.put(targetUid, targetUris);
6239 }
6240
6241 UriPermission perm = targetUris.get(uri);
6242 if (perm == null) {
6243 perm = new UriPermission(targetUid, uri);
6244 targetUris.put(uri, perm);
6245
6246 }
6247 perm.modeFlags |= modeFlags;
6248 if (activity == null) {
6249 perm.globalModeFlags |= modeFlags;
6250 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6251 perm.readActivities.add(activity);
6252 if (activity.readUriPermissions == null) {
6253 activity.readUriPermissions = new HashSet<UriPermission>();
6254 }
6255 activity.readUriPermissions.add(perm);
6256 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6257 perm.writeActivities.add(activity);
6258 if (activity.writeUriPermissions == null) {
6259 activity.writeUriPermissions = new HashSet<UriPermission>();
6260 }
6261 activity.writeUriPermissions.add(perm);
6262 }
6263 }
6264
6265 private void grantUriPermissionFromIntentLocked(int callingUid,
6266 String targetPkg, Intent intent, HistoryRecord activity) {
6267 if (intent == null) {
6268 return;
6269 }
6270 Uri data = intent.getData();
6271 if (data == null) {
6272 return;
6273 }
6274 grantUriPermissionLocked(callingUid, targetPkg, data,
6275 intent.getFlags(), activity);
6276 }
6277
6278 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6279 Uri uri, int modeFlags) {
6280 synchronized(this) {
6281 final ProcessRecord r = getRecordForAppLocked(caller);
6282 if (r == null) {
6283 throw new SecurityException("Unable to find app for caller "
6284 + caller
6285 + " when granting permission to uri " + uri);
6286 }
6287 if (targetPkg == null) {
6288 Log.w(TAG, "grantUriPermission: null target");
6289 return;
6290 }
6291 if (uri == null) {
6292 Log.w(TAG, "grantUriPermission: null uri");
6293 return;
6294 }
6295
6296 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6297 null);
6298 }
6299 }
6300
6301 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6302 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6303 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6304 HashMap<Uri, UriPermission> perms
6305 = mGrantedUriPermissions.get(perm.uid);
6306 if (perms != null) {
6307 perms.remove(perm.uri);
6308 if (perms.size() == 0) {
6309 mGrantedUriPermissions.remove(perm.uid);
6310 }
6311 }
6312 }
6313 }
6314
6315 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6316 if (activity.readUriPermissions != null) {
6317 for (UriPermission perm : activity.readUriPermissions) {
6318 perm.readActivities.remove(activity);
6319 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6320 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6321 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6322 removeUriPermissionIfNeededLocked(perm);
6323 }
6324 }
6325 }
6326 if (activity.writeUriPermissions != null) {
6327 for (UriPermission perm : activity.writeUriPermissions) {
6328 perm.writeActivities.remove(activity);
6329 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6330 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6331 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6332 removeUriPermissionIfNeededLocked(perm);
6333 }
6334 }
6335 }
6336 }
6337
6338 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6339 int modeFlags) {
6340 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6341 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6342 if (modeFlags == 0) {
6343 return;
6344 }
6345
6346 final IPackageManager pm = ActivityThread.getPackageManager();
6347
6348 final String authority = uri.getAuthority();
6349 ProviderInfo pi = null;
6350 ContentProviderRecord cpr
6351 = (ContentProviderRecord)mProvidersByName.get(authority);
6352 if (cpr != null) {
6353 pi = cpr.info;
6354 } else {
6355 try {
6356 pi = pm.resolveContentProvider(authority,
6357 PackageManager.GET_URI_PERMISSION_PATTERNS);
6358 } catch (RemoteException ex) {
6359 }
6360 }
6361 if (pi == null) {
6362 Log.w(TAG, "No content provider found for: " + authority);
6363 return;
6364 }
6365
6366 // Does the caller have this permission on the URI?
6367 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6368 // Right now, if you are not the original owner of the permission,
6369 // you are not allowed to revoke it.
6370 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6371 throw new SecurityException("Uid " + callingUid
6372 + " does not have permission to uri " + uri);
6373 //}
6374 }
6375
6376 // Go through all of the permissions and remove any that match.
6377 final List<String> SEGMENTS = uri.getPathSegments();
6378 if (SEGMENTS != null) {
6379 final int NS = SEGMENTS.size();
6380 int N = mGrantedUriPermissions.size();
6381 for (int i=0; i<N; i++) {
6382 HashMap<Uri, UriPermission> perms
6383 = mGrantedUriPermissions.valueAt(i);
6384 Iterator<UriPermission> it = perms.values().iterator();
6385 toploop:
6386 while (it.hasNext()) {
6387 UriPermission perm = it.next();
6388 Uri targetUri = perm.uri;
6389 if (!authority.equals(targetUri.getAuthority())) {
6390 continue;
6391 }
6392 List<String> targetSegments = targetUri.getPathSegments();
6393 if (targetSegments == null) {
6394 continue;
6395 }
6396 if (targetSegments.size() < NS) {
6397 continue;
6398 }
6399 for (int j=0; j<NS; j++) {
6400 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6401 continue toploop;
6402 }
6403 }
6404 perm.clearModes(modeFlags);
6405 if (perm.modeFlags == 0) {
6406 it.remove();
6407 }
6408 }
6409 if (perms.size() == 0) {
6410 mGrantedUriPermissions.remove(
6411 mGrantedUriPermissions.keyAt(i));
6412 N--;
6413 i--;
6414 }
6415 }
6416 }
6417 }
6418
6419 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6420 int modeFlags) {
6421 synchronized(this) {
6422 final ProcessRecord r = getRecordForAppLocked(caller);
6423 if (r == null) {
6424 throw new SecurityException("Unable to find app for caller "
6425 + caller
6426 + " when revoking permission to uri " + uri);
6427 }
6428 if (uri == null) {
6429 Log.w(TAG, "revokeUriPermission: null uri");
6430 return;
6431 }
6432
6433 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6434 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6435 if (modeFlags == 0) {
6436 return;
6437 }
6438
6439 final IPackageManager pm = ActivityThread.getPackageManager();
6440
6441 final String authority = uri.getAuthority();
6442 ProviderInfo pi = null;
6443 ContentProviderRecord cpr
6444 = (ContentProviderRecord)mProvidersByName.get(authority);
6445 if (cpr != null) {
6446 pi = cpr.info;
6447 } else {
6448 try {
6449 pi = pm.resolveContentProvider(authority,
6450 PackageManager.GET_URI_PERMISSION_PATTERNS);
6451 } catch (RemoteException ex) {
6452 }
6453 }
6454 if (pi == null) {
6455 Log.w(TAG, "No content provider found for: " + authority);
6456 return;
6457 }
6458
6459 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6460 }
6461 }
6462
6463 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6464 synchronized (this) {
6465 ProcessRecord app =
6466 who != null ? getRecordForAppLocked(who) : null;
6467 if (app == null) return;
6468
6469 Message msg = Message.obtain();
6470 msg.what = WAIT_FOR_DEBUGGER_MSG;
6471 msg.obj = app;
6472 msg.arg1 = waiting ? 1 : 0;
6473 mHandler.sendMessage(msg);
6474 }
6475 }
6476
6477 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6478 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006479 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006481 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 }
6483
6484 // =========================================================
6485 // TASK MANAGEMENT
6486 // =========================================================
6487
6488 public List getTasks(int maxNum, int flags,
6489 IThumbnailReceiver receiver) {
6490 ArrayList list = new ArrayList();
6491
6492 PendingThumbnailsRecord pending = null;
6493 IApplicationThread topThumbnail = null;
6494 HistoryRecord topRecord = null;
6495
6496 synchronized(this) {
6497 if (localLOGV) Log.v(
6498 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6499 + ", receiver=" + receiver);
6500
6501 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6502 != PackageManager.PERMISSION_GRANTED) {
6503 if (receiver != null) {
6504 // If the caller wants to wait for pending thumbnails,
6505 // it ain't gonna get them.
6506 try {
6507 receiver.finished();
6508 } catch (RemoteException ex) {
6509 }
6510 }
6511 String msg = "Permission Denial: getTasks() from pid="
6512 + Binder.getCallingPid()
6513 + ", uid=" + Binder.getCallingUid()
6514 + " requires " + android.Manifest.permission.GET_TASKS;
6515 Log.w(TAG, msg);
6516 throw new SecurityException(msg);
6517 }
6518
6519 int pos = mHistory.size()-1;
6520 HistoryRecord next =
6521 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6522 HistoryRecord top = null;
6523 CharSequence topDescription = null;
6524 TaskRecord curTask = null;
6525 int numActivities = 0;
6526 int numRunning = 0;
6527 while (pos >= 0 && maxNum > 0) {
6528 final HistoryRecord r = next;
6529 pos--;
6530 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6531
6532 // Initialize state for next task if needed.
6533 if (top == null ||
6534 (top.state == ActivityState.INITIALIZING
6535 && top.task == r.task)) {
6536 top = r;
6537 topDescription = r.description;
6538 curTask = r.task;
6539 numActivities = numRunning = 0;
6540 }
6541
6542 // Add 'r' into the current task.
6543 numActivities++;
6544 if (r.app != null && r.app.thread != null) {
6545 numRunning++;
6546 }
6547 if (topDescription == null) {
6548 topDescription = r.description;
6549 }
6550
6551 if (localLOGV) Log.v(
6552 TAG, r.intent.getComponent().flattenToShortString()
6553 + ": task=" + r.task);
6554
6555 // If the next one is a different task, generate a new
6556 // TaskInfo entry for what we have.
6557 if (next == null || next.task != curTask) {
6558 ActivityManager.RunningTaskInfo ci
6559 = new ActivityManager.RunningTaskInfo();
6560 ci.id = curTask.taskId;
6561 ci.baseActivity = r.intent.getComponent();
6562 ci.topActivity = top.intent.getComponent();
6563 ci.thumbnail = top.thumbnail;
6564 ci.description = topDescription;
6565 ci.numActivities = numActivities;
6566 ci.numRunning = numRunning;
6567 //System.out.println(
6568 // "#" + maxNum + ": " + " descr=" + ci.description);
6569 if (ci.thumbnail == null && receiver != null) {
6570 if (localLOGV) Log.v(
6571 TAG, "State=" + top.state + "Idle=" + top.idle
6572 + " app=" + top.app
6573 + " thr=" + (top.app != null ? top.app.thread : null));
6574 if (top.state == ActivityState.RESUMED
6575 || top.state == ActivityState.PAUSING) {
6576 if (top.idle && top.app != null
6577 && top.app.thread != null) {
6578 topRecord = top;
6579 topThumbnail = top.app.thread;
6580 } else {
6581 top.thumbnailNeeded = true;
6582 }
6583 }
6584 if (pending == null) {
6585 pending = new PendingThumbnailsRecord(receiver);
6586 }
6587 pending.pendingRecords.add(top);
6588 }
6589 list.add(ci);
6590 maxNum--;
6591 top = null;
6592 }
6593 }
6594
6595 if (pending != null) {
6596 mPendingThumbnails.add(pending);
6597 }
6598 }
6599
6600 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
6601
6602 if (topThumbnail != null) {
6603 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
6604 try {
6605 topThumbnail.requestThumbnail(topRecord);
6606 } catch (Exception e) {
6607 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
6608 sendPendingThumbnail(null, topRecord, null, null, true);
6609 }
6610 }
6611
6612 if (pending == null && receiver != null) {
6613 // In this case all thumbnails were available and the client
6614 // is being asked to be told when the remaining ones come in...
6615 // which is unusually, since the top-most currently running
6616 // activity should never have a canned thumbnail! Oh well.
6617 try {
6618 receiver.finished();
6619 } catch (RemoteException ex) {
6620 }
6621 }
6622
6623 return list;
6624 }
6625
6626 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6627 int flags) {
6628 synchronized (this) {
6629 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6630 "getRecentTasks()");
6631
6632 final int N = mRecentTasks.size();
6633 ArrayList<ActivityManager.RecentTaskInfo> res
6634 = new ArrayList<ActivityManager.RecentTaskInfo>(
6635 maxNum < N ? maxNum : N);
6636 for (int i=0; i<N && maxNum > 0; i++) {
6637 TaskRecord tr = mRecentTasks.get(i);
6638 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6639 || (tr.intent == null)
6640 || ((tr.intent.getFlags()
6641 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6642 ActivityManager.RecentTaskInfo rti
6643 = new ActivityManager.RecentTaskInfo();
6644 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6645 rti.baseIntent = new Intent(
6646 tr.intent != null ? tr.intent : tr.affinityIntent);
6647 rti.origActivity = tr.origActivity;
6648 res.add(rti);
6649 maxNum--;
6650 }
6651 }
6652 return res;
6653 }
6654 }
6655
6656 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6657 int j;
6658 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6659 TaskRecord jt = startTask;
6660
6661 // First look backwards
6662 for (j=startIndex-1; j>=0; j--) {
6663 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6664 if (r.task != jt) {
6665 jt = r.task;
6666 if (affinity.equals(jt.affinity)) {
6667 return j;
6668 }
6669 }
6670 }
6671
6672 // Now look forwards
6673 final int N = mHistory.size();
6674 jt = startTask;
6675 for (j=startIndex+1; j<N; j++) {
6676 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6677 if (r.task != jt) {
6678 if (affinity.equals(jt.affinity)) {
6679 return j;
6680 }
6681 jt = r.task;
6682 }
6683 }
6684
6685 // Might it be at the top?
6686 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6687 return N-1;
6688 }
6689
6690 return -1;
6691 }
6692
6693 /**
6694 * Perform a reset of the given task, if needed as part of launching it.
6695 * Returns the new HistoryRecord at the top of the task.
6696 */
6697 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6698 HistoryRecord newActivity) {
6699 boolean forceReset = (newActivity.info.flags
6700 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6701 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6702 if ((newActivity.info.flags
6703 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6704 forceReset = true;
6705 }
6706 }
6707
6708 final TaskRecord task = taskTop.task;
6709
6710 // We are going to move through the history list so that we can look
6711 // at each activity 'target' with 'below' either the interesting
6712 // activity immediately below it in the stack or null.
6713 HistoryRecord target = null;
6714 int targetI = 0;
6715 int taskTopI = -1;
6716 int replyChainEnd = -1;
6717 int lastReparentPos = -1;
6718 for (int i=mHistory.size()-1; i>=-1; i--) {
6719 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6720
6721 if (below != null && below.finishing) {
6722 continue;
6723 }
6724 if (target == null) {
6725 target = below;
6726 targetI = i;
6727 // If we were in the middle of a reply chain before this
6728 // task, it doesn't appear like the root of the chain wants
6729 // anything interesting, so drop it.
6730 replyChainEnd = -1;
6731 continue;
6732 }
6733
6734 final int flags = target.info.flags;
6735
6736 final boolean finishOnTaskLaunch =
6737 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6738 final boolean allowTaskReparenting =
6739 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6740
6741 if (target.task == task) {
6742 // We are inside of the task being reset... we'll either
6743 // finish this activity, push it out for another task,
6744 // or leave it as-is. We only do this
6745 // for activities that are not the root of the task (since
6746 // if we finish the root, we may no longer have the task!).
6747 if (taskTopI < 0) {
6748 taskTopI = targetI;
6749 }
6750 if (below != null && below.task == task) {
6751 final boolean clearWhenTaskReset =
6752 (target.intent.getFlags()
6753 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006754 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 // If this activity is sending a reply to a previous
6756 // activity, we can't do anything with it now until
6757 // we reach the start of the reply chain.
6758 // XXX note that we are assuming the result is always
6759 // to the previous activity, which is almost always
6760 // the case but we really shouldn't count on.
6761 if (replyChainEnd < 0) {
6762 replyChainEnd = targetI;
6763 }
Ed Heyl73798232009-03-24 21:32:21 -07006764 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 && target.taskAffinity != null
6766 && !target.taskAffinity.equals(task.affinity)) {
6767 // If this activity has an affinity for another
6768 // task, then we need to move it out of here. We will
6769 // move it as far out of the way as possible, to the
6770 // bottom of the activity stack. This also keeps it
6771 // correctly ordered with any activities we previously
6772 // moved.
6773 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6774 if (target.taskAffinity != null
6775 && target.taskAffinity.equals(p.task.affinity)) {
6776 // If the activity currently at the bottom has the
6777 // same task affinity as the one we are moving,
6778 // then merge it into the same task.
6779 target.task = p.task;
6780 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6781 + " out to bottom task " + p.task);
6782 } else {
6783 mCurTask++;
6784 if (mCurTask <= 0) {
6785 mCurTask = 1;
6786 }
6787 target.task = new TaskRecord(mCurTask, target.info, null,
6788 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6789 target.task.affinityIntent = target.intent;
6790 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6791 + " out to new task " + target.task);
6792 }
6793 mWindowManager.setAppGroupId(target, task.taskId);
6794 if (replyChainEnd < 0) {
6795 replyChainEnd = targetI;
6796 }
6797 int dstPos = 0;
6798 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6799 p = (HistoryRecord)mHistory.get(srcPos);
6800 if (p.finishing) {
6801 continue;
6802 }
6803 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6804 + " out to target's task " + target.task);
6805 task.numActivities--;
6806 p.task = target.task;
6807 target.task.numActivities++;
6808 mHistory.remove(srcPos);
6809 mHistory.add(dstPos, p);
6810 mWindowManager.moveAppToken(dstPos, p);
6811 mWindowManager.setAppGroupId(p, p.task.taskId);
6812 dstPos++;
6813 if (VALIDATE_TOKENS) {
6814 mWindowManager.validateAppTokens(mHistory);
6815 }
6816 i++;
6817 }
6818 if (taskTop == p) {
6819 taskTop = below;
6820 }
6821 if (taskTopI == replyChainEnd) {
6822 taskTopI = -1;
6823 }
6824 replyChainEnd = -1;
6825 addRecentTask(target.task);
6826 } else if (forceReset || finishOnTaskLaunch
6827 || clearWhenTaskReset) {
6828 // If the activity should just be removed -- either
6829 // because it asks for it, or the task should be
6830 // cleared -- then finish it and anything that is
6831 // part of its reply chain.
6832 if (clearWhenTaskReset) {
6833 // In this case, we want to finish this activity
6834 // and everything above it, so be sneaky and pretend
6835 // like these are all in the reply chain.
6836 replyChainEnd = targetI+1;
6837 while (replyChainEnd < mHistory.size() &&
6838 ((HistoryRecord)mHistory.get(
6839 replyChainEnd)).task == task) {
6840 replyChainEnd++;
6841 }
6842 replyChainEnd--;
6843 } else if (replyChainEnd < 0) {
6844 replyChainEnd = targetI;
6845 }
6846 HistoryRecord p = null;
6847 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6848 p = (HistoryRecord)mHistory.get(srcPos);
6849 if (p.finishing) {
6850 continue;
6851 }
6852 if (finishActivityLocked(p, srcPos,
6853 Activity.RESULT_CANCELED, null, "reset")) {
6854 replyChainEnd--;
6855 srcPos--;
6856 }
6857 }
6858 if (taskTop == p) {
6859 taskTop = below;
6860 }
6861 if (taskTopI == replyChainEnd) {
6862 taskTopI = -1;
6863 }
6864 replyChainEnd = -1;
6865 } else {
6866 // If we were in the middle of a chain, well the
6867 // activity that started it all doesn't want anything
6868 // special, so leave it all as-is.
6869 replyChainEnd = -1;
6870 }
6871 } else {
6872 // Reached the bottom of the task -- any reply chain
6873 // should be left as-is.
6874 replyChainEnd = -1;
6875 }
6876
6877 } else if (target.resultTo != null) {
6878 // If this activity is sending a reply to a previous
6879 // activity, we can't do anything with it now until
6880 // we reach the start of the reply chain.
6881 // XXX note that we are assuming the result is always
6882 // to the previous activity, which is almost always
6883 // the case but we really shouldn't count on.
6884 if (replyChainEnd < 0) {
6885 replyChainEnd = targetI;
6886 }
6887
6888 } else if (taskTopI >= 0 && allowTaskReparenting
6889 && task.affinity != null
6890 && task.affinity.equals(target.taskAffinity)) {
6891 // We are inside of another task... if this activity has
6892 // an affinity for our task, then either remove it if we are
6893 // clearing or move it over to our task. Note that
6894 // we currently punt on the case where we are resetting a
6895 // task that is not at the top but who has activities above
6896 // with an affinity to it... this is really not a normal
6897 // case, and we will need to later pull that task to the front
6898 // and usually at that point we will do the reset and pick
6899 // up those remaining activities. (This only happens if
6900 // someone starts an activity in a new task from an activity
6901 // in a task that is not currently on top.)
6902 if (forceReset || finishOnTaskLaunch) {
6903 if (replyChainEnd < 0) {
6904 replyChainEnd = targetI;
6905 }
6906 HistoryRecord p = null;
6907 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6908 p = (HistoryRecord)mHistory.get(srcPos);
6909 if (p.finishing) {
6910 continue;
6911 }
6912 if (finishActivityLocked(p, srcPos,
6913 Activity.RESULT_CANCELED, null, "reset")) {
6914 taskTopI--;
6915 lastReparentPos--;
6916 replyChainEnd--;
6917 srcPos--;
6918 }
6919 }
6920 replyChainEnd = -1;
6921 } else {
6922 if (replyChainEnd < 0) {
6923 replyChainEnd = targetI;
6924 }
6925 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6926 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6927 if (p.finishing) {
6928 continue;
6929 }
6930 if (lastReparentPos < 0) {
6931 lastReparentPos = taskTopI;
6932 taskTop = p;
6933 } else {
6934 lastReparentPos--;
6935 }
6936 mHistory.remove(srcPos);
6937 p.task.numActivities--;
6938 p.task = task;
6939 mHistory.add(lastReparentPos, p);
6940 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6941 + " in to resetting task " + task);
6942 task.numActivities++;
6943 mWindowManager.moveAppToken(lastReparentPos, p);
6944 mWindowManager.setAppGroupId(p, p.task.taskId);
6945 if (VALIDATE_TOKENS) {
6946 mWindowManager.validateAppTokens(mHistory);
6947 }
6948 }
6949 replyChainEnd = -1;
6950
6951 // Now we've moved it in to place... but what if this is
6952 // a singleTop activity and we have put it on top of another
6953 // instance of the same activity? Then we drop the instance
6954 // below so it remains singleTop.
6955 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6956 for (int j=lastReparentPos-1; j>=0; j--) {
6957 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6958 if (p.finishing) {
6959 continue;
6960 }
6961 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6962 if (finishActivityLocked(p, j,
6963 Activity.RESULT_CANCELED, null, "replace")) {
6964 taskTopI--;
6965 lastReparentPos--;
6966 }
6967 }
6968 }
6969 }
6970 }
6971 }
6972
6973 target = below;
6974 targetI = i;
6975 }
6976
6977 return taskTop;
6978 }
6979
6980 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006981 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006982 */
6983 public void moveTaskToFront(int task) {
6984 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6985 "moveTaskToFront()");
6986
6987 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006988 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6989 Binder.getCallingUid(), "Task to front")) {
6990 return;
6991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006992 final long origId = Binder.clearCallingIdentity();
6993 try {
6994 int N = mRecentTasks.size();
6995 for (int i=0; i<N; i++) {
6996 TaskRecord tr = mRecentTasks.get(i);
6997 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006998 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006999 return;
7000 }
7001 }
7002 for (int i=mHistory.size()-1; i>=0; i--) {
7003 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7004 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007005 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 return;
7007 }
7008 }
7009 } finally {
7010 Binder.restoreCallingIdentity(origId);
7011 }
7012 }
7013 }
7014
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007015 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007016 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
7017
7018 final int task = tr.taskId;
7019 int top = mHistory.size()-1;
7020
7021 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7022 // nothing to do!
7023 return;
7024 }
7025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 ArrayList moved = new ArrayList();
7027
7028 // Applying the affinities may have removed entries from the history,
7029 // so get the size again.
7030 top = mHistory.size()-1;
7031 int pos = top;
7032
7033 // Shift all activities with this task up to the top
7034 // of the stack, keeping them in the same internal order.
7035 while (pos >= 0) {
7036 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7037 if (localLOGV) Log.v(
7038 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7039 boolean first = true;
7040 if (r.task.taskId == task) {
7041 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
7042 mHistory.remove(pos);
7043 mHistory.add(top, r);
7044 moved.add(0, r);
7045 top--;
7046 if (first) {
7047 addRecentTask(r.task);
7048 first = false;
7049 }
7050 }
7051 pos--;
7052 }
7053
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007054 if (DEBUG_TRANSITION) Log.v(TAG,
7055 "Prepare to front transition: task=" + tr);
7056 if (reason != null &&
7057 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7058 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7059 HistoryRecord r = topRunningActivityLocked(null);
7060 if (r != null) {
7061 mNoAnimActivities.add(r);
7062 }
7063 } else {
7064 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7065 }
7066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 mWindowManager.moveAppTokensToTop(moved);
7068 if (VALIDATE_TOKENS) {
7069 mWindowManager.validateAppTokens(mHistory);
7070 }
7071
7072 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007073 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 }
7075
7076 private final void finishTaskMove(int task) {
7077 resumeTopActivityLocked(null);
7078 }
7079
7080 public void moveTaskToBack(int task) {
7081 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7082 "moveTaskToBack()");
7083
7084 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007085 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7086 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7087 Binder.getCallingUid(), "Task to back")) {
7088 return;
7089 }
7090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007092 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 Binder.restoreCallingIdentity(origId);
7094 }
7095 }
7096
7097 /**
7098 * Moves an activity, and all of the other activities within the same task, to the bottom
7099 * of the history stack. The activity's order within the task is unchanged.
7100 *
7101 * @param token A reference to the activity we wish to move
7102 * @param nonRoot If false then this only works if the activity is the root
7103 * of a task; if true it will work for any activity in a task.
7104 * @return Returns true if the move completed, false if not.
7105 */
7106 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7107 synchronized(this) {
7108 final long origId = Binder.clearCallingIdentity();
7109 int taskId = getTaskForActivityLocked(token, !nonRoot);
7110 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007111 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007112 }
7113 Binder.restoreCallingIdentity(origId);
7114 }
7115 return false;
7116 }
7117
7118 /**
7119 * Worker method for rearranging history stack. Implements the function of moving all
7120 * activities for a specific task (gathering them if disjoint) into a single group at the
7121 * bottom of the stack.
7122 *
7123 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7124 * to premeptively cancel the move.
7125 *
7126 * @param task The taskId to collect and move to the bottom.
7127 * @return Returns true if the move completed, false if not.
7128 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007129 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 Log.i(TAG, "moveTaskToBack: " + task);
7131
7132 // If we have a watcher, preflight the move before committing to it. First check
7133 // for *other* available tasks, but if none are available, then try again allowing the
7134 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007135 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007136 HistoryRecord next = topRunningActivityLocked(null, task);
7137 if (next == null) {
7138 next = topRunningActivityLocked(null, 0);
7139 }
7140 if (next != null) {
7141 // ask watcher if this is allowed
7142 boolean moveOK = true;
7143 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007144 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007146 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 }
7148 if (!moveOK) {
7149 return false;
7150 }
7151 }
7152 }
7153
7154 ArrayList moved = new ArrayList();
7155
7156 if (DEBUG_TRANSITION) Log.v(TAG,
7157 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158
7159 final int N = mHistory.size();
7160 int bottom = 0;
7161 int pos = 0;
7162
7163 // Shift all activities with this task down to the bottom
7164 // of the stack, keeping them in the same internal order.
7165 while (pos < N) {
7166 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7167 if (localLOGV) Log.v(
7168 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7169 if (r.task.taskId == task) {
7170 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
7171 mHistory.remove(pos);
7172 mHistory.add(bottom, r);
7173 moved.add(r);
7174 bottom++;
7175 }
7176 pos++;
7177 }
7178
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007179 if (reason != null &&
7180 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7181 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7182 HistoryRecord r = topRunningActivityLocked(null);
7183 if (r != null) {
7184 mNoAnimActivities.add(r);
7185 }
7186 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007187 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007189 mWindowManager.moveAppTokensToBottom(moved);
7190 if (VALIDATE_TOKENS) {
7191 mWindowManager.validateAppTokens(mHistory);
7192 }
7193
7194 finishTaskMove(task);
7195 return true;
7196 }
7197
7198 public void moveTaskBackwards(int task) {
7199 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7200 "moveTaskBackwards()");
7201
7202 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007203 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7204 Binder.getCallingUid(), "Task backwards")) {
7205 return;
7206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 final long origId = Binder.clearCallingIdentity();
7208 moveTaskBackwardsLocked(task);
7209 Binder.restoreCallingIdentity(origId);
7210 }
7211 }
7212
7213 private final void moveTaskBackwardsLocked(int task) {
7214 Log.e(TAG, "moveTaskBackwards not yet implemented!");
7215 }
7216
7217 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7218 synchronized(this) {
7219 return getTaskForActivityLocked(token, onlyRoot);
7220 }
7221 }
7222
7223 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7224 final int N = mHistory.size();
7225 TaskRecord lastTask = null;
7226 for (int i=0; i<N; i++) {
7227 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7228 if (r == token) {
7229 if (!onlyRoot || lastTask != r.task) {
7230 return r.task.taskId;
7231 }
7232 return -1;
7233 }
7234 lastTask = r.task;
7235 }
7236
7237 return -1;
7238 }
7239
7240 /**
7241 * Returns the top activity in any existing task matching the given
7242 * Intent. Returns null if no such task is found.
7243 */
7244 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7245 ComponentName cls = intent.getComponent();
7246 if (info.targetActivity != null) {
7247 cls = new ComponentName(info.packageName, info.targetActivity);
7248 }
7249
7250 TaskRecord cp = null;
7251
7252 final int N = mHistory.size();
7253 for (int i=(N-1); i>=0; i--) {
7254 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7255 if (!r.finishing && r.task != cp
7256 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7257 cp = r.task;
7258 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
7259 // + "/aff=" + r.task.affinity + " to new cls="
7260 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7261 if (r.task.affinity != null) {
7262 if (r.task.affinity.equals(info.taskAffinity)) {
7263 //Log.i(TAG, "Found matching affinity!");
7264 return r;
7265 }
7266 } else if (r.task.intent != null
7267 && r.task.intent.getComponent().equals(cls)) {
7268 //Log.i(TAG, "Found matching class!");
7269 //dump();
7270 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7271 return r;
7272 } else if (r.task.affinityIntent != null
7273 && r.task.affinityIntent.getComponent().equals(cls)) {
7274 //Log.i(TAG, "Found matching class!");
7275 //dump();
7276 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7277 return r;
7278 }
7279 }
7280 }
7281
7282 return null;
7283 }
7284
7285 /**
7286 * Returns the first activity (starting from the top of the stack) that
7287 * is the same as the given activity. Returns null if no such activity
7288 * is found.
7289 */
7290 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7291 ComponentName cls = intent.getComponent();
7292 if (info.targetActivity != null) {
7293 cls = new ComponentName(info.packageName, info.targetActivity);
7294 }
7295
7296 final int N = mHistory.size();
7297 for (int i=(N-1); i>=0; i--) {
7298 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7299 if (!r.finishing) {
7300 if (r.intent.getComponent().equals(cls)) {
7301 //Log.i(TAG, "Found matching class!");
7302 //dump();
7303 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7304 return r;
7305 }
7306 }
7307 }
7308
7309 return null;
7310 }
7311
7312 public void finishOtherInstances(IBinder token, ComponentName className) {
7313 synchronized(this) {
7314 final long origId = Binder.clearCallingIdentity();
7315
7316 int N = mHistory.size();
7317 TaskRecord lastTask = null;
7318 for (int i=0; i<N; i++) {
7319 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7320 if (r.realActivity.equals(className)
7321 && r != token && lastTask != r.task) {
7322 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7323 null, "others")) {
7324 i--;
7325 N--;
7326 }
7327 }
7328 lastTask = r.task;
7329 }
7330
7331 Binder.restoreCallingIdentity(origId);
7332 }
7333 }
7334
7335 // =========================================================
7336 // THUMBNAILS
7337 // =========================================================
7338
7339 public void reportThumbnail(IBinder token,
7340 Bitmap thumbnail, CharSequence description) {
7341 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7342 final long origId = Binder.clearCallingIdentity();
7343 sendPendingThumbnail(null, token, thumbnail, description, true);
7344 Binder.restoreCallingIdentity(origId);
7345 }
7346
7347 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7348 Bitmap thumbnail, CharSequence description, boolean always) {
7349 TaskRecord task = null;
7350 ArrayList receivers = null;
7351
7352 //System.out.println("Send pending thumbnail: " + r);
7353
7354 synchronized(this) {
7355 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007356 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 if (index < 0) {
7358 return;
7359 }
7360 r = (HistoryRecord)mHistory.get(index);
7361 }
7362 if (thumbnail == null) {
7363 thumbnail = r.thumbnail;
7364 description = r.description;
7365 }
7366 if (thumbnail == null && !always) {
7367 // If there is no thumbnail, and this entry is not actually
7368 // going away, then abort for now and pick up the next
7369 // thumbnail we get.
7370 return;
7371 }
7372 task = r.task;
7373
7374 int N = mPendingThumbnails.size();
7375 int i=0;
7376 while (i<N) {
7377 PendingThumbnailsRecord pr =
7378 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7379 //System.out.println("Looking in " + pr.pendingRecords);
7380 if (pr.pendingRecords.remove(r)) {
7381 if (receivers == null) {
7382 receivers = new ArrayList();
7383 }
7384 receivers.add(pr);
7385 if (pr.pendingRecords.size() == 0) {
7386 pr.finished = true;
7387 mPendingThumbnails.remove(i);
7388 N--;
7389 continue;
7390 }
7391 }
7392 i++;
7393 }
7394 }
7395
7396 if (receivers != null) {
7397 final int N = receivers.size();
7398 for (int i=0; i<N; i++) {
7399 try {
7400 PendingThumbnailsRecord pr =
7401 (PendingThumbnailsRecord)receivers.get(i);
7402 pr.receiver.newThumbnail(
7403 task != null ? task.taskId : -1, thumbnail, description);
7404 if (pr.finished) {
7405 pr.receiver.finished();
7406 }
7407 } catch (Exception e) {
7408 Log.w(TAG, "Exception thrown when sending thumbnail", e);
7409 }
7410 }
7411 }
7412 }
7413
7414 // =========================================================
7415 // CONTENT PROVIDERS
7416 // =========================================================
7417
7418 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7419 List providers = null;
7420 try {
7421 providers = ActivityThread.getPackageManager().
7422 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007423 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 } catch (RemoteException ex) {
7425 }
7426 if (providers != null) {
7427 final int N = providers.size();
7428 for (int i=0; i<N; i++) {
7429 ProviderInfo cpi =
7430 (ProviderInfo)providers.get(i);
7431 ContentProviderRecord cpr =
7432 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7433 if (cpr == null) {
7434 cpr = new ContentProviderRecord(cpi, app.info);
7435 mProvidersByClass.put(cpi.name, cpr);
7436 }
7437 app.pubProviders.put(cpi.name, cpr);
7438 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007439 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 }
7441 }
7442 return providers;
7443 }
7444
7445 private final String checkContentProviderPermissionLocked(
7446 ProviderInfo cpi, ProcessRecord r, int mode) {
7447 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7448 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7449 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7450 cpi.exported ? -1 : cpi.applicationInfo.uid)
7451 == PackageManager.PERMISSION_GRANTED
7452 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7453 return null;
7454 }
7455 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7456 cpi.exported ? -1 : cpi.applicationInfo.uid)
7457 == PackageManager.PERMISSION_GRANTED) {
7458 return null;
7459 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007460
7461 PathPermission[] pps = cpi.pathPermissions;
7462 if (pps != null) {
7463 int i = pps.length;
7464 while (i > 0) {
7465 i--;
7466 PathPermission pp = pps[i];
7467 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7468 cpi.exported ? -1 : cpi.applicationInfo.uid)
7469 == PackageManager.PERMISSION_GRANTED
7470 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7471 return null;
7472 }
7473 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7474 cpi.exported ? -1 : cpi.applicationInfo.uid)
7475 == PackageManager.PERMISSION_GRANTED) {
7476 return null;
7477 }
7478 }
7479 }
7480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 String msg = "Permission Denial: opening provider " + cpi.name
7482 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7483 + ", uid=" + callingUid + ") requires "
7484 + cpi.readPermission + " or " + cpi.writePermission;
7485 Log.w(TAG, msg);
7486 return msg;
7487 }
7488
7489 private final ContentProviderHolder getContentProviderImpl(
7490 IApplicationThread caller, String name) {
7491 ContentProviderRecord cpr;
7492 ProviderInfo cpi = null;
7493
7494 synchronized(this) {
7495 ProcessRecord r = null;
7496 if (caller != null) {
7497 r = getRecordForAppLocked(caller);
7498 if (r == null) {
7499 throw new SecurityException(
7500 "Unable to find app for caller " + caller
7501 + " (pid=" + Binder.getCallingPid()
7502 + ") when getting content provider " + name);
7503 }
7504 }
7505
7506 // First check if this content provider has been published...
7507 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7508 if (cpr != null) {
7509 cpi = cpr.info;
7510 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7511 return new ContentProviderHolder(cpi,
7512 cpi.readPermission != null
7513 ? cpi.readPermission : cpi.writePermission);
7514 }
7515
7516 if (r != null && cpr.canRunHere(r)) {
7517 // This provider has been published or is in the process
7518 // of being published... but it is also allowed to run
7519 // in the caller's process, so don't make a connection
7520 // and just let the caller instantiate its own instance.
7521 if (cpr.provider != null) {
7522 // don't give caller the provider object, it needs
7523 // to make its own.
7524 cpr = new ContentProviderRecord(cpr);
7525 }
7526 return cpr;
7527 }
7528
7529 final long origId = Binder.clearCallingIdentity();
7530
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007531 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 // return it right away.
7533 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007534 if (DEBUG_PROVIDER) Log.v(TAG,
7535 "Adding provider requested by "
7536 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007537 + cpr.info.processName);
7538 Integer cnt = r.conProviders.get(cpr);
7539 if (cnt == null) {
7540 r.conProviders.put(cpr, new Integer(1));
7541 } else {
7542 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 cpr.clients.add(r);
7545 } else {
7546 cpr.externals++;
7547 }
7548
7549 if (cpr.app != null) {
7550 updateOomAdjLocked(cpr.app);
7551 }
7552
7553 Binder.restoreCallingIdentity(origId);
7554
7555 } else {
7556 try {
7557 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007558 resolveContentProvider(name,
7559 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 } catch (RemoteException ex) {
7561 }
7562 if (cpi == null) {
7563 return null;
7564 }
7565
7566 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7567 return new ContentProviderHolder(cpi,
7568 cpi.readPermission != null
7569 ? cpi.readPermission : cpi.writePermission);
7570 }
7571
7572 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7573 final boolean firstClass = cpr == null;
7574 if (firstClass) {
7575 try {
7576 ApplicationInfo ai =
7577 ActivityThread.getPackageManager().
7578 getApplicationInfo(
7579 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007580 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 if (ai == null) {
7582 Log.w(TAG, "No package info for content provider "
7583 + cpi.name);
7584 return null;
7585 }
7586 cpr = new ContentProviderRecord(cpi, ai);
7587 } catch (RemoteException ex) {
7588 // pm is in same process, this will never happen.
7589 }
7590 }
7591
7592 if (r != null && cpr.canRunHere(r)) {
7593 // If this is a multiprocess provider, then just return its
7594 // info and allow the caller to instantiate it. Only do
7595 // this if the provider is the same user as the caller's
7596 // process, or can run as root (so can be in any process).
7597 return cpr;
7598 }
7599
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007600 if (DEBUG_PROVIDER) {
7601 RuntimeException e = new RuntimeException("here");
7602 Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
7603 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 }
7605
7606 // This is single process, and our app is now connecting to it.
7607 // See if we are already in the process of launching this
7608 // provider.
7609 final int N = mLaunchingProviders.size();
7610 int i;
7611 for (i=0; i<N; i++) {
7612 if (mLaunchingProviders.get(i) == cpr) {
7613 break;
7614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 }
7616
7617 // If the provider is not already being launched, then get it
7618 // started.
7619 if (i >= N) {
7620 final long origId = Binder.clearCallingIdentity();
7621 ProcessRecord proc = startProcessLocked(cpi.processName,
7622 cpr.appInfo, false, 0, "content provider",
7623 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007624 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 if (proc == null) {
7626 Log.w(TAG, "Unable to launch app "
7627 + cpi.applicationInfo.packageName + "/"
7628 + cpi.applicationInfo.uid + " for provider "
7629 + name + ": process is bad");
7630 return null;
7631 }
7632 cpr.launchingApp = proc;
7633 mLaunchingProviders.add(cpr);
7634 Binder.restoreCallingIdentity(origId);
7635 }
7636
7637 // Make sure the provider is published (the same provider class
7638 // may be published under multiple names).
7639 if (firstClass) {
7640 mProvidersByClass.put(cpi.name, cpr);
7641 }
7642 mProvidersByName.put(name, cpr);
7643
7644 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007645 if (DEBUG_PROVIDER) Log.v(TAG,
7646 "Adding provider requested by "
7647 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007648 + cpr.info.processName);
7649 Integer cnt = r.conProviders.get(cpr);
7650 if (cnt == null) {
7651 r.conProviders.put(cpr, new Integer(1));
7652 } else {
7653 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 cpr.clients.add(r);
7656 } else {
7657 cpr.externals++;
7658 }
7659 }
7660 }
7661
7662 // Wait for the provider to be published...
7663 synchronized (cpr) {
7664 while (cpr.provider == null) {
7665 if (cpr.launchingApp == null) {
7666 Log.w(TAG, "Unable to launch app "
7667 + cpi.applicationInfo.packageName + "/"
7668 + cpi.applicationInfo.uid + " for provider "
7669 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007670 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671 cpi.applicationInfo.packageName,
7672 cpi.applicationInfo.uid, name);
7673 return null;
7674 }
7675 try {
7676 cpr.wait();
7677 } catch (InterruptedException ex) {
7678 }
7679 }
7680 }
7681 return cpr;
7682 }
7683
7684 public final ContentProviderHolder getContentProvider(
7685 IApplicationThread caller, String name) {
7686 if (caller == null) {
7687 String msg = "null IApplicationThread when getting content provider "
7688 + name;
7689 Log.w(TAG, msg);
7690 throw new SecurityException(msg);
7691 }
7692
7693 return getContentProviderImpl(caller, name);
7694 }
7695
7696 private ContentProviderHolder getContentProviderExternal(String name) {
7697 return getContentProviderImpl(null, name);
7698 }
7699
7700 /**
7701 * Drop a content provider from a ProcessRecord's bookkeeping
7702 * @param cpr
7703 */
7704 public void removeContentProvider(IApplicationThread caller, String name) {
7705 synchronized (this) {
7706 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7707 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007708 // remove from mProvidersByClass
7709 if (DEBUG_PROVIDER) Log.v(TAG, name +
7710 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 return;
7712 }
7713 final ProcessRecord r = getRecordForAppLocked(caller);
7714 if (r == null) {
7715 throw new SecurityException(
7716 "Unable to find app for caller " + caller +
7717 " when removing content provider " + name);
7718 }
7719 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007720 ContentProviderRecord localCpr = (ContentProviderRecord)
7721 mProvidersByClass.get(cpr.info.name);
7722 if (DEBUG_PROVIDER) Log.v(TAG, "Removing provider requested by "
7723 + r.info.processName + " from process "
7724 + localCpr.appInfo.processName);
7725 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 //should not happen. taken care of as a local provider
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007727 Log.w(TAG, "removeContentProvider called on local provider: "
7728 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 return;
7730 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007731 Integer cnt = r.conProviders.get(localCpr);
7732 if (cnt == null || cnt.intValue() <= 1) {
7733 localCpr.clients.remove(r);
7734 r.conProviders.remove(localCpr);
7735 } else {
7736 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007738 }
7739 updateOomAdjLocked();
7740 }
7741 }
7742
7743 private void removeContentProviderExternal(String name) {
7744 synchronized (this) {
7745 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7746 if(cpr == null) {
7747 //remove from mProvidersByClass
7748 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
7749 return;
7750 }
7751
7752 //update content provider record entry info
7753 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7754 localCpr.externals--;
7755 if (localCpr.externals < 0) {
7756 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
7757 }
7758 updateOomAdjLocked();
7759 }
7760 }
7761
7762 public final void publishContentProviders(IApplicationThread caller,
7763 List<ContentProviderHolder> providers) {
7764 if (providers == null) {
7765 return;
7766 }
7767
7768 synchronized(this) {
7769 final ProcessRecord r = getRecordForAppLocked(caller);
7770 if (r == null) {
7771 throw new SecurityException(
7772 "Unable to find app for caller " + caller
7773 + " (pid=" + Binder.getCallingPid()
7774 + ") when publishing content providers");
7775 }
7776
7777 final long origId = Binder.clearCallingIdentity();
7778
7779 final int N = providers.size();
7780 for (int i=0; i<N; i++) {
7781 ContentProviderHolder src = providers.get(i);
7782 if (src == null || src.info == null || src.provider == null) {
7783 continue;
7784 }
7785 ContentProviderRecord dst =
7786 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7787 if (dst != null) {
7788 mProvidersByClass.put(dst.info.name, dst);
7789 String names[] = dst.info.authority.split(";");
7790 for (int j = 0; j < names.length; j++) {
7791 mProvidersByName.put(names[j], dst);
7792 }
7793
7794 int NL = mLaunchingProviders.size();
7795 int j;
7796 for (j=0; j<NL; j++) {
7797 if (mLaunchingProviders.get(j) == dst) {
7798 mLaunchingProviders.remove(j);
7799 j--;
7800 NL--;
7801 }
7802 }
7803 synchronized (dst) {
7804 dst.provider = src.provider;
7805 dst.app = r;
7806 dst.notifyAll();
7807 }
7808 updateOomAdjLocked(r);
7809 }
7810 }
7811
7812 Binder.restoreCallingIdentity(origId);
7813 }
7814 }
7815
7816 public static final void installSystemProviders() {
7817 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7818 List providers = mSelf.generateApplicationProvidersLocked(app);
7819 mSystemThread.installSystemProviders(providers);
7820 }
7821
7822 // =========================================================
7823 // GLOBAL MANAGEMENT
7824 // =========================================================
7825
7826 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7827 ApplicationInfo info, String customProcess) {
7828 String proc = customProcess != null ? customProcess : info.processName;
7829 BatteryStatsImpl.Uid.Proc ps = null;
7830 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7831 synchronized (stats) {
7832 ps = stats.getProcessStatsLocked(info.uid, proc);
7833 }
7834 return new ProcessRecord(ps, thread, info, proc);
7835 }
7836
7837 final ProcessRecord addAppLocked(ApplicationInfo info) {
7838 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7839
7840 if (app == null) {
7841 app = newProcessRecordLocked(null, info, null);
7842 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007843 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844 }
7845
7846 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7847 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7848 app.persistent = true;
7849 app.maxAdj = CORE_SERVER_ADJ;
7850 }
7851 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7852 mPersistentStartingProcesses.add(app);
7853 startProcessLocked(app, "added application", app.processName);
7854 }
7855
7856 return app;
7857 }
7858
7859 public void unhandledBack() {
7860 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7861 "unhandledBack()");
7862
7863 synchronized(this) {
7864 int count = mHistory.size();
Dianne Hackborn03abb812010-01-04 18:43:19 -08007865 if (DEBUG_SWITCH) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 TAG, "Performing unhandledBack(): stack size = " + count);
7867 if (count > 1) {
7868 final long origId = Binder.clearCallingIdentity();
7869 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7870 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7871 Binder.restoreCallingIdentity(origId);
7872 }
7873 }
7874 }
7875
7876 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7877 String name = uri.getAuthority();
7878 ContentProviderHolder cph = getContentProviderExternal(name);
7879 ParcelFileDescriptor pfd = null;
7880 if (cph != null) {
7881 // We record the binder invoker's uid in thread-local storage before
7882 // going to the content provider to open the file. Later, in the code
7883 // that handles all permissions checks, we look for this uid and use
7884 // that rather than the Activity Manager's own uid. The effect is that
7885 // we do the check against the caller's permissions even though it looks
7886 // to the content provider like the Activity Manager itself is making
7887 // the request.
7888 sCallerIdentity.set(new Identity(
7889 Binder.getCallingPid(), Binder.getCallingUid()));
7890 try {
7891 pfd = cph.provider.openFile(uri, "r");
7892 } catch (FileNotFoundException e) {
7893 // do nothing; pfd will be returned null
7894 } finally {
7895 // Ensure that whatever happens, we clean up the identity state
7896 sCallerIdentity.remove();
7897 }
7898
7899 // We've got the fd now, so we're done with the provider.
7900 removeContentProviderExternal(name);
7901 } else {
7902 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7903 }
7904 return pfd;
7905 }
7906
7907 public void goingToSleep() {
7908 synchronized(this) {
7909 mSleeping = true;
7910 mWindowManager.setEventDispatching(false);
7911
7912 if (mResumedActivity != null) {
7913 pauseIfSleepingLocked();
7914 } else {
7915 Log.w(TAG, "goingToSleep with no resumed activity!");
7916 }
7917 }
7918 }
7919
Dianne Hackborn55280a92009-05-07 15:53:46 -07007920 public boolean shutdown(int timeout) {
7921 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7922 != PackageManager.PERMISSION_GRANTED) {
7923 throw new SecurityException("Requires permission "
7924 + android.Manifest.permission.SHUTDOWN);
7925 }
7926
7927 boolean timedout = false;
7928
7929 synchronized(this) {
7930 mShuttingDown = true;
7931 mWindowManager.setEventDispatching(false);
7932
7933 if (mResumedActivity != null) {
7934 pauseIfSleepingLocked();
7935 final long endTime = System.currentTimeMillis() + timeout;
7936 while (mResumedActivity != null || mPausingActivity != null) {
7937 long delay = endTime - System.currentTimeMillis();
7938 if (delay <= 0) {
7939 Log.w(TAG, "Activity manager shutdown timed out");
7940 timedout = true;
7941 break;
7942 }
7943 try {
7944 this.wait();
7945 } catch (InterruptedException e) {
7946 }
7947 }
7948 }
7949 }
7950
7951 mUsageStatsService.shutdown();
7952 mBatteryStatsService.shutdown();
7953
7954 return timedout;
7955 }
7956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007958 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 if (!mGoingToSleep.isHeld()) {
7960 mGoingToSleep.acquire();
7961 if (mLaunchingActivity.isHeld()) {
7962 mLaunchingActivity.release();
7963 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7964 }
7965 }
7966
7967 // If we are not currently pausing an activity, get the current
7968 // one to pause. If we are pausing one, we will just let that stuff
7969 // run and release the wake lock when all done.
7970 if (mPausingActivity == null) {
7971 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7972 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7973 startPausingLocked(false, true);
7974 }
7975 }
7976 }
7977
7978 public void wakingUp() {
7979 synchronized(this) {
7980 if (mGoingToSleep.isHeld()) {
7981 mGoingToSleep.release();
7982 }
7983 mWindowManager.setEventDispatching(true);
7984 mSleeping = false;
7985 resumeTopActivityLocked(null);
7986 }
7987 }
7988
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007989 public void stopAppSwitches() {
7990 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7991 != PackageManager.PERMISSION_GRANTED) {
7992 throw new SecurityException("Requires permission "
7993 + android.Manifest.permission.STOP_APP_SWITCHES);
7994 }
7995
7996 synchronized(this) {
7997 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
7998 + APP_SWITCH_DELAY_TIME;
7999 mDidAppSwitch = false;
8000 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8001 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8002 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8003 }
8004 }
8005
8006 public void resumeAppSwitches() {
8007 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8008 != PackageManager.PERMISSION_GRANTED) {
8009 throw new SecurityException("Requires permission "
8010 + android.Manifest.permission.STOP_APP_SWITCHES);
8011 }
8012
8013 synchronized(this) {
8014 // Note that we don't execute any pending app switches... we will
8015 // let those wait until either the timeout, or the next start
8016 // activity request.
8017 mAppSwitchesAllowedTime = 0;
8018 }
8019 }
8020
8021 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8022 String name) {
8023 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8024 return true;
8025 }
8026
8027 final int perm = checkComponentPermission(
8028 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8029 callingUid, -1);
8030 if (perm == PackageManager.PERMISSION_GRANTED) {
8031 return true;
8032 }
8033
8034 Log.w(TAG, name + " request from " + callingUid + " stopped");
8035 return false;
8036 }
8037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 public void setDebugApp(String packageName, boolean waitForDebugger,
8039 boolean persistent) {
8040 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8041 "setDebugApp()");
8042
8043 // Note that this is not really thread safe if there are multiple
8044 // callers into it at the same time, but that's not a situation we
8045 // care about.
8046 if (persistent) {
8047 final ContentResolver resolver = mContext.getContentResolver();
8048 Settings.System.putString(
8049 resolver, Settings.System.DEBUG_APP,
8050 packageName);
8051 Settings.System.putInt(
8052 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8053 waitForDebugger ? 1 : 0);
8054 }
8055
8056 synchronized (this) {
8057 if (!persistent) {
8058 mOrigDebugApp = mDebugApp;
8059 mOrigWaitForDebugger = mWaitForDebugger;
8060 }
8061 mDebugApp = packageName;
8062 mWaitForDebugger = waitForDebugger;
8063 mDebugTransient = !persistent;
8064 if (packageName != null) {
8065 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008066 forceStopPackageLocked(packageName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067 Binder.restoreCallingIdentity(origId);
8068 }
8069 }
8070 }
8071
8072 public void setAlwaysFinish(boolean enabled) {
8073 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8074 "setAlwaysFinish()");
8075
8076 Settings.System.putInt(
8077 mContext.getContentResolver(),
8078 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8079
8080 synchronized (this) {
8081 mAlwaysFinishActivities = enabled;
8082 }
8083 }
8084
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008085 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008087 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008088 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008089 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008090 }
8091 }
8092
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008093 public boolean isUserAMonkey() {
8094 // For now the fact that there is a controller implies
8095 // we have a monkey.
8096 synchronized (this) {
8097 return mController != null;
8098 }
8099 }
8100
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008101 public void registerActivityWatcher(IActivityWatcher watcher) {
8102 mWatchers.register(watcher);
8103 }
8104
8105 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8106 mWatchers.unregister(watcher);
8107 }
8108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 public final void enterSafeMode() {
8110 synchronized(this) {
8111 // It only makes sense to do this before the system is ready
8112 // and started launching other packages.
8113 if (!mSystemReady) {
8114 try {
8115 ActivityThread.getPackageManager().enterSafeMode();
8116 } catch (RemoteException e) {
8117 }
8118
8119 View v = LayoutInflater.from(mContext).inflate(
8120 com.android.internal.R.layout.safe_mode, null);
8121 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8122 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8123 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8124 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8125 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8126 lp.format = v.getBackground().getOpacity();
8127 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8128 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8129 ((WindowManager)mContext.getSystemService(
8130 Context.WINDOW_SERVICE)).addView(v, lp);
8131 }
8132 }
8133 }
8134
8135 public void noteWakeupAlarm(IIntentSender sender) {
8136 if (!(sender instanceof PendingIntentRecord)) {
8137 return;
8138 }
8139 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8140 synchronized (stats) {
8141 if (mBatteryStatsService.isOnBattery()) {
8142 mBatteryStatsService.enforceCallingPermission();
8143 PendingIntentRecord rec = (PendingIntentRecord)sender;
8144 int MY_UID = Binder.getCallingUid();
8145 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8146 BatteryStatsImpl.Uid.Pkg pkg =
8147 stats.getPackageStatsLocked(uid, rec.key.packageName);
8148 pkg.incWakeupsLocked();
8149 }
8150 }
8151 }
8152
8153 public boolean killPidsForMemory(int[] pids) {
8154 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8155 throw new SecurityException("killPidsForMemory only available to the system");
8156 }
8157
8158 // XXX Note: don't acquire main activity lock here, because the window
8159 // manager calls in with its locks held.
8160
8161 boolean killed = false;
8162 synchronized (mPidsSelfLocked) {
8163 int[] types = new int[pids.length];
8164 int worstType = 0;
8165 for (int i=0; i<pids.length; i++) {
8166 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8167 if (proc != null) {
8168 int type = proc.setAdj;
8169 types[i] = type;
8170 if (type > worstType) {
8171 worstType = type;
8172 }
8173 }
8174 }
8175
8176 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8177 // then constrain it so we will kill all hidden procs.
8178 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8179 worstType = HIDDEN_APP_MIN_ADJ;
8180 }
8181 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
8182 for (int i=0; i<pids.length; i++) {
8183 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8184 if (proc == null) {
8185 continue;
8186 }
8187 int adj = proc.setAdj;
8188 if (adj >= worstType) {
8189 Log.w(TAG, "Killing for memory: " + proc + " (adj "
8190 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008191 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008192 proc.processName, adj);
8193 killed = true;
8194 Process.killProcess(pids[i]);
8195 }
8196 }
8197 }
8198 return killed;
8199 }
8200
8201 public void reportPss(IApplicationThread caller, int pss) {
8202 Watchdog.PssRequestor req;
8203 String name;
8204 ProcessRecord callerApp;
8205 synchronized (this) {
8206 if (caller == null) {
8207 return;
8208 }
8209 callerApp = getRecordForAppLocked(caller);
8210 if (callerApp == null) {
8211 return;
8212 }
8213 callerApp.lastPss = pss;
8214 req = callerApp;
8215 name = callerApp.processName;
8216 }
8217 Watchdog.getInstance().reportPss(req, name, pss);
8218 if (!callerApp.persistent) {
8219 removeRequestedPss(callerApp);
8220 }
8221 }
8222
8223 public void requestPss(Runnable completeCallback) {
8224 ArrayList<ProcessRecord> procs;
8225 synchronized (this) {
8226 mRequestPssCallback = completeCallback;
8227 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008228 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8229 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 if (!proc.persistent) {
8231 mRequestPssList.add(proc);
8232 }
8233 }
8234 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8235 }
8236
8237 int oldPri = Process.getThreadPriority(Process.myTid());
8238 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8239 for (int i=procs.size()-1; i>=0; i--) {
8240 ProcessRecord proc = procs.get(i);
8241 proc.lastPss = 0;
8242 proc.requestPss();
8243 }
8244 Process.setThreadPriority(oldPri);
8245 }
8246
8247 void removeRequestedPss(ProcessRecord proc) {
8248 Runnable callback = null;
8249 synchronized (this) {
8250 if (mRequestPssList.remove(proc)) {
8251 if (mRequestPssList.size() == 0) {
8252 callback = mRequestPssCallback;
8253 mRequestPssCallback = null;
8254 }
8255 }
8256 }
8257
8258 if (callback != null) {
8259 callback.run();
8260 }
8261 }
8262
8263 public void collectPss(Watchdog.PssStats stats) {
8264 stats.mEmptyPss = 0;
8265 stats.mEmptyCount = 0;
8266 stats.mBackgroundPss = 0;
8267 stats.mBackgroundCount = 0;
8268 stats.mServicePss = 0;
8269 stats.mServiceCount = 0;
8270 stats.mVisiblePss = 0;
8271 stats.mVisibleCount = 0;
8272 stats.mForegroundPss = 0;
8273 stats.mForegroundCount = 0;
8274 stats.mNoPssCount = 0;
8275 synchronized (this) {
8276 int i;
8277 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8278 ? mProcDeaths.length : stats.mProcDeaths.length;
8279 int aggr = 0;
8280 for (i=0; i<NPD; i++) {
8281 aggr += mProcDeaths[i];
8282 stats.mProcDeaths[i] = aggr;
8283 }
8284 while (i<stats.mProcDeaths.length) {
8285 stats.mProcDeaths[i] = 0;
8286 i++;
8287 }
8288
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008289 for (i=mLruProcesses.size()-1; i>=0; i--) {
8290 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 if (proc.persistent) {
8292 continue;
8293 }
8294 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
8295 if (proc.lastPss == 0) {
8296 stats.mNoPssCount++;
8297 continue;
8298 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008299 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8300 if (proc.empty) {
8301 stats.mEmptyPss += proc.lastPss;
8302 stats.mEmptyCount++;
8303 } else {
8304 stats.mBackgroundPss += proc.lastPss;
8305 stats.mBackgroundCount++;
8306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008307 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8308 stats.mVisiblePss += proc.lastPss;
8309 stats.mVisibleCount++;
8310 } else {
8311 stats.mForegroundPss += proc.lastPss;
8312 stats.mForegroundCount++;
8313 }
8314 }
8315 }
8316 }
8317
8318 public final void startRunning(String pkg, String cls, String action,
8319 String data) {
8320 synchronized(this) {
8321 if (mStartRunning) {
8322 return;
8323 }
8324 mStartRunning = true;
8325 mTopComponent = pkg != null && cls != null
8326 ? new ComponentName(pkg, cls) : null;
8327 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8328 mTopData = data;
8329 if (!mSystemReady) {
8330 return;
8331 }
8332 }
8333
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008334 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 }
8336
8337 private void retrieveSettings() {
8338 final ContentResolver resolver = mContext.getContentResolver();
8339 String debugApp = Settings.System.getString(
8340 resolver, Settings.System.DEBUG_APP);
8341 boolean waitForDebugger = Settings.System.getInt(
8342 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8343 boolean alwaysFinishActivities = Settings.System.getInt(
8344 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8345
8346 Configuration configuration = new Configuration();
8347 Settings.System.getConfiguration(resolver, configuration);
8348
8349 synchronized (this) {
8350 mDebugApp = mOrigDebugApp = debugApp;
8351 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8352 mAlwaysFinishActivities = alwaysFinishActivities;
8353 // This happens before any activities are started, so we can
8354 // change mConfiguration in-place.
8355 mConfiguration.updateFrom(configuration);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07008356 if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 }
8358 }
8359
8360 public boolean testIsSystemReady() {
8361 // no need to synchronize(this) just to read & return the value
8362 return mSystemReady;
8363 }
8364
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008365 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366 // In the simulator, startRunning will never have been called, which
8367 // normally sets a few crucial variables. Do it here instead.
8368 if (!Process.supportsProcesses()) {
8369 mStartRunning = true;
8370 mTopAction = Intent.ACTION_MAIN;
8371 }
8372
8373 synchronized(this) {
8374 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008375 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 return;
8377 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008378
8379 // Check to see if there are any update receivers to run.
8380 if (!mDidUpdate) {
8381 if (mWaitingUpdate) {
8382 return;
8383 }
8384 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8385 List<ResolveInfo> ris = null;
8386 try {
8387 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8388 intent, null, 0);
8389 } catch (RemoteException e) {
8390 }
8391 if (ris != null) {
8392 for (int i=ris.size()-1; i>=0; i--) {
8393 if ((ris.get(i).activityInfo.applicationInfo.flags
8394 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8395 ris.remove(i);
8396 }
8397 }
8398 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8399 for (int i=0; i<ris.size(); i++) {
8400 ActivityInfo ai = ris.get(i).activityInfo;
8401 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8402 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008403 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008404 finisher = new IIntentReceiver.Stub() {
8405 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008406 String data, Bundle extras, boolean ordered,
8407 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008408 throws RemoteException {
8409 synchronized (ActivityManagerService.this) {
8410 mDidUpdate = true;
8411 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008412 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008413 }
8414 };
8415 }
8416 Log.i(TAG, "Sending system update to: " + intent.getComponent());
8417 broadcastIntentLocked(null, null, intent, null, finisher,
8418 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008419 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008420 mWaitingUpdate = true;
8421 }
8422 }
8423 }
8424 if (mWaitingUpdate) {
8425 return;
8426 }
8427 mDidUpdate = true;
8428 }
8429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 mSystemReady = true;
8431 if (!mStartRunning) {
8432 return;
8433 }
8434 }
8435
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008436 ArrayList<ProcessRecord> procsToKill = null;
8437 synchronized(mPidsSelfLocked) {
8438 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8439 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8440 if (!isAllowedWhileBooting(proc.info)){
8441 if (procsToKill == null) {
8442 procsToKill = new ArrayList<ProcessRecord>();
8443 }
8444 procsToKill.add(proc);
8445 }
8446 }
8447 }
8448
8449 if (procsToKill != null) {
8450 synchronized(this) {
8451 for (int i=procsToKill.size()-1; i>=0; i--) {
8452 ProcessRecord proc = procsToKill.get(i);
8453 Log.i(TAG, "Removing system update proc: " + proc);
8454 removeProcessLocked(proc, true);
8455 }
8456 }
8457 }
8458
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008459 Log.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008460 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 SystemClock.uptimeMillis());
8462
8463 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008464 // Make sure we have no pre-ready processes sitting around.
8465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008466 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8467 ResolveInfo ri = mContext.getPackageManager()
8468 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008469 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 CharSequence errorMsg = null;
8471 if (ri != null) {
8472 ActivityInfo ai = ri.activityInfo;
8473 ApplicationInfo app = ai.applicationInfo;
8474 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8475 mTopAction = Intent.ACTION_FACTORY_TEST;
8476 mTopData = null;
8477 mTopComponent = new ComponentName(app.packageName,
8478 ai.name);
8479 } else {
8480 errorMsg = mContext.getResources().getText(
8481 com.android.internal.R.string.factorytest_not_system);
8482 }
8483 } else {
8484 errorMsg = mContext.getResources().getText(
8485 com.android.internal.R.string.factorytest_no_action);
8486 }
8487 if (errorMsg != null) {
8488 mTopAction = null;
8489 mTopData = null;
8490 mTopComponent = null;
8491 Message msg = Message.obtain();
8492 msg.what = SHOW_FACTORY_ERROR_MSG;
8493 msg.getData().putCharSequence("msg", errorMsg);
8494 mHandler.sendMessage(msg);
8495 }
8496 }
8497 }
8498
8499 retrieveSettings();
8500
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008501 if (goingCallback != null) goingCallback.run();
8502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008503 synchronized (this) {
8504 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8505 try {
8506 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008507 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 if (apps != null) {
8509 int N = apps.size();
8510 int i;
8511 for (i=0; i<N; i++) {
8512 ApplicationInfo info
8513 = (ApplicationInfo)apps.get(i);
8514 if (info != null &&
8515 !info.packageName.equals("android")) {
8516 addAppLocked(info);
8517 }
8518 }
8519 }
8520 } catch (RemoteException ex) {
8521 // pm is in same process, this will never happen.
8522 }
8523 }
8524
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008525 // Start up initial activity.
8526 mBooting = true;
8527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 try {
8529 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8530 Message msg = Message.obtain();
8531 msg.what = SHOW_UID_ERROR_MSG;
8532 mHandler.sendMessage(msg);
8533 }
8534 } catch (RemoteException e) {
8535 }
8536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 resumeTopActivityLocked(null);
8538 }
8539 }
8540
Dan Egnorb7f03672009-12-09 16:22:32 -08008541 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008542 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008544 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008545 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 startAppProblemLocked(app);
8547 app.stopFreezingAllLocked();
8548 return handleAppCrashLocked(app);
8549 }
8550
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008551 private ComponentName getErrorReportReceiver(ProcessRecord app) {
Doug Zongker43866e02010-01-07 12:09:54 -08008552 // check if error reporting is enabled in secure settings
8553 int enabled = Settings.Secure.getInt(mContext.getContentResolver(),
8554 Settings.Secure.SEND_ACTION_APP_ERROR, 0);
Jacek Surazskia2339432009-09-18 15:01:26 +02008555 if (enabled == 0) {
8556 return null;
8557 }
8558
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008559 IPackageManager pm = ActivityThread.getPackageManager();
Jacek Surazski82a73df2009-06-17 14:33:18 +02008560
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008561 try {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008562 // look for receiver in the installer package
8563 String candidate = pm.getInstallerPackageName(app.info.packageName);
8564 ComponentName result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8565 if (result != null) {
8566 return result;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008567 }
8568
Jacek Surazski82a73df2009-06-17 14:33:18 +02008569 // if the error app is on the system image, look for system apps
8570 // error receiver
8571 if ((app.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8572 candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
8573 result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8574 if (result != null) {
8575 return result;
8576 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008577 }
8578
Jacek Surazski82a73df2009-06-17 14:33:18 +02008579 // if there is a default receiver, try that
8580 candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
8581 return getErrorReportReceiver(pm, app.info.packageName, candidate);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008582 } catch (RemoteException e) {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008583 // should not happen
8584 Log.e(TAG, "error talking to PackageManager", e);
8585 return null;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008586 }
Jacek Surazski82a73df2009-06-17 14:33:18 +02008587 }
8588
8589 /**
8590 * Return activity in receiverPackage that handles ACTION_APP_ERROR.
8591 *
8592 * @param pm PackageManager isntance
8593 * @param errorPackage package which caused the error
8594 * @param receiverPackage candidate package to receive the error
8595 * @return activity component within receiverPackage which handles
8596 * ACTION_APP_ERROR, or null if not found
8597 */
8598 private ComponentName getErrorReportReceiver(IPackageManager pm, String errorPackage,
8599 String receiverPackage) throws RemoteException {
8600 if (receiverPackage == null || receiverPackage.length() == 0) {
8601 return null;
8602 }
8603
8604 // break the loop if it's the error report receiver package that crashed
8605 if (receiverPackage.equals(errorPackage)) {
8606 return null;
8607 }
8608
8609 Intent intent = new Intent(Intent.ACTION_APP_ERROR);
8610 intent.setPackage(receiverPackage);
8611 ResolveInfo info = pm.resolveIntent(intent, null, 0);
8612 if (info == null || info.activityInfo == null) {
8613 return null;
8614 }
8615 return new ComponentName(receiverPackage, info.activityInfo.name);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008616 }
8617
Dan Egnorb7f03672009-12-09 16:22:32 -08008618 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008619 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008621 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008622 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8623 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 startAppProblemLocked(app);
8625 app.stopFreezingAllLocked();
8626 }
8627
8628 /**
8629 * Generate a process error record, suitable for attachment to a ProcessRecord.
8630 *
8631 * @param app The ProcessRecord in which the error occurred.
8632 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8633 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008634 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 * @param shortMsg Short message describing the crash.
8636 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008637 * @param stackTrace Full crash stack trace, may be null.
8638 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 * @return Returns a fully-formed AppErrorStateInfo record.
8640 */
8641 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008642 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 report.condition = condition;
8646 report.processName = app.processName;
8647 report.pid = app.pid;
8648 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008649 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 report.shortMsg = shortMsg;
8651 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008652 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653
8654 return report;
8655 }
8656
Dan Egnor42471dd2010-01-07 17:25:22 -08008657 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008658 synchronized (this) {
8659 app.crashing = false;
8660 app.crashingReport = null;
8661 app.notResponding = false;
8662 app.notRespondingReport = null;
8663 if (app.anrDialog == fromDialog) {
8664 app.anrDialog = null;
8665 }
8666 if (app.waitDialog == fromDialog) {
8667 app.waitDialog = null;
8668 }
8669 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008670 handleAppCrashLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 Log.i(ActivityManagerService.TAG, "Killing process "
8672 + app.processName
8673 + " (pid=" + app.pid + ") at user's request");
8674 Process.killProcess(app.pid);
8675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 }
8677 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008678
Dan Egnorb7f03672009-12-09 16:22:32 -08008679 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 long now = SystemClock.uptimeMillis();
8681
8682 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8683 app.info.uid);
8684 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8685 // This process loses!
8686 Log.w(TAG, "Process " + app.info.processName
8687 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008688 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 app.info.processName, app.info.uid);
8690 killServicesLocked(app, false);
8691 for (int i=mHistory.size()-1; i>=0; i--) {
8692 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8693 if (r.app == app) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08008694 Log.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008695 + r.intent.getComponent().flattenToShortString());
8696 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8697 }
8698 }
8699 if (!app.persistent) {
8700 // We don't want to start this process again until the user
8701 // explicitly does so... but for persistent process, we really
8702 // need to keep it running. If a persistent process is actually
8703 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008704 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 app.info.processName);
8706 mBadProcesses.put(app.info.processName, app.info.uid, now);
8707 app.bad = true;
8708 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8709 app.removed = true;
8710 removeProcessLocked(app, false);
8711 return false;
8712 }
8713 }
8714
8715 // Bump up the crash count of any services currently running in the proc.
8716 if (app.services.size() != 0) {
8717 // Any services running in the application need to be placed
8718 // back in the pending list.
8719 Iterator it = app.services.iterator();
8720 while (it.hasNext()) {
8721 ServiceRecord sr = (ServiceRecord)it.next();
8722 sr.crashCount++;
8723 }
8724 }
8725
8726 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8727 return true;
8728 }
8729
8730 void startAppProblemLocked(ProcessRecord app) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008731 app.errorReportReceiver = getErrorReportReceiver(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 skipCurrentReceiverLocked(app);
8733 }
8734
8735 void skipCurrentReceiverLocked(ProcessRecord app) {
8736 boolean reschedule = false;
8737 BroadcastRecord r = app.curReceiver;
8738 if (r != null) {
8739 // The current broadcast is waiting for this app's receiver
8740 // to be finished. Looks like that's not going to happen, so
8741 // let the broadcast continue.
8742 logBroadcastReceiverDiscard(r);
8743 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8744 r.resultExtras, r.resultAbort, true);
8745 reschedule = true;
8746 }
8747 r = mPendingBroadcast;
8748 if (r != null && r.curApp == app) {
8749 if (DEBUG_BROADCAST) Log.v(TAG,
8750 "skip & discard pending app " + r);
8751 logBroadcastReceiverDiscard(r);
8752 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8753 r.resultExtras, r.resultAbort, true);
8754 reschedule = true;
8755 }
8756 if (reschedule) {
8757 scheduleBroadcastsLocked();
8758 }
8759 }
8760
Dan Egnor60d87622009-12-16 16:32:58 -08008761 /**
8762 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8763 * The application process will exit immediately after this call returns.
8764 * @param app object of the crashing app, null for the system server
8765 * @param crashInfo describing the exception
8766 */
8767 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8768 ProcessRecord r = findAppProcess(app);
8769
8770 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8771 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008772 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008773 crashInfo.exceptionClassName,
8774 crashInfo.exceptionMessage,
8775 crashInfo.throwFileName,
8776 crashInfo.throwLineNumber);
8777
Dan Egnor42471dd2010-01-07 17:25:22 -08008778 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008779
8780 crashApplication(r, crashInfo);
8781 }
8782
8783 /**
8784 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8785 * @param app object of the crashing app, null for the system server
8786 * @param tag reported by the caller
8787 * @param crashInfo describing the context of the error
8788 * @return true if the process should exit immediately (WTF is fatal)
8789 */
8790 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008791 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008792 ProcessRecord r = findAppProcess(app);
8793
8794 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8795 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008796 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008797 tag, crashInfo.exceptionMessage);
8798
Dan Egnor42471dd2010-01-07 17:25:22 -08008799 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008800
Doug Zongker43866e02010-01-07 12:09:54 -08008801 if (Settings.Secure.getInt(mContext.getContentResolver(),
8802 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008803 crashApplication(r, crashInfo);
8804 return true;
8805 } else {
8806 return false;
8807 }
8808 }
8809
8810 /**
8811 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8812 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8813 */
8814 private ProcessRecord findAppProcess(IBinder app) {
8815 if (app == null) {
8816 return null;
8817 }
8818
8819 synchronized (this) {
8820 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8821 final int NA = apps.size();
8822 for (int ia=0; ia<NA; ia++) {
8823 ProcessRecord p = apps.valueAt(ia);
8824 if (p.thread != null && p.thread.asBinder() == app) {
8825 return p;
8826 }
8827 }
8828 }
8829
8830 Log.w(TAG, "Can't find mystery application: " + app);
8831 return null;
8832 }
8833 }
8834
8835 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008836 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008837 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008838 * @param process which caused the error, null means the system server
8839 * @param activity which triggered the error, null if unknown
8840 * @param parent activity related to the error, null if unknown
8841 * @param subject line related to the error, null if absent
8842 * @param report in long form describing the error, null if absent
8843 * @param logFile to include in the report, null if none
8844 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008845 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008846 private void addErrorToDropBox(String eventType,
8847 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8848 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008849 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008850 String dropboxTag;
8851 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008852 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008853 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008854 dropboxTag = "system_app_" + eventType;
8855 } else {
8856 dropboxTag = "data_app_" + eventType;
8857 }
8858
8859 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8860 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8861 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008862 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008863 sb.append("Process: system_server\n");
8864 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008865 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008866 }
8867 if (process != null) {
8868 int flags = process.info.flags;
8869 IPackageManager pm = ActivityThread.getPackageManager();
8870 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8871 for (String pkg : process.pkgList) {
8872 sb.append("Package: ").append(pkg);
8873 try {
8874 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8875 if (pi != null) {
8876 sb.append(" v").append(pi.versionCode);
8877 if (pi.versionName != null) {
8878 sb.append(" (").append(pi.versionName).append(")");
8879 }
8880 }
8881 } catch (RemoteException e) {
8882 Log.e(TAG, "Error getting package info: " + pkg, e);
8883 }
8884 sb.append("\n");
8885 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008886 }
8887 if (activity != null) {
8888 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8889 }
8890 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8891 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8892 }
8893 if (parent != null && parent != activity) {
8894 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8895 }
8896 if (subject != null) {
8897 sb.append("Subject: ").append(subject).append("\n");
8898 }
8899 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8900 sb.append("\n");
8901 if (report != null) {
8902 sb.append(report);
8903 }
8904 if (logFile != null) {
8905 try {
8906 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8907 } catch (IOException e) {
8908 Log.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008909 }
8910 }
Dan Egnor60d87622009-12-16 16:32:58 -08008911 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008912 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08008913 }
8914 dbox.addText(dropboxTag, sb.toString());
8915 }
8916 }
8917
8918 /**
8919 * Bring up the "unexpected error" dialog box for a crashing app.
8920 * Deal with edge cases (intercepts from instrumented applications,
8921 * ActivityController, error intent receivers, that sort of thing).
8922 * @param r the application crashing
8923 * @param crashInfo describing the failure
8924 */
8925 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008926 long timeMillis = System.currentTimeMillis();
8927 String shortMsg = crashInfo.exceptionClassName;
8928 String longMsg = crashInfo.exceptionMessage;
8929 String stackTrace = crashInfo.stackTrace;
8930 if (shortMsg != null && longMsg != null) {
8931 longMsg = shortMsg + ": " + longMsg;
8932 } else if (shortMsg != null) {
8933 longMsg = shortMsg;
8934 }
8935
Dan Egnor60d87622009-12-16 16:32:58 -08008936 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008938 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 try {
8940 String name = r != null ? r.processName : null;
8941 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008942 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008943 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008944 Log.w(TAG, "Force-killing crashed app " + name
8945 + " at watcher's request");
8946 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008947 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 }
8949 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008950 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008951 }
8952 }
8953
8954 final long origId = Binder.clearCallingIdentity();
8955
8956 // If this process is running instrumentation, finish it.
8957 if (r != null && r.instrumentationClass != null) {
8958 Log.w(TAG, "Error in app " + r.processName
8959 + " running instrumentation " + r.instrumentationClass + ":");
8960 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
8961 if (longMsg != null) Log.w(TAG, " " + longMsg);
8962 Bundle info = new Bundle();
8963 info.putString("shortMsg", shortMsg);
8964 info.putString("longMsg", longMsg);
8965 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8966 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008967 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 }
8969
Dan Egnor60d87622009-12-16 16:32:58 -08008970 // If we can't identify the process or it's already exceeded its crash quota,
8971 // quit right away without showing a crash dialog.
8972 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008974 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 }
8976
8977 Message msg = Message.obtain();
8978 msg.what = SHOW_ERROR_MSG;
8979 HashMap data = new HashMap();
8980 data.put("result", result);
8981 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 msg.obj = data;
8983 mHandler.sendMessage(msg);
8984
8985 Binder.restoreCallingIdentity(origId);
8986 }
8987
8988 int res = result.get();
8989
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008990 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 synchronized (this) {
8992 if (r != null) {
8993 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8994 SystemClock.uptimeMillis());
8995 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008996 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008997 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008998 }
8999 }
9000
9001 if (appErrorIntent != null) {
9002 try {
9003 mContext.startActivity(appErrorIntent);
9004 } catch (ActivityNotFoundException e) {
9005 Log.w(TAG, "bug report receiver dissappeared", e);
9006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009008 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009009
9010 Intent createAppErrorIntentLocked(ProcessRecord r,
9011 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9012 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009013 if (report == null) {
9014 return null;
9015 }
9016 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9017 result.setComponent(r.errorReportReceiver);
9018 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9019 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9020 return result;
9021 }
9022
Dan Egnorb7f03672009-12-09 16:22:32 -08009023 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9024 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009025 if (r.errorReportReceiver == null) {
9026 return null;
9027 }
9028
9029 if (!r.crashing && !r.notResponding) {
9030 return null;
9031 }
9032
Dan Egnorb7f03672009-12-09 16:22:32 -08009033 ApplicationErrorReport report = new ApplicationErrorReport();
9034 report.packageName = r.info.packageName;
9035 report.installerPackageName = r.errorReportReceiver.getPackageName();
9036 report.processName = r.processName;
9037 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009038 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009039
Dan Egnorb7f03672009-12-09 16:22:32 -08009040 if (r.crashing) {
9041 report.type = ApplicationErrorReport.TYPE_CRASH;
9042 report.crashInfo = crashInfo;
9043 } else if (r.notResponding) {
9044 report.type = ApplicationErrorReport.TYPE_ANR;
9045 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009046
Dan Egnorb7f03672009-12-09 16:22:32 -08009047 report.anrInfo.activity = r.notRespondingReport.tag;
9048 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9049 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009050 }
9051
Dan Egnorb7f03672009-12-09 16:22:32 -08009052 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009053 }
9054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9056 // assume our apps are happy - lazy create the list
9057 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9058
9059 synchronized (this) {
9060
9061 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009062 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9063 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009064 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9065 // This one's in trouble, so we'll generate a report for it
9066 // crashes are higher priority (in case there's a crash *and* an anr)
9067 ActivityManager.ProcessErrorStateInfo report = null;
9068 if (app.crashing) {
9069 report = app.crashingReport;
9070 } else if (app.notResponding) {
9071 report = app.notRespondingReport;
9072 }
9073
9074 if (report != null) {
9075 if (errList == null) {
9076 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9077 }
9078 errList.add(report);
9079 } else {
9080 Log.w(TAG, "Missing app error report, app = " + app.processName +
9081 " crashing = " + app.crashing +
9082 " notResponding = " + app.notResponding);
9083 }
9084 }
9085 }
9086 }
9087
9088 return errList;
9089 }
9090
9091 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9092 // Lazy instantiation of list
9093 List<ActivityManager.RunningAppProcessInfo> runList = null;
9094 synchronized (this) {
9095 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009096 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9097 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9099 // Generate process state info for running application
9100 ActivityManager.RunningAppProcessInfo currApp =
9101 new ActivityManager.RunningAppProcessInfo(app.processName,
9102 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009103 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009105 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009106 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9107 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9108 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009109 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9110 } else if (adj >= HOME_APP_ADJ) {
9111 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9112 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 } else if (adj >= SECONDARY_SERVER_ADJ) {
9114 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9115 } else if (adj >= VISIBLE_APP_ADJ) {
9116 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9117 } else {
9118 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9119 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009120 currApp.importanceReasonCode = app.adjTypeCode;
9121 if (app.adjSource instanceof ProcessRecord) {
9122 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9123 } else if (app.adjSource instanceof HistoryRecord) {
9124 HistoryRecord r = (HistoryRecord)app.adjSource;
9125 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9126 }
9127 if (app.adjTarget instanceof ComponentName) {
9128 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
9131 // + " lru=" + currApp.lru);
9132 if (runList == null) {
9133 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9134 }
9135 runList.add(currApp);
9136 }
9137 }
9138 }
9139 return runList;
9140 }
9141
9142 @Override
9143 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009144 if (checkCallingPermission(android.Manifest.permission.DUMP)
9145 != PackageManager.PERMISSION_GRANTED) {
9146 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9147 + Binder.getCallingPid()
9148 + ", uid=" + Binder.getCallingUid()
9149 + " without permission "
9150 + android.Manifest.permission.DUMP);
9151 return;
9152 }
9153
9154 boolean dumpAll = false;
9155
9156 int opti = 0;
9157 while (opti < args.length) {
9158 String opt = args[opti];
9159 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9160 break;
9161 }
9162 opti++;
9163 if ("-a".equals(opt)) {
9164 dumpAll = true;
9165 } else if ("-h".equals(opt)) {
9166 pw.println("Activity manager dump options:");
9167 pw.println(" [-a] [h- [cmd] ...");
9168 pw.println(" cmd may be one of:");
9169 pw.println(" activities: activity stack state");
9170 pw.println(" broadcasts: broadcast state");
9171 pw.println(" intents: pending intent state");
9172 pw.println(" processes: process state");
9173 pw.println(" providers: content provider state");
9174 pw.println(" services: service state");
9175 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009177 } else {
9178 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009180 }
9181
9182 // Is the caller requesting to dump a particular piece of data?
9183 if (opti < args.length) {
9184 String cmd = args[opti];
9185 opti++;
9186 if ("activities".equals(cmd) || "a".equals(cmd)) {
9187 synchronized (this) {
9188 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009190 return;
9191 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9192 synchronized (this) {
9193 dumpBroadcastsLocked(fd, pw, args, opti, true);
9194 }
9195 return;
9196 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9197 synchronized (this) {
9198 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9199 }
9200 return;
9201 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9202 synchronized (this) {
9203 dumpProcessesLocked(fd, pw, args, opti, true);
9204 }
9205 return;
9206 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9207 synchronized (this) {
9208 dumpProvidersLocked(fd, pw, args, opti, true);
9209 }
9210 return;
9211 } else if ("service".equals(cmd)) {
9212 dumpService(fd, pw, args, opti, true);
9213 return;
9214 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9215 synchronized (this) {
9216 dumpServicesLocked(fd, pw, args, opti, true);
9217 }
9218 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009220 }
9221
9222 // No piece of data specified, dump everything.
9223 synchronized (this) {
9224 boolean needSep;
9225 if (dumpAll) {
9226 pw.println("Providers in Current Activity Manager State:");
9227 }
9228 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9229 if (needSep) {
9230 pw.println(" ");
9231 }
9232 if (dumpAll) {
9233 pw.println("-------------------------------------------------------------------------------");
9234 pw.println("Broadcasts in Current Activity Manager State:");
9235 }
9236 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9237 if (needSep) {
9238 pw.println(" ");
9239 }
9240 if (dumpAll) {
9241 pw.println("-------------------------------------------------------------------------------");
9242 pw.println("Services in Current Activity Manager State:");
9243 }
9244 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9245 if (needSep) {
9246 pw.println(" ");
9247 }
9248 if (dumpAll) {
9249 pw.println("-------------------------------------------------------------------------------");
9250 pw.println("PendingIntents in Current Activity Manager State:");
9251 }
9252 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9253 if (needSep) {
9254 pw.println(" ");
9255 }
9256 if (dumpAll) {
9257 pw.println("-------------------------------------------------------------------------------");
9258 pw.println("Activities in Current Activity Manager State:");
9259 }
9260 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9261 if (needSep) {
9262 pw.println(" ");
9263 }
9264 if (dumpAll) {
9265 pw.println("-------------------------------------------------------------------------------");
9266 pw.println("Processes in Current Activity Manager State:");
9267 }
9268 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9269 }
9270 }
9271
9272 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9273 int opti, boolean dumpAll, boolean needHeader) {
9274 if (needHeader) {
9275 pw.println(" Activity stack:");
9276 }
9277 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9278 pw.println(" ");
9279 pw.println(" Running activities (most recent first):");
9280 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9281 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009282 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009283 pw.println(" Activities waiting for another to become visible:");
9284 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9285 }
9286 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009288 pw.println(" Activities waiting to stop:");
9289 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9290 }
9291 if (mFinishingActivities.size() > 0) {
9292 pw.println(" ");
9293 pw.println(" Activities waiting to finish:");
9294 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009297 pw.println(" ");
9298 pw.println(" mPausingActivity: " + mPausingActivity);
9299 pw.println(" mResumedActivity: " + mResumedActivity);
9300 pw.println(" mFocusedActivity: " + mFocusedActivity);
9301 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009303 if (dumpAll && mRecentTasks.size() > 0) {
9304 pw.println(" ");
9305 pw.println("Recent tasks in Current Activity Manager State:");
9306
9307 final int N = mRecentTasks.size();
9308 for (int i=0; i<N; i++) {
9309 TaskRecord tr = mRecentTasks.get(i);
9310 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9311 pw.println(tr);
9312 mRecentTasks.get(i).dump(pw, " ");
9313 }
9314 }
9315
9316 pw.println(" ");
9317 pw.println(" mCurTask: " + mCurTask);
9318
9319 return true;
9320 }
9321
9322 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9323 int opti, boolean dumpAll) {
9324 boolean needSep = false;
9325 int numPers = 0;
9326
9327 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009328 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9329 final int NA = procs.size();
9330 for (int ia=0; ia<NA; ia++) {
9331 if (!needSep) {
9332 pw.println(" All known processes:");
9333 needSep = true;
9334 }
9335 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009336 pw.print(r.persistent ? " *PERS*" : " *APP*");
9337 pw.print(" UID "); pw.print(procs.keyAt(ia));
9338 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 r.dump(pw, " ");
9340 if (r.persistent) {
9341 numPers++;
9342 }
9343 }
9344 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009345 }
9346
9347 if (mLruProcesses.size() > 0) {
9348 if (needSep) pw.println(" ");
9349 needSep = true;
9350 pw.println(" Running processes (most recent first):");
9351 dumpProcessList(pw, this, mLruProcesses, " ",
9352 "App ", "PERS", true);
9353 needSep = true;
9354 }
9355
9356 synchronized (mPidsSelfLocked) {
9357 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 if (needSep) pw.println(" ");
9359 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009360 pw.println(" PID mappings:");
9361 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9362 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9363 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009364 }
9365 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009366 }
9367
9368 if (mForegroundProcesses.size() > 0) {
9369 if (needSep) pw.println(" ");
9370 needSep = true;
9371 pw.println(" Foreground Processes:");
9372 for (int i=0; i<mForegroundProcesses.size(); i++) {
9373 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9374 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009376 }
9377
9378 if (mPersistentStartingProcesses.size() > 0) {
9379 if (needSep) pw.println(" ");
9380 needSep = true;
9381 pw.println(" Persisent processes that are starting:");
9382 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9383 "Starting Norm", "Restarting PERS", false);
9384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009386 if (mStartingProcesses.size() > 0) {
9387 if (needSep) pw.println(" ");
9388 needSep = true;
9389 pw.println(" Processes that are starting:");
9390 dumpProcessList(pw, this, mStartingProcesses, " ",
9391 "Starting Norm", "Starting PERS", false);
9392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009393
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009394 if (mRemovedProcesses.size() > 0) {
9395 if (needSep) pw.println(" ");
9396 needSep = true;
9397 pw.println(" Processes that are being removed:");
9398 dumpProcessList(pw, this, mRemovedProcesses, " ",
9399 "Removed Norm", "Removed PERS", false);
9400 }
9401
9402 if (mProcessesOnHold.size() > 0) {
9403 if (needSep) pw.println(" ");
9404 needSep = true;
9405 pw.println(" Processes that are on old until the system is ready:");
9406 dumpProcessList(pw, this, mProcessesOnHold, " ",
9407 "OnHold Norm", "OnHold PERS", false);
9408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009410 if (mProcessesToGc.size() > 0) {
9411 if (needSep) pw.println(" ");
9412 needSep = true;
9413 pw.println(" Processes that are waiting to GC:");
9414 long now = SystemClock.uptimeMillis();
9415 for (int i=0; i<mProcessesToGc.size(); i++) {
9416 ProcessRecord proc = mProcessesToGc.get(i);
9417 pw.print(" Process "); pw.println(proc);
9418 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9419 pw.print(", last gced=");
9420 pw.print(now-proc.lastRequestedGc);
9421 pw.print(" ms ago, last lowMem=");
9422 pw.print(now-proc.lastLowMemory);
9423 pw.println(" ms ago");
9424
9425 }
9426 }
9427
9428 if (mProcessCrashTimes.getMap().size() > 0) {
9429 if (needSep) pw.println(" ");
9430 needSep = true;
9431 pw.println(" Time since processes crashed:");
9432 long now = SystemClock.uptimeMillis();
9433 for (Map.Entry<String, SparseArray<Long>> procs
9434 : mProcessCrashTimes.getMap().entrySet()) {
9435 SparseArray<Long> uids = procs.getValue();
9436 final int N = uids.size();
9437 for (int i=0; i<N; i++) {
9438 pw.print(" Process "); pw.print(procs.getKey());
9439 pw.print(" uid "); pw.print(uids.keyAt(i));
9440 pw.print(": last crashed ");
9441 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009442 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009443 }
9444 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009447 if (mBadProcesses.getMap().size() > 0) {
9448 if (needSep) pw.println(" ");
9449 needSep = true;
9450 pw.println(" Bad processes:");
9451 for (Map.Entry<String, SparseArray<Long>> procs
9452 : mBadProcesses.getMap().entrySet()) {
9453 SparseArray<Long> uids = procs.getValue();
9454 final int N = uids.size();
9455 for (int i=0; i<N; i++) {
9456 pw.print(" Bad process "); pw.print(procs.getKey());
9457 pw.print(" uid "); pw.print(uids.keyAt(i));
9458 pw.print(": crashed at time ");
9459 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460 }
9461 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009463
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009464 pw.println(" ");
9465 pw.println(" mHomeProcess: " + mHomeProcess);
9466 pw.println(" mConfiguration: " + mConfiguration);
9467 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9468 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9469 || mOrigWaitForDebugger) {
9470 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9471 + " mDebugTransient=" + mDebugTransient
9472 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9473 }
9474 if (mAlwaysFinishActivities || mController != null) {
9475 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9476 + " mController=" + mController);
9477 }
9478 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009480 pw.println(" mStartRunning=" + mStartRunning
9481 + " mSystemReady=" + mSystemReady
9482 + " mBooting=" + mBooting
9483 + " mBooted=" + mBooted
9484 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009485 pw.println(" mGoingToSleep=" + mGoingToSleep);
9486 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009487 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009488
9489 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 }
9491
9492 /**
9493 * There are three ways to call this:
9494 * - no service specified: dump all the services
9495 * - a flattened component name that matched an existing service was specified as the
9496 * first arg: dump that one service
9497 * - the first arg isn't the flattened component name of an existing service:
9498 * dump all services whose component contains the first arg as a substring
9499 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009500 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9501 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 String[] newArgs;
9503 String componentNameString;
9504 ServiceRecord r;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009505 if (opti <= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506 componentNameString = null;
9507 newArgs = EMPTY_STRING_ARRAY;
9508 r = null;
9509 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009510 componentNameString = args[opti];
9511 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9513 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009514 newArgs = new String[args.length - opti];
9515 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 }
9517
9518 if (r != null) {
9519 dumpService(fd, pw, r, newArgs);
9520 } else {
9521 for (ServiceRecord r1 : mServices.values()) {
9522 if (componentNameString == null
9523 || r1.name.flattenToString().contains(componentNameString)) {
9524 dumpService(fd, pw, r1, newArgs);
9525 }
9526 }
9527 }
9528 }
9529
9530 /**
9531 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9532 * there is a thread associated with the service.
9533 */
9534 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9535 pw.println(" Service " + r.name.flattenToString());
9536 if (r.app != null && r.app.thread != null) {
9537 try {
9538 // flush anything that is already in the PrintWriter since the thread is going
9539 // to write to the file descriptor directly
9540 pw.flush();
9541 r.app.thread.dumpService(fd, r, args);
9542 pw.print("\n");
9543 } catch (RemoteException e) {
9544 pw.println("got a RemoteException while dumping the service");
9545 }
9546 }
9547 }
9548
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009549 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9550 int opti, boolean dumpAll) {
9551 boolean needSep = false;
9552
9553 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 if (mRegisteredReceivers.size() > 0) {
9555 pw.println(" ");
9556 pw.println(" Registered Receivers:");
9557 Iterator it = mRegisteredReceivers.values().iterator();
9558 while (it.hasNext()) {
9559 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009560 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009561 r.dump(pw, " ");
9562 }
9563 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 pw.println(" ");
9566 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009567 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009568 needSep = true;
9569 }
9570
9571 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9572 || mPendingBroadcast != null) {
9573 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009575 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009577 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9578 pw.println(" Broadcast #" + i + ":");
9579 mParallelBroadcasts.get(i).dump(pw, " ");
9580 }
9581 if (mOrderedBroadcasts.size() > 0) {
9582 pw.println(" ");
9583 pw.println(" Active serialized broadcasts:");
9584 }
9585 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9586 pw.println(" Serialized Broadcast #" + i + ":");
9587 mOrderedBroadcasts.get(i).dump(pw, " ");
9588 }
9589 pw.println(" ");
9590 pw.println(" Pending broadcast:");
9591 if (mPendingBroadcast != null) {
9592 mPendingBroadcast.dump(pw, " ");
9593 } else {
9594 pw.println(" (null)");
9595 }
9596 needSep = true;
9597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009599 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009601 pw.println(" Historical broadcasts:");
9602 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9603 BroadcastRecord r = mBroadcastHistory[i];
9604 if (r == null) {
9605 break;
9606 }
9607 pw.println(" Historical Broadcast #" + i + ":");
9608 r.dump(pw, " ");
9609 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009610 needSep = true;
9611 }
9612
9613 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009614 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009615 pw.println(" Sticky broadcasts:");
9616 StringBuilder sb = new StringBuilder(128);
9617 for (Map.Entry<String, ArrayList<Intent>> ent
9618 : mStickyBroadcasts.entrySet()) {
9619 pw.print(" * Sticky action "); pw.print(ent.getKey());
9620 pw.println(":");
9621 ArrayList<Intent> intents = ent.getValue();
9622 final int N = intents.size();
9623 for (int i=0; i<N; i++) {
9624 sb.setLength(0);
9625 sb.append(" Intent: ");
9626 intents.get(i).toShortString(sb, true, false);
9627 pw.println(sb.toString());
9628 Bundle bundle = intents.get(i).getExtras();
9629 if (bundle != null) {
9630 pw.print(" ");
9631 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 }
9633 }
9634 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009635 needSep = true;
9636 }
9637
9638 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009640 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641 pw.println(" mHandler:");
9642 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009643 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009645
9646 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009647 }
9648
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009649 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9650 int opti, boolean dumpAll) {
9651 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009653 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654 if (mServices.size() > 0) {
9655 pw.println(" Active services:");
9656 Iterator<ServiceRecord> it = mServices.values().iterator();
9657 while (it.hasNext()) {
9658 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009659 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 r.dump(pw, " ");
9661 }
9662 needSep = true;
9663 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009665
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009666 if (mPendingServices.size() > 0) {
9667 if (needSep) pw.println(" ");
9668 pw.println(" Pending services:");
9669 for (int i=0; i<mPendingServices.size(); i++) {
9670 ServiceRecord r = mPendingServices.get(i);
9671 pw.print(" * Pending "); pw.println(r);
9672 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009674 needSep = true;
9675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009677 if (mRestartingServices.size() > 0) {
9678 if (needSep) pw.println(" ");
9679 pw.println(" Restarting services:");
9680 for (int i=0; i<mRestartingServices.size(); i++) {
9681 ServiceRecord r = mRestartingServices.get(i);
9682 pw.print(" * Restarting "); pw.println(r);
9683 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009685 needSep = true;
9686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009688 if (mStoppingServices.size() > 0) {
9689 if (needSep) pw.println(" ");
9690 pw.println(" Stopping services:");
9691 for (int i=0; i<mStoppingServices.size(); i++) {
9692 ServiceRecord r = mStoppingServices.get(i);
9693 pw.print(" * Stopping "); pw.println(r);
9694 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009696 needSep = true;
9697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009699 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 if (mServiceConnections.size() > 0) {
9701 if (needSep) pw.println(" ");
9702 pw.println(" Connection bindings to services:");
9703 Iterator<ConnectionRecord> it
9704 = mServiceConnections.values().iterator();
9705 while (it.hasNext()) {
9706 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009707 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009708 r.dump(pw, " ");
9709 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009710 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 }
9712 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009713
9714 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 }
9716
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009717 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9718 int opti, boolean dumpAll) {
9719 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009721 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009722 if (mProvidersByClass.size() > 0) {
9723 if (needSep) pw.println(" ");
9724 pw.println(" Published content providers (by class):");
9725 Iterator it = mProvidersByClass.entrySet().iterator();
9726 while (it.hasNext()) {
9727 Map.Entry e = (Map.Entry)it.next();
9728 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009729 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 r.dump(pw, " ");
9731 }
9732 needSep = true;
9733 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009734
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009735 if (mProvidersByName.size() > 0) {
9736 pw.println(" ");
9737 pw.println(" Authority to provider mappings:");
9738 Iterator it = mProvidersByName.entrySet().iterator();
9739 while (it.hasNext()) {
9740 Map.Entry e = (Map.Entry)it.next();
9741 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9742 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9743 pw.println(r);
9744 }
9745 needSep = true;
9746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009748
9749 if (mLaunchingProviders.size() > 0) {
9750 if (needSep) pw.println(" ");
9751 pw.println(" Launching content providers:");
9752 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9753 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9754 pw.println(mLaunchingProviders.get(i));
9755 }
9756 needSep = true;
9757 }
9758
9759 if (mGrantedUriPermissions.size() > 0) {
9760 pw.println();
9761 pw.println("Granted Uri Permissions:");
9762 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9763 int uid = mGrantedUriPermissions.keyAt(i);
9764 HashMap<Uri, UriPermission> perms
9765 = mGrantedUriPermissions.valueAt(i);
9766 pw.print(" * UID "); pw.print(uid);
9767 pw.println(" holds:");
9768 for (UriPermission perm : perms.values()) {
9769 pw.print(" "); pw.println(perm);
9770 perm.dump(pw, " ");
9771 }
9772 }
9773 needSep = true;
9774 }
9775
9776 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 }
9778
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009779 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9780 int opti, boolean dumpAll) {
9781 boolean needSep = false;
9782
9783 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 if (this.mIntentSenderRecords.size() > 0) {
9785 Iterator<WeakReference<PendingIntentRecord>> it
9786 = mIntentSenderRecords.values().iterator();
9787 while (it.hasNext()) {
9788 WeakReference<PendingIntentRecord> ref = it.next();
9789 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009790 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009792 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 rec.dump(pw, " ");
9794 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009795 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 }
9797 }
9798 }
9799 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009800
9801 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 }
9803
9804 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009805 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806 TaskRecord lastTask = null;
9807 for (int i=list.size()-1; i>=0; i--) {
9808 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009809 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 if (lastTask != r.task) {
9811 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009812 pw.print(prefix);
9813 pw.print(full ? "* " : " ");
9814 pw.println(lastTask);
9815 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009816 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009819 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9820 pw.print(" #"); pw.print(i); pw.print(": ");
9821 pw.println(r);
9822 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009823 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 }
9826 }
9827
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009828 private static String buildOomTag(String prefix, String space, int val, int base) {
9829 if (val == base) {
9830 if (space == null) return prefix;
9831 return prefix + " ";
9832 }
9833 return prefix + "+" + Integer.toString(val-base);
9834 }
9835
9836 private static final int dumpProcessList(PrintWriter pw,
9837 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009838 String prefix, String normalLabel, String persistentLabel,
9839 boolean inclOomAdj) {
9840 int numPers = 0;
9841 for (int i=list.size()-1; i>=0; i--) {
9842 ProcessRecord r = (ProcessRecord)list.get(i);
9843 if (false) {
9844 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9845 + " #" + i + ":");
9846 r.dump(pw, prefix + " ");
9847 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009848 String oomAdj;
9849 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009850 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009851 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009852 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9853 } else if (r.setAdj >= HOME_APP_ADJ) {
9854 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9855 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9856 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9857 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9858 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9859 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9860 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9861 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9862 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009863 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009864 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009865 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009866 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009867 } else {
9868 oomAdj = Integer.toString(r.setAdj);
9869 }
9870 String schedGroup;
9871 switch (r.setSchedGroup) {
9872 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9873 schedGroup = "B";
9874 break;
9875 case Process.THREAD_GROUP_DEFAULT:
9876 schedGroup = "F";
9877 break;
9878 default:
9879 schedGroup = Integer.toString(r.setSchedGroup);
9880 break;
9881 }
9882 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009884 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009885 if (r.adjSource != null || r.adjTarget != null) {
9886 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009887 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 } else {
9890 pw.println(String.format("%s%s #%2d: %s",
9891 prefix, (r.persistent ? persistentLabel : normalLabel),
9892 i, r.toString()));
9893 }
9894 if (r.persistent) {
9895 numPers++;
9896 }
9897 }
9898 return numPers;
9899 }
9900
9901 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
9902 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009903 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009904 long uptime = SystemClock.uptimeMillis();
9905 long realtime = SystemClock.elapsedRealtime();
9906
9907 if (isCheckinRequest) {
9908 // short checkin version
9909 pw.println(uptime + "," + realtime);
9910 pw.flush();
9911 } else {
9912 pw.println("Applications Memory Usage (kB):");
9913 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9914 }
9915 for (int i = list.size() - 1 ; i >= 0 ; i--) {
9916 ProcessRecord r = (ProcessRecord)list.get(i);
9917 if (r.thread != null) {
9918 if (!isCheckinRequest) {
9919 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9920 pw.flush();
9921 }
9922 try {
9923 r.thread.asBinder().dump(fd, args);
9924 } catch (RemoteException e) {
9925 if (!isCheckinRequest) {
9926 pw.println("Got RemoteException!");
9927 pw.flush();
9928 }
9929 }
9930 }
9931 }
9932 }
9933
9934 /**
9935 * Searches array of arguments for the specified string
9936 * @param args array of argument strings
9937 * @param value value to search for
9938 * @return true if the value is contained in the array
9939 */
9940 private static boolean scanArgs(String[] args, String value) {
9941 if (args != null) {
9942 for (String arg : args) {
9943 if (value.equals(arg)) {
9944 return true;
9945 }
9946 }
9947 }
9948 return false;
9949 }
9950
Dianne Hackborn75b03852009-06-12 15:43:26 -07009951 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 int count = mHistory.size();
9953
9954 // convert the token to an entry in the history.
9955 HistoryRecord r = null;
9956 int index = -1;
9957 for (int i=count-1; i>=0; i--) {
9958 Object o = mHistory.get(i);
9959 if (o == token) {
9960 r = (HistoryRecord)o;
9961 index = i;
9962 break;
9963 }
9964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965
9966 return index;
9967 }
9968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009969 private final void killServicesLocked(ProcessRecord app,
9970 boolean allowRestart) {
9971 // Report disconnected services.
9972 if (false) {
9973 // XXX we are letting the client link to the service for
9974 // death notifications.
9975 if (app.services.size() > 0) {
9976 Iterator it = app.services.iterator();
9977 while (it.hasNext()) {
9978 ServiceRecord r = (ServiceRecord)it.next();
9979 if (r.connections.size() > 0) {
9980 Iterator<ConnectionRecord> jt
9981 = r.connections.values().iterator();
9982 while (jt.hasNext()) {
9983 ConnectionRecord c = jt.next();
9984 if (c.binding.client != app) {
9985 try {
9986 //c.conn.connected(r.className, null);
9987 } catch (Exception e) {
9988 // todo: this should be asynchronous!
9989 Log.w(TAG, "Exception thrown disconnected servce "
9990 + r.shortName
9991 + " from app " + app.processName, e);
9992 }
9993 }
9994 }
9995 }
9996 }
9997 }
9998 }
9999
10000 // Clean up any connections this application has to other services.
10001 if (app.connections.size() > 0) {
10002 Iterator<ConnectionRecord> it = app.connections.iterator();
10003 while (it.hasNext()) {
10004 ConnectionRecord r = it.next();
10005 removeConnectionLocked(r, app, null);
10006 }
10007 }
10008 app.connections.clear();
10009
10010 if (app.services.size() != 0) {
10011 // Any services running in the application need to be placed
10012 // back in the pending list.
10013 Iterator it = app.services.iterator();
10014 while (it.hasNext()) {
10015 ServiceRecord sr = (ServiceRecord)it.next();
10016 synchronized (sr.stats.getBatteryStats()) {
10017 sr.stats.stopLaunchedLocked();
10018 }
10019 sr.app = null;
10020 sr.executeNesting = 0;
10021 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010022
10023 boolean hasClients = sr.bindings.size() > 0;
10024 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 Iterator<IntentBindRecord> bindings
10026 = sr.bindings.values().iterator();
10027 while (bindings.hasNext()) {
10028 IntentBindRecord b = bindings.next();
10029 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
10030 + ": shouldUnbind=" + b.hasBound);
10031 b.binder = null;
10032 b.requested = b.received = b.hasBound = false;
10033 }
10034 }
10035
10036 if (sr.crashCount >= 2) {
10037 Log.w(TAG, "Service crashed " + sr.crashCount
10038 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010039 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 sr.crashCount, sr.shortName, app.pid);
10041 bringDownServiceLocked(sr, true);
10042 } else if (!allowRestart) {
10043 bringDownServiceLocked(sr, true);
10044 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010045 boolean canceled = scheduleServiceRestartLocked(sr, true);
10046
10047 // Should the service remain running? Note that in the
10048 // extreme case of so many attempts to deliver a command
10049 // that it failed, that we also will stop it here.
10050 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10051 if (sr.pendingStarts.size() == 0) {
10052 sr.startRequested = false;
10053 if (!hasClients) {
10054 // Whoops, no reason to restart!
10055 bringDownServiceLocked(sr, true);
10056 }
10057 }
10058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010059 }
10060 }
10061
10062 if (!allowRestart) {
10063 app.services.clear();
10064 }
10065 }
10066
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010067 // Make sure we have no more records on the stopping list.
10068 int i = mStoppingServices.size();
10069 while (i > 0) {
10070 i--;
10071 ServiceRecord sr = mStoppingServices.get(i);
10072 if (sr.app == app) {
10073 mStoppingServices.remove(i);
10074 }
10075 }
10076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 app.executingServices.clear();
10078 }
10079
10080 private final void removeDyingProviderLocked(ProcessRecord proc,
10081 ContentProviderRecord cpr) {
10082 synchronized (cpr) {
10083 cpr.launchingApp = null;
10084 cpr.notifyAll();
10085 }
10086
10087 mProvidersByClass.remove(cpr.info.name);
10088 String names[] = cpr.info.authority.split(";");
10089 for (int j = 0; j < names.length; j++) {
10090 mProvidersByName.remove(names[j]);
10091 }
10092
10093 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10094 while (cit.hasNext()) {
10095 ProcessRecord capp = cit.next();
10096 if (!capp.persistent && capp.thread != null
10097 && capp.pid != 0
10098 && capp.pid != MY_PID) {
10099 Log.i(TAG, "Killing app " + capp.processName
10100 + " (pid " + capp.pid
10101 + ") because provider " + cpr.info.name
10102 + " is in dying process " + proc.processName);
10103 Process.killProcess(capp.pid);
10104 }
10105 }
10106
10107 mLaunchingProviders.remove(cpr);
10108 }
10109
10110 /**
10111 * Main code for cleaning up a process when it has gone away. This is
10112 * called both as a result of the process dying, or directly when stopping
10113 * a process when running in single process mode.
10114 */
10115 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10116 boolean restarting, int index) {
10117 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010118 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119 }
10120
Dianne Hackborn36124872009-10-08 16:22:03 -070010121 mProcessesToGc.remove(app);
10122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123 // Dismiss any open dialogs.
10124 if (app.crashDialog != null) {
10125 app.crashDialog.dismiss();
10126 app.crashDialog = null;
10127 }
10128 if (app.anrDialog != null) {
10129 app.anrDialog.dismiss();
10130 app.anrDialog = null;
10131 }
10132 if (app.waitDialog != null) {
10133 app.waitDialog.dismiss();
10134 app.waitDialog = null;
10135 }
10136
10137 app.crashing = false;
10138 app.notResponding = false;
10139
10140 app.resetPackageList();
10141 app.thread = null;
10142 app.forcingToForeground = null;
10143 app.foregroundServices = false;
10144
10145 killServicesLocked(app, true);
10146
10147 boolean restart = false;
10148
10149 int NL = mLaunchingProviders.size();
10150
10151 // Remove published content providers.
10152 if (!app.pubProviders.isEmpty()) {
10153 Iterator it = app.pubProviders.values().iterator();
10154 while (it.hasNext()) {
10155 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10156 cpr.provider = null;
10157 cpr.app = null;
10158
10159 // See if someone is waiting for this provider... in which
10160 // case we don't remove it, but just let it restart.
10161 int i = 0;
10162 if (!app.bad) {
10163 for (; i<NL; i++) {
10164 if (mLaunchingProviders.get(i) == cpr) {
10165 restart = true;
10166 break;
10167 }
10168 }
10169 } else {
10170 i = NL;
10171 }
10172
10173 if (i >= NL) {
10174 removeDyingProviderLocked(app, cpr);
10175 NL = mLaunchingProviders.size();
10176 }
10177 }
10178 app.pubProviders.clear();
10179 }
10180
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010181 // Take care of any launching providers waiting for this process.
10182 if (checkAppInLaunchingProvidersLocked(app, false)) {
10183 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186 // Unregister from connected content providers.
10187 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010188 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 while (it.hasNext()) {
10190 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10191 cpr.clients.remove(app);
10192 }
10193 app.conProviders.clear();
10194 }
10195
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010196 // At this point there may be remaining entries in mLaunchingProviders
10197 // where we were the only one waiting, so they are no longer of use.
10198 // Look for these and clean up if found.
10199 // XXX Commented out for now. Trying to figure out a way to reproduce
10200 // the actual situation to identify what is actually going on.
10201 if (false) {
10202 for (int i=0; i<NL; i++) {
10203 ContentProviderRecord cpr = (ContentProviderRecord)
10204 mLaunchingProviders.get(i);
10205 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10206 synchronized (cpr) {
10207 cpr.launchingApp = null;
10208 cpr.notifyAll();
10209 }
10210 }
10211 }
10212 }
10213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010214 skipCurrentReceiverLocked(app);
10215
10216 // Unregister any receivers.
10217 if (app.receivers.size() > 0) {
10218 Iterator<ReceiverList> it = app.receivers.iterator();
10219 while (it.hasNext()) {
10220 removeReceiverLocked(it.next());
10221 }
10222 app.receivers.clear();
10223 }
10224
Christopher Tate181fafa2009-05-14 11:12:14 -070010225 // If the app is undergoing backup, tell the backup manager about it
10226 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
10227 if (DEBUG_BACKUP) Log.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
10228 try {
10229 IBackupManager bm = IBackupManager.Stub.asInterface(
10230 ServiceManager.getService(Context.BACKUP_SERVICE));
10231 bm.agentDisconnected(app.info.packageName);
10232 } catch (RemoteException e) {
10233 // can't happen; backup manager is local
10234 }
10235 }
10236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 // If the caller is restarting this app, then leave it in its
10238 // current lists and let the caller take care of it.
10239 if (restarting) {
10240 return;
10241 }
10242
10243 if (!app.persistent) {
10244 if (DEBUG_PROCESSES) Log.v(TAG,
10245 "Removing non-persistent process during cleanup: " + app);
10246 mProcessNames.remove(app.processName, app.info.uid);
10247 } else if (!app.removed) {
10248 // This app is persistent, so we need to keep its record around.
10249 // If it is not already on the pending app list, add it there
10250 // and start a new process for it.
10251 app.thread = null;
10252 app.forcingToForeground = null;
10253 app.foregroundServices = false;
10254 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10255 mPersistentStartingProcesses.add(app);
10256 restart = true;
10257 }
10258 }
10259 mProcessesOnHold.remove(app);
10260
The Android Open Source Project4df24232009-03-05 14:34:35 -080010261 if (app == mHomeProcess) {
10262 mHomeProcess = null;
10263 }
10264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010265 if (restart) {
10266 // We have components that still need to be running in the
10267 // process, so re-launch it.
10268 mProcessNames.put(app.processName, app.info.uid, app);
10269 startProcessLocked(app, "restart", app.processName);
10270 } else if (app.pid > 0 && app.pid != MY_PID) {
10271 // Goodbye!
10272 synchronized (mPidsSelfLocked) {
10273 mPidsSelfLocked.remove(app.pid);
10274 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10275 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010276 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277 }
10278 }
10279
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010280 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10281 // Look through the content providers we are waiting to have launched,
10282 // and if any run in this process then either schedule a restart of
10283 // the process or kill the client waiting for it if this process has
10284 // gone bad.
10285 int NL = mLaunchingProviders.size();
10286 boolean restart = false;
10287 for (int i=0; i<NL; i++) {
10288 ContentProviderRecord cpr = (ContentProviderRecord)
10289 mLaunchingProviders.get(i);
10290 if (cpr.launchingApp == app) {
10291 if (!alwaysBad && !app.bad) {
10292 restart = true;
10293 } else {
10294 removeDyingProviderLocked(app, cpr);
10295 NL = mLaunchingProviders.size();
10296 }
10297 }
10298 }
10299 return restart;
10300 }
10301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 // =========================================================
10303 // SERVICES
10304 // =========================================================
10305
10306 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10307 ActivityManager.RunningServiceInfo info =
10308 new ActivityManager.RunningServiceInfo();
10309 info.service = r.name;
10310 if (r.app != null) {
10311 info.pid = r.app.pid;
10312 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010313 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 info.process = r.processName;
10315 info.foreground = r.isForeground;
10316 info.activeSince = r.createTime;
10317 info.started = r.startRequested;
10318 info.clientCount = r.connections.size();
10319 info.crashCount = r.crashCount;
10320 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010321 if (r.isForeground) {
10322 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10323 }
10324 if (r.startRequested) {
10325 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10326 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010327 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010328 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10329 }
10330 if (r.app != null && r.app.persistent) {
10331 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10332 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010333 for (ConnectionRecord conn : r.connections.values()) {
10334 if (conn.clientLabel != 0) {
10335 info.clientPackage = conn.binding.client.info.packageName;
10336 info.clientLabel = conn.clientLabel;
10337 break;
10338 }
10339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 return info;
10341 }
10342
10343 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10344 int flags) {
10345 synchronized (this) {
10346 ArrayList<ActivityManager.RunningServiceInfo> res
10347 = new ArrayList<ActivityManager.RunningServiceInfo>();
10348
10349 if (mServices.size() > 0) {
10350 Iterator<ServiceRecord> it = mServices.values().iterator();
10351 while (it.hasNext() && res.size() < maxNum) {
10352 res.add(makeRunningServiceInfoLocked(it.next()));
10353 }
10354 }
10355
10356 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10357 ServiceRecord r = mRestartingServices.get(i);
10358 ActivityManager.RunningServiceInfo info =
10359 makeRunningServiceInfoLocked(r);
10360 info.restarting = r.nextRestartTime;
10361 res.add(info);
10362 }
10363
10364 return res;
10365 }
10366 }
10367
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010368 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10369 synchronized (this) {
10370 ServiceRecord r = mServices.get(name);
10371 if (r != null) {
10372 for (ConnectionRecord conn : r.connections.values()) {
10373 if (conn.clientIntent != null) {
10374 return conn.clientIntent;
10375 }
10376 }
10377 }
10378 }
10379 return null;
10380 }
10381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 private final ServiceRecord findServiceLocked(ComponentName name,
10383 IBinder token) {
10384 ServiceRecord r = mServices.get(name);
10385 return r == token ? r : null;
10386 }
10387
10388 private final class ServiceLookupResult {
10389 final ServiceRecord record;
10390 final String permission;
10391
10392 ServiceLookupResult(ServiceRecord _record, String _permission) {
10393 record = _record;
10394 permission = _permission;
10395 }
10396 };
10397
10398 private ServiceLookupResult findServiceLocked(Intent service,
10399 String resolvedType) {
10400 ServiceRecord r = null;
10401 if (service.getComponent() != null) {
10402 r = mServices.get(service.getComponent());
10403 }
10404 if (r == null) {
10405 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10406 r = mServicesByIntent.get(filter);
10407 }
10408
10409 if (r == null) {
10410 try {
10411 ResolveInfo rInfo =
10412 ActivityThread.getPackageManager().resolveService(
10413 service, resolvedType, 0);
10414 ServiceInfo sInfo =
10415 rInfo != null ? rInfo.serviceInfo : null;
10416 if (sInfo == null) {
10417 return null;
10418 }
10419
10420 ComponentName name = new ComponentName(
10421 sInfo.applicationInfo.packageName, sInfo.name);
10422 r = mServices.get(name);
10423 } catch (RemoteException ex) {
10424 // pm is in same process, this will never happen.
10425 }
10426 }
10427 if (r != null) {
10428 int callingPid = Binder.getCallingPid();
10429 int callingUid = Binder.getCallingUid();
10430 if (checkComponentPermission(r.permission,
10431 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10432 != PackageManager.PERMISSION_GRANTED) {
10433 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10434 + " from pid=" + callingPid
10435 + ", uid=" + callingUid
10436 + " requires " + r.permission);
10437 return new ServiceLookupResult(null, r.permission);
10438 }
10439 return new ServiceLookupResult(r, null);
10440 }
10441 return null;
10442 }
10443
10444 private class ServiceRestarter implements Runnable {
10445 private ServiceRecord mService;
10446
10447 void setService(ServiceRecord service) {
10448 mService = service;
10449 }
10450
10451 public void run() {
10452 synchronized(ActivityManagerService.this) {
10453 performServiceRestartLocked(mService);
10454 }
10455 }
10456 }
10457
10458 private ServiceLookupResult retrieveServiceLocked(Intent service,
10459 String resolvedType, int callingPid, int callingUid) {
10460 ServiceRecord r = null;
10461 if (service.getComponent() != null) {
10462 r = mServices.get(service.getComponent());
10463 }
10464 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10465 r = mServicesByIntent.get(filter);
10466 if (r == null) {
10467 try {
10468 ResolveInfo rInfo =
10469 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010470 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010471 ServiceInfo sInfo =
10472 rInfo != null ? rInfo.serviceInfo : null;
10473 if (sInfo == null) {
10474 Log.w(TAG, "Unable to start service " + service +
10475 ": not found");
10476 return null;
10477 }
10478
10479 ComponentName name = new ComponentName(
10480 sInfo.applicationInfo.packageName, sInfo.name);
10481 r = mServices.get(name);
10482 if (r == null) {
10483 filter = new Intent.FilterComparison(service.cloneFilter());
10484 ServiceRestarter res = new ServiceRestarter();
10485 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10486 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10487 synchronized (stats) {
10488 ss = stats.getServiceStatsLocked(
10489 sInfo.applicationInfo.uid, sInfo.packageName,
10490 sInfo.name);
10491 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010492 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493 res.setService(r);
10494 mServices.put(name, r);
10495 mServicesByIntent.put(filter, r);
10496
10497 // Make sure this component isn't in the pending list.
10498 int N = mPendingServices.size();
10499 for (int i=0; i<N; i++) {
10500 ServiceRecord pr = mPendingServices.get(i);
10501 if (pr.name.equals(name)) {
10502 mPendingServices.remove(i);
10503 i--;
10504 N--;
10505 }
10506 }
10507 }
10508 } catch (RemoteException ex) {
10509 // pm is in same process, this will never happen.
10510 }
10511 }
10512 if (r != null) {
10513 if (checkComponentPermission(r.permission,
10514 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10515 != PackageManager.PERMISSION_GRANTED) {
10516 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10517 + " from pid=" + Binder.getCallingPid()
10518 + ", uid=" + Binder.getCallingUid()
10519 + " requires " + r.permission);
10520 return new ServiceLookupResult(null, r.permission);
10521 }
10522 return new ServiceLookupResult(r, null);
10523 }
10524 return null;
10525 }
10526
10527 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10528 long now = SystemClock.uptimeMillis();
10529 if (r.executeNesting == 0 && r.app != null) {
10530 if (r.app.executingServices.size() == 0) {
10531 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10532 msg.obj = r.app;
10533 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10534 }
10535 r.app.executingServices.add(r);
10536 }
10537 r.executeNesting++;
10538 r.executingStart = now;
10539 }
10540
10541 private final void sendServiceArgsLocked(ServiceRecord r,
10542 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010543 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 if (N == 0) {
10545 return;
10546 }
10547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 int i = 0;
10549 while (i < N) {
10550 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010551 ServiceRecord.StartItem si = r.pendingStarts.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010553 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010554 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010555 // If somehow we got a dummy start at the front, then
10556 // just drop it here.
10557 i++;
10558 continue;
10559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 bumpServiceExecutingLocked(r);
10561 if (!oomAdjusted) {
10562 oomAdjusted = true;
10563 updateOomAdjLocked(r.app);
10564 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010565 int flags = 0;
10566 if (si.deliveryCount > 0) {
10567 flags |= Service.START_FLAG_RETRY;
10568 }
10569 if (si.doneExecutingCount > 0) {
10570 flags |= Service.START_FLAG_REDELIVERY;
10571 }
10572 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10573 si.deliveredTime = SystemClock.uptimeMillis();
10574 r.deliveredStarts.add(si);
10575 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010576 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010577 } catch (RemoteException e) {
10578 // Remote process gone... we'll let the normal cleanup take
10579 // care of this.
10580 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 } catch (Exception e) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010582 Log.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 break;
10584 }
10585 }
10586 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010587 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 } else {
10589 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010590 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010591 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 }
10593 }
10594 }
10595
10596 private final boolean requestServiceBindingLocked(ServiceRecord r,
10597 IntentBindRecord i, boolean rebind) {
10598 if (r.app == null || r.app.thread == null) {
10599 // If service is not currently running, can't yet bind.
10600 return false;
10601 }
10602 if ((!i.requested || rebind) && i.apps.size() > 0) {
10603 try {
10604 bumpServiceExecutingLocked(r);
10605 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
10606 + ": shouldUnbind=" + i.hasBound);
10607 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10608 if (!rebind) {
10609 i.requested = true;
10610 }
10611 i.hasBound = true;
10612 i.doRebind = false;
10613 } catch (RemoteException e) {
10614 return false;
10615 }
10616 }
10617 return true;
10618 }
10619
10620 private final void requestServiceBindingsLocked(ServiceRecord r) {
10621 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10622 while (bindings.hasNext()) {
10623 IntentBindRecord i = bindings.next();
10624 if (!requestServiceBindingLocked(r, i, false)) {
10625 break;
10626 }
10627 }
10628 }
10629
10630 private final void realStartServiceLocked(ServiceRecord r,
10631 ProcessRecord app) throws RemoteException {
10632 if (app.thread == null) {
10633 throw new RemoteException();
10634 }
10635
10636 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010637 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638
10639 app.services.add(r);
10640 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010641 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642
10643 boolean created = false;
10644 try {
10645 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
10646 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010647 mStringBuilder.setLength(0);
10648 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010649 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010650 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010651 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 synchronized (r.stats.getBatteryStats()) {
10653 r.stats.startLaunchedLocked();
10654 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010655 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010657 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 created = true;
10659 } finally {
10660 if (!created) {
10661 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010662 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 }
10664 }
10665
10666 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010667
10668 // If the service is in the started state, and there are no
10669 // pending arguments, then fake up one so its onStartCommand() will
10670 // be called.
10671 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10672 r.lastStartId++;
10673 if (r.lastStartId < 1) {
10674 r.lastStartId = 1;
10675 }
10676 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10677 }
10678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 sendServiceArgsLocked(r, true);
10680 }
10681
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010682 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10683 boolean allowCancel) {
10684 boolean canceled = false;
10685
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010686 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010687 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010688 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010689
10690 // Any delivered but not yet finished starts should be put back
10691 // on the pending list.
10692 final int N = r.deliveredStarts.size();
10693 if (N > 0) {
10694 for (int i=N-1; i>=0; i--) {
10695 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10696 if (si.intent == null) {
10697 // We'll generate this again if needed.
10698 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10699 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10700 r.pendingStarts.add(0, si);
10701 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10702 dur *= 2;
10703 if (minDuration < dur) minDuration = dur;
10704 if (resetTime < dur) resetTime = dur;
10705 } else {
10706 Log.w(TAG, "Canceling start item " + si.intent + " in service "
10707 + r.name);
10708 canceled = true;
10709 }
10710 }
10711 r.deliveredStarts.clear();
10712 }
10713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010714 r.totalRestartCount++;
10715 if (r.restartDelay == 0) {
10716 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010717 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 } else {
10719 // If it has been a "reasonably long time" since the service
10720 // was started, then reset our restart duration back to
10721 // the beginning, so we don't infinitely increase the duration
10722 // on a service that just occasionally gets killed (which is
10723 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010724 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010726 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010727 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010728 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010729 if (r.restartDelay < minDuration) {
10730 r.restartDelay = minDuration;
10731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 }
10733 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010734
10735 r.nextRestartTime = now + r.restartDelay;
10736
10737 // Make sure that we don't end up restarting a bunch of services
10738 // all at the same time.
10739 boolean repeat;
10740 do {
10741 repeat = false;
10742 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10743 ServiceRecord r2 = mRestartingServices.get(i);
10744 if (r2 != r && r.nextRestartTime
10745 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10746 && r.nextRestartTime
10747 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10748 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10749 r.restartDelay = r.nextRestartTime - now;
10750 repeat = true;
10751 break;
10752 }
10753 }
10754 } while (repeat);
10755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 if (!mRestartingServices.contains(r)) {
10757 mRestartingServices.add(r);
10758 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010759
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010760 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010763 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
10765 Log.w(TAG, "Scheduling restart of crashed service "
10766 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010767 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 r.shortName, r.restartDelay);
10769
10770 Message msg = Message.obtain();
10771 msg.what = SERVICE_ERROR_MSG;
10772 msg.obj = r;
10773 mHandler.sendMessage(msg);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010774
10775 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 }
10777
10778 final void performServiceRestartLocked(ServiceRecord r) {
10779 if (!mRestartingServices.contains(r)) {
10780 return;
10781 }
10782 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10783 }
10784
10785 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10786 if (r.restartDelay == 0) {
10787 return false;
10788 }
10789 r.resetRestartCounter();
10790 mRestartingServices.remove(r);
10791 mHandler.removeCallbacks(r.restarter);
10792 return true;
10793 }
10794
10795 private final boolean bringUpServiceLocked(ServiceRecord r,
10796 int intentFlags, boolean whileRestarting) {
10797 //Log.i(TAG, "Bring up service:");
10798 //r.dump(" ");
10799
Dianne Hackborn36124872009-10-08 16:22:03 -070010800 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 sendServiceArgsLocked(r, false);
10802 return true;
10803 }
10804
10805 if (!whileRestarting && r.restartDelay > 0) {
10806 // If waiting for a restart, then do nothing.
10807 return true;
10808 }
10809
10810 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
10811 + " " + r.intent);
10812
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010813 // We are now bringing the service up, so no longer in the
10814 // restarting state.
10815 mRestartingServices.remove(r);
10816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 final String appName = r.processName;
10818 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10819 if (app != null && app.thread != null) {
10820 try {
10821 realStartServiceLocked(r, app);
10822 return true;
10823 } catch (RemoteException e) {
10824 Log.w(TAG, "Exception when starting service " + r.shortName, e);
10825 }
10826
10827 // If a dead object exception was thrown -- fall through to
10828 // restart the application.
10829 }
10830
Dianne Hackborn36124872009-10-08 16:22:03 -070010831 // Not running -- get it started, and enqueue this service record
10832 // to be executed when the app comes up.
10833 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10834 "service", r.name, false) == null) {
10835 Log.w(TAG, "Unable to launch app "
10836 + r.appInfo.packageName + "/"
10837 + r.appInfo.uid + " for service "
10838 + r.intent.getIntent() + ": process is bad");
10839 bringDownServiceLocked(r, true);
10840 return false;
10841 }
10842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010843 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 mPendingServices.add(r);
10845 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 return true;
10848 }
10849
10850 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
10851 //Log.i(TAG, "Bring down service:");
10852 //r.dump(" ");
10853
10854 // Does it still need to run?
10855 if (!force && r.startRequested) {
10856 return;
10857 }
10858 if (r.connections.size() > 0) {
10859 if (!force) {
10860 // XXX should probably keep a count of the number of auto-create
10861 // connections directly in the service.
10862 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10863 while (it.hasNext()) {
10864 ConnectionRecord cr = it.next();
10865 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10866 return;
10867 }
10868 }
10869 }
10870
10871 // Report to all of the connections that the service is no longer
10872 // available.
10873 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10874 while (it.hasNext()) {
10875 ConnectionRecord c = it.next();
10876 try {
10877 // todo: shouldn't be a synchronous call!
10878 c.conn.connected(r.name, null);
10879 } catch (Exception e) {
10880 Log.w(TAG, "Failure disconnecting service " + r.name +
10881 " to connection " + c.conn.asBinder() +
10882 " (in " + c.binding.client.processName + ")", e);
10883 }
10884 }
10885 }
10886
10887 // Tell the service that it has been unbound.
10888 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10889 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10890 while (it.hasNext()) {
10891 IntentBindRecord ibr = it.next();
10892 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
10893 + ": hasBound=" + ibr.hasBound);
10894 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10895 try {
10896 bumpServiceExecutingLocked(r);
10897 updateOomAdjLocked(r.app);
10898 ibr.hasBound = false;
10899 r.app.thread.scheduleUnbindService(r,
10900 ibr.intent.getIntent());
10901 } catch (Exception e) {
10902 Log.w(TAG, "Exception when unbinding service "
10903 + r.shortName, e);
10904 serviceDoneExecutingLocked(r, true);
10905 }
10906 }
10907 }
10908 }
10909
10910 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
10911 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010912 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 System.identityHashCode(r), r.shortName,
10914 (r.app != null) ? r.app.pid : -1);
10915
10916 mServices.remove(r.name);
10917 mServicesByIntent.remove(r.intent);
10918 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
10919 r.totalRestartCount = 0;
10920 unscheduleServiceRestartLocked(r);
10921
10922 // Also make sure it is not on the pending list.
10923 int N = mPendingServices.size();
10924 for (int i=0; i<N; i++) {
10925 if (mPendingServices.get(i) == r) {
10926 mPendingServices.remove(i);
10927 if (DEBUG_SERVICE) Log.v(
10928 TAG, "Removed pending service: " + r.shortName);
10929 i--;
10930 N--;
10931 }
10932 }
10933
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010934 r.cancelNotification();
10935 r.isForeground = false;
10936 r.foregroundId = 0;
10937 r.foregroundNoti = null;
10938
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010939 // Clear start entries.
10940 r.deliveredStarts.clear();
10941 r.pendingStarts.clear();
10942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 if (r.app != null) {
10944 synchronized (r.stats.getBatteryStats()) {
10945 r.stats.stopLaunchedLocked();
10946 }
10947 r.app.services.remove(r);
10948 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949 try {
Dianne Hackborna1e989b2009-09-01 19:54:29 -070010950 if (DEBUG_SERVICE) Log.v(TAG,
10951 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 bumpServiceExecutingLocked(r);
10953 mStoppingServices.add(r);
10954 updateOomAdjLocked(r.app);
10955 r.app.thread.scheduleStopService(r);
10956 } catch (Exception e) {
10957 Log.w(TAG, "Exception when stopping service "
10958 + r.shortName, e);
10959 serviceDoneExecutingLocked(r, true);
10960 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010961 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 } else {
10963 if (DEBUG_SERVICE) Log.v(
10964 TAG, "Removed service that has no process: " + r.shortName);
10965 }
10966 } else {
10967 if (DEBUG_SERVICE) Log.v(
10968 TAG, "Removed service that is not running: " + r.shortName);
10969 }
10970 }
10971
10972 ComponentName startServiceLocked(IApplicationThread caller,
10973 Intent service, String resolvedType,
10974 int callingPid, int callingUid) {
10975 synchronized(this) {
10976 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
10977 + " type=" + resolvedType + " args=" + service.getExtras());
10978
10979 if (caller != null) {
10980 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10981 if (callerApp == null) {
10982 throw new SecurityException(
10983 "Unable to find app for caller " + caller
10984 + " (pid=" + Binder.getCallingPid()
10985 + ") when starting service " + service);
10986 }
10987 }
10988
10989 ServiceLookupResult res =
10990 retrieveServiceLocked(service, resolvedType,
10991 callingPid, callingUid);
10992 if (res == null) {
10993 return null;
10994 }
10995 if (res.record == null) {
10996 return new ComponentName("!", res.permission != null
10997 ? res.permission : "private to package");
10998 }
10999 ServiceRecord r = res.record;
11000 if (unscheduleServiceRestartLocked(r)) {
11001 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
11002 + r.shortName);
11003 }
11004 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011005 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 r.lastStartId++;
11007 if (r.lastStartId < 1) {
11008 r.lastStartId = 1;
11009 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011010 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 r.lastActivity = SystemClock.uptimeMillis();
11012 synchronized (r.stats.getBatteryStats()) {
11013 r.stats.startRunningLocked();
11014 }
11015 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11016 return new ComponentName("!", "Service process is bad");
11017 }
11018 return r.name;
11019 }
11020 }
11021
11022 public ComponentName startService(IApplicationThread caller, Intent service,
11023 String resolvedType) {
11024 // Refuse possible leaked file descriptors
11025 if (service != null && service.hasFileDescriptors() == true) {
11026 throw new IllegalArgumentException("File descriptors passed in Intent");
11027 }
11028
11029 synchronized(this) {
11030 final int callingPid = Binder.getCallingPid();
11031 final int callingUid = Binder.getCallingUid();
11032 final long origId = Binder.clearCallingIdentity();
11033 ComponentName res = startServiceLocked(caller, service,
11034 resolvedType, callingPid, callingUid);
11035 Binder.restoreCallingIdentity(origId);
11036 return res;
11037 }
11038 }
11039
11040 ComponentName startServiceInPackage(int uid,
11041 Intent service, String resolvedType) {
11042 synchronized(this) {
11043 final long origId = Binder.clearCallingIdentity();
11044 ComponentName res = startServiceLocked(null, service,
11045 resolvedType, -1, uid);
11046 Binder.restoreCallingIdentity(origId);
11047 return res;
11048 }
11049 }
11050
11051 public int stopService(IApplicationThread caller, Intent service,
11052 String resolvedType) {
11053 // Refuse possible leaked file descriptors
11054 if (service != null && service.hasFileDescriptors() == true) {
11055 throw new IllegalArgumentException("File descriptors passed in Intent");
11056 }
11057
11058 synchronized(this) {
11059 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
11060 + " type=" + resolvedType);
11061
11062 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11063 if (caller != null && callerApp == null) {
11064 throw new SecurityException(
11065 "Unable to find app for caller " + caller
11066 + " (pid=" + Binder.getCallingPid()
11067 + ") when stopping service " + service);
11068 }
11069
11070 // If this service is active, make sure it is stopped.
11071 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11072 if (r != null) {
11073 if (r.record != null) {
11074 synchronized (r.record.stats.getBatteryStats()) {
11075 r.record.stats.stopRunningLocked();
11076 }
11077 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011078 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 final long origId = Binder.clearCallingIdentity();
11080 bringDownServiceLocked(r.record, false);
11081 Binder.restoreCallingIdentity(origId);
11082 return 1;
11083 }
11084 return -1;
11085 }
11086 }
11087
11088 return 0;
11089 }
11090
11091 public IBinder peekService(Intent service, String resolvedType) {
11092 // Refuse possible leaked file descriptors
11093 if (service != null && service.hasFileDescriptors() == true) {
11094 throw new IllegalArgumentException("File descriptors passed in Intent");
11095 }
11096
11097 IBinder ret = null;
11098
11099 synchronized(this) {
11100 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11101
11102 if (r != null) {
11103 // r.record is null if findServiceLocked() failed the caller permission check
11104 if (r.record == null) {
11105 throw new SecurityException(
11106 "Permission Denial: Accessing service " + r.record.name
11107 + " from pid=" + Binder.getCallingPid()
11108 + ", uid=" + Binder.getCallingUid()
11109 + " requires " + r.permission);
11110 }
11111 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11112 if (ib != null) {
11113 ret = ib.binder;
11114 }
11115 }
11116 }
11117
11118 return ret;
11119 }
11120
11121 public boolean stopServiceToken(ComponentName className, IBinder token,
11122 int startId) {
11123 synchronized(this) {
11124 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
11125 + " " + token + " startId=" + startId);
11126 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011127 if (r != null) {
11128 if (startId >= 0) {
11129 // Asked to only stop if done with all work. Note that
11130 // to avoid leaks, we will take this as dropping all
11131 // start items up to and including this one.
11132 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11133 if (si != null) {
11134 while (r.deliveredStarts.size() > 0) {
11135 if (r.deliveredStarts.remove(0) == si) {
11136 break;
11137 }
11138 }
11139 }
11140
11141 if (r.lastStartId != startId) {
11142 return false;
11143 }
11144
11145 if (r.deliveredStarts.size() > 0) {
11146 Log.w(TAG, "stopServiceToken startId " + startId
11147 + " is last, but have " + r.deliveredStarts.size()
11148 + " remaining args");
11149 }
11150 }
11151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 synchronized (r.stats.getBatteryStats()) {
11153 r.stats.stopRunningLocked();
11154 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011155 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 }
11157 final long origId = Binder.clearCallingIdentity();
11158 bringDownServiceLocked(r, false);
11159 Binder.restoreCallingIdentity(origId);
11160 return true;
11161 }
11162 }
11163 return false;
11164 }
11165
11166 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011167 int id, Notification notification, boolean removeNotification) {
11168 final long origId = Binder.clearCallingIdentity();
11169 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 synchronized(this) {
11171 ServiceRecord r = findServiceLocked(className, token);
11172 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011173 if (id != 0) {
11174 if (notification == null) {
11175 throw new IllegalArgumentException("null notification");
11176 }
11177 if (r.foregroundId != id) {
11178 r.cancelNotification();
11179 r.foregroundId = id;
11180 }
11181 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11182 r.foregroundNoti = notification;
11183 r.isForeground = true;
11184 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 if (r.app != null) {
11186 updateServiceForegroundLocked(r.app, true);
11187 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011188 } else {
11189 if (r.isForeground) {
11190 r.isForeground = false;
11191 if (r.app != null) {
11192 updateServiceForegroundLocked(r.app, true);
11193 }
11194 }
11195 if (removeNotification) {
11196 r.cancelNotification();
11197 r.foregroundId = 0;
11198 r.foregroundNoti = null;
11199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011200 }
11201 }
11202 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011203 } finally {
11204 Binder.restoreCallingIdentity(origId);
11205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 }
11207
11208 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11209 boolean anyForeground = false;
11210 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11211 if (sr.isForeground) {
11212 anyForeground = true;
11213 break;
11214 }
11215 }
11216 if (anyForeground != proc.foregroundServices) {
11217 proc.foregroundServices = anyForeground;
11218 if (oomAdj) {
11219 updateOomAdjLocked();
11220 }
11221 }
11222 }
11223
11224 public int bindService(IApplicationThread caller, IBinder token,
11225 Intent service, String resolvedType,
11226 IServiceConnection connection, int flags) {
11227 // Refuse possible leaked file descriptors
11228 if (service != null && service.hasFileDescriptors() == true) {
11229 throw new IllegalArgumentException("File descriptors passed in Intent");
11230 }
11231
11232 synchronized(this) {
11233 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
11234 + " type=" + resolvedType + " conn=" + connection.asBinder()
11235 + " flags=0x" + Integer.toHexString(flags));
11236 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11237 if (callerApp == null) {
11238 throw new SecurityException(
11239 "Unable to find app for caller " + caller
11240 + " (pid=" + Binder.getCallingPid()
11241 + ") when binding service " + service);
11242 }
11243
11244 HistoryRecord activity = null;
11245 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011246 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 if (aindex < 0) {
11248 Log.w(TAG, "Binding with unknown activity: " + token);
11249 return 0;
11250 }
11251 activity = (HistoryRecord)mHistory.get(aindex);
11252 }
11253
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011254 int clientLabel = 0;
11255 PendingIntent clientIntent = null;
11256
11257 if (callerApp.info.uid == Process.SYSTEM_UID) {
11258 // Hacky kind of thing -- allow system stuff to tell us
11259 // what they are, so we can report this elsewhere for
11260 // others to know why certain services are running.
11261 try {
11262 clientIntent = (PendingIntent)service.getParcelableExtra(
11263 Intent.EXTRA_CLIENT_INTENT);
11264 } catch (RuntimeException e) {
11265 }
11266 if (clientIntent != null) {
11267 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11268 if (clientLabel != 0) {
11269 // There are no useful extras in the intent, trash them.
11270 // System code calling with this stuff just needs to know
11271 // this will happen.
11272 service = service.cloneFilter();
11273 }
11274 }
11275 }
11276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011277 ServiceLookupResult res =
11278 retrieveServiceLocked(service, resolvedType,
11279 Binder.getCallingPid(), Binder.getCallingUid());
11280 if (res == null) {
11281 return 0;
11282 }
11283 if (res.record == null) {
11284 return -1;
11285 }
11286 ServiceRecord s = res.record;
11287
11288 final long origId = Binder.clearCallingIdentity();
11289
11290 if (unscheduleServiceRestartLocked(s)) {
11291 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
11292 + s.shortName);
11293 }
11294
11295 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11296 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011297 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298
11299 IBinder binder = connection.asBinder();
11300 s.connections.put(binder, c);
11301 b.connections.add(c);
11302 if (activity != null) {
11303 if (activity.connections == null) {
11304 activity.connections = new HashSet<ConnectionRecord>();
11305 }
11306 activity.connections.add(c);
11307 }
11308 b.client.connections.add(c);
11309 mServiceConnections.put(binder, c);
11310
11311 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11312 s.lastActivity = SystemClock.uptimeMillis();
11313 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11314 return 0;
11315 }
11316 }
11317
11318 if (s.app != null) {
11319 // This could have made the service more important.
11320 updateOomAdjLocked(s.app);
11321 }
11322
11323 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
11324 + ": received=" + b.intent.received
11325 + " apps=" + b.intent.apps.size()
11326 + " doRebind=" + b.intent.doRebind);
11327
11328 if (s.app != null && b.intent.received) {
11329 // Service is already running, so we can immediately
11330 // publish the connection.
11331 try {
11332 c.conn.connected(s.name, b.intent.binder);
11333 } catch (Exception e) {
11334 Log.w(TAG, "Failure sending service " + s.shortName
11335 + " to connection " + c.conn.asBinder()
11336 + " (in " + c.binding.client.processName + ")", e);
11337 }
11338
11339 // If this is the first app connected back to this binding,
11340 // and the service had previously asked to be told when
11341 // rebound, then do so.
11342 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11343 requestServiceBindingLocked(s, b.intent, true);
11344 }
11345 } else if (!b.intent.requested) {
11346 requestServiceBindingLocked(s, b.intent, false);
11347 }
11348
11349 Binder.restoreCallingIdentity(origId);
11350 }
11351
11352 return 1;
11353 }
11354
11355 private void removeConnectionLocked(
11356 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11357 IBinder binder = c.conn.asBinder();
11358 AppBindRecord b = c.binding;
11359 ServiceRecord s = b.service;
11360 s.connections.remove(binder);
11361 b.connections.remove(c);
11362 if (c.activity != null && c.activity != skipAct) {
11363 if (c.activity.connections != null) {
11364 c.activity.connections.remove(c);
11365 }
11366 }
11367 if (b.client != skipApp) {
11368 b.client.connections.remove(c);
11369 }
11370 mServiceConnections.remove(binder);
11371
11372 if (b.connections.size() == 0) {
11373 b.intent.apps.remove(b.client);
11374 }
11375
11376 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
11377 + ": shouldUnbind=" + b.intent.hasBound);
11378 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11379 && b.intent.hasBound) {
11380 try {
11381 bumpServiceExecutingLocked(s);
11382 updateOomAdjLocked(s.app);
11383 b.intent.hasBound = false;
11384 // Assume the client doesn't want to know about a rebind;
11385 // we will deal with that later if it asks for one.
11386 b.intent.doRebind = false;
11387 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11388 } catch (Exception e) {
11389 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
11390 serviceDoneExecutingLocked(s, true);
11391 }
11392 }
11393
11394 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11395 bringDownServiceLocked(s, false);
11396 }
11397 }
11398
11399 public boolean unbindService(IServiceConnection connection) {
11400 synchronized (this) {
11401 IBinder binder = connection.asBinder();
11402 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
11403 ConnectionRecord r = mServiceConnections.get(binder);
11404 if (r == null) {
11405 Log.w(TAG, "Unbind failed: could not find connection for "
11406 + connection.asBinder());
11407 return false;
11408 }
11409
11410 final long origId = Binder.clearCallingIdentity();
11411
11412 removeConnectionLocked(r, null, null);
11413
11414 if (r.binding.service.app != null) {
11415 // This could have made the service less important.
11416 updateOomAdjLocked(r.binding.service.app);
11417 }
11418
11419 Binder.restoreCallingIdentity(origId);
11420 }
11421
11422 return true;
11423 }
11424
11425 public void publishService(IBinder token, Intent intent, IBinder service) {
11426 // Refuse possible leaked file descriptors
11427 if (intent != null && intent.hasFileDescriptors() == true) {
11428 throw new IllegalArgumentException("File descriptors passed in Intent");
11429 }
11430
11431 synchronized(this) {
11432 if (!(token instanceof ServiceRecord)) {
11433 throw new IllegalArgumentException("Invalid service token");
11434 }
11435 ServiceRecord r = (ServiceRecord)token;
11436
11437 final long origId = Binder.clearCallingIdentity();
11438
11439 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
11440 + " " + intent + ": " + service);
11441 if (r != null) {
11442 Intent.FilterComparison filter
11443 = new Intent.FilterComparison(intent);
11444 IntentBindRecord b = r.bindings.get(filter);
11445 if (b != null && !b.received) {
11446 b.binder = service;
11447 b.requested = true;
11448 b.received = true;
11449 if (r.connections.size() > 0) {
11450 Iterator<ConnectionRecord> it
11451 = r.connections.values().iterator();
11452 while (it.hasNext()) {
11453 ConnectionRecord c = it.next();
11454 if (!filter.equals(c.binding.intent.intent)) {
11455 if (DEBUG_SERVICE) Log.v(
11456 TAG, "Not publishing to: " + c);
11457 if (DEBUG_SERVICE) Log.v(
11458 TAG, "Bound intent: " + c.binding.intent.intent);
11459 if (DEBUG_SERVICE) Log.v(
11460 TAG, "Published intent: " + intent);
11461 continue;
11462 }
11463 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
11464 try {
11465 c.conn.connected(r.name, service);
11466 } catch (Exception e) {
11467 Log.w(TAG, "Failure sending service " + r.name +
11468 " to connection " + c.conn.asBinder() +
11469 " (in " + c.binding.client.processName + ")", e);
11470 }
11471 }
11472 }
11473 }
11474
11475 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11476
11477 Binder.restoreCallingIdentity(origId);
11478 }
11479 }
11480 }
11481
11482 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11483 // Refuse possible leaked file descriptors
11484 if (intent != null && intent.hasFileDescriptors() == true) {
11485 throw new IllegalArgumentException("File descriptors passed in Intent");
11486 }
11487
11488 synchronized(this) {
11489 if (!(token instanceof ServiceRecord)) {
11490 throw new IllegalArgumentException("Invalid service token");
11491 }
11492 ServiceRecord r = (ServiceRecord)token;
11493
11494 final long origId = Binder.clearCallingIdentity();
11495
11496 if (r != null) {
11497 Intent.FilterComparison filter
11498 = new Intent.FilterComparison(intent);
11499 IntentBindRecord b = r.bindings.get(filter);
11500 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
11501 + " at " + b + ": apps="
11502 + (b != null ? b.apps.size() : 0));
11503 if (b != null) {
11504 if (b.apps.size() > 0) {
11505 // Applications have already bound since the last
11506 // unbind, so just rebind right here.
11507 requestServiceBindingLocked(r, b, true);
11508 } else {
11509 // Note to tell the service the next time there is
11510 // a new client.
11511 b.doRebind = true;
11512 }
11513 }
11514
11515 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11516
11517 Binder.restoreCallingIdentity(origId);
11518 }
11519 }
11520 }
11521
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011522 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011523 synchronized(this) {
11524 if (!(token instanceof ServiceRecord)) {
11525 throw new IllegalArgumentException("Invalid service token");
11526 }
11527 ServiceRecord r = (ServiceRecord)token;
11528 boolean inStopping = mStoppingServices.contains(token);
11529 if (r != null) {
11530 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
11531 + ": nesting=" + r.executeNesting
11532 + ", inStopping=" + inStopping);
11533 if (r != token) {
11534 Log.w(TAG, "Done executing service " + r.name
11535 + " with incorrect token: given " + token
11536 + ", expected " + r);
11537 return;
11538 }
11539
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011540 if (type == 1) {
11541 // This is a call from a service start... take care of
11542 // book-keeping.
11543 r.callStart = true;
11544 switch (res) {
11545 case Service.START_STICKY_COMPATIBILITY:
11546 case Service.START_STICKY: {
11547 // We are done with the associated start arguments.
11548 r.findDeliveredStart(startId, true);
11549 // Don't stop if killed.
11550 r.stopIfKilled = false;
11551 break;
11552 }
11553 case Service.START_NOT_STICKY: {
11554 // We are done with the associated start arguments.
11555 r.findDeliveredStart(startId, true);
11556 if (r.lastStartId == startId) {
11557 // There is no more work, and this service
11558 // doesn't want to hang around if killed.
11559 r.stopIfKilled = true;
11560 }
11561 break;
11562 }
11563 case Service.START_REDELIVER_INTENT: {
11564 // We'll keep this item until they explicitly
11565 // call stop for it, but keep track of the fact
11566 // that it was delivered.
11567 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11568 if (si != null) {
11569 si.deliveryCount = 0;
11570 si.doneExecutingCount++;
11571 // Don't stop if killed.
11572 r.stopIfKilled = true;
11573 }
11574 break;
11575 }
11576 default:
11577 throw new IllegalArgumentException(
11578 "Unknown service start result: " + res);
11579 }
11580 if (res == Service.START_STICKY_COMPATIBILITY) {
11581 r.callStart = false;
11582 }
11583 }
11584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585 final long origId = Binder.clearCallingIdentity();
11586 serviceDoneExecutingLocked(r, inStopping);
11587 Binder.restoreCallingIdentity(origId);
11588 } else {
11589 Log.w(TAG, "Done executing unknown service " + r.name
11590 + " with token " + token);
11591 }
11592 }
11593 }
11594
11595 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11596 r.executeNesting--;
11597 if (r.executeNesting <= 0 && r.app != null) {
11598 r.app.executingServices.remove(r);
11599 if (r.app.executingServices.size() == 0) {
11600 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11601 }
11602 if (inStopping) {
11603 mStoppingServices.remove(r);
11604 }
11605 updateOomAdjLocked(r.app);
11606 }
11607 }
11608
11609 void serviceTimeout(ProcessRecord proc) {
11610 synchronized(this) {
11611 if (proc.executingServices.size() == 0 || proc.thread == null) {
11612 return;
11613 }
11614 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11615 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11616 ServiceRecord timeout = null;
11617 long nextTime = 0;
11618 while (it.hasNext()) {
11619 ServiceRecord sr = it.next();
11620 if (sr.executingStart < maxTime) {
11621 timeout = sr;
11622 break;
11623 }
11624 if (sr.executingStart > nextTime) {
11625 nextTime = sr.executingStart;
11626 }
11627 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011628 if (timeout != null && mLruProcesses.contains(proc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 Log.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011630 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 } else {
11632 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11633 msg.obj = proc;
11634 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11635 }
11636 }
11637 }
11638
11639 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011640 // BACKUP AND RESTORE
11641 // =========================================================
11642
11643 // Cause the target app to be launched if necessary and its backup agent
11644 // instantiated. The backup agent will invoke backupAgentCreated() on the
11645 // activity manager to announce its creation.
11646 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
11647 if (DEBUG_BACKUP) Log.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
11648 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11649
11650 synchronized(this) {
11651 // !!! TODO: currently no check here that we're already bound
11652 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11653 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11654 synchronized (stats) {
11655 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11656 }
11657
11658 BackupRecord r = new BackupRecord(ss, app, backupMode);
11659 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11660 // startProcessLocked() returns existing proc's record if it's already running
11661 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011662 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011663 if (proc == null) {
11664 Log.e(TAG, "Unable to start backup agent process " + r);
11665 return false;
11666 }
11667
11668 r.app = proc;
11669 mBackupTarget = r;
11670 mBackupAppName = app.packageName;
11671
Christopher Tate6fa95972009-06-05 18:43:55 -070011672 // Try not to kill the process during backup
11673 updateOomAdjLocked(proc);
11674
Christopher Tate181fafa2009-05-14 11:12:14 -070011675 // If the process is already attached, schedule the creation of the backup agent now.
11676 // If it is not yet live, this will be done when it attaches to the framework.
11677 if (proc.thread != null) {
11678 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc already running: " + proc);
11679 try {
11680 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11681 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011682 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011683 }
11684 } else {
11685 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc not running, waiting for attach");
11686 }
11687 // Invariants: at this point, the target app process exists and the application
11688 // is either already running or in the process of coming up. mBackupTarget and
11689 // mBackupAppName describe the app, so that when it binds back to the AM we
11690 // know that it's scheduled for a backup-agent operation.
11691 }
11692
11693 return true;
11694 }
11695
11696 // A backup agent has just come up
11697 public void backupAgentCreated(String agentPackageName, IBinder agent) {
11698 if (DEBUG_BACKUP) Log.v(TAG, "backupAgentCreated: " + agentPackageName
11699 + " = " + agent);
11700
11701 synchronized(this) {
11702 if (!agentPackageName.equals(mBackupAppName)) {
11703 Log.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
11704 return;
11705 }
11706
Christopher Tate043dadc2009-06-02 16:11:00 -070011707 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011708 try {
11709 IBackupManager bm = IBackupManager.Stub.asInterface(
11710 ServiceManager.getService(Context.BACKUP_SERVICE));
11711 bm.agentConnected(agentPackageName, agent);
11712 } catch (RemoteException e) {
11713 // can't happen; the backup manager service is local
11714 } catch (Exception e) {
11715 Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11716 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011717 } finally {
11718 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011719 }
11720 }
11721 }
11722
11723 // done with this agent
11724 public void unbindBackupAgent(ApplicationInfo appInfo) {
11725 if (DEBUG_BACKUP) Log.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011726 if (appInfo == null) {
11727 Log.w(TAG, "unbind backup agent for null app");
11728 return;
11729 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011730
11731 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011732 if (mBackupAppName == null) {
11733 Log.w(TAG, "Unbinding backup agent with no active backup");
11734 return;
11735 }
11736
Christopher Tate181fafa2009-05-14 11:12:14 -070011737 if (!mBackupAppName.equals(appInfo.packageName)) {
11738 Log.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
11739 return;
11740 }
11741
Christopher Tate6fa95972009-06-05 18:43:55 -070011742 ProcessRecord proc = mBackupTarget.app;
11743 mBackupTarget = null;
11744 mBackupAppName = null;
11745
11746 // Not backing this app up any more; reset its OOM adjustment
11747 updateOomAdjLocked(proc);
11748
Christopher Tatec7b31e32009-06-10 15:49:30 -070011749 // If the app crashed during backup, 'thread' will be null here
11750 if (proc.thread != null) {
11751 try {
11752 proc.thread.scheduleDestroyBackupAgent(appInfo);
11753 } catch (Exception e) {
11754 Log.e(TAG, "Exception when unbinding backup agent:");
11755 e.printStackTrace();
11756 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011757 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011758 }
11759 }
11760 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 // BROADCASTS
11762 // =========================================================
11763
11764 private final List getStickies(String action, IntentFilter filter,
11765 List cur) {
11766 final ContentResolver resolver = mContext.getContentResolver();
11767 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11768 if (list == null) {
11769 return cur;
11770 }
11771 int N = list.size();
11772 for (int i=0; i<N; i++) {
11773 Intent intent = list.get(i);
11774 if (filter.match(resolver, intent, true, TAG) >= 0) {
11775 if (cur == null) {
11776 cur = new ArrayList<Intent>();
11777 }
11778 cur.add(intent);
11779 }
11780 }
11781 return cur;
11782 }
11783
11784 private final void scheduleBroadcastsLocked() {
11785 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
11786 + mBroadcastsScheduled);
11787
11788 if (mBroadcastsScheduled) {
11789 return;
11790 }
11791 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11792 mBroadcastsScheduled = true;
11793 }
11794
11795 public Intent registerReceiver(IApplicationThread caller,
11796 IIntentReceiver receiver, IntentFilter filter, String permission) {
11797 synchronized(this) {
11798 ProcessRecord callerApp = null;
11799 if (caller != null) {
11800 callerApp = getRecordForAppLocked(caller);
11801 if (callerApp == null) {
11802 throw new SecurityException(
11803 "Unable to find app for caller " + caller
11804 + " (pid=" + Binder.getCallingPid()
11805 + ") when registering receiver " + receiver);
11806 }
11807 }
11808
11809 List allSticky = null;
11810
11811 // Look for any matching sticky broadcasts...
11812 Iterator actions = filter.actionsIterator();
11813 if (actions != null) {
11814 while (actions.hasNext()) {
11815 String action = (String)actions.next();
11816 allSticky = getStickies(action, filter, allSticky);
11817 }
11818 } else {
11819 allSticky = getStickies(null, filter, allSticky);
11820 }
11821
11822 // The first sticky in the list is returned directly back to
11823 // the client.
11824 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11825
11826 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
11827 + ": " + sticky);
11828
11829 if (receiver == null) {
11830 return sticky;
11831 }
11832
11833 ReceiverList rl
11834 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11835 if (rl == null) {
11836 rl = new ReceiverList(this, callerApp,
11837 Binder.getCallingPid(),
11838 Binder.getCallingUid(), receiver);
11839 if (rl.app != null) {
11840 rl.app.receivers.add(rl);
11841 } else {
11842 try {
11843 receiver.asBinder().linkToDeath(rl, 0);
11844 } catch (RemoteException e) {
11845 return sticky;
11846 }
11847 rl.linkedToDeath = true;
11848 }
11849 mRegisteredReceivers.put(receiver.asBinder(), rl);
11850 }
11851 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11852 rl.add(bf);
11853 if (!bf.debugCheck()) {
11854 Log.w(TAG, "==> For Dynamic broadast");
11855 }
11856 mReceiverResolver.addFilter(bf);
11857
11858 // Enqueue broadcasts for all existing stickies that match
11859 // this filter.
11860 if (allSticky != null) {
11861 ArrayList receivers = new ArrayList();
11862 receivers.add(bf);
11863
11864 int N = allSticky.size();
11865 for (int i=0; i<N; i++) {
11866 Intent intent = (Intent)allSticky.get(i);
11867 BroadcastRecord r = new BroadcastRecord(intent, null,
11868 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011869 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 if (mParallelBroadcasts.size() == 0) {
11871 scheduleBroadcastsLocked();
11872 }
11873 mParallelBroadcasts.add(r);
11874 }
11875 }
11876
11877 return sticky;
11878 }
11879 }
11880
11881 public void unregisterReceiver(IIntentReceiver receiver) {
11882 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
11883
11884 boolean doNext = false;
11885
11886 synchronized(this) {
11887 ReceiverList rl
11888 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11889 if (rl != null) {
11890 if (rl.curBroadcast != null) {
11891 BroadcastRecord r = rl.curBroadcast;
11892 doNext = finishReceiverLocked(
11893 receiver.asBinder(), r.resultCode, r.resultData,
11894 r.resultExtras, r.resultAbort, true);
11895 }
11896
11897 if (rl.app != null) {
11898 rl.app.receivers.remove(rl);
11899 }
11900 removeReceiverLocked(rl);
11901 if (rl.linkedToDeath) {
11902 rl.linkedToDeath = false;
11903 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11904 }
11905 }
11906 }
11907
11908 if (!doNext) {
11909 return;
11910 }
11911
11912 final long origId = Binder.clearCallingIdentity();
11913 processNextBroadcast(false);
11914 trimApplications();
11915 Binder.restoreCallingIdentity(origId);
11916 }
11917
11918 void removeReceiverLocked(ReceiverList rl) {
11919 mRegisteredReceivers.remove(rl.receiver.asBinder());
11920 int N = rl.size();
11921 for (int i=0; i<N; i++) {
11922 mReceiverResolver.removeFilter(rl.get(i));
11923 }
11924 }
11925
11926 private final int broadcastIntentLocked(ProcessRecord callerApp,
11927 String callerPackage, Intent intent, String resolvedType,
11928 IIntentReceiver resultTo, int resultCode, String resultData,
11929 Bundle map, String requiredPermission,
11930 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11931 intent = new Intent(intent);
11932
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011933 if (DEBUG_BROADCAST_LIGHT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11935 + " ordered=" + ordered);
11936 if ((resultTo != null) && !ordered) {
11937 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
11938 }
11939
11940 // Handle special intents: if this broadcast is from the package
11941 // manager about a package being removed, we need to remove all of
11942 // its activities from the history stack.
11943 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
11944 intent.getAction());
11945 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11946 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011947 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 || uidRemoved) {
11949 if (checkComponentPermission(
11950 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
11951 callingPid, callingUid, -1)
11952 == PackageManager.PERMISSION_GRANTED) {
11953 if (uidRemoved) {
11954 final Bundle intentExtras = intent.getExtras();
11955 final int uid = intentExtras != null
11956 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11957 if (uid >= 0) {
11958 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11959 synchronized (bs) {
11960 bs.removeUidStatsLocked(uid);
11961 }
11962 }
11963 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011964 // If resources are unvailble just force stop all
11965 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011966 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011967 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11968 if (list != null && (list.length > 0)) {
11969 for (String pkg : list) {
11970 forceStopPackageLocked(pkg, -1, false, true);
11971 }
11972 }
11973 } else {
11974 Uri data = intent.getData();
11975 String ssp;
11976 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11977 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11978 forceStopPackageLocked(ssp,
11979 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011981 }
11982 }
11983 }
11984 } else {
11985 String msg = "Permission Denial: " + intent.getAction()
11986 + " broadcast from " + callerPackage + " (pid=" + callingPid
11987 + ", uid=" + callingUid + ")"
11988 + " requires "
11989 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
11990 Log.w(TAG, msg);
11991 throw new SecurityException(msg);
11992 }
11993 }
11994
11995 /*
11996 * If this is the time zone changed action, queue up a message that will reset the timezone
11997 * of all currently running processes. This message will get queued up before the broadcast
11998 * happens.
11999 */
12000 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12001 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12002 }
12003
Dianne Hackborn854060af2009-07-09 18:14:31 -070012004 /*
12005 * Prevent non-system code (defined here to be non-persistent
12006 * processes) from sending protected broadcasts.
12007 */
12008 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12009 || callingUid == Process.SHELL_UID || callingUid == 0) {
12010 // Always okay.
12011 } else if (callerApp == null || !callerApp.persistent) {
12012 try {
12013 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12014 intent.getAction())) {
12015 String msg = "Permission Denial: not allowed to send broadcast "
12016 + intent.getAction() + " from pid="
12017 + callingPid + ", uid=" + callingUid;
12018 Log.w(TAG, msg);
12019 throw new SecurityException(msg);
12020 }
12021 } catch (RemoteException e) {
12022 Log.w(TAG, "Remote exception", e);
12023 return BROADCAST_SUCCESS;
12024 }
12025 }
12026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 // Add to the sticky list if requested.
12028 if (sticky) {
12029 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12030 callingPid, callingUid)
12031 != PackageManager.PERMISSION_GRANTED) {
12032 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12033 + callingPid + ", uid=" + callingUid
12034 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12035 Log.w(TAG, msg);
12036 throw new SecurityException(msg);
12037 }
12038 if (requiredPermission != null) {
12039 Log.w(TAG, "Can't broadcast sticky intent " + intent
12040 + " and enforce permission " + requiredPermission);
12041 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12042 }
12043 if (intent.getComponent() != null) {
12044 throw new SecurityException(
12045 "Sticky broadcasts can't target a specific component");
12046 }
12047 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12048 if (list == null) {
12049 list = new ArrayList<Intent>();
12050 mStickyBroadcasts.put(intent.getAction(), list);
12051 }
12052 int N = list.size();
12053 int i;
12054 for (i=0; i<N; i++) {
12055 if (intent.filterEquals(list.get(i))) {
12056 // This sticky already exists, replace it.
12057 list.set(i, new Intent(intent));
12058 break;
12059 }
12060 }
12061 if (i >= N) {
12062 list.add(new Intent(intent));
12063 }
12064 }
12065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012066 // Figure out who all will receive this broadcast.
12067 List receivers = null;
12068 List<BroadcastFilter> registeredReceivers = null;
12069 try {
12070 if (intent.getComponent() != null) {
12071 // Broadcast is going to one specific receiver class...
12072 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012073 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074 if (ai != null) {
12075 receivers = new ArrayList();
12076 ResolveInfo ri = new ResolveInfo();
12077 ri.activityInfo = ai;
12078 receivers.add(ri);
12079 }
12080 } else {
12081 // Need to resolve the intent to interested receivers...
12082 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12083 == 0) {
12084 receivers =
12085 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012086 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012087 }
Mihai Preda074edef2009-05-18 17:13:31 +020012088 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 }
12090 } catch (RemoteException ex) {
12091 // pm is in same process, this will never happen.
12092 }
12093
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012094 final boolean replacePending =
12095 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12096
12097 if (DEBUG_BROADCAST) Log.v(TAG, "Enqueing broadcast: " + intent.getAction()
12098 + " replacePending=" + replacePending);
12099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012100 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12101 if (!ordered && NR > 0) {
12102 // If we are not serializing this broadcast, then send the
12103 // registered receivers separately so they don't wait for the
12104 // components to be launched.
12105 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12106 callerPackage, callingPid, callingUid, requiredPermission,
12107 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012108 ordered, sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012109 if (DEBUG_BROADCAST) Log.v(
12110 TAG, "Enqueueing parallel broadcast " + r
12111 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012112 boolean replaced = false;
12113 if (replacePending) {
12114 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12115 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
12116 if (DEBUG_BROADCAST) Log.v(TAG,
12117 "***** DROPPING PARALLEL: " + intent);
12118 mParallelBroadcasts.set(i, r);
12119 replaced = true;
12120 break;
12121 }
12122 }
12123 }
12124 if (!replaced) {
12125 mParallelBroadcasts.add(r);
12126 scheduleBroadcastsLocked();
12127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012128 registeredReceivers = null;
12129 NR = 0;
12130 }
12131
12132 // Merge into one list.
12133 int ir = 0;
12134 if (receivers != null) {
12135 // A special case for PACKAGE_ADDED: do not allow the package
12136 // being added to see this broadcast. This prevents them from
12137 // using this as a back door to get run as soon as they are
12138 // installed. Maybe in the future we want to have a special install
12139 // broadcast or such for apps, but we'd like to deliberately make
12140 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012141 String skipPackages[] = null;
12142 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12143 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12144 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12145 Uri data = intent.getData();
12146 if (data != null) {
12147 String pkgName = data.getSchemeSpecificPart();
12148 if (pkgName != null) {
12149 skipPackages = new String[] { pkgName };
12150 }
12151 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012152 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012153 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012154 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012155 if (skipPackages != null && (skipPackages.length > 0)) {
12156 for (String skipPackage : skipPackages) {
12157 if (skipPackage != null) {
12158 int NT = receivers.size();
12159 for (int it=0; it<NT; it++) {
12160 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12161 if (curt.activityInfo.packageName.equals(skipPackage)) {
12162 receivers.remove(it);
12163 it--;
12164 NT--;
12165 }
12166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012167 }
12168 }
12169 }
12170
12171 int NT = receivers != null ? receivers.size() : 0;
12172 int it = 0;
12173 ResolveInfo curt = null;
12174 BroadcastFilter curr = null;
12175 while (it < NT && ir < NR) {
12176 if (curt == null) {
12177 curt = (ResolveInfo)receivers.get(it);
12178 }
12179 if (curr == null) {
12180 curr = registeredReceivers.get(ir);
12181 }
12182 if (curr.getPriority() >= curt.priority) {
12183 // Insert this broadcast record into the final list.
12184 receivers.add(it, curr);
12185 ir++;
12186 curr = null;
12187 it++;
12188 NT++;
12189 } else {
12190 // Skip to the next ResolveInfo in the final list.
12191 it++;
12192 curt = null;
12193 }
12194 }
12195 }
12196 while (ir < NR) {
12197 if (receivers == null) {
12198 receivers = new ArrayList();
12199 }
12200 receivers.add(registeredReceivers.get(ir));
12201 ir++;
12202 }
12203
12204 if ((receivers != null && receivers.size() > 0)
12205 || resultTo != null) {
12206 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12207 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012208 receivers, resultTo, resultCode, resultData, map, ordered,
12209 sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 if (DEBUG_BROADCAST) Log.v(
12211 TAG, "Enqueueing ordered broadcast " + r
12212 + ": prev had " + mOrderedBroadcasts.size());
12213 if (DEBUG_BROADCAST) {
12214 int seq = r.intent.getIntExtra("seq", -1);
12215 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
12216 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012217 boolean replaced = false;
12218 if (replacePending) {
12219 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12220 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
12221 if (DEBUG_BROADCAST) Log.v(TAG,
12222 "***** DROPPING ORDERED: " + intent);
12223 mOrderedBroadcasts.set(i, r);
12224 replaced = true;
12225 break;
12226 }
12227 }
12228 }
12229 if (!replaced) {
12230 mOrderedBroadcasts.add(r);
12231 scheduleBroadcastsLocked();
12232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 }
12234
12235 return BROADCAST_SUCCESS;
12236 }
12237
12238 public final int broadcastIntent(IApplicationThread caller,
12239 Intent intent, String resolvedType, IIntentReceiver resultTo,
12240 int resultCode, String resultData, Bundle map,
12241 String requiredPermission, boolean serialized, boolean sticky) {
12242 // Refuse possible leaked file descriptors
12243 if (intent != null && intent.hasFileDescriptors() == true) {
12244 throw new IllegalArgumentException("File descriptors passed in Intent");
12245 }
12246
12247 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012248 int flags = intent.getFlags();
12249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012250 if (!mSystemReady) {
12251 // if the caller really truly claims to know what they're doing, go
12252 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012253 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12254 intent = new Intent(intent);
12255 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12256 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
12257 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12258 + " before boot completion");
12259 throw new IllegalStateException("Cannot broadcast before boot completed");
12260 }
12261 }
12262
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012263 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12264 throw new IllegalArgumentException(
12265 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12266 }
12267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012268 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12269 final int callingPid = Binder.getCallingPid();
12270 final int callingUid = Binder.getCallingUid();
12271 final long origId = Binder.clearCallingIdentity();
12272 int res = broadcastIntentLocked(callerApp,
12273 callerApp != null ? callerApp.info.packageName : null,
12274 intent, resolvedType, resultTo,
12275 resultCode, resultData, map, requiredPermission, serialized,
12276 sticky, callingPid, callingUid);
12277 Binder.restoreCallingIdentity(origId);
12278 return res;
12279 }
12280 }
12281
12282 int broadcastIntentInPackage(String packageName, int uid,
12283 Intent intent, String resolvedType, IIntentReceiver resultTo,
12284 int resultCode, String resultData, Bundle map,
12285 String requiredPermission, boolean serialized, boolean sticky) {
12286 synchronized(this) {
12287 final long origId = Binder.clearCallingIdentity();
12288 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12289 resultTo, resultCode, resultData, map, requiredPermission,
12290 serialized, sticky, -1, uid);
12291 Binder.restoreCallingIdentity(origId);
12292 return res;
12293 }
12294 }
12295
12296 public final void unbroadcastIntent(IApplicationThread caller,
12297 Intent intent) {
12298 // Refuse possible leaked file descriptors
12299 if (intent != null && intent.hasFileDescriptors() == true) {
12300 throw new IllegalArgumentException("File descriptors passed in Intent");
12301 }
12302
12303 synchronized(this) {
12304 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12305 != PackageManager.PERMISSION_GRANTED) {
12306 String msg = "Permission Denial: unbroadcastIntent() from pid="
12307 + Binder.getCallingPid()
12308 + ", uid=" + Binder.getCallingUid()
12309 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12310 Log.w(TAG, msg);
12311 throw new SecurityException(msg);
12312 }
12313 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12314 if (list != null) {
12315 int N = list.size();
12316 int i;
12317 for (i=0; i<N; i++) {
12318 if (intent.filterEquals(list.get(i))) {
12319 list.remove(i);
12320 break;
12321 }
12322 }
12323 }
12324 }
12325 }
12326
12327 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12328 String resultData, Bundle resultExtras, boolean resultAbort,
12329 boolean explicit) {
12330 if (mOrderedBroadcasts.size() == 0) {
12331 if (explicit) {
12332 Log.w(TAG, "finishReceiver called but no pending broadcasts");
12333 }
12334 return false;
12335 }
12336 BroadcastRecord r = mOrderedBroadcasts.get(0);
12337 if (r.receiver == null) {
12338 if (explicit) {
12339 Log.w(TAG, "finishReceiver called but none active");
12340 }
12341 return false;
12342 }
12343 if (r.receiver != receiver) {
12344 Log.w(TAG, "finishReceiver called but active receiver is different");
12345 return false;
12346 }
12347 int state = r.state;
12348 r.state = r.IDLE;
12349 if (state == r.IDLE) {
12350 if (explicit) {
12351 Log.w(TAG, "finishReceiver called but state is IDLE");
12352 }
12353 }
12354 r.receiver = null;
12355 r.intent.setComponent(null);
12356 if (r.curApp != null) {
12357 r.curApp.curReceiver = null;
12358 }
12359 if (r.curFilter != null) {
12360 r.curFilter.receiverList.curBroadcast = null;
12361 }
12362 r.curFilter = null;
12363 r.curApp = null;
12364 r.curComponent = null;
12365 r.curReceiver = null;
12366 mPendingBroadcast = null;
12367
12368 r.resultCode = resultCode;
12369 r.resultData = resultData;
12370 r.resultExtras = resultExtras;
12371 r.resultAbort = resultAbort;
12372
12373 // We will process the next receiver right now if this is finishing
12374 // an app receiver (which is always asynchronous) or after we have
12375 // come back from calling a receiver.
12376 return state == BroadcastRecord.APP_RECEIVE
12377 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12378 }
12379
12380 public void finishReceiver(IBinder who, int resultCode, String resultData,
12381 Bundle resultExtras, boolean resultAbort) {
12382 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
12383
12384 // Refuse possible leaked file descriptors
12385 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12386 throw new IllegalArgumentException("File descriptors passed in Bundle");
12387 }
12388
12389 boolean doNext;
12390
12391 final long origId = Binder.clearCallingIdentity();
12392
12393 synchronized(this) {
12394 doNext = finishReceiverLocked(
12395 who, resultCode, resultData, resultExtras, resultAbort, true);
12396 }
12397
12398 if (doNext) {
12399 processNextBroadcast(false);
12400 }
12401 trimApplications();
12402
12403 Binder.restoreCallingIdentity(origId);
12404 }
12405
12406 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12407 if (r.nextReceiver > 0) {
12408 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12409 if (curReceiver instanceof BroadcastFilter) {
12410 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012411 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012412 System.identityHashCode(r),
12413 r.intent.getAction(),
12414 r.nextReceiver - 1,
12415 System.identityHashCode(bf));
12416 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012417 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 System.identityHashCode(r),
12419 r.intent.getAction(),
12420 r.nextReceiver - 1,
12421 ((ResolveInfo)curReceiver).toString());
12422 }
12423 } else {
12424 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
12425 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012426 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012427 System.identityHashCode(r),
12428 r.intent.getAction(),
12429 r.nextReceiver,
12430 "NONE");
12431 }
12432 }
12433
12434 private final void broadcastTimeout() {
12435 synchronized (this) {
12436 if (mOrderedBroadcasts.size() == 0) {
12437 return;
12438 }
12439 long now = SystemClock.uptimeMillis();
12440 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012441 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012442 if (DEBUG_BROADCAST) Log.v(TAG,
12443 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012444 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012446 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 return;
12448 }
12449
12450 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012451 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 r.anrCount++;
12453
12454 // Current receiver has passed its expiration date.
12455 if (r.nextReceiver <= 0) {
12456 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12457 return;
12458 }
12459
12460 ProcessRecord app = null;
12461
12462 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12463 Log.w(TAG, "Receiver during timeout: " + curReceiver);
12464 logBroadcastReceiverDiscard(r);
12465 if (curReceiver instanceof BroadcastFilter) {
12466 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12467 if (bf.receiverList.pid != 0
12468 && bf.receiverList.pid != MY_PID) {
12469 synchronized (this.mPidsSelfLocked) {
12470 app = this.mPidsSelfLocked.get(
12471 bf.receiverList.pid);
12472 }
12473 }
12474 } else {
12475 app = r.curApp;
12476 }
12477
12478 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012479 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012480 }
12481
12482 if (mPendingBroadcast == r) {
12483 mPendingBroadcast = null;
12484 }
12485
12486 // Move on to the next receiver.
12487 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12488 r.resultExtras, r.resultAbort, true);
12489 scheduleBroadcastsLocked();
12490 }
12491 }
12492
12493 private final void processCurBroadcastLocked(BroadcastRecord r,
12494 ProcessRecord app) throws RemoteException {
12495 if (app.thread == null) {
12496 throw new RemoteException();
12497 }
12498 r.receiver = app.thread.asBinder();
12499 r.curApp = app;
12500 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012501 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012502
12503 // Tell the application to launch this receiver.
12504 r.intent.setComponent(r.curComponent);
12505
12506 boolean started = false;
12507 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012508 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 "Delivering to component " + r.curComponent
12510 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012511 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12513 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12514 started = true;
12515 } finally {
12516 if (!started) {
12517 r.receiver = null;
12518 r.curApp = null;
12519 app.curReceiver = null;
12520 }
12521 }
12522
12523 }
12524
12525 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012526 Intent intent, int resultCode, String data, Bundle extras,
12527 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528 if (app != null && app.thread != null) {
12529 // If we have an app thread, do the call through that so it is
12530 // correctly ordered with other one-way calls.
12531 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012532 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012534 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 }
12536 }
12537
12538 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12539 BroadcastFilter filter, boolean ordered) {
12540 boolean skip = false;
12541 if (filter.requiredPermission != null) {
12542 int perm = checkComponentPermission(filter.requiredPermission,
12543 r.callingPid, r.callingUid, -1);
12544 if (perm != PackageManager.PERMISSION_GRANTED) {
12545 Log.w(TAG, "Permission Denial: broadcasting "
12546 + r.intent.toString()
12547 + " from " + r.callerPackage + " (pid="
12548 + r.callingPid + ", uid=" + r.callingUid + ")"
12549 + " requires " + filter.requiredPermission
12550 + " due to registered receiver " + filter);
12551 skip = true;
12552 }
12553 }
12554 if (r.requiredPermission != null) {
12555 int perm = checkComponentPermission(r.requiredPermission,
12556 filter.receiverList.pid, filter.receiverList.uid, -1);
12557 if (perm != PackageManager.PERMISSION_GRANTED) {
12558 Log.w(TAG, "Permission Denial: receiving "
12559 + r.intent.toString()
12560 + " to " + filter.receiverList.app
12561 + " (pid=" + filter.receiverList.pid
12562 + ", uid=" + filter.receiverList.uid + ")"
12563 + " requires " + r.requiredPermission
12564 + " due to sender " + r.callerPackage
12565 + " (uid " + r.callingUid + ")");
12566 skip = true;
12567 }
12568 }
12569
12570 if (!skip) {
12571 // If this is not being sent as an ordered broadcast, then we
12572 // don't want to touch the fields that keep track of the current
12573 // state of ordered broadcasts.
12574 if (ordered) {
12575 r.receiver = filter.receiverList.receiver.asBinder();
12576 r.curFilter = filter;
12577 filter.receiverList.curBroadcast = r;
12578 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012579 if (filter.receiverList.app != null) {
12580 // Bump hosting application to no longer be in background
12581 // scheduling class. Note that we can't do that if there
12582 // isn't an app... but we can only be in that case for
12583 // things that directly call the IActivityManager API, which
12584 // are already core system stuff so don't matter for this.
12585 r.curApp = filter.receiverList.app;
12586 filter.receiverList.app.curReceiver = r;
12587 updateOomAdjLocked();
12588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012589 }
12590 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012591 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012592 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012593 Log.i(TAG, "Delivering to " + filter.receiverList.app
12594 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012595 }
12596 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12597 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012598 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 if (ordered) {
12600 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12601 }
12602 } catch (RemoteException e) {
12603 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
12604 if (ordered) {
12605 r.receiver = null;
12606 r.curFilter = null;
12607 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012608 if (filter.receiverList.app != null) {
12609 filter.receiverList.app.curReceiver = null;
12610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012611 }
12612 }
12613 }
12614 }
12615
Dianne Hackborn12527f92009-11-11 17:39:50 -080012616 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12617 if (r.callingUid < 0) {
12618 // This was from a registerReceiver() call; ignore it.
12619 return;
12620 }
12621 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12622 MAX_BROADCAST_HISTORY-1);
12623 r.finishTime = SystemClock.uptimeMillis();
12624 mBroadcastHistory[0] = r;
12625 }
12626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012627 private final void processNextBroadcast(boolean fromMsg) {
12628 synchronized(this) {
12629 BroadcastRecord r;
12630
12631 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
12632 + mParallelBroadcasts.size() + " broadcasts, "
12633 + mOrderedBroadcasts.size() + " serialized broadcasts");
12634
12635 updateCpuStats();
12636
12637 if (fromMsg) {
12638 mBroadcastsScheduled = false;
12639 }
12640
12641 // First, deliver any non-serialized broadcasts right away.
12642 while (mParallelBroadcasts.size() > 0) {
12643 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012644 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012645 final int N = r.receivers.size();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012646 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing parallel broadcast "
12647 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012648 for (int i=0; i<N; i++) {
12649 Object target = r.receivers.get(i);
12650 if (DEBUG_BROADCAST) Log.v(TAG,
12651 "Delivering non-serialized to registered "
12652 + target + ": " + r);
12653 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12654 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012655 addBroadcastToHistoryLocked(r);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012656 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Done with parallel broadcast "
12657 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012658 }
12659
12660 // Now take care of the next serialized one...
12661
12662 // If we are waiting for a process to come up to handle the next
12663 // broadcast, then do nothing at this point. Just in case, we
12664 // check that the process we're waiting for still exists.
12665 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012666 if (DEBUG_BROADCAST_LIGHT) {
12667 Log.v(TAG, "processNextBroadcast: waiting for "
12668 + mPendingBroadcast.curApp);
12669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012670
12671 boolean isDead;
12672 synchronized (mPidsSelfLocked) {
12673 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12674 }
12675 if (!isDead) {
12676 // It's still alive, so keep waiting
12677 return;
12678 } else {
12679 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
12680 + " died before responding to broadcast");
12681 mPendingBroadcast = null;
12682 }
12683 }
12684
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012685 boolean looped = false;
12686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012687 do {
12688 if (mOrderedBroadcasts.size() == 0) {
12689 // No more broadcasts pending, so all done!
12690 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012691 if (looped) {
12692 // If we had finished the last ordered broadcast, then
12693 // make sure all processes have correct oom and sched
12694 // adjustments.
12695 updateOomAdjLocked();
12696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 return;
12698 }
12699 r = mOrderedBroadcasts.get(0);
12700 boolean forceReceive = false;
12701
12702 // Ensure that even if something goes awry with the timeout
12703 // detection, we catch "hung" broadcasts here, discard them,
12704 // and continue to make progress.
12705 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12706 long now = SystemClock.uptimeMillis();
12707 if (r.dispatchTime > 0) {
12708 if ((numReceivers > 0) &&
12709 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
12710 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
12711 + " now=" + now
12712 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012713 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012714 + " intent=" + r.intent
12715 + " numReceivers=" + numReceivers
12716 + " nextReceiver=" + r.nextReceiver
12717 + " state=" + r.state);
12718 broadcastTimeout(); // forcibly finish this broadcast
12719 forceReceive = true;
12720 r.state = BroadcastRecord.IDLE;
12721 }
12722 }
12723
12724 if (r.state != BroadcastRecord.IDLE) {
12725 if (DEBUG_BROADCAST) Log.d(TAG,
12726 "processNextBroadcast() called when not idle (state="
12727 + r.state + ")");
12728 return;
12729 }
12730
12731 if (r.receivers == null || r.nextReceiver >= numReceivers
12732 || r.resultAbort || forceReceive) {
12733 // No more receivers for this broadcast! Send the final
12734 // result if requested...
12735 if (r.resultTo != null) {
12736 try {
12737 if (DEBUG_BROADCAST) {
12738 int seq = r.intent.getIntExtra("seq", -1);
12739 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
12740 + " seq=" + seq + " app=" + r.callerApp);
12741 }
12742 performReceive(r.callerApp, r.resultTo,
12743 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012744 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 } catch (RemoteException e) {
12746 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
12747 }
12748 }
12749
12750 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
12751 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12752
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012753 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Finished with ordered broadcast "
12754 + r);
12755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012756 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012757 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 mOrderedBroadcasts.remove(0);
12759 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012760 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012761 continue;
12762 }
12763 } while (r == null);
12764
12765 // Get the next receiver...
12766 int recIdx = r.nextReceiver++;
12767
12768 // Keep track of when this receiver started, and make sure there
12769 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012770 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012772 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012773
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012774 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing ordered broadcast "
12775 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012776 if (DEBUG_BROADCAST) Log.v(TAG,
12777 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012778 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012779 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012780 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012781 }
12782
12783 Object nextReceiver = r.receivers.get(recIdx);
12784 if (nextReceiver instanceof BroadcastFilter) {
12785 // Simple case: this is a registered receiver who gets
12786 // a direct call.
12787 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
12788 if (DEBUG_BROADCAST) Log.v(TAG,
12789 "Delivering serialized to registered "
12790 + filter + ": " + r);
12791 deliverToRegisteredReceiver(r, filter, r.ordered);
12792 if (r.receiver == null || !r.ordered) {
12793 // The receiver has already finished, so schedule to
12794 // process the next one.
12795 r.state = BroadcastRecord.IDLE;
12796 scheduleBroadcastsLocked();
12797 }
12798 return;
12799 }
12800
12801 // Hard case: need to instantiate the receiver, possibly
12802 // starting its application process to host it.
12803
12804 ResolveInfo info =
12805 (ResolveInfo)nextReceiver;
12806
12807 boolean skip = false;
12808 int perm = checkComponentPermission(info.activityInfo.permission,
12809 r.callingPid, r.callingUid,
12810 info.activityInfo.exported
12811 ? -1 : info.activityInfo.applicationInfo.uid);
12812 if (perm != PackageManager.PERMISSION_GRANTED) {
12813 Log.w(TAG, "Permission Denial: broadcasting "
12814 + r.intent.toString()
12815 + " from " + r.callerPackage + " (pid=" + r.callingPid
12816 + ", uid=" + r.callingUid + ")"
12817 + " requires " + info.activityInfo.permission
12818 + " due to receiver " + info.activityInfo.packageName
12819 + "/" + info.activityInfo.name);
12820 skip = true;
12821 }
12822 if (r.callingUid != Process.SYSTEM_UID &&
12823 r.requiredPermission != null) {
12824 try {
12825 perm = ActivityThread.getPackageManager().
12826 checkPermission(r.requiredPermission,
12827 info.activityInfo.applicationInfo.packageName);
12828 } catch (RemoteException e) {
12829 perm = PackageManager.PERMISSION_DENIED;
12830 }
12831 if (perm != PackageManager.PERMISSION_GRANTED) {
12832 Log.w(TAG, "Permission Denial: receiving "
12833 + r.intent + " to "
12834 + info.activityInfo.applicationInfo.packageName
12835 + " requires " + r.requiredPermission
12836 + " due to sender " + r.callerPackage
12837 + " (uid " + r.callingUid + ")");
12838 skip = true;
12839 }
12840 }
12841 if (r.curApp != null && r.curApp.crashing) {
12842 // If the target process is crashing, just skip it.
12843 skip = true;
12844 }
12845
12846 if (skip) {
12847 r.receiver = null;
12848 r.curFilter = null;
12849 r.state = BroadcastRecord.IDLE;
12850 scheduleBroadcastsLocked();
12851 return;
12852 }
12853
12854 r.state = BroadcastRecord.APP_RECEIVE;
12855 String targetProcess = info.activityInfo.processName;
12856 r.curComponent = new ComponentName(
12857 info.activityInfo.applicationInfo.packageName,
12858 info.activityInfo.name);
12859 r.curReceiver = info.activityInfo;
12860
12861 // Is this receiver's application already running?
12862 ProcessRecord app = getProcessRecordLocked(targetProcess,
12863 info.activityInfo.applicationInfo.uid);
12864 if (app != null && app.thread != null) {
12865 try {
12866 processCurBroadcastLocked(r, app);
12867 return;
12868 } catch (RemoteException e) {
12869 Log.w(TAG, "Exception when sending broadcast to "
12870 + r.curComponent, e);
12871 }
12872
12873 // If a dead object exception was thrown -- fall through to
12874 // restart the application.
12875 }
12876
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012877 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012878 if ((r.curApp=startProcessLocked(targetProcess,
12879 info.activityInfo.applicationInfo, true,
12880 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012881 "broadcast", r.curComponent,
12882 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12883 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012884 // Ah, this recipient is unavailable. Finish it if necessary,
12885 // and mark the broadcast record as ready for the next.
12886 Log.w(TAG, "Unable to launch app "
12887 + info.activityInfo.applicationInfo.packageName + "/"
12888 + info.activityInfo.applicationInfo.uid + " for broadcast "
12889 + r.intent + ": process is bad");
12890 logBroadcastReceiverDiscard(r);
12891 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12892 r.resultExtras, r.resultAbort, true);
12893 scheduleBroadcastsLocked();
12894 r.state = BroadcastRecord.IDLE;
12895 return;
12896 }
12897
12898 mPendingBroadcast = r;
12899 }
12900 }
12901
12902 // =========================================================
12903 // INSTRUMENTATION
12904 // =========================================================
12905
12906 public boolean startInstrumentation(ComponentName className,
12907 String profileFile, int flags, Bundle arguments,
12908 IInstrumentationWatcher watcher) {
12909 // Refuse possible leaked file descriptors
12910 if (arguments != null && arguments.hasFileDescriptors()) {
12911 throw new IllegalArgumentException("File descriptors passed in Bundle");
12912 }
12913
12914 synchronized(this) {
12915 InstrumentationInfo ii = null;
12916 ApplicationInfo ai = null;
12917 try {
12918 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012919 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012920 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012921 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012922 } catch (PackageManager.NameNotFoundException e) {
12923 }
12924 if (ii == null) {
12925 reportStartInstrumentationFailure(watcher, className,
12926 "Unable to find instrumentation info for: " + className);
12927 return false;
12928 }
12929 if (ai == null) {
12930 reportStartInstrumentationFailure(watcher, className,
12931 "Unable to find instrumentation target package: " + ii.targetPackage);
12932 return false;
12933 }
12934
12935 int match = mContext.getPackageManager().checkSignatures(
12936 ii.targetPackage, ii.packageName);
12937 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12938 String msg = "Permission Denial: starting instrumentation "
12939 + className + " from pid="
12940 + Binder.getCallingPid()
12941 + ", uid=" + Binder.getCallingPid()
12942 + " not allowed because package " + ii.packageName
12943 + " does not have a signature matching the target "
12944 + ii.targetPackage;
12945 reportStartInstrumentationFailure(watcher, className, msg);
12946 throw new SecurityException(msg);
12947 }
12948
12949 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012950 forceStopPackageLocked(ii.targetPackage, -1, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012951 ProcessRecord app = addAppLocked(ai);
12952 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012953 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012954 app.instrumentationProfileFile = profileFile;
12955 app.instrumentationArguments = arguments;
12956 app.instrumentationWatcher = watcher;
12957 app.instrumentationResultClass = className;
12958 Binder.restoreCallingIdentity(origId);
12959 }
12960
12961 return true;
12962 }
12963
12964 /**
12965 * Report errors that occur while attempting to start Instrumentation. Always writes the
12966 * error to the logs, but if somebody is watching, send the report there too. This enables
12967 * the "am" command to report errors with more information.
12968 *
12969 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12970 * @param cn The component name of the instrumentation.
12971 * @param report The error report.
12972 */
12973 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12974 ComponentName cn, String report) {
12975 Log.w(TAG, report);
12976 try {
12977 if (watcher != null) {
12978 Bundle results = new Bundle();
12979 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12980 results.putString("Error", report);
12981 watcher.instrumentationStatus(cn, -1, results);
12982 }
12983 } catch (RemoteException e) {
12984 Log.w(TAG, e);
12985 }
12986 }
12987
12988 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12989 if (app.instrumentationWatcher != null) {
12990 try {
12991 // NOTE: IInstrumentationWatcher *must* be oneway here
12992 app.instrumentationWatcher.instrumentationFinished(
12993 app.instrumentationClass,
12994 resultCode,
12995 results);
12996 } catch (RemoteException e) {
12997 }
12998 }
12999 app.instrumentationWatcher = null;
13000 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013001 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013002 app.instrumentationProfileFile = null;
13003 app.instrumentationArguments = null;
13004
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013005 forceStopPackageLocked(app.processName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013006 }
13007
13008 public void finishInstrumentation(IApplicationThread target,
13009 int resultCode, Bundle results) {
13010 // Refuse possible leaked file descriptors
13011 if (results != null && results.hasFileDescriptors()) {
13012 throw new IllegalArgumentException("File descriptors passed in Intent");
13013 }
13014
13015 synchronized(this) {
13016 ProcessRecord app = getRecordForAppLocked(target);
13017 if (app == null) {
13018 Log.w(TAG, "finishInstrumentation: no app for " + target);
13019 return;
13020 }
13021 final long origId = Binder.clearCallingIdentity();
13022 finishInstrumentationLocked(app, resultCode, results);
13023 Binder.restoreCallingIdentity(origId);
13024 }
13025 }
13026
13027 // =========================================================
13028 // CONFIGURATION
13029 // =========================================================
13030
13031 public ConfigurationInfo getDeviceConfigurationInfo() {
13032 ConfigurationInfo config = new ConfigurationInfo();
13033 synchronized (this) {
13034 config.reqTouchScreen = mConfiguration.touchscreen;
13035 config.reqKeyboardType = mConfiguration.keyboard;
13036 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013037 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13038 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013039 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13040 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013041 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13042 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013043 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13044 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013045 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013046 }
13047 return config;
13048 }
13049
13050 public Configuration getConfiguration() {
13051 Configuration ci;
13052 synchronized(this) {
13053 ci = new Configuration(mConfiguration);
13054 }
13055 return ci;
13056 }
13057
13058 public void updateConfiguration(Configuration values) {
13059 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13060 "updateConfiguration()");
13061
13062 synchronized(this) {
13063 if (values == null && mWindowManager != null) {
13064 // sentinel: fetch the current configuration from the window manager
13065 values = mWindowManager.computeNewConfiguration();
13066 }
13067
13068 final long origId = Binder.clearCallingIdentity();
13069 updateConfigurationLocked(values, null);
13070 Binder.restoreCallingIdentity(origId);
13071 }
13072 }
13073
13074 /**
13075 * Do either or both things: (1) change the current configuration, and (2)
13076 * make sure the given activity is running with the (now) current
13077 * configuration. Returns true if the activity has been left running, or
13078 * false if <var>starting</var> is being destroyed to match the new
13079 * configuration.
13080 */
13081 public boolean updateConfigurationLocked(Configuration values,
13082 HistoryRecord starting) {
13083 int changes = 0;
13084
13085 boolean kept = true;
13086
13087 if (values != null) {
13088 Configuration newConfig = new Configuration(mConfiguration);
13089 changes = newConfig.updateFrom(values);
13090 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013091 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013092 Log.i(TAG, "Updating configuration to: " + values);
13093 }
13094
Doug Zongker2bec3d42009-12-04 12:52:44 -080013095 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013096
13097 if (values.locale != null) {
13098 saveLocaleLocked(values.locale,
13099 !values.locale.equals(mConfiguration.locale),
13100 values.userSetLocale);
13101 }
13102
13103 mConfiguration = newConfig;
Dianne Hackborna8f60182009-09-01 19:01:50 -070013104 Log.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013105
13106 AttributeCache ac = AttributeCache.instance();
13107 if (ac != null) {
13108 ac.updateConfiguration(mConfiguration);
13109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110
13111 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13112 msg.obj = new Configuration(mConfiguration);
13113 mHandler.sendMessage(msg);
13114
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013115 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13116 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013117 try {
13118 if (app.thread != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013119 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending to proc "
13120 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121 app.thread.scheduleConfigurationChanged(mConfiguration);
13122 }
13123 } catch (Exception e) {
13124 }
13125 }
13126 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013127 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13128 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013129 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13130 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013131 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13132 broadcastIntentLocked(null, null,
13133 new Intent(Intent.ACTION_LOCALE_CHANGED),
13134 null, null, 0, null, null,
13135 null, false, false, MY_PID, Process.SYSTEM_UID);
13136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013137 }
13138 }
13139
13140 if (changes != 0 && starting == null) {
13141 // If the configuration changed, and the caller is not already
13142 // in the process of starting an activity, then find the top
13143 // activity to check if its configuration needs to change.
13144 starting = topRunningActivityLocked(null);
13145 }
13146
13147 if (starting != null) {
13148 kept = ensureActivityConfigurationLocked(starting, changes);
13149 if (kept) {
13150 // If this didn't result in the starting activity being
13151 // destroyed, then we need to make sure at this point that all
13152 // other activities are made visible.
13153 if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
13154 + ", ensuring others are correct.");
13155 ensureActivitiesVisibleLocked(starting, changes);
13156 }
13157 }
13158
13159 return kept;
13160 }
13161
13162 private final boolean relaunchActivityLocked(HistoryRecord r,
13163 int changes, boolean andResume) {
13164 List<ResultInfo> results = null;
13165 List<Intent> newIntents = null;
13166 if (andResume) {
13167 results = r.results;
13168 newIntents = r.newIntents;
13169 }
13170 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
13171 + " with results=" + results + " newIntents=" + newIntents
13172 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013173 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13174 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013175 r.task.taskId, r.shortComponentName);
13176
13177 r.startFreezingScreenLocked(r.app, 0);
13178
13179 try {
13180 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
13181 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013182 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 // Note: don't need to call pauseIfSleepingLocked() here, because
13184 // the caller will only pass in 'andResume' if this activity is
13185 // currently resumed, which implies we aren't sleeping.
13186 } catch (RemoteException e) {
13187 return false;
13188 }
13189
13190 if (andResume) {
13191 r.results = null;
13192 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013193 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013194 }
13195
13196 return true;
13197 }
13198
13199 /**
13200 * Make sure the given activity matches the current configuration. Returns
13201 * false if the activity had to be destroyed. Returns true if the
13202 * configuration is the same, or the activity will remain running as-is
13203 * for whatever reason. Ensures the HistoryRecord is updated with the
13204 * correct configuration and all other bookkeeping is handled.
13205 */
13206 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13207 int globalChanges) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013208 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13209 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210
13211 // Short circuit: if the two configurations are the exact same
13212 // object (the common case), then there is nothing to do.
13213 Configuration newConfig = mConfiguration;
13214 if (r.configuration == newConfig) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013215 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13216 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013217 return true;
13218 }
13219
13220 // We don't worry about activities that are finishing.
13221 if (r.finishing) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013222 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013223 "Configuration doesn't matter in finishing " + r);
13224 r.stopFreezingScreenLocked(false);
13225 return true;
13226 }
13227
13228 // Okay we now are going to make this activity have the new config.
13229 // But then we need to figure out how it needs to deal with that.
13230 Configuration oldConfig = r.configuration;
13231 r.configuration = newConfig;
13232
13233 // If the activity isn't currently running, just leave the new
13234 // configuration and it will pick that up next time it starts.
13235 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013236 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013237 "Configuration doesn't matter not running " + r);
13238 r.stopFreezingScreenLocked(false);
13239 return true;
13240 }
13241
13242 // If the activity isn't persistent, there is a chance we will
13243 // need to restart it.
13244 if (!r.persistent) {
13245
13246 // Figure out what has changed between the two configurations.
13247 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013248 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
13249 Log.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013250 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013251 + Integer.toHexString(r.info.configChanges)
13252 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013253 }
13254 if ((changes&(~r.info.configChanges)) != 0) {
13255 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13256 r.configChangeFlags |= changes;
13257 r.startFreezingScreenLocked(r.app, globalChanges);
13258 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013259 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13260 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013261 destroyActivityLocked(r, true);
13262 } else if (r.state == ActivityState.PAUSING) {
13263 // A little annoying: we are waiting for this activity to
13264 // finish pausing. Let's not do anything now, but just
13265 // flag that it needs to be restarted when done pausing.
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013266 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13267 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 r.configDestroy = true;
13269 return true;
13270 } else if (r.state == ActivityState.RESUMED) {
13271 // Try to optimize this case: the configuration is changing
13272 // and we need to restart the top, resumed activity.
13273 // Instead of doing the normal handshaking, just say
13274 // "restart!".
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013275 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13276 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013277 relaunchActivityLocked(r, r.configChangeFlags, true);
13278 r.configChangeFlags = 0;
13279 } else {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013280 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13281 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013282 relaunchActivityLocked(r, r.configChangeFlags, false);
13283 r.configChangeFlags = 0;
13284 }
13285
13286 // All done... tell the caller we weren't able to keep this
13287 // activity around.
13288 return false;
13289 }
13290 }
13291
13292 // Default case: the activity can handle this new configuration, so
13293 // hand it over. Note that we don't need to give it the new
13294 // configuration, since we always send configuration changes to all
13295 // process when they happen so it can just use whatever configuration
13296 // it last got.
13297 if (r.app != null && r.app.thread != null) {
13298 try {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013299 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 r.app.thread.scheduleActivityConfigurationChanged(r);
13301 } catch (RemoteException e) {
13302 // If process died, whatever.
13303 }
13304 }
13305 r.stopFreezingScreenLocked(false);
13306
13307 return true;
13308 }
13309
13310 /**
13311 * Save the locale. You must be inside a synchronized (this) block.
13312 */
13313 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13314 if(isDiff) {
13315 SystemProperties.set("user.language", l.getLanguage());
13316 SystemProperties.set("user.region", l.getCountry());
13317 }
13318
13319 if(isPersist) {
13320 SystemProperties.set("persist.sys.language", l.getLanguage());
13321 SystemProperties.set("persist.sys.country", l.getCountry());
13322 SystemProperties.set("persist.sys.localevar", l.getVariant());
13323 }
13324 }
13325
13326 // =========================================================
13327 // LIFETIME MANAGEMENT
13328 // =========================================================
13329
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013330 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13331 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013332 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013333 // This adjustment has already been computed. If we are calling
13334 // from the top, we may have already computed our adjustment with
13335 // an earlier hidden adjustment that isn't really for us... if
13336 // so, use the new hidden adjustment.
13337 if (!recursed && app.hidden) {
13338 app.curAdj = hiddenAdj;
13339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013340 return app.curAdj;
13341 }
13342
13343 if (app.thread == null) {
13344 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013345 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013346 return (app.curAdj=EMPTY_APP_ADJ);
13347 }
13348
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013349 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13350 // The max adjustment doesn't allow this app to be anything
13351 // below foreground, so it is not worth doing work for it.
13352 app.adjType = "fixed";
13353 app.adjSeq = mAdjSeq;
13354 app.curRawAdj = app.maxAdj;
13355 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13356 return (app.curAdj=app.maxAdj);
13357 }
13358
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013359 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013360 app.adjSource = null;
13361 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013362 app.empty = false;
13363 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013364
The Android Open Source Project4df24232009-03-05 14:34:35 -080013365 // Determine the importance of the process, starting with most
13366 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013367 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013368 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013370 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 // The last app on the list is the foreground app.
13372 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013373 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013374 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013375 } else if (app.instrumentationClass != null) {
13376 // Don't want to kill running instrumentation.
13377 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013378 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013379 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013380 } else if (app.persistentActivities > 0) {
13381 // Special persistent activities... shouldn't be used these days.
13382 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013383 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013384 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 } else if (app.curReceiver != null ||
13386 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13387 // An app that is currently receiving a broadcast also
13388 // counts as being in the foreground.
13389 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013390 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013391 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 } else if (app.executingServices.size() > 0) {
13393 // An app that is currently executing a service callback also
13394 // counts as being in the foreground.
13395 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013396 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013397 app.adjType = "exec-service";
13398 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013399 // The user is aware of this app, so make it visible.
13400 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013401 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013402 app.adjType = "foreground-service";
13403 } else if (app.forcingToForeground != null) {
13404 // The user is aware of this app, so make it visible.
13405 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013406 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013407 app.adjType = "force-foreground";
13408 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013409 } else if (app == mHomeProcess) {
13410 // This process is hosting what we currently consider to be the
13411 // home app, so we don't want to let it go into the background.
13412 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013413 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013414 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 } else if ((N=app.activities.size()) != 0) {
13416 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013417 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013419 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013420 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013421 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 for (int j=0; j<N; j++) {
13423 if (((HistoryRecord)app.activities.get(j)).visible) {
13424 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013425 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013426 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013427 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013428 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013429 break;
13430 }
13431 }
13432 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013433 // A very not-needed process. If this is lower in the lru list,
13434 // we will push it in to the empty bucket.
13435 app.hidden = true;
13436 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013437 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013438 adj = hiddenAdj;
13439 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440 }
13441
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013442 //Log.i(TAG, "OOM " + app + ": initial adj=" + adj);
13443
The Android Open Source Project4df24232009-03-05 14:34:35 -080013444 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013445 // there are applications dependent on our services or providers, but
13446 // this gives us a baseline and makes sure we don't get into an
13447 // infinite recursion.
13448 app.adjSeq = mAdjSeq;
13449 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013450
Christopher Tate6fa95972009-06-05 18:43:55 -070013451 if (mBackupTarget != null && app == mBackupTarget.app) {
13452 // If possible we want to avoid killing apps while they're being backed up
13453 if (adj > BACKUP_APP_ADJ) {
13454 if (DEBUG_BACKUP) Log.v(TAG, "oom BACKUP_APP_ADJ for " + app);
13455 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013456 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013457 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013458 }
13459 }
13460
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013461 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13462 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013463 final long now = SystemClock.uptimeMillis();
13464 // This process is more important if the top activity is
13465 // bound to the service.
13466 Iterator jt = app.services.iterator();
13467 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13468 ServiceRecord s = (ServiceRecord)jt.next();
13469 if (s.startRequested) {
13470 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13471 // This service has seen some activity within
13472 // recent memory, so we will keep its process ahead
13473 // of the background processes.
13474 if (adj > SECONDARY_SERVER_ADJ) {
13475 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013476 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013477 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013478 }
13479 }
13480 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013481 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13482 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483 Iterator<ConnectionRecord> kt
13484 = s.connections.values().iterator();
13485 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13486 // XXX should compute this based on the max of
13487 // all connected clients.
13488 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013489 if (cr.binding.client == app) {
13490 // Binding to ourself is not interesting.
13491 continue;
13492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013493 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13494 ProcessRecord client = cr.binding.client;
13495 int myHiddenAdj = hiddenAdj;
13496 if (myHiddenAdj > client.hiddenAdj) {
13497 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13498 myHiddenAdj = client.hiddenAdj;
13499 } else {
13500 myHiddenAdj = VISIBLE_APP_ADJ;
13501 }
13502 }
13503 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013504 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013505 if (adj > clientAdj) {
13506 adj = clientAdj > VISIBLE_APP_ADJ
13507 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013508 if (!client.hidden) {
13509 app.hidden = false;
13510 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013511 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013512 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13513 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013514 app.adjSource = cr.binding.client;
13515 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013517 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13518 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13519 schedGroup = Process.THREAD_GROUP_DEFAULT;
13520 }
13521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013522 }
13523 HistoryRecord a = cr.activity;
13524 //if (a != null) {
13525 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
13526 //}
13527 if (a != null && adj > FOREGROUND_APP_ADJ &&
13528 (a.state == ActivityState.RESUMED
13529 || a.state == ActivityState.PAUSING)) {
13530 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013531 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013532 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013533 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013534 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13535 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013536 app.adjSource = a;
13537 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 }
13539 }
13540 }
13541 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013542
13543 // Finally, f this process has active services running in it, we
13544 // would like to avoid killing it unless it would prevent the current
13545 // application from running. By default we put the process in
13546 // with the rest of the background processes; as we scan through
13547 // its services we may bump it up from there.
13548 if (adj > hiddenAdj) {
13549 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013550 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013551 app.adjType = "bg-services";
13552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013553 }
13554
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013555 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13556 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013557 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013558 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13559 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013560 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13561 if (cpr.clients.size() != 0) {
13562 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13563 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13564 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013565 if (client == app) {
13566 // Being our own client is not interesting.
13567 continue;
13568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569 int myHiddenAdj = hiddenAdj;
13570 if (myHiddenAdj > client.hiddenAdj) {
13571 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13572 myHiddenAdj = client.hiddenAdj;
13573 } else {
13574 myHiddenAdj = FOREGROUND_APP_ADJ;
13575 }
13576 }
13577 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013578 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 if (adj > clientAdj) {
13580 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013581 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013582 if (!client.hidden) {
13583 app.hidden = false;
13584 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013585 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013586 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13587 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013588 app.adjSource = client;
13589 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013590 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013591 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13592 schedGroup = Process.THREAD_GROUP_DEFAULT;
13593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013594 }
13595 }
13596 // If the provider has external (non-framework) process
13597 // dependencies, ensure that its adjustment is at least
13598 // FOREGROUND_APP_ADJ.
13599 if (cpr.externals != 0) {
13600 if (adj > FOREGROUND_APP_ADJ) {
13601 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013602 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013603 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013604 app.adjType = "provider";
13605 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013606 }
13607 }
13608 }
13609 }
13610
13611 app.curRawAdj = adj;
13612
13613 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
13614 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13615 if (adj > app.maxAdj) {
13616 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013617 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13618 schedGroup = Process.THREAD_GROUP_DEFAULT;
13619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 }
13621
13622 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013623 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013625 return adj;
13626 }
13627
13628 /**
13629 * Ask a given process to GC right now.
13630 */
13631 final void performAppGcLocked(ProcessRecord app) {
13632 try {
13633 app.lastRequestedGc = SystemClock.uptimeMillis();
13634 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013635 if (app.reportLowMemory) {
13636 app.reportLowMemory = false;
13637 app.thread.scheduleLowMemory();
13638 } else {
13639 app.thread.processInBackground();
13640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013641 }
13642 } catch (Exception e) {
13643 // whatever.
13644 }
13645 }
13646
13647 /**
13648 * Returns true if things are idle enough to perform GCs.
13649 */
13650 private final boolean canGcNow() {
13651 return mParallelBroadcasts.size() == 0
13652 && mOrderedBroadcasts.size() == 0
13653 && (mSleeping || (mResumedActivity != null &&
13654 mResumedActivity.idle));
13655 }
13656
13657 /**
13658 * Perform GCs on all processes that are waiting for it, but only
13659 * if things are idle.
13660 */
13661 final void performAppGcsLocked() {
13662 final int N = mProcessesToGc.size();
13663 if (N <= 0) {
13664 return;
13665 }
13666 if (canGcNow()) {
13667 while (mProcessesToGc.size() > 0) {
13668 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013669 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13670 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13671 <= SystemClock.uptimeMillis()) {
13672 // To avoid spamming the system, we will GC processes one
13673 // at a time, waiting a few seconds between each.
13674 performAppGcLocked(proc);
13675 scheduleAppGcsLocked();
13676 return;
13677 } else {
13678 // It hasn't been long enough since we last GCed this
13679 // process... put it in the list to wait for its time.
13680 addProcessToGcListLocked(proc);
13681 break;
13682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013683 }
13684 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013685
13686 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013687 }
13688 }
13689
13690 /**
13691 * If all looks good, perform GCs on all processes waiting for them.
13692 */
13693 final void performAppGcsIfAppropriateLocked() {
13694 if (canGcNow()) {
13695 performAppGcsLocked();
13696 return;
13697 }
13698 // Still not idle, wait some more.
13699 scheduleAppGcsLocked();
13700 }
13701
13702 /**
13703 * Schedule the execution of all pending app GCs.
13704 */
13705 final void scheduleAppGcsLocked() {
13706 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013707
13708 if (mProcessesToGc.size() > 0) {
13709 // Schedule a GC for the time to the next process.
13710 ProcessRecord proc = mProcessesToGc.get(0);
13711 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13712
13713 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13714 long now = SystemClock.uptimeMillis();
13715 if (when < (now+GC_TIMEOUT)) {
13716 when = now + GC_TIMEOUT;
13717 }
13718 mHandler.sendMessageAtTime(msg, when);
13719 }
13720 }
13721
13722 /**
13723 * Add a process to the array of processes waiting to be GCed. Keeps the
13724 * list in sorted order by the last GC time. The process can't already be
13725 * on the list.
13726 */
13727 final void addProcessToGcListLocked(ProcessRecord proc) {
13728 boolean added = false;
13729 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13730 if (mProcessesToGc.get(i).lastRequestedGc <
13731 proc.lastRequestedGc) {
13732 added = true;
13733 mProcessesToGc.add(i+1, proc);
13734 break;
13735 }
13736 }
13737 if (!added) {
13738 mProcessesToGc.add(0, proc);
13739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013740 }
13741
13742 /**
13743 * Set up to ask a process to GC itself. This will either do it
13744 * immediately, or put it on the list of processes to gc the next
13745 * time things are idle.
13746 */
13747 final void scheduleAppGcLocked(ProcessRecord app) {
13748 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013749 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013750 return;
13751 }
13752 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013753 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013754 scheduleAppGcsLocked();
13755 }
13756 }
13757
13758 private final boolean updateOomAdjLocked(
13759 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13760 app.hiddenAdj = hiddenAdj;
13761
13762 if (app.thread == null) {
13763 return true;
13764 }
13765
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013766 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013767
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013768 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013769 if (app.curRawAdj != app.setRawAdj) {
13770 if (app.curRawAdj > FOREGROUND_APP_ADJ
13771 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13772 // If this app is transitioning from foreground to
13773 // non-foreground, have it do a gc.
13774 scheduleAppGcLocked(app);
13775 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13776 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13777 // Likewise do a gc when an app is moving in to the
13778 // background (such as a service stopping).
13779 scheduleAppGcLocked(app);
13780 }
13781 app.setRawAdj = app.curRawAdj;
13782 }
13783 if (adj != app.setAdj) {
13784 if (Process.setOomAdj(app.pid, adj)) {
13785 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
13786 TAG, "Set app " + app.processName +
13787 " oom adj to " + adj);
13788 app.setAdj = adj;
13789 } else {
13790 return false;
13791 }
13792 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013793 if (app.setSchedGroup != app.curSchedGroup) {
13794 app.setSchedGroup = app.curSchedGroup;
13795 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG,
13796 "Setting process group of " + app.processName
13797 + " to " + app.curSchedGroup);
13798 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013799 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013800 try {
13801 Process.setProcessGroup(app.pid, app.curSchedGroup);
13802 } catch (Exception e) {
13803 Log.w(TAG, "Failed setting process group of " + app.pid
13804 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013805 e.printStackTrace();
13806 } finally {
13807 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013808 }
13809 }
13810 if (false) {
13811 if (app.thread != null) {
13812 try {
13813 app.thread.setSchedulingGroup(app.curSchedGroup);
13814 } catch (RemoteException e) {
13815 }
13816 }
13817 }
13818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013819 }
13820
13821 return true;
13822 }
13823
13824 private final HistoryRecord resumedAppLocked() {
13825 HistoryRecord resumedActivity = mResumedActivity;
13826 if (resumedActivity == null || resumedActivity.app == null) {
13827 resumedActivity = mPausingActivity;
13828 if (resumedActivity == null || resumedActivity.app == null) {
13829 resumedActivity = topRunningActivityLocked(null);
13830 }
13831 }
13832 return resumedActivity;
13833 }
13834
13835 private final boolean updateOomAdjLocked(ProcessRecord app) {
13836 final HistoryRecord TOP_ACT = resumedAppLocked();
13837 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13838 int curAdj = app.curAdj;
13839 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13840 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13841
13842 mAdjSeq++;
13843
13844 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13845 if (res) {
13846 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13847 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13848 if (nowHidden != wasHidden) {
13849 // Changed to/from hidden state, so apps after it in the LRU
13850 // list may also be changed.
13851 updateOomAdjLocked();
13852 }
13853 }
13854 return res;
13855 }
13856
13857 private final boolean updateOomAdjLocked() {
13858 boolean didOomAdj = true;
13859 final HistoryRecord TOP_ACT = resumedAppLocked();
13860 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13861
13862 if (false) {
13863 RuntimeException e = new RuntimeException();
13864 e.fillInStackTrace();
13865 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
13866 }
13867
13868 mAdjSeq++;
13869
13870 // First try updating the OOM adjustment for each of the
13871 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013872 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13874 while (i > 0) {
13875 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013876 ProcessRecord app = mLruProcesses.get(i);
13877 //Log.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013878 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013879 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013880 && app.curAdj == curHiddenAdj) {
13881 curHiddenAdj++;
13882 }
13883 } else {
13884 didOomAdj = false;
13885 }
13886 }
13887
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013888 // If we return false, we will fall back on killing processes to
13889 // have a fixed limit. Do this if a limit has been requested; else
13890 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013891 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13892 }
13893
13894 private final void trimApplications() {
13895 synchronized (this) {
13896 int i;
13897
13898 // First remove any unused application processes whose package
13899 // has been removed.
13900 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13901 final ProcessRecord app = mRemovedProcesses.get(i);
13902 if (app.activities.size() == 0
13903 && app.curReceiver == null && app.services.size() == 0) {
13904 Log.i(
13905 TAG, "Exiting empty application process "
13906 + app.processName + " ("
13907 + (app.thread != null ? app.thread.asBinder() : null)
13908 + ")\n");
13909 if (app.pid > 0 && app.pid != MY_PID) {
13910 Process.killProcess(app.pid);
13911 } else {
13912 try {
13913 app.thread.scheduleExit();
13914 } catch (Exception e) {
13915 // Ignore exceptions.
13916 }
13917 }
13918 cleanUpApplicationRecordLocked(app, false, -1);
13919 mRemovedProcesses.remove(i);
13920
13921 if (app.persistent) {
13922 if (app.persistent) {
13923 addAppLocked(app.info);
13924 }
13925 }
13926 }
13927 }
13928
13929 // Now try updating the OOM adjustment for each of the
13930 // application processes based on their current state.
13931 // If the setOomAdj() API is not supported, then go with our
13932 // back-up plan...
13933 if (!updateOomAdjLocked()) {
13934
13935 // Count how many processes are running services.
13936 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013937 for (i=mLruProcesses.size()-1; i>=0; i--) {
13938 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013939
13940 if (app.persistent || app.services.size() != 0
13941 || app.curReceiver != null
13942 || app.persistentActivities > 0) {
13943 // Don't count processes holding services against our
13944 // maximum process count.
13945 if (localLOGV) Log.v(
13946 TAG, "Not trimming app " + app + " with services: "
13947 + app.services);
13948 numServiceProcs++;
13949 }
13950 }
13951
13952 int curMaxProcs = mProcessLimit;
13953 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13954 if (mAlwaysFinishActivities) {
13955 curMaxProcs = 1;
13956 }
13957 curMaxProcs += numServiceProcs;
13958
13959 // Quit as many processes as we can to get down to the desired
13960 // process count. First remove any processes that no longer
13961 // have activites running in them.
13962 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013963 i<mLruProcesses.size()
13964 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013965 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013966 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013967 // Quit an application only if it is not currently
13968 // running any activities.
13969 if (!app.persistent && app.activities.size() == 0
13970 && app.curReceiver == null && app.services.size() == 0) {
13971 Log.i(
13972 TAG, "Exiting empty application process "
13973 + app.processName + " ("
13974 + (app.thread != null ? app.thread.asBinder() : null)
13975 + ")\n");
13976 if (app.pid > 0 && app.pid != MY_PID) {
13977 Process.killProcess(app.pid);
13978 } else {
13979 try {
13980 app.thread.scheduleExit();
13981 } catch (Exception e) {
13982 // Ignore exceptions.
13983 }
13984 }
13985 // todo: For now we assume the application is not buggy
13986 // or evil, and will quit as a result of our request.
13987 // Eventually we need to drive this off of the death
13988 // notification, and kill the process if it takes too long.
13989 cleanUpApplicationRecordLocked(app, false, i);
13990 i--;
13991 }
13992 }
13993
13994 // If we still have too many processes, now from the least
13995 // recently used process we start finishing activities.
13996 if (Config.LOGV) Log.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013997 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013998 " of " + curMaxProcs + " processes");
13999 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014000 i<mLruProcesses.size()
14001 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014002 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014003 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014004 // Quit the application only if we have a state saved for
14005 // all of its activities.
14006 boolean canQuit = !app.persistent && app.curReceiver == null
14007 && app.services.size() == 0
14008 && app.persistentActivities == 0;
14009 int NUMA = app.activities.size();
14010 int j;
14011 if (Config.LOGV) Log.v(
14012 TAG, "Looking to quit " + app.processName);
14013 for (j=0; j<NUMA && canQuit; j++) {
14014 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14015 if (Config.LOGV) Log.v(
14016 TAG, " " + r.intent.getComponent().flattenToShortString()
14017 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14018 canQuit = (r.haveState || !r.stateNotNeeded)
14019 && !r.visible && r.stopped;
14020 }
14021 if (canQuit) {
14022 // Finish all of the activities, and then the app itself.
14023 for (j=0; j<NUMA; j++) {
14024 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14025 if (!r.finishing) {
14026 destroyActivityLocked(r, false);
14027 }
14028 r.resultTo = null;
14029 }
14030 Log.i(TAG, "Exiting application process "
14031 + app.processName + " ("
14032 + (app.thread != null ? app.thread.asBinder() : null)
14033 + ")\n");
14034 if (app.pid > 0 && app.pid != MY_PID) {
14035 Process.killProcess(app.pid);
14036 } else {
14037 try {
14038 app.thread.scheduleExit();
14039 } catch (Exception e) {
14040 // Ignore exceptions.
14041 }
14042 }
14043 // todo: For now we assume the application is not buggy
14044 // or evil, and will quit as a result of our request.
14045 // Eventually we need to drive this off of the death
14046 // notification, and kill the process if it takes too long.
14047 cleanUpApplicationRecordLocked(app, false, i);
14048 i--;
14049 //dump();
14050 }
14051 }
14052
14053 }
14054
14055 int curMaxActivities = MAX_ACTIVITIES;
14056 if (mAlwaysFinishActivities) {
14057 curMaxActivities = 1;
14058 }
14059
14060 // Finally, if there are too many activities now running, try to
14061 // finish as many as we can to get back down to the limit.
14062 for ( i=0;
14063 i<mLRUActivities.size()
14064 && mLRUActivities.size() > curMaxActivities;
14065 i++) {
14066 final HistoryRecord r
14067 = (HistoryRecord)mLRUActivities.get(i);
14068
14069 // We can finish this one if we have its icicle saved and
14070 // it is not persistent.
14071 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14072 && r.stopped && !r.persistent && !r.finishing) {
14073 final int origSize = mLRUActivities.size();
14074 destroyActivityLocked(r, true);
14075
14076 // This will remove it from the LRU list, so keep
14077 // our index at the same value. Note that this check to
14078 // see if the size changes is just paranoia -- if
14079 // something unexpected happens, we don't want to end up
14080 // in an infinite loop.
14081 if (origSize > mLRUActivities.size()) {
14082 i--;
14083 }
14084 }
14085 }
14086 }
14087 }
14088
14089 /** This method sends the specified signal to each of the persistent apps */
14090 public void signalPersistentProcesses(int sig) throws RemoteException {
14091 if (sig != Process.SIGNAL_USR1) {
14092 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14093 }
14094
14095 synchronized (this) {
14096 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14097 != PackageManager.PERMISSION_GRANTED) {
14098 throw new SecurityException("Requires permission "
14099 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14100 }
14101
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014102 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14103 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014104 if (r.thread != null && r.persistent) {
14105 Process.sendSignal(r.pid, sig);
14106 }
14107 }
14108 }
14109 }
14110
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014111 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014112 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014113
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014114 try {
14115 synchronized (this) {
14116 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14117 // its own permission.
14118 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14119 != PackageManager.PERMISSION_GRANTED) {
14120 throw new SecurityException("Requires permission "
14121 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014122 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014123
14124 if (start && fd == null) {
14125 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014126 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014127
14128 ProcessRecord proc = null;
14129 try {
14130 int pid = Integer.parseInt(process);
14131 synchronized (mPidsSelfLocked) {
14132 proc = mPidsSelfLocked.get(pid);
14133 }
14134 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014135 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014136
14137 if (proc == null) {
14138 HashMap<String, SparseArray<ProcessRecord>> all
14139 = mProcessNames.getMap();
14140 SparseArray<ProcessRecord> procs = all.get(process);
14141 if (procs != null && procs.size() > 0) {
14142 proc = procs.valueAt(0);
14143 }
14144 }
14145
14146 if (proc == null || proc.thread == null) {
14147 throw new IllegalArgumentException("Unknown process: " + process);
14148 }
14149
14150 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14151 if (isSecure) {
14152 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14153 throw new SecurityException("Process not debuggable: " + proc);
14154 }
14155 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014156
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014157 proc.thread.profilerControl(start, path, fd);
14158 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014159 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014160 }
14161 } catch (RemoteException e) {
14162 throw new IllegalStateException("Process disappeared");
14163 } finally {
14164 if (fd != null) {
14165 try {
14166 fd.close();
14167 } catch (IOException e) {
14168 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014169 }
14170 }
14171 }
14172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014173 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14174 public void monitor() {
14175 synchronized (this) { }
14176 }
14177}