blob: 5b37f477727d504c8af85ed6256d946f40ed6866 [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;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080050import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.ComponentName;
52import android.content.ContentResolver;
53import android.content.Context;
54import android.content.Intent;
55import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070056import android.content.IIntentReceiver;
57import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070058import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.pm.ActivityInfo;
60import android.content.pm.ApplicationInfo;
61import android.content.pm.ConfigurationInfo;
62import android.content.pm.IPackageDataObserver;
63import android.content.pm.IPackageManager;
64import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080065import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070067import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.content.pm.ProviderInfo;
69import android.content.pm.ResolveInfo;
70import android.content.pm.ServiceInfo;
71import android.content.res.Configuration;
72import android.graphics.Bitmap;
73import android.net.Uri;
74import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080075import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080076import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070077import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080078import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080080import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.os.FileUtils;
82import android.os.Handler;
83import android.os.IBinder;
84import android.os.IPermissionController;
85import android.os.Looper;
86import android.os.Message;
87import android.os.Parcel;
88import android.os.ParcelFileDescriptor;
89import android.os.PowerManager;
90import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070091import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.RemoteException;
93import android.os.ServiceManager;
94import android.os.SystemClock;
95import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.util.Config;
98import android.util.EventLog;
99import android.util.Log;
100import android.util.PrintWriterPrinter;
101import android.util.SparseArray;
102import android.view.Gravity;
103import android.view.LayoutInflater;
104import android.view.View;
105import android.view.WindowManager;
106import android.view.WindowManagerPolicy;
107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.io.File;
109import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200111import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.PrintWriter;
113import java.lang.IllegalStateException;
114import java.lang.ref.WeakReference;
115import java.util.ArrayList;
116import java.util.HashMap;
117import java.util.HashSet;
118import java.util.Iterator;
119import java.util.List;
120import java.util.Locale;
121import java.util.Map;
122
123public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
124 static final String TAG = "ActivityManager";
125 static final boolean DEBUG = false;
126 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
127 static final boolean DEBUG_SWITCH = localLOGV || false;
128 static final boolean DEBUG_TASKS = localLOGV || false;
129 static final boolean DEBUG_PAUSE = localLOGV || false;
130 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
131 static final boolean DEBUG_TRANSITION = localLOGV || false;
132 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700133 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 static final boolean DEBUG_SERVICE = localLOGV || false;
135 static final boolean DEBUG_VISBILITY = localLOGV || false;
136 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700137 static final boolean DEBUG_PROVIDER = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700139 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700140 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700141 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 static final boolean VALIDATE_TOKENS = false;
143 static final boolean SHOW_ACTIVITY_START_TIME = true;
144
145 // Control over CPU and battery monitoring.
146 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
147 static final boolean MONITOR_CPU_USAGE = true;
148 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
149 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
150 static final boolean MONITOR_THREAD_CPU_USAGE = false;
151
Dianne Hackborn1655be42009-05-08 14:29:01 -0700152 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700153 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 private static final String SYSTEM_SECURE = "ro.secure";
156
157 // This is the maximum number of application processes we would like
158 // to have running. Due to the asynchronous nature of things, we can
159 // temporarily go beyond this limit.
160 static final int MAX_PROCESSES = 2;
161
162 // Set to false to leave processes running indefinitely, relying on
163 // the kernel killing them as resources are required.
164 static final boolean ENFORCE_PROCESS_LIMIT = false;
165
166 // This is the maximum number of activities that we would like to have
167 // running at a given time.
168 static final int MAX_ACTIVITIES = 20;
169
170 // Maximum number of recent tasks that we can remember.
171 static final int MAX_RECENT_TASKS = 20;
172
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700173 // Amount of time after a call to stopAppSwitches() during which we will
174 // prevent further untrusted switches from happening.
175 static final long APP_SWITCH_DELAY_TIME = 5*1000;
176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 // How long until we reset a task when the user returns to it. Currently
178 // 30 minutes.
179 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
180
181 // Set to true to disable the icon that is shown while a new activity
182 // is being started.
183 static final boolean SHOW_APP_STARTING_ICON = true;
184
185 // How long we wait until giving up on the last activity to pause. This
186 // is short because it directly impacts the responsiveness of starting the
187 // next activity.
188 static final int PAUSE_TIMEOUT = 500;
189
190 /**
191 * How long we can hold the launch wake lock before giving up.
192 */
193 static final int LAUNCH_TIMEOUT = 10*1000;
194
195 // How long we wait for a launched process to attach to the activity manager
196 // before we decide it's never going to come up for real.
197 static final int PROC_START_TIMEOUT = 10*1000;
198
199 // How long we wait until giving up on the last activity telling us it
200 // is idle.
201 static final int IDLE_TIMEOUT = 10*1000;
202
203 // How long to wait after going idle before forcing apps to GC.
204 static final int GC_TIMEOUT = 5*1000;
205
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700206 // The minimum amount of time between successive GC requests for a process.
207 static final int GC_MIN_INTERVAL = 60*1000;
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // How long we wait until giving up on an activity telling us it has
210 // finished destroying itself.
211 static final int DESTROY_TIMEOUT = 10*1000;
212
213 // How long we allow a receiver to run before giving up on it.
214 static final int BROADCAST_TIMEOUT = 10*1000;
215
216 // How long we wait for a service to finish executing.
217 static final int SERVICE_TIMEOUT = 20*1000;
218
219 // How long a service needs to be running until restarting its process
220 // is no longer considered to be a relaunch of the service.
221 static final int SERVICE_RESTART_DURATION = 5*1000;
222
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700223 // How long a service needs to be running until it will start back at
224 // SERVICE_RESTART_DURATION after being killed.
225 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
226
227 // Multiplying factor to increase restart duration time by, for each time
228 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
229 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
230
231 // The minimum amount of time between restarting services that we allow.
232 // That is, when multiple services are restarting, we won't allow each
233 // to restart less than this amount of time from the last one.
234 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 // Maximum amount of time for there to be no activity on a service before
237 // we consider it non-essential and allow its process to go on the
238 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700239 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240
241 // How long we wait until we timeout on key dispatching.
242 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
243
244 // The minimum time we allow between crashes, for us to consider this
245 // application to be bad and stop and its services and reject broadcasts.
246 static final int MIN_CRASH_INTERVAL = 60*1000;
247
248 // How long we wait until we timeout on key dispatching during instrumentation.
249 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
250
251 // OOM adjustments for processes in various states:
252
253 // This is a process without anything currently running in it. Definitely
254 // the first to go! Value set in system/rootdir/init.rc on startup.
255 // This value is initalized in the constructor, careful when refering to
256 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800257 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258
259 // This is a process only hosting activities that are not visible,
260 // so it can be killed without any disruption. Value set in
261 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800262 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 static int HIDDEN_APP_MIN_ADJ;
264
The Android Open Source Project4df24232009-03-05 14:34:35 -0800265 // This is a process holding the home application -- we want to try
266 // avoiding killing it, even if it would normally be in the background,
267 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800268 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800269
Christopher Tate6fa95972009-06-05 18:43:55 -0700270 // This is a process currently hosting a backup operation. Killing it
271 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 // This is a process holding a secondary server -- killing it will not
275 // have much of an impact as far as the user is concerned. Value set in
276 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800277 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278
279 // This is a process only hosting activities that are visible to the
280 // user, so we'd prefer they don't disappear. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is the process running the current foreground app. We'd really
285 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is a process running a core server, such as telephony. Definitely
289 // don't want to kill it, but doing so is not completely fatal.
290 static final int CORE_SERVER_ADJ = -12;
291
292 // The system process runs at the default adjustment.
293 static final int SYSTEM_ADJ = -16;
294
295 // Memory pages are 4K.
296 static final int PAGE_SIZE = 4*1024;
297
298 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800299 static final int EMPTY_APP_MEM;
300 static final int HIDDEN_APP_MEM;
301 static final int HOME_APP_MEM;
302 static final int BACKUP_APP_MEM;
303 static final int SECONDARY_SERVER_MEM;
304 static final int VISIBLE_APP_MEM;
305 static final int FOREGROUND_APP_MEM;
306
307 // The minimum number of hidden apps we want to be able to keep around,
308 // without empty apps being able to push them out of memory.
309 static final int MIN_HIDDEN_APPS = 2;
310
311 // We put empty content processes after any hidden processes that have
312 // been idle for less than 30 seconds.
313 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
314
315 // We put empty content processes after any hidden processes that have
316 // been idle for less than 60 seconds.
317 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
318
319 static {
320 // These values are set in system/rootdir/init.rc on startup.
321 FOREGROUND_APP_ADJ =
322 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
323 VISIBLE_APP_ADJ =
324 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
325 SECONDARY_SERVER_ADJ =
326 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
327 BACKUP_APP_ADJ =
328 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
329 HOME_APP_ADJ =
330 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
331 HIDDEN_APP_MIN_ADJ =
332 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
333 EMPTY_APP_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
335 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
336 FOREGROUND_APP_MEM =
337 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
338 VISIBLE_APP_MEM =
339 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
340 SECONDARY_SERVER_MEM =
341 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
342 BACKUP_APP_MEM =
343 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
344 HOME_APP_MEM =
345 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
346 HIDDEN_APP_MEM =
347 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
348 EMPTY_APP_MEM =
349 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351
Dan Egnor42471dd2010-01-07 17:25:22 -0800352 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353
354 static final String[] EMPTY_STRING_ARRAY = new String[0];
355
356 enum ActivityState {
357 INITIALIZING,
358 RESUMED,
359 PAUSING,
360 PAUSED,
361 STOPPING,
362 STOPPED,
363 FINISHING,
364 DESTROYING,
365 DESTROYED
366 }
367
368 /**
369 * The back history of all previous (and possibly still
370 * running) activities. It contains HistoryRecord objects.
371 */
372 final ArrayList mHistory = new ArrayList();
373
374 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700375 * Description of a request to start a new activity, which has been held
376 * due to app switches being disabled.
377 */
378 class PendingActivityLaunch {
379 HistoryRecord r;
380 HistoryRecord sourceRecord;
381 Uri[] grantedUriPermissions;
382 int grantedMode;
383 boolean onlyIfNeeded;
384 }
385
386 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
387 = new ArrayList<PendingActivityLaunch>();
388
389 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 * List of all active broadcasts that are to be executed immediately
391 * (without waiting for another broadcast to finish). Currently this only
392 * contains broadcasts to registered receivers, to avoid spinning up
393 * a bunch of processes to execute IntentReceiver components.
394 */
395 final ArrayList<BroadcastRecord> mParallelBroadcasts
396 = new ArrayList<BroadcastRecord>();
397
398 /**
399 * List of all active broadcasts that are to be executed one at a time.
400 * The object at the top of the list is the currently activity broadcasts;
401 * those after it are waiting for the top to finish..
402 */
403 final ArrayList<BroadcastRecord> mOrderedBroadcasts
404 = new ArrayList<BroadcastRecord>();
405
406 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800407 * Historical data of past broadcasts, for debugging.
408 */
409 static final int MAX_BROADCAST_HISTORY = 100;
410 final BroadcastRecord[] mBroadcastHistory
411 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
412
413 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * Set when we current have a BROADCAST_INTENT_MSG in flight.
415 */
416 boolean mBroadcastsScheduled = false;
417
418 /**
419 * Set to indicate whether to issue an onUserLeaving callback when a
420 * newly launched activity is being brought in front of us.
421 */
422 boolean mUserLeaving = false;
423
424 /**
425 * When we are in the process of pausing an activity, before starting the
426 * next one, this variable holds the activity that is currently being paused.
427 */
428 HistoryRecord mPausingActivity = null;
429
430 /**
431 * Current activity that is resumed, or null if there is none.
432 */
433 HistoryRecord mResumedActivity = null;
434
435 /**
436 * Activity we have told the window manager to have key focus.
437 */
438 HistoryRecord mFocusedActivity = null;
439
440 /**
441 * This is the last activity that we put into the paused state. This is
442 * used to determine if we need to do an activity transition while sleeping,
443 * when we normally hold the top activity paused.
444 */
445 HistoryRecord mLastPausedActivity = null;
446
447 /**
448 * List of activities that are waiting for a new activity
449 * to become visible before completing whatever operation they are
450 * supposed to do.
451 */
452 final ArrayList mWaitingVisibleActivities = new ArrayList();
453
454 /**
455 * List of activities that are ready to be stopped, but waiting
456 * for the next activity to settle down before doing so. It contains
457 * HistoryRecord objects.
458 */
459 final ArrayList<HistoryRecord> mStoppingActivities
460 = new ArrayList<HistoryRecord>();
461
462 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700463 * Animations that for the current transition have requested not to
464 * be considered for the transition animation.
465 */
466 final ArrayList<HistoryRecord> mNoAnimActivities
467 = new ArrayList<HistoryRecord>();
468
469 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 * List of intents that were used to start the most recent tasks.
471 */
472 final ArrayList<TaskRecord> mRecentTasks
473 = new ArrayList<TaskRecord>();
474
475 /**
476 * List of activities that are ready to be finished, but waiting
477 * for the previous activity to settle down before doing so. It contains
478 * HistoryRecord objects.
479 */
480 final ArrayList mFinishingActivities = new ArrayList();
481
482 /**
483 * All of the applications we currently have running organized by name.
484 * The keys are strings of the application package name (as
485 * returned by the package manager), and the keys are ApplicationRecord
486 * objects.
487 */
488 final ProcessMap<ProcessRecord> mProcessNames
489 = new ProcessMap<ProcessRecord>();
490
491 /**
492 * The last time that various processes have crashed.
493 */
494 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
495
496 /**
497 * Set of applications that we consider to be bad, and will reject
498 * incoming broadcasts from (which the user has no control over).
499 * Processes are added to this set when they have crashed twice within
500 * a minimum amount of time; they are removed from it when they are
501 * later restarted (hopefully due to some user action). The value is the
502 * time it was added to the list.
503 */
504 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
505
506 /**
507 * All of the processes we currently have running organized by pid.
508 * The keys are the pid running the application.
509 *
510 * <p>NOTE: This object is protected by its own lock, NOT the global
511 * activity manager lock!
512 */
513 final SparseArray<ProcessRecord> mPidsSelfLocked
514 = new SparseArray<ProcessRecord>();
515
516 /**
517 * All of the processes that have been forced to be foreground. The key
518 * is the pid of the caller who requested it (we hold a death
519 * link on it).
520 */
521 abstract class ForegroundToken implements IBinder.DeathRecipient {
522 int pid;
523 IBinder token;
524 }
525 final SparseArray<ForegroundToken> mForegroundProcesses
526 = new SparseArray<ForegroundToken>();
527
528 /**
529 * List of records for processes that someone had tried to start before the
530 * system was ready. We don't start them at that point, but ensure they
531 * are started by the time booting is complete.
532 */
533 final ArrayList<ProcessRecord> mProcessesOnHold
534 = new ArrayList<ProcessRecord>();
535
536 /**
537 * List of records for processes that we have started and are waiting
538 * for them to call back. This is really only needed when running in
539 * single processes mode, in which case we do not have a unique pid for
540 * each process.
541 */
542 final ArrayList<ProcessRecord> mStartingProcesses
543 = new ArrayList<ProcessRecord>();
544
545 /**
546 * List of persistent applications that are in the process
547 * of being started.
548 */
549 final ArrayList<ProcessRecord> mPersistentStartingProcesses
550 = new ArrayList<ProcessRecord>();
551
552 /**
553 * Processes that are being forcibly torn down.
554 */
555 final ArrayList<ProcessRecord> mRemovedProcesses
556 = new ArrayList<ProcessRecord>();
557
558 /**
559 * List of running applications, sorted by recent usage.
560 * The first entry in the list is the least recently used.
561 * It contains ApplicationRecord objects. This list does NOT include
562 * any persistent application records (since we never want to exit them).
563 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800564 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 = new ArrayList<ProcessRecord>();
566
567 /**
568 * List of processes that should gc as soon as things are idle.
569 */
570 final ArrayList<ProcessRecord> mProcessesToGc
571 = new ArrayList<ProcessRecord>();
572
573 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800574 * This is the process holding what we currently consider to be
575 * the "home" activity.
576 */
577 private ProcessRecord mHomeProcess;
578
579 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 * List of running activities, sorted by recent usage.
581 * The first entry in the list is the least recently used.
582 * It contains HistoryRecord objects.
583 */
584 private final ArrayList mLRUActivities = new ArrayList();
585
586 /**
587 * Set of PendingResultRecord objects that are currently active.
588 */
589 final HashSet mPendingResultRecords = new HashSet();
590
591 /**
592 * Set of IntentSenderRecord objects that are currently active.
593 */
594 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
595 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
596
597 /**
598 * Intent broadcast that we have tried to start, but are
599 * waiting for its application's process to be created. We only
600 * need one (instead of a list) because we always process broadcasts
601 * one at a time, so no others can be started while waiting for this
602 * one.
603 */
604 BroadcastRecord mPendingBroadcast = null;
605
606 /**
607 * Keeps track of all IIntentReceivers that have been registered for
608 * broadcasts. Hash keys are the receiver IBinder, hash value is
609 * a ReceiverList.
610 */
611 final HashMap mRegisteredReceivers = new HashMap();
612
613 /**
614 * Resolver for broadcast intents to registered receivers.
615 * Holds BroadcastFilter (subclass of IntentFilter).
616 */
617 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
618 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
619 @Override
620 protected boolean allowFilterResult(
621 BroadcastFilter filter, List<BroadcastFilter> dest) {
622 IBinder target = filter.receiverList.receiver.asBinder();
623 for (int i=dest.size()-1; i>=0; i--) {
624 if (dest.get(i).receiverList.receiver.asBinder() == target) {
625 return false;
626 }
627 }
628 return true;
629 }
630 };
631
632 /**
633 * State of all active sticky broadcasts. Keys are the action of the
634 * sticky Intent, values are an ArrayList of all broadcasted intents with
635 * that action (which should usually be one).
636 */
637 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
638 new HashMap<String, ArrayList<Intent>>();
639
640 /**
641 * All currently running services.
642 */
643 final HashMap<ComponentName, ServiceRecord> mServices =
644 new HashMap<ComponentName, ServiceRecord>();
645
646 /**
647 * All currently running services indexed by the Intent used to start them.
648 */
649 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
650 new HashMap<Intent.FilterComparison, ServiceRecord>();
651
652 /**
653 * All currently bound service connections. Keys are the IBinder of
654 * the client's IServiceConnection.
655 */
656 final HashMap<IBinder, ConnectionRecord> mServiceConnections
657 = new HashMap<IBinder, ConnectionRecord>();
658
659 /**
660 * List of services that we have been asked to start,
661 * but haven't yet been able to. It is used to hold start requests
662 * while waiting for their corresponding application thread to get
663 * going.
664 */
665 final ArrayList<ServiceRecord> mPendingServices
666 = new ArrayList<ServiceRecord>();
667
668 /**
669 * List of services that are scheduled to restart following a crash.
670 */
671 final ArrayList<ServiceRecord> mRestartingServices
672 = new ArrayList<ServiceRecord>();
673
674 /**
675 * List of services that are in the process of being stopped.
676 */
677 final ArrayList<ServiceRecord> mStoppingServices
678 = new ArrayList<ServiceRecord>();
679
680 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700681 * Backup/restore process management
682 */
683 String mBackupAppName = null;
684 BackupRecord mBackupTarget = null;
685
686 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 * List of PendingThumbnailsRecord objects of clients who are still
688 * waiting to receive all of the thumbnails for a task.
689 */
690 final ArrayList mPendingThumbnails = new ArrayList();
691
692 /**
693 * List of HistoryRecord objects that have been finished and must
694 * still report back to a pending thumbnail receiver.
695 */
696 final ArrayList mCancelledThumbnails = new ArrayList();
697
698 /**
699 * All of the currently running global content providers. Keys are a
700 * string containing the provider name and values are a
701 * ContentProviderRecord object containing the data about it. Note
702 * that a single provider may be published under multiple names, so
703 * there may be multiple entries here for a single one in mProvidersByClass.
704 */
705 final HashMap mProvidersByName = new HashMap();
706
707 /**
708 * All of the currently running global content providers. Keys are a
709 * string containing the provider's implementation class and values are a
710 * ContentProviderRecord object containing the data about it.
711 */
712 final HashMap mProvidersByClass = new HashMap();
713
714 /**
715 * List of content providers who have clients waiting for them. The
716 * application is currently being launched and the provider will be
717 * removed from this list once it is published.
718 */
719 final ArrayList mLaunchingProviders = new ArrayList();
720
721 /**
722 * Global set of specific Uri permissions that have been granted.
723 */
724 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
725 = new SparseArray<HashMap<Uri, UriPermission>>();
726
727 /**
728 * Thread-local storage used to carry caller permissions over through
729 * indirect content-provider access.
730 * @see #ActivityManagerService.openContentUri()
731 */
732 private class Identity {
733 public int pid;
734 public int uid;
735
736 Identity(int _pid, int _uid) {
737 pid = _pid;
738 uid = _uid;
739 }
740 }
741 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
742
743 /**
744 * All information we have collected about the runtime performance of
745 * any user id that can impact battery performance.
746 */
747 final BatteryStatsService mBatteryStatsService;
748
749 /**
750 * information about component usage
751 */
752 final UsageStatsService mUsageStatsService;
753
754 /**
755 * Current configuration information. HistoryRecord objects are given
756 * a reference to this object to indicate which configuration they are
757 * currently running in, so this object must be kept immutable.
758 */
759 Configuration mConfiguration = new Configuration();
760
761 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800762 * Current sequencing integer of the configuration, for skipping old
763 * configurations.
764 */
765 int mConfigurationSeq = 0;
766
767 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700768 * Hardware-reported OpenGLES version.
769 */
770 final int GL_ES_VERSION;
771
772 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 * List of initialization arguments to pass to all processes when binding applications to them.
774 * For example, references to the commonly used services.
775 */
776 HashMap<String, IBinder> mAppBindArgs;
777
778 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700779 * Temporary to avoid allocations. Protected by main lock.
780 */
781 final StringBuilder mStringBuilder = new StringBuilder(256);
782
783 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 * Used to control how we initialize the service.
785 */
786 boolean mStartRunning = false;
787 ComponentName mTopComponent;
788 String mTopAction;
789 String mTopData;
790 boolean mSystemReady = false;
791 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700792 boolean mWaitingUpdate = false;
793 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794
795 Context mContext;
796
797 int mFactoryTest;
798
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700799 boolean mCheckedForSetup;
800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700802 * The time at which we will allow normal application switches again,
803 * after a call to {@link #stopAppSwitches()}.
804 */
805 long mAppSwitchesAllowedTime;
806
807 /**
808 * This is set to true after the first switch after mAppSwitchesAllowedTime
809 * is set; any switches after that will clear the time.
810 */
811 boolean mDidAppSwitch;
812
813 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 * Set while we are wanting to sleep, to prevent any
815 * activities from being started/resumed.
816 */
817 boolean mSleeping = false;
818
819 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700820 * Set if we are shutting down the system, similar to sleeping.
821 */
822 boolean mShuttingDown = false;
823
824 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 * Set when the system is going to sleep, until we have
826 * successfully paused the current activity and released our wake lock.
827 * At that point the system is allowed to actually sleep.
828 */
829 PowerManager.WakeLock mGoingToSleep;
830
831 /**
832 * We don't want to allow the device to go to sleep while in the process
833 * of launching an activity. This is primarily to allow alarm intent
834 * receivers to launch an activity and get that to run before the device
835 * goes back to sleep.
836 */
837 PowerManager.WakeLock mLaunchingActivity;
838
839 /**
840 * Task identifier that activities are currently being started
841 * in. Incremented each time a new task is created.
842 * todo: Replace this with a TokenSpace class that generates non-repeating
843 * integers that won't wrap.
844 */
845 int mCurTask = 1;
846
847 /**
848 * Current sequence id for oom_adj computation traversal.
849 */
850 int mAdjSeq = 0;
851
852 /**
853 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
854 * is set, indicating the user wants processes started in such a way
855 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
856 * running in each process (thus no pre-initialized process, etc).
857 */
858 boolean mSimpleProcessManagement = false;
859
860 /**
861 * System monitoring: number of processes that died since the last
862 * N procs were started.
863 */
864 int[] mProcDeaths = new int[20];
865
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700866 /**
867 * This is set if we had to do a delayed dexopt of an app before launching
868 * it, to increasing the ANR timeouts in that case.
869 */
870 boolean mDidDexOpt;
871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 String mDebugApp = null;
873 boolean mWaitForDebugger = false;
874 boolean mDebugTransient = false;
875 String mOrigDebugApp = null;
876 boolean mOrigWaitForDebugger = false;
877 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700878 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700880 final RemoteCallbackList<IActivityWatcher> mWatchers
881 = new RemoteCallbackList<IActivityWatcher>();
882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 /**
884 * Callback of last caller to {@link #requestPss}.
885 */
886 Runnable mRequestPssCallback;
887
888 /**
889 * Remaining processes for which we are waiting results from the last
890 * call to {@link #requestPss}.
891 */
892 final ArrayList<ProcessRecord> mRequestPssList
893 = new ArrayList<ProcessRecord>();
894
895 /**
896 * Runtime statistics collection thread. This object's lock is used to
897 * protect all related state.
898 */
899 final Thread mProcessStatsThread;
900
901 /**
902 * Used to collect process stats when showing not responding dialog.
903 * Protected by mProcessStatsThread.
904 */
905 final ProcessStats mProcessStats = new ProcessStats(
906 MONITOR_THREAD_CPU_USAGE);
907 long mLastCpuTime = 0;
908 long mLastWriteTime = 0;
909
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700910 long mInitialStartTime = 0;
911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 /**
913 * Set to true after the system has finished booting.
914 */
915 boolean mBooted = false;
916
917 int mProcessLimit = 0;
918
919 WindowManagerService mWindowManager;
920
921 static ActivityManagerService mSelf;
922 static ActivityThread mSystemThread;
923
924 private final class AppDeathRecipient implements IBinder.DeathRecipient {
925 final ProcessRecord mApp;
926 final int mPid;
927 final IApplicationThread mAppThread;
928
929 AppDeathRecipient(ProcessRecord app, int pid,
930 IApplicationThread thread) {
931 if (localLOGV) Log.v(
932 TAG, "New death recipient " + this
933 + " for thread " + thread.asBinder());
934 mApp = app;
935 mPid = pid;
936 mAppThread = thread;
937 }
938
939 public void binderDied() {
940 if (localLOGV) Log.v(
941 TAG, "Death received in " + this
942 + " for thread " + mAppThread.asBinder());
943 removeRequestedPss(mApp);
944 synchronized(ActivityManagerService.this) {
945 appDiedLocked(mApp, mPid, mAppThread);
946 }
947 }
948 }
949
950 static final int SHOW_ERROR_MSG = 1;
951 static final int SHOW_NOT_RESPONDING_MSG = 2;
952 static final int SHOW_FACTORY_ERROR_MSG = 3;
953 static final int UPDATE_CONFIGURATION_MSG = 4;
954 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
955 static final int WAIT_FOR_DEBUGGER_MSG = 6;
956 static final int BROADCAST_INTENT_MSG = 7;
957 static final int BROADCAST_TIMEOUT_MSG = 8;
958 static final int PAUSE_TIMEOUT_MSG = 9;
959 static final int IDLE_TIMEOUT_MSG = 10;
960 static final int IDLE_NOW_MSG = 11;
961 static final int SERVICE_TIMEOUT_MSG = 12;
962 static final int UPDATE_TIME_ZONE = 13;
963 static final int SHOW_UID_ERROR_MSG = 14;
964 static final int IM_FEELING_LUCKY_MSG = 15;
965 static final int LAUNCH_TIMEOUT_MSG = 16;
966 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 static final int RESUME_TOP_ACTIVITY_MSG = 19;
968 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700969 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700970 static final int KILL_APPLICATION_MSG = 22;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971
972 AlertDialog mUidAlert;
973
974 final Handler mHandler = new Handler() {
975 //public Handler() {
976 // if (localLOGV) Log.v(TAG, "Handler started!");
977 //}
978
979 public void handleMessage(Message msg) {
980 switch (msg.what) {
981 case SHOW_ERROR_MSG: {
982 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 synchronized (ActivityManagerService.this) {
984 ProcessRecord proc = (ProcessRecord)data.get("app");
985 if (proc != null && proc.crashDialog != null) {
986 Log.e(TAG, "App already has crash dialog: " + proc);
987 return;
988 }
989 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700990 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800991 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 d.show();
993 proc.crashDialog = d;
994 } else {
995 // The device is asleep, so just pretend that the user
996 // saw a crash dialog and hit "force quit".
997 res.set(0);
998 }
999 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001000
1001 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 } break;
1003 case SHOW_NOT_RESPONDING_MSG: {
1004 synchronized (ActivityManagerService.this) {
1005 HashMap data = (HashMap) msg.obj;
1006 ProcessRecord proc = (ProcessRecord)data.get("app");
1007 if (proc != null && proc.anrDialog != null) {
1008 Log.e(TAG, "App already has anr dialog: " + proc);
1009 return;
1010 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001011
1012 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1013 null, null, 0, null, null, null,
1014 false, false, MY_PID, Process.SYSTEM_UID);
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1017 mContext, proc, (HistoryRecord)data.get("activity"));
1018 d.show();
1019 proc.anrDialog = d;
1020 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001021
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001022 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 } break;
1024 case SHOW_FACTORY_ERROR_MSG: {
1025 Dialog d = new FactoryErrorDialog(
1026 mContext, msg.getData().getCharSequence("msg"));
1027 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001028 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 } break;
1030 case UPDATE_CONFIGURATION_MSG: {
1031 final ContentResolver resolver = mContext.getContentResolver();
1032 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1033 } break;
1034 case GC_BACKGROUND_PROCESSES_MSG: {
1035 synchronized (ActivityManagerService.this) {
1036 performAppGcsIfAppropriateLocked();
1037 }
1038 } break;
1039 case WAIT_FOR_DEBUGGER_MSG: {
1040 synchronized (ActivityManagerService.this) {
1041 ProcessRecord app = (ProcessRecord)msg.obj;
1042 if (msg.arg1 != 0) {
1043 if (!app.waitedForDebugger) {
1044 Dialog d = new AppWaitingForDebuggerDialog(
1045 ActivityManagerService.this,
1046 mContext, app);
1047 app.waitDialog = d;
1048 app.waitedForDebugger = true;
1049 d.show();
1050 }
1051 } else {
1052 if (app.waitDialog != null) {
1053 app.waitDialog.dismiss();
1054 app.waitDialog = null;
1055 }
1056 }
1057 }
1058 } break;
1059 case BROADCAST_INTENT_MSG: {
1060 if (DEBUG_BROADCAST) Log.v(
1061 TAG, "Received BROADCAST_INTENT_MSG");
1062 processNextBroadcast(true);
1063 } break;
1064 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001065 if (mDidDexOpt) {
1066 mDidDexOpt = false;
1067 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1068 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1069 return;
1070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 broadcastTimeout();
1072 } break;
1073 case PAUSE_TIMEOUT_MSG: {
1074 IBinder token = (IBinder)msg.obj;
1075 // We don't at this point know if the activity is fullscreen,
1076 // so we need to be conservative and assume it isn't.
1077 Log.w(TAG, "Activity pause timeout for " + token);
1078 activityPaused(token, null, true);
1079 } break;
1080 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001081 if (mDidDexOpt) {
1082 mDidDexOpt = false;
1083 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1084 nmsg.obj = msg.obj;
1085 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1086 return;
1087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 // We don't at this point know if the activity is fullscreen,
1089 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001090 IBinder token = (IBinder)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 Log.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001092 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 } break;
1094 case DESTROY_TIMEOUT_MSG: {
1095 IBinder token = (IBinder)msg.obj;
1096 // We don't at this point know if the activity is fullscreen,
1097 // so we need to be conservative and assume it isn't.
1098 Log.w(TAG, "Activity destroy timeout for " + token);
1099 activityDestroyed(token);
1100 } break;
1101 case IDLE_NOW_MSG: {
1102 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001103 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 } break;
1105 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001106 if (mDidDexOpt) {
1107 mDidDexOpt = false;
1108 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1109 nmsg.obj = msg.obj;
1110 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1111 return;
1112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 serviceTimeout((ProcessRecord)msg.obj);
1114 } break;
1115 case UPDATE_TIME_ZONE: {
1116 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001117 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1118 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 if (r.thread != null) {
1120 try {
1121 r.thread.updateTimeZone();
1122 } catch (RemoteException ex) {
1123 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
1124 }
1125 }
1126 }
1127 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001128 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 case SHOW_UID_ERROR_MSG: {
1130 // XXX This is a temporary dialog, no need to localize.
1131 AlertDialog d = new BaseErrorDialog(mContext);
1132 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1133 d.setCancelable(false);
1134 d.setTitle("System UIDs Inconsistent");
1135 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1136 d.setButton("I'm Feeling Lucky",
1137 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1138 mUidAlert = d;
1139 d.show();
1140 } break;
1141 case IM_FEELING_LUCKY_MSG: {
1142 if (mUidAlert != null) {
1143 mUidAlert.dismiss();
1144 mUidAlert = null;
1145 }
1146 } break;
1147 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001148 if (mDidDexOpt) {
1149 mDidDexOpt = false;
1150 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1151 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1152 return;
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 synchronized (ActivityManagerService.this) {
1155 if (mLaunchingActivity.isHeld()) {
1156 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1157 mLaunchingActivity.release();
1158 }
1159 }
1160 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 case RESUME_TOP_ACTIVITY_MSG: {
1162 synchronized (ActivityManagerService.this) {
1163 resumeTopActivityLocked(null);
1164 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001165 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001167 if (mDidDexOpt) {
1168 mDidDexOpt = false;
1169 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1170 nmsg.obj = msg.obj;
1171 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1172 return;
1173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 ProcessRecord app = (ProcessRecord)msg.obj;
1175 synchronized (ActivityManagerService.this) {
1176 processStartTimedOutLocked(app);
1177 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001178 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001179 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1180 synchronized (ActivityManagerService.this) {
1181 doPendingActivityLaunchesLocked(true);
1182 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001183 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001184 case KILL_APPLICATION_MSG: {
1185 synchronized (ActivityManagerService.this) {
1186 int uid = msg.arg1;
1187 boolean restart = (msg.arg2 == 1);
1188 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001189 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001190 }
1191 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 }
1193 }
1194 };
1195
1196 public static void setSystemProcess() {
1197 try {
1198 ActivityManagerService m = mSelf;
1199
1200 ServiceManager.addService("activity", m);
1201 ServiceManager.addService("meminfo", new MemBinder(m));
1202 if (MONITOR_CPU_USAGE) {
1203 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 ServiceManager.addService("permission", new PermissionController(m));
1206
1207 ApplicationInfo info =
1208 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001209 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001210 mSystemThread.installSystemApplicationInfo(info);
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 synchronized (mSelf) {
1213 ProcessRecord app = mSelf.newProcessRecordLocked(
1214 mSystemThread.getApplicationThread(), info,
1215 info.processName);
1216 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001217 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 app.maxAdj = SYSTEM_ADJ;
1219 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1220 synchronized (mSelf.mPidsSelfLocked) {
1221 mSelf.mPidsSelfLocked.put(app.pid, app);
1222 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001223 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 } catch (PackageManager.NameNotFoundException e) {
1226 throw new RuntimeException(
1227 "Unable to find android system package", e);
1228 }
1229 }
1230
1231 public void setWindowManager(WindowManagerService wm) {
1232 mWindowManager = wm;
1233 }
1234
1235 public static final Context main(int factoryTest) {
1236 AThread thr = new AThread();
1237 thr.start();
1238
1239 synchronized (thr) {
1240 while (thr.mService == null) {
1241 try {
1242 thr.wait();
1243 } catch (InterruptedException e) {
1244 }
1245 }
1246 }
1247
1248 ActivityManagerService m = thr.mService;
1249 mSelf = m;
1250 ActivityThread at = ActivityThread.systemMain();
1251 mSystemThread = at;
1252 Context context = at.getSystemContext();
1253 m.mContext = context;
1254 m.mFactoryTest = factoryTest;
1255 PowerManager pm =
1256 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1257 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1258 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1259 m.mLaunchingActivity.setReferenceCounted(false);
1260
1261 m.mBatteryStatsService.publish(context);
1262 m.mUsageStatsService.publish(context);
1263
1264 synchronized (thr) {
1265 thr.mReady = true;
1266 thr.notifyAll();
1267 }
1268
1269 m.startRunning(null, null, null, null);
1270
1271 return context;
1272 }
1273
1274 public static ActivityManagerService self() {
1275 return mSelf;
1276 }
1277
1278 static class AThread extends Thread {
1279 ActivityManagerService mService;
1280 boolean mReady = false;
1281
1282 public AThread() {
1283 super("ActivityManager");
1284 }
1285
1286 public void run() {
1287 Looper.prepare();
1288
1289 android.os.Process.setThreadPriority(
1290 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1291
1292 ActivityManagerService m = new ActivityManagerService();
1293
1294 synchronized (this) {
1295 mService = m;
1296 notifyAll();
1297 }
1298
1299 synchronized (this) {
1300 while (!mReady) {
1301 try {
1302 wait();
1303 } catch (InterruptedException e) {
1304 }
1305 }
1306 }
1307
1308 Looper.loop();
1309 }
1310 }
1311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 static class MemBinder extends Binder {
1313 ActivityManagerService mActivityManagerService;
1314 MemBinder(ActivityManagerService activityManagerService) {
1315 mActivityManagerService = activityManagerService;
1316 }
1317
1318 @Override
1319 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1320 ActivityManagerService service = mActivityManagerService;
1321 ArrayList<ProcessRecord> procs;
1322 synchronized (mActivityManagerService) {
1323 if (args != null && args.length > 0
1324 && args[0].charAt(0) != '-') {
1325 procs = new ArrayList<ProcessRecord>();
1326 int pid = -1;
1327 try {
1328 pid = Integer.parseInt(args[0]);
1329 } catch (NumberFormatException e) {
1330
1331 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001332 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1333 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 if (proc.pid == pid) {
1335 procs.add(proc);
1336 } else if (proc.processName.equals(args[0])) {
1337 procs.add(proc);
1338 }
1339 }
1340 if (procs.size() <= 0) {
1341 pw.println("No process found for: " + args[0]);
1342 return;
1343 }
1344 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001345 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 }
1347 }
1348 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1349 }
1350 }
1351
1352 static class CpuBinder extends Binder {
1353 ActivityManagerService mActivityManagerService;
1354 CpuBinder(ActivityManagerService activityManagerService) {
1355 mActivityManagerService = activityManagerService;
1356 }
1357
1358 @Override
1359 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1360 synchronized (mActivityManagerService.mProcessStatsThread) {
1361 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1362 }
1363 }
1364 }
1365
1366 private ActivityManagerService() {
1367 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1368 if (v != null && Integer.getInteger(v) != 0) {
1369 mSimpleProcessManagement = true;
1370 }
1371 v = System.getenv("ANDROID_DEBUG_APP");
1372 if (v != null) {
1373 mSimpleProcessManagement = true;
1374 }
1375
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001376 Log.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
1377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 File dataDir = Environment.getDataDirectory();
1379 File systemDir = new File(dataDir, "system");
1380 systemDir.mkdirs();
1381 mBatteryStatsService = new BatteryStatsService(new File(
1382 systemDir, "batterystats.bin").toString());
1383 mBatteryStatsService.getActiveStatistics().readLocked();
1384 mBatteryStatsService.getActiveStatistics().writeLocked();
1385
1386 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001387 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388
Jack Palevichb90d28c2009-07-22 15:35:24 -07001389 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1390 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1391
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001392 mConfiguration.setToDefaults();
1393 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 mProcessStats.init();
1395
1396 // Add ourself to the Watchdog monitors.
1397 Watchdog.getInstance().addMonitor(this);
1398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 mProcessStatsThread = new Thread("ProcessStats") {
1400 public void run() {
1401 while (true) {
1402 try {
1403 try {
1404 synchronized(this) {
1405 final long now = SystemClock.uptimeMillis();
1406 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1407 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
1408 //Log.i(TAG, "Cpu delay=" + nextCpuDelay
1409 // + ", write delay=" + nextWriteDelay);
1410 if (nextWriteDelay < nextCpuDelay) {
1411 nextCpuDelay = nextWriteDelay;
1412 }
1413 if (nextCpuDelay > 0) {
1414 this.wait(nextCpuDelay);
1415 }
1416 }
1417 } catch (InterruptedException e) {
1418 }
1419
1420 updateCpuStatsNow();
1421 } catch (Exception e) {
1422 Log.e(TAG, "Unexpected exception collecting process stats", e);
1423 }
1424 }
1425 }
1426 };
1427 mProcessStatsThread.start();
1428 }
1429
1430 @Override
1431 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1432 throws RemoteException {
1433 try {
1434 return super.onTransact(code, data, reply, flags);
1435 } catch (RuntimeException e) {
1436 // The activity manager only throws security exceptions, so let's
1437 // log all others.
1438 if (!(e instanceof SecurityException)) {
1439 Log.e(TAG, "Activity Manager Crash", e);
1440 }
1441 throw e;
1442 }
1443 }
1444
1445 void updateCpuStats() {
1446 synchronized (mProcessStatsThread) {
1447 final long now = SystemClock.uptimeMillis();
1448 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1449 mProcessStatsThread.notify();
1450 }
1451 }
1452 }
1453
1454 void updateCpuStatsNow() {
1455 synchronized (mProcessStatsThread) {
1456 final long now = SystemClock.uptimeMillis();
1457 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 if (MONITOR_CPU_USAGE &&
1460 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1461 mLastCpuTime = now;
1462 haveNewCpuStats = true;
1463 mProcessStats.update();
1464 //Log.i(TAG, mProcessStats.printCurrentState());
1465 //Log.i(TAG, "Total CPU usage: "
1466 // + mProcessStats.getTotalCpuPercent() + "%");
1467
1468 // Log the cpu usage if the property is set.
1469 if ("true".equals(SystemProperties.get("events.cpu"))) {
1470 int user = mProcessStats.getLastUserTime();
1471 int system = mProcessStats.getLastSystemTime();
1472 int iowait = mProcessStats.getLastIoWaitTime();
1473 int irq = mProcessStats.getLastIrqTime();
1474 int softIrq = mProcessStats.getLastSoftIrqTime();
1475 int idle = mProcessStats.getLastIdleTime();
1476
1477 int total = user + system + iowait + irq + softIrq + idle;
1478 if (total == 0) total = 1;
1479
Doug Zongker2bec3d42009-12-04 12:52:44 -08001480 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 ((user+system+iowait+irq+softIrq) * 100) / total,
1482 (user * 100) / total,
1483 (system * 100) / total,
1484 (iowait * 100) / total,
1485 (irq * 100) / total,
1486 (softIrq * 100) / total);
1487 }
1488 }
1489
Amith Yamasanie43530a2009-08-21 13:11:37 -07001490 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001491 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001492 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 synchronized(mPidsSelfLocked) {
1494 if (haveNewCpuStats) {
1495 if (mBatteryStatsService.isOnBattery()) {
1496 final int N = mProcessStats.countWorkingStats();
1497 for (int i=0; i<N; i++) {
1498 ProcessStats.Stats st
1499 = mProcessStats.getWorkingStats(i);
1500 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1501 if (pr != null) {
1502 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1503 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001504 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001505 } else {
1506 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001507 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001508 if (ps != null) {
1509 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001510 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 }
1513 }
1514 }
1515 }
1516 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1519 mLastWriteTime = now;
1520 mBatteryStatsService.getActiveStatistics().writeLocked();
1521 }
1522 }
1523 }
1524 }
1525
1526 /**
1527 * Initialize the application bind args. These are passed to each
1528 * process when the bindApplication() IPC is sent to the process. They're
1529 * lazily setup to make sure the services are running when they're asked for.
1530 */
1531 private HashMap<String, IBinder> getCommonServicesLocked() {
1532 if (mAppBindArgs == null) {
1533 mAppBindArgs = new HashMap<String, IBinder>();
1534
1535 // Setup the application init args
1536 mAppBindArgs.put("package", ServiceManager.getService("package"));
1537 mAppBindArgs.put("window", ServiceManager.getService("window"));
1538 mAppBindArgs.put(Context.ALARM_SERVICE,
1539 ServiceManager.getService(Context.ALARM_SERVICE));
1540 }
1541 return mAppBindArgs;
1542 }
1543
1544 private final void setFocusedActivityLocked(HistoryRecord r) {
1545 if (mFocusedActivity != r) {
1546 mFocusedActivity = r;
1547 mWindowManager.setFocusedApp(r, true);
1548 }
1549 }
1550
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001551 private final void updateLruProcessLocked(ProcessRecord app,
1552 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001554 int lrui = mLruProcesses.indexOf(app);
1555 if (lrui >= 0) mLruProcesses.remove(lrui);
1556
1557 int i = mLruProcesses.size()-1;
1558 int skipTop = 0;
1559
1560 // compute the new weight for this process.
1561 if (updateActivityTime) {
1562 app.lastActivityTime = SystemClock.uptimeMillis();
1563 }
1564 if (app.activities.size() > 0) {
1565 // If this process has activities, we more strongly want to keep
1566 // it around.
1567 app.lruWeight = app.lastActivityTime;
1568 } else if (app.pubProviders.size() > 0) {
1569 // If this process contains content providers, we want to keep
1570 // it a little more strongly.
1571 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1572 // Also don't let it kick out the first few "real" hidden processes.
1573 skipTop = MIN_HIDDEN_APPS;
1574 } else {
1575 // If this process doesn't have activities, we less strongly
1576 // want to keep it around, and generally want to avoid getting
1577 // in front of any very recently used activities.
1578 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1579 // Also don't let it kick out the first few "real" hidden processes.
1580 skipTop = MIN_HIDDEN_APPS;
1581 }
1582 while (i >= 0) {
1583 ProcessRecord p = mLruProcesses.get(i);
1584 // If this app shouldn't be in front of the first N background
1585 // apps, then skip over that many that are currently hidden.
1586 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1587 skipTop--;
1588 }
1589 if (p.lruWeight <= app.lruWeight){
1590 mLruProcesses.add(i+1, app);
1591 break;
1592 }
1593 i--;
1594 }
1595 if (i < 0) {
1596 mLruProcesses.add(0, app);
1597 }
1598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 //Log.i(TAG, "Putting proc to front: " + app.processName);
1600 if (oomAdj) {
1601 updateOomAdjLocked();
1602 }
1603 }
1604
1605 private final boolean updateLRUListLocked(HistoryRecord r) {
1606 final boolean hadit = mLRUActivities.remove(r);
1607 mLRUActivities.add(r);
1608 return hadit;
1609 }
1610
1611 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1612 int i = mHistory.size()-1;
1613 while (i >= 0) {
1614 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1615 if (!r.finishing && r != notTop) {
1616 return r;
1617 }
1618 i--;
1619 }
1620 return null;
1621 }
1622
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001623 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1624 int i = mHistory.size()-1;
1625 while (i >= 0) {
1626 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1627 if (!r.finishing && !r.delayedResume && r != notTop) {
1628 return r;
1629 }
1630 i--;
1631 }
1632 return null;
1633 }
1634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 /**
1636 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001637 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 *
1639 * @param token If non-null, any history records matching this token will be skipped.
1640 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1641 *
1642 * @return Returns the HistoryRecord of the next activity on the stack.
1643 */
1644 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1645 int i = mHistory.size()-1;
1646 while (i >= 0) {
1647 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1648 // Note: the taskId check depends on real taskId fields being non-zero
1649 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1650 return r;
1651 }
1652 i--;
1653 }
1654 return null;
1655 }
1656
1657 private final ProcessRecord getProcessRecordLocked(
1658 String processName, int uid) {
1659 if (uid == Process.SYSTEM_UID) {
1660 // The system gets to run in any process. If there are multiple
1661 // processes with the same uid, just pick the first (this
1662 // should never happen).
1663 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1664 processName);
1665 return procs != null ? procs.valueAt(0) : null;
1666 }
1667 ProcessRecord proc = mProcessNames.get(processName, uid);
1668 return proc;
1669 }
1670
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001671 private void ensurePackageDexOpt(String packageName) {
1672 IPackageManager pm = ActivityThread.getPackageManager();
1673 try {
1674 if (pm.performDexOpt(packageName)) {
1675 mDidDexOpt = true;
1676 }
1677 } catch (RemoteException e) {
1678 }
1679 }
1680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 private boolean isNextTransitionForward() {
1682 int transit = mWindowManager.getPendingAppTransition();
1683 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1684 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1685 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1686 }
1687
1688 private final boolean realStartActivityLocked(HistoryRecord r,
1689 ProcessRecord app, boolean andResume, boolean checkConfig)
1690 throws RemoteException {
1691
1692 r.startFreezingScreenLocked(app, 0);
1693 mWindowManager.setAppVisibility(r, true);
1694
1695 // Have the window manager re-evaluate the orientation of
1696 // the screen based on the new activity order. Note that
1697 // as a result of this, it can call back into the activity
1698 // manager with a new orientation. We don't care about that,
1699 // because the activity is not currently running so we are
1700 // just restarting it anyway.
1701 if (checkConfig) {
1702 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001703 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 r.mayFreezeScreenLocked(app) ? r : null);
1705 updateConfigurationLocked(config, r);
1706 }
1707
1708 r.app = app;
1709
1710 if (localLOGV) Log.v(TAG, "Launching: " + r);
1711
1712 int idx = app.activities.indexOf(r);
1713 if (idx < 0) {
1714 app.activities.add(r);
1715 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001716 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717
1718 try {
1719 if (app.thread == null) {
1720 throw new RemoteException();
1721 }
1722 List<ResultInfo> results = null;
1723 List<Intent> newIntents = null;
1724 if (andResume) {
1725 results = r.results;
1726 newIntents = r.newIntents;
1727 }
1728 if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
1729 + " icicle=" + r.icicle
1730 + " with results=" + results + " newIntents=" + newIntents
1731 + " andResume=" + andResume);
1732 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001733 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 System.identityHashCode(r),
1735 r.task.taskId, r.shortComponentName);
1736 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001737 if (r.isHomeActivity) {
1738 mHomeProcess = app;
1739 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001740 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001742 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 r.info, r.icicle, results, newIntents, !andResume,
1744 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 } catch (RemoteException e) {
1746 if (r.launchFailed) {
1747 // This is the second time we failed -- finish activity
1748 // and give up.
1749 Log.e(TAG, "Second failure launching "
1750 + r.intent.getComponent().flattenToShortString()
1751 + ", giving up", e);
1752 appDiedLocked(app, app.pid, app.thread);
1753 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1754 "2nd-crash");
1755 return false;
1756 }
1757
1758 // This is the first time we failed -- restart process and
1759 // retry.
1760 app.activities.remove(r);
1761 throw e;
1762 }
1763
1764 r.launchFailed = false;
1765 if (updateLRUListLocked(r)) {
1766 Log.w(TAG, "Activity " + r
1767 + " being launched, but already in LRU list");
1768 }
1769
1770 if (andResume) {
1771 // As part of the process of launching, ActivityThread also performs
1772 // a resume.
1773 r.state = ActivityState.RESUMED;
1774 r.icicle = null;
1775 r.haveState = false;
1776 r.stopped = false;
1777 mResumedActivity = r;
1778 r.task.touchActiveTime();
1779 completeResumeLocked(r);
1780 pauseIfSleepingLocked();
1781 } else {
1782 // This activity is not starting in the resumed state... which
1783 // should look like we asked it to pause+stop (but remain visible),
1784 // and it has done so and reported back the current icicle and
1785 // other state.
1786 r.state = ActivityState.STOPPED;
1787 r.stopped = true;
1788 }
1789
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001790 // Launch the new version setup screen if needed. We do this -after-
1791 // launching the initial activity (that is, home), so that it can have
1792 // a chance to initialize itself while in the background, making the
1793 // switch back to it faster and look better.
1794 startSetupActivityLocked();
1795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 return true;
1797 }
1798
1799 private final void startSpecificActivityLocked(HistoryRecord r,
1800 boolean andResume, boolean checkConfig) {
1801 // Is this activity's application already running?
1802 ProcessRecord app = getProcessRecordLocked(r.processName,
1803 r.info.applicationInfo.uid);
1804
1805 if (r.startTime == 0) {
1806 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001807 if (mInitialStartTime == 0) {
1808 mInitialStartTime = r.startTime;
1809 }
1810 } else if (mInitialStartTime == 0) {
1811 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
1813
1814 if (app != null && app.thread != null) {
1815 try {
1816 realStartActivityLocked(r, app, andResume, checkConfig);
1817 return;
1818 } catch (RemoteException e) {
1819 Log.w(TAG, "Exception when starting activity "
1820 + r.intent.getComponent().flattenToShortString(), e);
1821 }
1822
1823 // If a dead object exception was thrown -- fall through to
1824 // restart the application.
1825 }
1826
1827 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001828 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 }
1830
1831 private final ProcessRecord startProcessLocked(String processName,
1832 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001833 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1835 // We don't have to do anything more if:
1836 // (1) There is an existing application record; and
1837 // (2) The caller doesn't think it is dead, OR there is no thread
1838 // object attached to it so we know it couldn't have crashed; and
1839 // (3) There is a pid assigned to it, so it is either starting or
1840 // already running.
1841 if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
1842 + " app=" + app + " knownToBeDead=" + knownToBeDead
1843 + " thread=" + (app != null ? app.thread : null)
1844 + " pid=" + (app != null ? app.pid : -1));
1845 if (app != null &&
1846 (!knownToBeDead || app.thread == null) && app.pid > 0) {
1847 return app;
1848 }
1849
1850 String hostingNameStr = hostingName != null
1851 ? hostingName.flattenToShortString() : null;
1852
1853 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1854 // If we are in the background, then check to see if this process
1855 // is bad. If so, we will just silently fail.
1856 if (mBadProcesses.get(info.processName, info.uid) != null) {
1857 return null;
1858 }
1859 } else {
1860 // When the user is explicitly starting a process, then clear its
1861 // crash count so that we won't make it bad until they see at
1862 // least one crash dialog again, and make the process good again
1863 // if it had been bad.
1864 mProcessCrashTimes.remove(info.processName, info.uid);
1865 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001866 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 info.processName);
1868 mBadProcesses.remove(info.processName, info.uid);
1869 if (app != null) {
1870 app.bad = false;
1871 }
1872 }
1873 }
1874
1875 if (app == null) {
1876 app = newProcessRecordLocked(null, info, processName);
1877 mProcessNames.put(processName, info.uid, app);
1878 } else {
1879 // If this is a new package in the process, add the package to the list
1880 app.addPackage(info.packageName);
1881 }
1882
1883 // If the system is not ready yet, then hold off on starting this
1884 // process until it is.
1885 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001886 && !isAllowedWhileBooting(info)
1887 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 if (!mProcessesOnHold.contains(app)) {
1889 mProcessesOnHold.add(app);
1890 }
1891 return app;
1892 }
1893
1894 startProcessLocked(app, hostingType, hostingNameStr);
1895 return (app.pid != 0) ? app : null;
1896 }
1897
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001898 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1899 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1900 }
1901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 private final void startProcessLocked(ProcessRecord app,
1903 String hostingType, String hostingNameStr) {
1904 if (app.pid > 0 && app.pid != MY_PID) {
1905 synchronized (mPidsSelfLocked) {
1906 mPidsSelfLocked.remove(app.pid);
1907 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1908 }
1909 app.pid = 0;
1910 }
1911
1912 mProcessesOnHold.remove(app);
1913
1914 updateCpuStats();
1915
1916 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1917 mProcDeaths[0] = 0;
1918
1919 try {
1920 int uid = app.info.uid;
1921 int[] gids = null;
1922 try {
1923 gids = mContext.getPackageManager().getPackageGids(
1924 app.info.packageName);
1925 } catch (PackageManager.NameNotFoundException e) {
1926 Log.w(TAG, "Unable to retrieve gids", e);
1927 }
1928 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1929 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1930 && mTopComponent != null
1931 && app.processName.equals(mTopComponent.getPackageName())) {
1932 uid = 0;
1933 }
1934 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1935 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1936 uid = 0;
1937 }
1938 }
1939 int debugFlags = 0;
1940 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1941 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1942 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001943 // Run the app in safe mode if its manifest requests so or the
1944 // system is booted in safe mode.
1945 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1946 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001947 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1950 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1951 }
1952 if ("1".equals(SystemProperties.get("debug.assert"))) {
1953 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1954 }
1955 int pid = Process.start("android.app.ActivityThread",
1956 mSimpleProcessManagement ? app.processName : null, uid, uid,
1957 gids, debugFlags, null);
1958 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1959 synchronized (bs) {
1960 if (bs.isOnBattery()) {
1961 app.batteryStats.incStartsLocked();
1962 }
1963 }
1964
Doug Zongker2bec3d42009-12-04 12:52:44 -08001965 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 app.processName, hostingType,
1967 hostingNameStr != null ? hostingNameStr : "");
1968
1969 if (app.persistent) {
1970 Watchdog.getInstance().processStarted(app, app.processName, pid);
1971 }
1972
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001973 StringBuilder buf = mStringBuilder;
1974 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 buf.append("Start proc ");
1976 buf.append(app.processName);
1977 buf.append(" for ");
1978 buf.append(hostingType);
1979 if (hostingNameStr != null) {
1980 buf.append(" ");
1981 buf.append(hostingNameStr);
1982 }
1983 buf.append(": pid=");
1984 buf.append(pid);
1985 buf.append(" uid=");
1986 buf.append(uid);
1987 buf.append(" gids={");
1988 if (gids != null) {
1989 for (int gi=0; gi<gids.length; gi++) {
1990 if (gi != 0) buf.append(", ");
1991 buf.append(gids[gi]);
1992
1993 }
1994 }
1995 buf.append("}");
1996 Log.i(TAG, buf.toString());
1997 if (pid == 0 || pid == MY_PID) {
1998 // Processes are being emulated with threads.
1999 app.pid = MY_PID;
2000 app.removed = false;
2001 mStartingProcesses.add(app);
2002 } else if (pid > 0) {
2003 app.pid = pid;
2004 app.removed = false;
2005 synchronized (mPidsSelfLocked) {
2006 this.mPidsSelfLocked.put(pid, app);
2007 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2008 msg.obj = app;
2009 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2010 }
2011 } else {
2012 app.pid = 0;
2013 RuntimeException e = new RuntimeException(
2014 "Failure starting process " + app.processName
2015 + ": returned pid=" + pid);
2016 Log.e(TAG, e.getMessage(), e);
2017 }
2018 } catch (RuntimeException e) {
2019 // XXX do better error recovery.
2020 app.pid = 0;
2021 Log.e(TAG, "Failure starting process " + app.processName, e);
2022 }
2023 }
2024
2025 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2026 if (mPausingActivity != null) {
2027 RuntimeException e = new RuntimeException();
2028 Log.e(TAG, "Trying to pause when pause is already pending for "
2029 + mPausingActivity, e);
2030 }
2031 HistoryRecord prev = mResumedActivity;
2032 if (prev == null) {
2033 RuntimeException e = new RuntimeException();
2034 Log.e(TAG, "Trying to pause when nothing is resumed", e);
2035 resumeTopActivityLocked(null);
2036 return;
2037 }
2038 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
2039 mResumedActivity = null;
2040 mPausingActivity = prev;
2041 mLastPausedActivity = prev;
2042 prev.state = ActivityState.PAUSING;
2043 prev.task.touchActiveTime();
2044
2045 updateCpuStats();
2046
2047 if (prev.app != null && prev.app.thread != null) {
2048 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
2049 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002050 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 System.identityHashCode(prev),
2052 prev.shortComponentName);
2053 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2054 prev.configChangeFlags);
2055 updateUsageStats(prev, false);
2056 } catch (Exception e) {
2057 // Ignore exception, if process died other code will cleanup.
2058 Log.w(TAG, "Exception thrown during pause", e);
2059 mPausingActivity = null;
2060 mLastPausedActivity = null;
2061 }
2062 } else {
2063 mPausingActivity = null;
2064 mLastPausedActivity = null;
2065 }
2066
2067 // If we are not going to sleep, we want to ensure the device is
2068 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002069 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 mLaunchingActivity.acquire();
2071 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2072 // To be safe, don't allow the wake lock to be held for too long.
2073 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2074 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2075 }
2076 }
2077
2078
2079 if (mPausingActivity != null) {
2080 // Have the window manager pause its key dispatching until the new
2081 // activity has started. If we're pausing the activity just because
2082 // the screen is being turned off and the UI is sleeping, don't interrupt
2083 // key dispatch; the same activity will pick it up again on wakeup.
2084 if (!uiSleeping) {
2085 prev.pauseKeyDispatchingLocked();
2086 } else {
2087 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
2088 }
2089
2090 // Schedule a pause timeout in case the app doesn't respond.
2091 // We don't give it much time because this directly impacts the
2092 // responsiveness seen by the user.
2093 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2094 msg.obj = prev;
2095 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
2096 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
2097 } else {
2098 // This activity failed to schedule the
2099 // pause, so just treat it as being paused now.
2100 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
2101 resumeTopActivityLocked(null);
2102 }
2103 }
2104
2105 private final void completePauseLocked() {
2106 HistoryRecord prev = mPausingActivity;
2107 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
2108
2109 if (prev != null) {
2110 if (prev.finishing) {
2111 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
2112 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2113 } else if (prev.app != null) {
2114 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
2115 if (prev.waitingVisible) {
2116 prev.waitingVisible = false;
2117 mWaitingVisibleActivities.remove(prev);
2118 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
2119 TAG, "Complete pause, no longer waiting: " + prev);
2120 }
2121 if (prev.configDestroy) {
2122 // The previous is being paused because the configuration
2123 // is changing, which means it is actually stopping...
2124 // To juggle the fact that we are also starting a new
2125 // instance right now, we need to first completely stop
2126 // the current instance before starting the new one.
2127 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
2128 destroyActivityLocked(prev, true);
2129 } else {
2130 mStoppingActivities.add(prev);
2131 if (mStoppingActivities.size() > 3) {
2132 // If we already have a few activities waiting to stop,
2133 // then give up on things going idle and start clearing
2134 // them out.
2135 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
2136 Message msg = Message.obtain();
2137 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2138 mHandler.sendMessage(msg);
2139 }
2140 }
2141 } else {
2142 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
2143 prev = null;
2144 }
2145 mPausingActivity = null;
2146 }
2147
Dianne Hackborn55280a92009-05-07 15:53:46 -07002148 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 resumeTopActivityLocked(prev);
2150 } else {
2151 if (mGoingToSleep.isHeld()) {
2152 mGoingToSleep.release();
2153 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002154 if (mShuttingDown) {
2155 notifyAll();
2156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 }
2158
2159 if (prev != null) {
2160 prev.resumeKeyDispatchingLocked();
2161 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002162
2163 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2164 long diff = 0;
2165 synchronized (mProcessStatsThread) {
2166 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2167 }
2168 if (diff > 0) {
2169 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2170 synchronized (bsi) {
2171 BatteryStatsImpl.Uid.Proc ps =
2172 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2173 prev.info.packageName);
2174 if (ps != null) {
2175 ps.addForegroundTimeLocked(diff);
2176 }
2177 }
2178 }
2179 }
2180 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
2182
2183 /**
2184 * Once we know that we have asked an application to put an activity in
2185 * the resumed state (either by launching it or explicitly telling it),
2186 * this function updates the rest of our state to match that fact.
2187 */
2188 private final void completeResumeLocked(HistoryRecord next) {
2189 next.idle = false;
2190 next.results = null;
2191 next.newIntents = null;
2192
2193 // schedule an idle timeout in case the app doesn't do it for us.
2194 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2195 msg.obj = next;
2196 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2197
2198 if (false) {
2199 // The activity was never told to pause, so just keep
2200 // things going as-is. To maintain our own state,
2201 // we need to emulate it coming back and saying it is
2202 // idle.
2203 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2204 msg.obj = next;
2205 mHandler.sendMessage(msg);
2206 }
2207
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002208 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 next.thumbnail = null;
2211 setFocusedActivityLocked(next);
2212 next.resumeKeyDispatchingLocked();
2213 ensureActivitiesVisibleLocked(null, 0);
2214 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002215 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002216
2217 // Mark the point when the activity is resuming
2218 // TODO: To be more accurate, the mark should be before the onCreate,
2219 // not after the onResume. But for subsequent starts, onResume is fine.
2220 if (next.app != null) {
2221 synchronized (mProcessStatsThread) {
2222 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2223 }
2224 } else {
2225 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 }
2228
2229 /**
2230 * Make sure that all activities that need to be visible (that is, they
2231 * currently can be seen by the user) actually are.
2232 */
2233 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2234 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2235 if (DEBUG_VISBILITY) Log.v(
2236 TAG, "ensureActivitiesVisible behind " + top
2237 + " configChanges=0x" + Integer.toHexString(configChanges));
2238
2239 // If the top activity is not fullscreen, then we need to
2240 // make sure any activities under it are now visible.
2241 final int count = mHistory.size();
2242 int i = count-1;
2243 while (mHistory.get(i) != top) {
2244 i--;
2245 }
2246 HistoryRecord r;
2247 boolean behindFullscreen = false;
2248 for (; i>=0; i--) {
2249 r = (HistoryRecord)mHistory.get(i);
2250 if (DEBUG_VISBILITY) Log.v(
2251 TAG, "Make visible? " + r + " finishing=" + r.finishing
2252 + " state=" + r.state);
2253 if (r.finishing) {
2254 continue;
2255 }
2256
2257 final boolean doThisProcess = onlyThisProcess == null
2258 || onlyThisProcess.equals(r.processName);
2259
2260 // First: if this is not the current activity being started, make
2261 // sure it matches the current configuration.
2262 if (r != starting && doThisProcess) {
2263 ensureActivityConfigurationLocked(r, 0);
2264 }
2265
2266 if (r.app == null || r.app.thread == null) {
2267 if (onlyThisProcess == null
2268 || onlyThisProcess.equals(r.processName)) {
2269 // This activity needs to be visible, but isn't even
2270 // running... get it started, but don't resume it
2271 // at this point.
2272 if (DEBUG_VISBILITY) Log.v(
2273 TAG, "Start and freeze screen for " + r);
2274 if (r != starting) {
2275 r.startFreezingScreenLocked(r.app, configChanges);
2276 }
2277 if (!r.visible) {
2278 if (DEBUG_VISBILITY) Log.v(
2279 TAG, "Starting and making visible: " + r);
2280 mWindowManager.setAppVisibility(r, true);
2281 }
2282 if (r != starting) {
2283 startSpecificActivityLocked(r, false, false);
2284 }
2285 }
2286
2287 } else if (r.visible) {
2288 // If this activity is already visible, then there is nothing
2289 // else to do here.
2290 if (DEBUG_VISBILITY) Log.v(
2291 TAG, "Skipping: already visible at " + r);
2292 r.stopFreezingScreenLocked(false);
2293
2294 } else if (onlyThisProcess == null) {
2295 // This activity is not currently visible, but is running.
2296 // Tell it to become visible.
2297 r.visible = true;
2298 if (r.state != ActivityState.RESUMED && r != starting) {
2299 // If this activity is paused, tell it
2300 // to now show its window.
2301 if (DEBUG_VISBILITY) Log.v(
2302 TAG, "Making visible and scheduling visibility: " + r);
2303 try {
2304 mWindowManager.setAppVisibility(r, true);
2305 r.app.thread.scheduleWindowVisibility(r, true);
2306 r.stopFreezingScreenLocked(false);
2307 } catch (Exception e) {
2308 // Just skip on any failure; we'll make it
2309 // visible when it next restarts.
2310 Log.w(TAG, "Exception thrown making visibile: "
2311 + r.intent.getComponent(), e);
2312 }
2313 }
2314 }
2315
2316 // Aggregate current change flags.
2317 configChanges |= r.configChangeFlags;
2318
2319 if (r.fullscreen) {
2320 // At this point, nothing else needs to be shown
2321 if (DEBUG_VISBILITY) Log.v(
2322 TAG, "Stopping: fullscreen at " + r);
2323 behindFullscreen = true;
2324 i--;
2325 break;
2326 }
2327 }
2328
2329 // Now for any activities that aren't visible to the user, make
2330 // sure they no longer are keeping the screen frozen.
2331 while (i >= 0) {
2332 r = (HistoryRecord)mHistory.get(i);
2333 if (DEBUG_VISBILITY) Log.v(
2334 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2335 + " state=" + r.state
2336 + " behindFullscreen=" + behindFullscreen);
2337 if (!r.finishing) {
2338 if (behindFullscreen) {
2339 if (r.visible) {
2340 if (DEBUG_VISBILITY) Log.v(
2341 TAG, "Making invisible: " + r);
2342 r.visible = false;
2343 try {
2344 mWindowManager.setAppVisibility(r, false);
2345 if ((r.state == ActivityState.STOPPING
2346 || r.state == ActivityState.STOPPED)
2347 && r.app != null && r.app.thread != null) {
2348 if (DEBUG_VISBILITY) Log.v(
2349 TAG, "Scheduling invisibility: " + r);
2350 r.app.thread.scheduleWindowVisibility(r, false);
2351 }
2352 } catch (Exception e) {
2353 // Just skip on any failure; we'll make it
2354 // visible when it next restarts.
2355 Log.w(TAG, "Exception thrown making hidden: "
2356 + r.intent.getComponent(), e);
2357 }
2358 } else {
2359 if (DEBUG_VISBILITY) Log.v(
2360 TAG, "Already invisible: " + r);
2361 }
2362 } else if (r.fullscreen) {
2363 if (DEBUG_VISBILITY) Log.v(
2364 TAG, "Now behindFullscreen: " + r);
2365 behindFullscreen = true;
2366 }
2367 }
2368 i--;
2369 }
2370 }
2371
2372 /**
2373 * Version of ensureActivitiesVisible that can easily be called anywhere.
2374 */
2375 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2376 int configChanges) {
2377 HistoryRecord r = topRunningActivityLocked(null);
2378 if (r != null) {
2379 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2380 }
2381 }
2382
2383 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2384 if (resumed) {
2385 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2386 } else {
2387 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2388 }
2389 }
2390
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002391 private boolean startHomeActivityLocked() {
2392 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2393 && mTopAction == null) {
2394 // We are running in factory test mode, but unable to find
2395 // the factory test app, so just sit around displaying the
2396 // error message and don't try to start anything.
2397 return false;
2398 }
2399 Intent intent = new Intent(
2400 mTopAction,
2401 mTopData != null ? Uri.parse(mTopData) : null);
2402 intent.setComponent(mTopComponent);
2403 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2404 intent.addCategory(Intent.CATEGORY_HOME);
2405 }
2406 ActivityInfo aInfo =
2407 intent.resolveActivityInfo(mContext.getPackageManager(),
2408 STOCK_PM_FLAGS);
2409 if (aInfo != null) {
2410 intent.setComponent(new ComponentName(
2411 aInfo.applicationInfo.packageName, aInfo.name));
2412 // Don't do this if the home app is currently being
2413 // instrumented.
2414 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2415 aInfo.applicationInfo.uid);
2416 if (app == null || app.instrumentationClass == null) {
2417 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2418 startActivityLocked(null, intent, null, null, 0, aInfo,
2419 null, null, 0, 0, 0, false, false);
2420 }
2421 }
2422
2423
2424 return true;
2425 }
2426
2427 /**
2428 * Starts the "new version setup screen" if appropriate.
2429 */
2430 private void startSetupActivityLocked() {
2431 // Only do this once per boot.
2432 if (mCheckedForSetup) {
2433 return;
2434 }
2435
2436 // We will show this screen if the current one is a different
2437 // version than the last one shown, and we are not running in
2438 // low-level factory test mode.
2439 final ContentResolver resolver = mContext.getContentResolver();
2440 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2441 Settings.Secure.getInt(resolver,
2442 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2443 mCheckedForSetup = true;
2444
2445 // See if we should be showing the platform update setup UI.
2446 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2447 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2448 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2449
2450 // We don't allow third party apps to replace this.
2451 ResolveInfo ri = null;
2452 for (int i=0; ris != null && i<ris.size(); i++) {
2453 if ((ris.get(i).activityInfo.applicationInfo.flags
2454 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2455 ri = ris.get(i);
2456 break;
2457 }
2458 }
2459
2460 if (ri != null) {
2461 String vers = ri.activityInfo.metaData != null
2462 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2463 : null;
2464 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2465 vers = ri.activityInfo.applicationInfo.metaData.getString(
2466 Intent.METADATA_SETUP_VERSION);
2467 }
2468 String lastVers = Settings.Secure.getString(
2469 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2470 if (vers != null && !vers.equals(lastVers)) {
2471 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2472 intent.setComponent(new ComponentName(
2473 ri.activityInfo.packageName, ri.activityInfo.name));
2474 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2475 null, null, 0, 0, 0, false, false);
2476 }
2477 }
2478 }
2479 }
2480
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002481 private void reportResumedActivityLocked(HistoryRecord r) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002482 //Log.i(TAG, "**** REPORT RESUME: " + r);
2483
2484 final int identHash = System.identityHashCode(r);
2485 updateUsageStats(r, true);
2486
2487 int i = mWatchers.beginBroadcast();
2488 while (i > 0) {
2489 i--;
2490 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2491 if (w != null) {
2492 try {
2493 w.activityResuming(identHash);
2494 } catch (RemoteException e) {
2495 }
2496 }
2497 }
2498 mWatchers.finishBroadcast();
2499 }
2500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 /**
2502 * Ensure that the top activity in the stack is resumed.
2503 *
2504 * @param prev The previously resumed activity, for when in the process
2505 * of pausing; can be null to call from elsewhere.
2506 *
2507 * @return Returns true if something is being resumed, or false if
2508 * nothing happened.
2509 */
2510 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2511 // Find the first activity that is not finishing.
2512 HistoryRecord next = topRunningActivityLocked(null);
2513
2514 // Remember how we'll process this pause/resume situation, and ensure
2515 // that the state is reset however we wind up proceeding.
2516 final boolean userLeaving = mUserLeaving;
2517 mUserLeaving = false;
2518
2519 if (next == null) {
2520 // There are no more activities! Let's just start up the
2521 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002522 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 }
2524
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002525 next.delayedResume = false;
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 // If the top activity is the resumed one, nothing to do.
2528 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2529 // Make sure we have executed any pending transitions, since there
2530 // should be nothing left to do at this point.
2531 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002532 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 return false;
2534 }
2535
2536 // If we are sleeping, and there is no resumed activity, and the top
2537 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002538 if ((mSleeping || mShuttingDown)
2539 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 // Make sure we have executed any pending transitions, since there
2541 // should be nothing left to do at this point.
2542 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002543 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 return false;
2545 }
2546
2547 // The activity may be waiting for stop, but that is no longer
2548 // appropriate for it.
2549 mStoppingActivities.remove(next);
2550 mWaitingVisibleActivities.remove(next);
2551
2552 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2553
2554 // If we are currently pausing an activity, then don't do anything
2555 // until that is done.
2556 if (mPausingActivity != null) {
2557 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2558 return false;
2559 }
2560
2561 // We need to start pausing the current activity so the top one
2562 // can be resumed...
2563 if (mResumedActivity != null) {
2564 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2565 startPausingLocked(userLeaving, false);
2566 return true;
2567 }
2568
2569 if (prev != null && prev != next) {
2570 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2571 prev.waitingVisible = true;
2572 mWaitingVisibleActivities.add(prev);
2573 if (DEBUG_SWITCH) Log.v(
2574 TAG, "Resuming top, waiting visible to hide: " + prev);
2575 } else {
2576 // The next activity is already visible, so hide the previous
2577 // activity's windows right now so we can show the new one ASAP.
2578 // We only do this if the previous is finishing, which should mean
2579 // it is on top of the one being resumed so hiding it quickly
2580 // is good. Otherwise, we want to do the normal route of allowing
2581 // the resumed activity to be shown so we can decide if the
2582 // previous should actually be hidden depending on whether the
2583 // new one is found to be full-screen or not.
2584 if (prev.finishing) {
2585 mWindowManager.setAppVisibility(prev, false);
2586 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2587 + prev + ", waitingVisible="
2588 + (prev != null ? prev.waitingVisible : null)
2589 + ", nowVisible=" + next.nowVisible);
2590 } else {
2591 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2592 + prev + ", waitingVisible="
2593 + (prev != null ? prev.waitingVisible : null)
2594 + ", nowVisible=" + next.nowVisible);
2595 }
2596 }
2597 }
2598
2599 // We are starting up the next activity, so tell the window manager
2600 // that the previous one will be hidden soon. This way it can know
2601 // to ignore it when computing the desired screen orientation.
2602 if (prev != null) {
2603 if (prev.finishing) {
2604 if (DEBUG_TRANSITION) Log.v(TAG,
2605 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002606 if (mNoAnimActivities.contains(prev)) {
2607 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2608 } else {
2609 mWindowManager.prepareAppTransition(prev.task == next.task
2610 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2611 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 mWindowManager.setAppWillBeHidden(prev);
2614 mWindowManager.setAppVisibility(prev, false);
2615 } else {
2616 if (DEBUG_TRANSITION) Log.v(TAG,
2617 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002618 if (mNoAnimActivities.contains(next)) {
2619 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2620 } else {
2621 mWindowManager.prepareAppTransition(prev.task == next.task
2622 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2623 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 }
2626 if (false) {
2627 mWindowManager.setAppWillBeHidden(prev);
2628 mWindowManager.setAppVisibility(prev, false);
2629 }
2630 } else if (mHistory.size() > 1) {
2631 if (DEBUG_TRANSITION) Log.v(TAG,
2632 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002633 if (mNoAnimActivities.contains(next)) {
2634 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2635 } else {
2636 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 }
2639
2640 if (next.app != null && next.app.thread != null) {
2641 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2642
2643 // This activity is now becoming visible.
2644 mWindowManager.setAppVisibility(next, true);
2645
2646 HistoryRecord lastResumedActivity = mResumedActivity;
2647 ActivityState lastState = next.state;
2648
2649 updateCpuStats();
2650
2651 next.state = ActivityState.RESUMED;
2652 mResumedActivity = next;
2653 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002654 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 updateLRUListLocked(next);
2656
2657 // Have the window manager re-evaluate the orientation of
2658 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002659 boolean updated;
2660 synchronized (this) {
2661 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2662 mConfiguration,
2663 next.mayFreezeScreenLocked(next.app) ? next : null);
2664 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002665 next.frozenBeforeDestroy = true;
2666 }
2667 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002669 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 // The configuration update wasn't able to keep the existing
2671 // instance of the activity, and instead started a new one.
2672 // We should be all done, but let's just make sure our activity
2673 // is still at the top and schedule another run if something
2674 // weird happened.
2675 HistoryRecord nextNext = topRunningActivityLocked(null);
2676 if (DEBUG_SWITCH) Log.i(TAG,
2677 "Activity config changed during resume: " + next
2678 + ", new next: " + nextNext);
2679 if (nextNext != next) {
2680 // Do over!
2681 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2682 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002683 setFocusedActivityLocked(next);
2684 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002686 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 return true;
2688 }
2689
2690 try {
2691 // Deliver all pending results.
2692 ArrayList a = next.results;
2693 if (a != null) {
2694 final int N = a.size();
2695 if (!next.finishing && N > 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002696 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 TAG, "Delivering results to " + next
2698 + ": " + a);
2699 next.app.thread.scheduleSendResult(next, a);
2700 }
2701 }
2702
2703 if (next.newIntents != null) {
2704 next.app.thread.scheduleNewIntent(next.newIntents, next);
2705 }
2706
Doug Zongker2bec3d42009-12-04 12:52:44 -08002707 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 System.identityHashCode(next),
2709 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710
2711 next.app.thread.scheduleResumeActivity(next,
2712 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 pauseIfSleepingLocked();
2715
2716 } catch (Exception e) {
2717 // Whoops, need to restart this activity!
2718 next.state = lastState;
2719 mResumedActivity = lastResumedActivity;
Dianne Hackborn03abb812010-01-04 18:43:19 -08002720 Log.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 if (!next.hasBeenLaunched) {
2722 next.hasBeenLaunched = true;
2723 } else {
2724 if (SHOW_APP_STARTING_ICON) {
2725 mWindowManager.setAppStartingWindow(
2726 next, next.packageName, next.theme,
2727 next.nonLocalizedLabel,
2728 next.labelRes, next.icon, null, true);
2729 }
2730 }
2731 startSpecificActivityLocked(next, true, false);
2732 return true;
2733 }
2734
2735 // From this point on, if something goes wrong there is no way
2736 // to recover the activity.
2737 try {
2738 next.visible = true;
2739 completeResumeLocked(next);
2740 } catch (Exception e) {
2741 // If any exception gets thrown, toss away this
2742 // activity and try the next one.
2743 Log.w(TAG, "Exception thrown during resume of " + next, e);
2744 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2745 "resume-exception");
2746 return true;
2747 }
2748
2749 // Didn't need to use the icicle, and it is now out of date.
2750 next.icicle = null;
2751 next.haveState = false;
2752 next.stopped = false;
2753
2754 } else {
2755 // Whoops, need to restart this activity!
2756 if (!next.hasBeenLaunched) {
2757 next.hasBeenLaunched = true;
2758 } else {
2759 if (SHOW_APP_STARTING_ICON) {
2760 mWindowManager.setAppStartingWindow(
2761 next, next.packageName, next.theme,
2762 next.nonLocalizedLabel,
2763 next.labelRes, next.icon, null, true);
2764 }
2765 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2766 }
2767 startSpecificActivityLocked(next, true, true);
2768 }
2769
2770 return true;
2771 }
2772
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002773 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2774 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 final int NH = mHistory.size();
2776
2777 int addPos = -1;
2778
2779 if (!newTask) {
2780 // If starting in an existing task, find where that is...
2781 HistoryRecord next = null;
2782 boolean startIt = true;
2783 for (int i = NH-1; i >= 0; i--) {
2784 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2785 if (p.finishing) {
2786 continue;
2787 }
2788 if (p.task == r.task) {
2789 // Here it is! Now, if this is not yet visible to the
2790 // user, then just add it without starting; it will
2791 // get started when the user navigates back to it.
2792 addPos = i+1;
2793 if (!startIt) {
2794 mHistory.add(addPos, r);
2795 r.inHistory = true;
2796 r.task.numActivities++;
2797 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2798 r.info.screenOrientation, r.fullscreen);
2799 if (VALIDATE_TOKENS) {
2800 mWindowManager.validateAppTokens(mHistory);
2801 }
2802 return;
2803 }
2804 break;
2805 }
2806 if (p.fullscreen) {
2807 startIt = false;
2808 }
2809 next = p;
2810 }
2811 }
2812
2813 // Place a new activity at top of stack, so it is next to interact
2814 // with the user.
2815 if (addPos < 0) {
2816 addPos = mHistory.size();
2817 }
2818
2819 // If we are not placing the new activity frontmost, we do not want
2820 // to deliver the onUserLeaving callback to the actual frontmost
2821 // activity
2822 if (addPos < NH) {
2823 mUserLeaving = false;
2824 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2825 }
2826
2827 // Slot the activity into the history stack and proceed
2828 mHistory.add(addPos, r);
2829 r.inHistory = true;
2830 r.frontOfTask = newTask;
2831 r.task.numActivities++;
2832 if (NH > 0) {
2833 // We want to show the starting preview window if we are
2834 // switching to a new task, or the next activity's process is
2835 // not currently running.
2836 boolean showStartingIcon = newTask;
2837 ProcessRecord proc = r.app;
2838 if (proc == null) {
2839 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2840 }
2841 if (proc == null || proc.thread == null) {
2842 showStartingIcon = true;
2843 }
2844 if (DEBUG_TRANSITION) Log.v(TAG,
2845 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002846 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2847 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2848 mNoAnimActivities.add(r);
2849 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2850 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2851 mNoAnimActivities.remove(r);
2852 } else {
2853 mWindowManager.prepareAppTransition(newTask
2854 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2855 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2856 mNoAnimActivities.remove(r);
2857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002858 mWindowManager.addAppToken(
2859 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2860 boolean doShow = true;
2861 if (newTask) {
2862 // Even though this activity is starting fresh, we still need
2863 // to reset it to make sure we apply affinities to move any
2864 // existing activities from other tasks in to it.
2865 // If the caller has requested that the target task be
2866 // reset, then do so.
2867 if ((r.intent.getFlags()
2868 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2869 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002870 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 }
2872 }
2873 if (SHOW_APP_STARTING_ICON && doShow) {
2874 // Figure out if we are transitioning from another activity that is
2875 // "has the same starting icon" as the next one. This allows the
2876 // window manager to keep the previous window it had previously
2877 // created, if it still had one.
2878 HistoryRecord prev = mResumedActivity;
2879 if (prev != null) {
2880 // We don't want to reuse the previous starting preview if:
2881 // (1) The current activity is in a different task.
2882 if (prev.task != r.task) prev = null;
2883 // (2) The current activity is already displayed.
2884 else if (prev.nowVisible) prev = null;
2885 }
2886 mWindowManager.setAppStartingWindow(
2887 r, r.packageName, r.theme, r.nonLocalizedLabel,
2888 r.labelRes, r.icon, prev, showStartingIcon);
2889 }
2890 } else {
2891 // If this is the first activity, don't do any fancy animations,
2892 // because there is nothing for it to animate on top of.
2893 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2894 r.info.screenOrientation, r.fullscreen);
2895 }
2896 if (VALIDATE_TOKENS) {
2897 mWindowManager.validateAppTokens(mHistory);
2898 }
2899
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002900 if (doResume) {
2901 resumeTopActivityLocked(null);
2902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
2904
2905 /**
2906 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002907 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2908 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909 * an instance of that activity in the stack and, if found, finish all
2910 * activities on top of it and return the instance.
2911 *
2912 * @param newR Description of the new activity being started.
2913 * @return Returns the old activity that should be continue to be used,
2914 * or null if none was found.
2915 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002916 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002917 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002919
2920 // First find the requested task.
2921 while (i > 0) {
2922 i--;
2923 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2924 if (r.task.taskId == taskId) {
2925 i++;
2926 break;
2927 }
2928 }
2929
2930 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 while (i > 0) {
2932 i--;
2933 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2934 if (r.finishing) {
2935 continue;
2936 }
2937 if (r.task.taskId != taskId) {
2938 return null;
2939 }
2940 if (r.realActivity.equals(newR.realActivity)) {
2941 // Here it is! Now finish everything in front...
2942 HistoryRecord ret = r;
2943 if (doClear) {
2944 while (i < (mHistory.size()-1)) {
2945 i++;
2946 r = (HistoryRecord)mHistory.get(i);
2947 if (r.finishing) {
2948 continue;
2949 }
2950 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2951 null, "clear")) {
2952 i--;
2953 }
2954 }
2955 }
2956
2957 // Finally, if this is a normal launch mode (that is, not
2958 // expecting onNewIntent()), then we will finish the current
2959 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002960 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2961 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002963 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 if (index >= 0) {
2965 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2966 null, "clear");
2967 }
2968 return null;
2969 }
2970 }
2971
2972 return ret;
2973 }
2974 }
2975
2976 return null;
2977 }
2978
2979 /**
2980 * Find the activity in the history stack within the given task. Returns
2981 * the index within the history at which it's found, or < 0 if not found.
2982 */
2983 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
2984 int i = mHistory.size();
2985 while (i > 0) {
2986 i--;
2987 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
2988 if (candidate.task.taskId != task) {
2989 break;
2990 }
2991 if (candidate.realActivity.equals(r.realActivity)) {
2992 return i;
2993 }
2994 }
2995
2996 return -1;
2997 }
2998
2999 /**
3000 * Reorder the history stack so that the activity at the given index is
3001 * brought to the front.
3002 */
3003 private final HistoryRecord moveActivityToFrontLocked(int where) {
3004 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3005 int top = mHistory.size();
3006 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3007 mHistory.add(top, newTop);
3008 oldTop.frontOfTask = false;
3009 newTop.frontOfTask = true;
3010 return newTop;
3011 }
3012
3013 /**
3014 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3015 * method will be called at the proper time.
3016 */
3017 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3018 boolean sent = false;
3019 if (r.state == ActivityState.RESUMED
3020 && r.app != null && r.app.thread != null) {
3021 try {
3022 ArrayList<Intent> ar = new ArrayList<Intent>();
3023 ar.add(new Intent(intent));
3024 r.app.thread.scheduleNewIntent(ar, r);
3025 sent = true;
3026 } catch (Exception e) {
3027 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
3028 }
3029 }
3030 if (!sent) {
3031 r.addNewIntentLocked(new Intent(intent));
3032 }
3033 }
3034
3035 private final void logStartActivity(int tag, HistoryRecord r,
3036 TaskRecord task) {
3037 EventLog.writeEvent(tag,
3038 System.identityHashCode(r), task.taskId,
3039 r.shortComponentName, r.intent.getAction(),
3040 r.intent.getType(), r.intent.getDataString(),
3041 r.intent.getFlags());
3042 }
3043
3044 private final int startActivityLocked(IApplicationThread caller,
3045 Intent intent, String resolvedType,
3046 Uri[] grantedUriPermissions,
3047 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3048 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003049 int callingPid, int callingUid, boolean onlyIfNeeded,
3050 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 Log.i(TAG, "Starting activity: " + intent);
3052
3053 HistoryRecord sourceRecord = null;
3054 HistoryRecord resultRecord = null;
3055 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003056 int index = indexOfTokenLocked(resultTo);
The Android Open Source Project10592532009-03-18 17:39:46 -07003057 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3059 if (index >= 0) {
3060 sourceRecord = (HistoryRecord)mHistory.get(index);
3061 if (requestCode >= 0 && !sourceRecord.finishing) {
3062 resultRecord = sourceRecord;
3063 }
3064 }
3065 }
3066
3067 int launchFlags = intent.getFlags();
3068
3069 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3070 && sourceRecord != null) {
3071 // Transfer the result target from the source activity to the new
3072 // one being started, including any failures.
3073 if (requestCode >= 0) {
3074 return START_FORWARD_AND_REQUEST_CONFLICT;
3075 }
3076 resultRecord = sourceRecord.resultTo;
3077 resultWho = sourceRecord.resultWho;
3078 requestCode = sourceRecord.requestCode;
3079 sourceRecord.resultTo = null;
3080 if (resultRecord != null) {
3081 resultRecord.removeResultsLocked(
3082 sourceRecord, resultWho, requestCode);
3083 }
3084 }
3085
3086 int err = START_SUCCESS;
3087
3088 if (intent.getComponent() == null) {
3089 // We couldn't find a class that can handle the given Intent.
3090 // That's the end of that!
3091 err = START_INTENT_NOT_RESOLVED;
3092 }
3093
3094 if (err == START_SUCCESS && aInfo == null) {
3095 // We couldn't find the specific class specified in the Intent.
3096 // Also the end of the line.
3097 err = START_CLASS_NOT_FOUND;
3098 }
3099
3100 ProcessRecord callerApp = null;
3101 if (err == START_SUCCESS && caller != null) {
3102 callerApp = getRecordForAppLocked(caller);
3103 if (callerApp != null) {
3104 callingPid = callerApp.pid;
3105 callingUid = callerApp.info.uid;
3106 } else {
3107 Log.w(TAG, "Unable to find app for caller " + caller
3108 + " (pid=" + callingPid + ") when starting: "
3109 + intent.toString());
3110 err = START_PERMISSION_DENIED;
3111 }
3112 }
3113
3114 if (err != START_SUCCESS) {
3115 if (resultRecord != null) {
3116 sendActivityResultLocked(-1,
3117 resultRecord, resultWho, requestCode,
3118 Activity.RESULT_CANCELED, null);
3119 }
3120 return err;
3121 }
3122
3123 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3124 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3125 if (perm != PackageManager.PERMISSION_GRANTED) {
3126 if (resultRecord != null) {
3127 sendActivityResultLocked(-1,
3128 resultRecord, resultWho, requestCode,
3129 Activity.RESULT_CANCELED, null);
3130 }
3131 String msg = "Permission Denial: starting " + intent.toString()
3132 + " from " + callerApp + " (pid=" + callingPid
3133 + ", uid=" + callingUid + ")"
3134 + " requires " + aInfo.permission;
3135 Log.w(TAG, msg);
3136 throw new SecurityException(msg);
3137 }
3138
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003139 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 boolean abort = false;
3141 try {
3142 // The Intent we give to the watcher has the extra data
3143 // stripped off, since it can contain private information.
3144 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003145 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 aInfo.applicationInfo.packageName);
3147 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003148 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 }
3150
3151 if (abort) {
3152 if (resultRecord != null) {
3153 sendActivityResultLocked(-1,
3154 resultRecord, resultWho, requestCode,
3155 Activity.RESULT_CANCELED, null);
3156 }
3157 // We pretend to the caller that it was really started, but
3158 // they will just get a cancel result.
3159 return START_SUCCESS;
3160 }
3161 }
3162
3163 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3164 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003165 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003167 if (mResumedActivity == null
3168 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3169 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3170 PendingActivityLaunch pal = new PendingActivityLaunch();
3171 pal.r = r;
3172 pal.sourceRecord = sourceRecord;
3173 pal.grantedUriPermissions = grantedUriPermissions;
3174 pal.grantedMode = grantedMode;
3175 pal.onlyIfNeeded = onlyIfNeeded;
3176 mPendingActivityLaunches.add(pal);
3177 return START_SWITCHES_CANCELED;
3178 }
3179 }
3180
3181 if (mDidAppSwitch) {
3182 // This is the second allowed switch since we stopped switches,
3183 // so now just generally allow switches. Use case: user presses
3184 // home (switches disabled, switch to home, mDidAppSwitch now true);
3185 // user taps a home icon (coming from home so allowed, we hit here
3186 // and now allow anyone to switch again).
3187 mAppSwitchesAllowedTime = 0;
3188 } else {
3189 mDidAppSwitch = true;
3190 }
3191
3192 doPendingActivityLaunchesLocked(false);
3193
3194 return startActivityUncheckedLocked(r, sourceRecord,
3195 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3196 }
3197
3198 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3199 final int N = mPendingActivityLaunches.size();
3200 if (N <= 0) {
3201 return;
3202 }
3203 for (int i=0; i<N; i++) {
3204 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3205 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3206 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3207 doResume && i == (N-1));
3208 }
3209 mPendingActivityLaunches.clear();
3210 }
3211
3212 private final int startActivityUncheckedLocked(HistoryRecord r,
3213 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3214 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3215 final Intent intent = r.intent;
3216 final int callingUid = r.launchedFromUid;
3217
3218 int launchFlags = intent.getFlags();
3219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 // We'll invoke onUserLeaving before onPause only if the launching
3221 // activity did not explicitly state that this is an automated launch.
3222 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
3223 if (DEBUG_USER_LEAVING) Log.v(TAG,
3224 "startActivity() => mUserLeaving=" + mUserLeaving);
3225
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003226 // If the caller has asked not to resume at this point, we make note
3227 // of this in the record so that we can skip it when trying to find
3228 // the top running activity.
3229 if (!doResume) {
3230 r.delayedResume = true;
3231 }
3232
3233 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3234 != 0 ? r : null;
3235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 // If the onlyIfNeeded flag is set, then we can do this if the activity
3237 // being launched is the same as the one making the call... or, as
3238 // a special case, if we do not know the caller then we count the
3239 // current top activity as the caller.
3240 if (onlyIfNeeded) {
3241 HistoryRecord checkedCaller = sourceRecord;
3242 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003243 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 }
3245 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3246 // Caller is not the same as launcher, so always needed.
3247 onlyIfNeeded = false;
3248 }
3249 }
3250
3251 if (grantedUriPermissions != null && callingUid > 0) {
3252 for (int i=0; i<grantedUriPermissions.length; i++) {
3253 grantUriPermissionLocked(callingUid, r.packageName,
3254 grantedUriPermissions[i], grantedMode, r);
3255 }
3256 }
3257
3258 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3259 intent, r);
3260
3261 if (sourceRecord == null) {
3262 // This activity is not being started from another... in this
3263 // case we -always- start a new task.
3264 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
3265 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
3266 + intent);
3267 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3268 }
3269 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3270 // The original activity who is starting us is running as a single
3271 // instance... this new activity it is starting must go on its
3272 // own task.
3273 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3274 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3275 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3276 // The activity being started is a single instance... it always
3277 // gets launched into its own task.
3278 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3279 }
3280
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003281 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 // For whatever reason this activity is being launched into a new
3283 // task... yet the caller has requested a result back. Well, that
3284 // is pretty messed up, so instead immediately send back a cancel
3285 // and let the new task continue launched as normal without a
3286 // dependency on its originator.
3287 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3288 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003289 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 Activity.RESULT_CANCELED, null);
3291 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 }
3293
3294 boolean addingToTask = false;
3295 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3296 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3297 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3298 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3299 // If bring to front is requested, and no result is requested, and
3300 // we can find a task that was started with this same
3301 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003302 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 // See if there is a task to bring to the front. If this is
3304 // a SINGLE_INSTANCE activity, there can be one and only one
3305 // instance of it in the history, and it is always in its own
3306 // unique task, so we do a special search.
3307 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3308 ? findTaskLocked(intent, r.info)
3309 : findActivityLocked(intent, r.info);
3310 if (taskTop != null) {
3311 if (taskTop.task.intent == null) {
3312 // This task was started because of movement of
3313 // the activity based on affinity... now that we
3314 // are actually launching it, we can assign the
3315 // base intent.
3316 taskTop.task.setIntent(intent, r.info);
3317 }
3318 // If the target task is not in the front, then we need
3319 // to bring it to the front... except... well, with
3320 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3321 // to have the same behavior as if a new instance was
3322 // being started, which means not bringing it to the front
3323 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003324 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 if (curTop.task != taskTop.task) {
3326 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3327 boolean callerAtFront = sourceRecord == null
3328 || curTop.task == sourceRecord.task;
3329 if (callerAtFront) {
3330 // We really do want to push this one into the
3331 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003332 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333 }
3334 }
3335 // If the caller has requested that the target task be
3336 // reset, then do so.
3337 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3338 taskTop = resetTaskIfNeededLocked(taskTop, r);
3339 }
3340 if (onlyIfNeeded) {
3341 // We don't need to start a new activity, and
3342 // the client said not to do anything if that
3343 // is the case, so this is it! And for paranoia, make
3344 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003345 if (doResume) {
3346 resumeTopActivityLocked(null);
3347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 return START_RETURN_INTENT_TO_CALLER;
3349 }
3350 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3351 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3352 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3353 // In this situation we want to remove all activities
3354 // from the task up to the one being started. In most
3355 // cases this means we are resetting the task to its
3356 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003357 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003358 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 if (top != null) {
3360 if (top.frontOfTask) {
3361 // Activity aliases may mean we use different
3362 // intents for the top activity, so make sure
3363 // the task now has the identity of the new
3364 // intent.
3365 top.task.setIntent(r.intent, r.info);
3366 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003367 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 deliverNewIntentLocked(top, r.intent);
3369 } else {
3370 // A special case: we need to
3371 // start the activity because it is not currently
3372 // running, and the caller has asked to clear the
3373 // current task to have this activity at the top.
3374 addingToTask = true;
3375 // Now pretend like this activity is being started
3376 // by the top of its task, so it is put in the
3377 // right place.
3378 sourceRecord = taskTop;
3379 }
3380 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3381 // In this case the top activity on the task is the
3382 // same as the one being launched, so we take that
3383 // as a request to bring the task to the foreground.
3384 // If the top activity in the task is the root
3385 // activity, deliver this new intent to it if it
3386 // desires.
3387 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3388 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003389 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003390 if (taskTop.frontOfTask) {
3391 taskTop.task.setIntent(r.intent, r.info);
3392 }
3393 deliverNewIntentLocked(taskTop, r.intent);
3394 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3395 // In this case we are launching the root activity
3396 // of the task, but with a different intent. We
3397 // should start a new instance on top.
3398 addingToTask = true;
3399 sourceRecord = taskTop;
3400 }
3401 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3402 // In this case an activity is being launched in to an
3403 // existing task, without resetting that task. This
3404 // is typically the situation of launching an activity
3405 // from a notification or shortcut. We want to place
3406 // the new activity on top of the current task.
3407 addingToTask = true;
3408 sourceRecord = taskTop;
3409 } else if (!taskTop.task.rootWasReset) {
3410 // In this case we are launching in to an existing task
3411 // that has not yet been started from its front door.
3412 // The current task has been brought to the front.
3413 // Ideally, we'd probably like to place this new task
3414 // at the bottom of its stack, but that's a little hard
3415 // to do with the current organization of the code so
3416 // for now we'll just drop it.
3417 taskTop.task.setIntent(r.intent, r.info);
3418 }
3419 if (!addingToTask) {
3420 // We didn't do anything... but it was needed (a.k.a., client
3421 // don't use that intent!) And for paranoia, make
3422 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003423 if (doResume) {
3424 resumeTopActivityLocked(null);
3425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 return START_TASK_TO_FRONT;
3427 }
3428 }
3429 }
3430 }
3431
3432 //String uri = r.intent.toURI();
3433 //Intent intent2 = new Intent(uri);
3434 //Log.i(TAG, "Given intent: " + r.intent);
3435 //Log.i(TAG, "URI is: " + uri);
3436 //Log.i(TAG, "To intent: " + intent2);
3437
3438 if (r.packageName != null) {
3439 // If the activity being launched is the same as the one currently
3440 // at the top, then we need to check if it should only be launched
3441 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003442 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3443 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 if (top.realActivity.equals(r.realActivity)) {
3445 if (top.app != null && top.app.thread != null) {
3446 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3447 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3448 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003449 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 // For paranoia, make sure we have correctly
3451 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003452 if (doResume) {
3453 resumeTopActivityLocked(null);
3454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 if (onlyIfNeeded) {
3456 // We don't need to start a new activity, and
3457 // the client said not to do anything if that
3458 // is the case, so this is it!
3459 return START_RETURN_INTENT_TO_CALLER;
3460 }
3461 deliverNewIntentLocked(top, r.intent);
3462 return START_DELIVERED_TO_TOP;
3463 }
3464 }
3465 }
3466 }
3467
3468 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003469 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003471 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 Activity.RESULT_CANCELED, null);
3473 }
3474 return START_CLASS_NOT_FOUND;
3475 }
3476
3477 boolean newTask = false;
3478
3479 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003480 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3482 // todo: should do better management of integers.
3483 mCurTask++;
3484 if (mCurTask <= 0) {
3485 mCurTask = 1;
3486 }
3487 r.task = new TaskRecord(mCurTask, r.info, intent,
3488 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3489 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3490 + " in new task " + r.task);
3491 newTask = true;
3492 addRecentTask(r.task);
3493
3494 } else if (sourceRecord != null) {
3495 if (!addingToTask &&
3496 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3497 // In this case, we are adding the activity to an existing
3498 // task, but the caller has asked to clear that task if the
3499 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003500 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003501 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003503 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 deliverNewIntentLocked(top, r.intent);
3505 // For paranoia, make sure we have correctly
3506 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003507 if (doResume) {
3508 resumeTopActivityLocked(null);
3509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 return START_DELIVERED_TO_TOP;
3511 }
3512 } else if (!addingToTask &&
3513 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3514 // In this case, we are launching an activity in our own task
3515 // that may already be running somewhere in the history, and
3516 // we want to shuffle it to the front of the stack if so.
3517 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3518 if (where >= 0) {
3519 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003520 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003522 if (doResume) {
3523 resumeTopActivityLocked(null);
3524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 return START_DELIVERED_TO_TOP;
3526 }
3527 }
3528 // An existing activity is starting this new activity, so we want
3529 // to keep the new one in the same task as the one that is starting
3530 // it.
3531 r.task = sourceRecord.task;
3532 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3533 + " in existing task " + r.task);
3534
3535 } else {
3536 // This not being started from an existing activity, and not part
3537 // of a new task... just put it in the top task, though these days
3538 // this case should never happen.
3539 final int N = mHistory.size();
3540 HistoryRecord prev =
3541 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3542 r.task = prev != null
3543 ? prev.task
3544 : new TaskRecord(mCurTask, r.info, intent,
3545 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3546 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3547 + " in new guessed " + r.task);
3548 }
3549 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003550 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003552 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003553 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 return START_SUCCESS;
3555 }
3556
3557 public final int startActivity(IApplicationThread caller,
3558 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3559 int grantedMode, IBinder resultTo,
3560 String resultWho, int requestCode, boolean onlyIfNeeded,
3561 boolean debug) {
3562 // Refuse possible leaked file descriptors
3563 if (intent != null && intent.hasFileDescriptors()) {
3564 throw new IllegalArgumentException("File descriptors passed in Intent");
3565 }
3566
The Android Open Source Project4df24232009-03-05 14:34:35 -08003567 final boolean componentSpecified = intent.getComponent() != null;
3568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 // Don't modify the client's object!
3570 intent = new Intent(intent);
3571
3572 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 ActivityInfo aInfo;
3574 try {
3575 ResolveInfo rInfo =
3576 ActivityThread.getPackageManager().resolveIntent(
3577 intent, resolvedType,
3578 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003579 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 aInfo = rInfo != null ? rInfo.activityInfo : null;
3581 } catch (RemoteException e) {
3582 aInfo = null;
3583 }
3584
3585 if (aInfo != null) {
3586 // Store the found target back into the intent, because now that
3587 // we have it we never want to do this again. For example, if the
3588 // user navigates back to this point in the history, we should
3589 // always restart the exact same activity.
3590 intent.setComponent(new ComponentName(
3591 aInfo.applicationInfo.packageName, aInfo.name));
3592
3593 // Don't debug things in the system process
3594 if (debug) {
3595 if (!aInfo.processName.equals("system")) {
3596 setDebugApp(aInfo.processName, true, false);
3597 }
3598 }
3599 }
3600
3601 synchronized(this) {
3602 final long origId = Binder.clearCallingIdentity();
3603 int res = startActivityLocked(caller, intent, resolvedType,
3604 grantedUriPermissions, grantedMode, aInfo,
3605 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003606 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 Binder.restoreCallingIdentity(origId);
3608 return res;
3609 }
3610 }
3611
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003612 public int startActivityIntentSender(IApplicationThread caller,
3613 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003614 IBinder resultTo, String resultWho, int requestCode,
3615 int flagsMask, int flagsValues) {
3616 // Refuse possible leaked file descriptors
3617 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3618 throw new IllegalArgumentException("File descriptors passed in Intent");
3619 }
3620
3621 IIntentSender sender = intent.getTarget();
3622 if (!(sender instanceof PendingIntentRecord)) {
3623 throw new IllegalArgumentException("Bad PendingIntent object");
3624 }
3625
3626 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003627
3628 synchronized (this) {
3629 // If this is coming from the currently resumed activity, it is
3630 // effectively saying that app switches are allowed at this point.
3631 if (mResumedActivity != null
3632 && mResumedActivity.info.applicationInfo.uid ==
3633 Binder.getCallingUid()) {
3634 mAppSwitchesAllowedTime = 0;
3635 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003636 }
3637
3638 return pir.sendInner(0, fillInIntent, resolvedType,
3639 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3640 }
3641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 public boolean startNextMatchingActivity(IBinder callingActivity,
3643 Intent intent) {
3644 // Refuse possible leaked file descriptors
3645 if (intent != null && intent.hasFileDescriptors() == true) {
3646 throw new IllegalArgumentException("File descriptors passed in Intent");
3647 }
3648
3649 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003650 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 if (index < 0) {
3652 return false;
3653 }
3654 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3655 if (r.app == null || r.app.thread == null) {
3656 // The caller is not running... d'oh!
3657 return false;
3658 }
3659 intent = new Intent(intent);
3660 // The caller is not allowed to change the data.
3661 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3662 // And we are resetting to find the next component...
3663 intent.setComponent(null);
3664
3665 ActivityInfo aInfo = null;
3666 try {
3667 List<ResolveInfo> resolves =
3668 ActivityThread.getPackageManager().queryIntentActivities(
3669 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003670 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671
3672 // Look for the original activity in the list...
3673 final int N = resolves != null ? resolves.size() : 0;
3674 for (int i=0; i<N; i++) {
3675 ResolveInfo rInfo = resolves.get(i);
3676 if (rInfo.activityInfo.packageName.equals(r.packageName)
3677 && rInfo.activityInfo.name.equals(r.info.name)) {
3678 // We found the current one... the next matching is
3679 // after it.
3680 i++;
3681 if (i<N) {
3682 aInfo = resolves.get(i).activityInfo;
3683 }
3684 break;
3685 }
3686 }
3687 } catch (RemoteException e) {
3688 }
3689
3690 if (aInfo == null) {
3691 // Nobody who is next!
3692 return false;
3693 }
3694
3695 intent.setComponent(new ComponentName(
3696 aInfo.applicationInfo.packageName, aInfo.name));
3697 intent.setFlags(intent.getFlags()&~(
3698 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3699 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3700 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3701 Intent.FLAG_ACTIVITY_NEW_TASK));
3702
3703 // Okay now we need to start the new activity, replacing the
3704 // currently running activity. This is a little tricky because
3705 // we want to start the new one as if the current one is finished,
3706 // but not finish the current one first so that there is no flicker.
3707 // And thus...
3708 final boolean wasFinishing = r.finishing;
3709 r.finishing = true;
3710
3711 // Propagate reply information over to the new activity.
3712 final HistoryRecord resultTo = r.resultTo;
3713 final String resultWho = r.resultWho;
3714 final int requestCode = r.requestCode;
3715 r.resultTo = null;
3716 if (resultTo != null) {
3717 resultTo.removeResultsLocked(r, resultWho, requestCode);
3718 }
3719
3720 final long origId = Binder.clearCallingIdentity();
3721 // XXX we are not dealing with propagating grantedUriPermissions...
3722 // those are not yet exposed to user code, so there is no need.
3723 int res = startActivityLocked(r.app.thread, intent,
3724 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003725 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 Binder.restoreCallingIdentity(origId);
3727
3728 r.finishing = wasFinishing;
3729 if (res != START_SUCCESS) {
3730 return false;
3731 }
3732 return true;
3733 }
3734 }
3735
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003736 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 Intent intent, String resolvedType, IBinder resultTo,
3738 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003739
3740 // This is so super not safe, that only the system (or okay root)
3741 // can do it.
3742 final int callingUid = Binder.getCallingUid();
3743 if (callingUid != 0 && callingUid != Process.myUid()) {
3744 throw new SecurityException(
3745 "startActivityInPackage only available to the system");
3746 }
3747
The Android Open Source Project4df24232009-03-05 14:34:35 -08003748 final boolean componentSpecified = intent.getComponent() != null;
3749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 // Don't modify the client's object!
3751 intent = new Intent(intent);
3752
3753 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 ActivityInfo aInfo;
3755 try {
3756 ResolveInfo rInfo =
3757 ActivityThread.getPackageManager().resolveIntent(
3758 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003759 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 aInfo = rInfo != null ? rInfo.activityInfo : null;
3761 } catch (RemoteException e) {
3762 aInfo = null;
3763 }
3764
3765 if (aInfo != null) {
3766 // Store the found target back into the intent, because now that
3767 // we have it we never want to do this again. For example, if the
3768 // user navigates back to this point in the history, we should
3769 // always restart the exact same activity.
3770 intent.setComponent(new ComponentName(
3771 aInfo.applicationInfo.packageName, aInfo.name));
3772 }
3773
3774 synchronized(this) {
3775 return startActivityLocked(null, intent, resolvedType,
3776 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003777 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 }
3779 }
3780
3781 private final void addRecentTask(TaskRecord task) {
3782 // Remove any existing entries that are the same kind of task.
3783 int N = mRecentTasks.size();
3784 for (int i=0; i<N; i++) {
3785 TaskRecord tr = mRecentTasks.get(i);
3786 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3787 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3788 mRecentTasks.remove(i);
3789 i--;
3790 N--;
3791 if (task.intent == null) {
3792 // If the new recent task we are adding is not fully
3793 // specified, then replace it with the existing recent task.
3794 task = tr;
3795 }
3796 }
3797 }
3798 if (N >= MAX_RECENT_TASKS) {
3799 mRecentTasks.remove(N-1);
3800 }
3801 mRecentTasks.add(0, task);
3802 }
3803
3804 public void setRequestedOrientation(IBinder token,
3805 int requestedOrientation) {
3806 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003807 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 if (index < 0) {
3809 return;
3810 }
3811 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3812 final long origId = Binder.clearCallingIdentity();
3813 mWindowManager.setAppOrientation(r, requestedOrientation);
3814 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003815 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 r.mayFreezeScreenLocked(r.app) ? r : null);
3817 if (config != null) {
3818 r.frozenBeforeDestroy = true;
3819 if (!updateConfigurationLocked(config, r)) {
3820 resumeTopActivityLocked(null);
3821 }
3822 }
3823 Binder.restoreCallingIdentity(origId);
3824 }
3825 }
3826
3827 public int getRequestedOrientation(IBinder token) {
3828 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003829 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 if (index < 0) {
3831 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3832 }
3833 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3834 return mWindowManager.getAppOrientation(r);
3835 }
3836 }
3837
3838 private final void stopActivityLocked(HistoryRecord r) {
3839 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3840 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3841 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3842 if (!r.finishing) {
3843 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3844 "no-history");
3845 }
3846 } else if (r.app != null && r.app.thread != null) {
3847 if (mFocusedActivity == r) {
3848 setFocusedActivityLocked(topRunningActivityLocked(null));
3849 }
3850 r.resumeKeyDispatchingLocked();
3851 try {
3852 r.stopped = false;
3853 r.state = ActivityState.STOPPING;
3854 if (DEBUG_VISBILITY) Log.v(
3855 TAG, "Stopping visible=" + r.visible + " for " + r);
3856 if (!r.visible) {
3857 mWindowManager.setAppVisibility(r, false);
3858 }
3859 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3860 } catch (Exception e) {
3861 // Maybe just ignore exceptions here... if the process
3862 // has crashed, our death notification will clean things
3863 // up.
3864 Log.w(TAG, "Exception thrown during pause", e);
3865 // Just in case, assume it to be stopped.
3866 r.stopped = true;
3867 r.state = ActivityState.STOPPED;
3868 if (r.configDestroy) {
3869 destroyActivityLocked(r, true);
3870 }
3871 }
3872 }
3873 }
3874
3875 /**
3876 * @return Returns true if the activity is being finished, false if for
3877 * some reason it is being left as-is.
3878 */
3879 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3880 Intent resultData, String reason) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003881 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 TAG, "Finishing activity: token=" + token
3883 + ", result=" + resultCode + ", data=" + resultData);
3884
Dianne Hackborn75b03852009-06-12 15:43:26 -07003885 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 if (index < 0) {
3887 return false;
3888 }
3889 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3890
3891 // Is this the last activity left?
3892 boolean lastActivity = true;
3893 for (int i=mHistory.size()-1; i>=0; i--) {
3894 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3895 if (!p.finishing && p != r) {
3896 lastActivity = false;
3897 break;
3898 }
3899 }
3900
3901 // If this is the last activity, but it is the home activity, then
3902 // just don't finish it.
3903 if (lastActivity) {
3904 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3905 return false;
3906 }
3907 }
3908
3909 finishActivityLocked(r, index, resultCode, resultData, reason);
3910 return true;
3911 }
3912
3913 /**
3914 * @return Returns true if this activity has been removed from the history
3915 * list, or false if it is still in the list and will be removed later.
3916 */
3917 private final boolean finishActivityLocked(HistoryRecord r, int index,
3918 int resultCode, Intent resultData, String reason) {
3919 if (r.finishing) {
3920 Log.w(TAG, "Duplicate finish request for " + r);
3921 return false;
3922 }
3923
3924 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08003925 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 System.identityHashCode(r),
3927 r.task.taskId, r.shortComponentName, reason);
3928 r.task.numActivities--;
3929 if (r.frontOfTask && index < (mHistory.size()-1)) {
3930 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3931 if (next.task == r.task) {
3932 next.frontOfTask = true;
3933 }
3934 }
3935
3936 r.pauseKeyDispatchingLocked();
3937 if (mFocusedActivity == r) {
3938 setFocusedActivityLocked(topRunningActivityLocked(null));
3939 }
3940
3941 // send the result
3942 HistoryRecord resultTo = r.resultTo;
3943 if (resultTo != null) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003944 if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
3945 + " who=" + r.resultWho + " req=" + r.requestCode
3946 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 if (r.info.applicationInfo.uid > 0) {
3948 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3949 r.packageName, resultData, r);
3950 }
3951 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3952 resultData);
3953 r.resultTo = null;
3954 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003955 else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956
3957 // Make sure this HistoryRecord is not holding on to other resources,
3958 // because clients have remote IPC references to this object so we
3959 // can't assume that will go away and want to avoid circular IPC refs.
3960 r.results = null;
3961 r.pendingResults = null;
3962 r.newIntents = null;
3963 r.icicle = null;
3964
3965 if (mPendingThumbnails.size() > 0) {
3966 // There are clients waiting to receive thumbnails so, in case
3967 // this is an activity that someone is waiting for, add it
3968 // to the pending list so we can correctly update the clients.
3969 mCancelledThumbnails.add(r);
3970 }
3971
3972 if (mResumedActivity == r) {
3973 boolean endTask = index <= 0
3974 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3975 if (DEBUG_TRANSITION) Log.v(TAG,
3976 "Prepare close transition: finishing " + r);
3977 mWindowManager.prepareAppTransition(endTask
3978 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3979 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
3980
3981 // Tell window manager to prepare for this one to be removed.
3982 mWindowManager.setAppVisibility(r, false);
3983
3984 if (mPausingActivity == null) {
3985 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
3986 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
3987 startPausingLocked(false, false);
3988 }
3989
3990 } else if (r.state != ActivityState.PAUSING) {
3991 // If the activity is PAUSING, we will complete the finish once
3992 // it is done pausing; else we can just directly finish it here.
3993 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
3994 return finishCurrentActivityLocked(r, index,
3995 FINISH_AFTER_PAUSE) == null;
3996 } else {
3997 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
3998 }
3999
4000 return false;
4001 }
4002
4003 private static final int FINISH_IMMEDIATELY = 0;
4004 private static final int FINISH_AFTER_PAUSE = 1;
4005 private static final int FINISH_AFTER_VISIBLE = 2;
4006
4007 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4008 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004009 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 if (index < 0) {
4011 return null;
4012 }
4013
4014 return finishCurrentActivityLocked(r, index, mode);
4015 }
4016
4017 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4018 int index, int mode) {
4019 // First things first: if this activity is currently visible,
4020 // and the resumed activity is not yet visible, then hold off on
4021 // finishing until the resumed one becomes visible.
4022 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4023 if (!mStoppingActivities.contains(r)) {
4024 mStoppingActivities.add(r);
4025 if (mStoppingActivities.size() > 3) {
4026 // If we already have a few activities waiting to stop,
4027 // then give up on things going idle and start clearing
4028 // them out.
4029 Message msg = Message.obtain();
4030 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4031 mHandler.sendMessage(msg);
4032 }
4033 }
4034 r.state = ActivityState.STOPPING;
4035 updateOomAdjLocked();
4036 return r;
4037 }
4038
4039 // make sure the record is cleaned out of other places.
4040 mStoppingActivities.remove(r);
4041 mWaitingVisibleActivities.remove(r);
4042 if (mResumedActivity == r) {
4043 mResumedActivity = null;
4044 }
4045 final ActivityState prevState = r.state;
4046 r.state = ActivityState.FINISHING;
4047
4048 if (mode == FINISH_IMMEDIATELY
4049 || prevState == ActivityState.STOPPED
4050 || prevState == ActivityState.INITIALIZING) {
4051 // If this activity is already stopped, we can just finish
4052 // it right now.
4053 return destroyActivityLocked(r, true) ? null : r;
4054 } else {
4055 // Need to go through the full pause cycle to get this
4056 // activity into the stopped state and then finish it.
4057 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
4058 mFinishingActivities.add(r);
4059 resumeTopActivityLocked(null);
4060 }
4061 return r;
4062 }
4063
4064 /**
4065 * This is the internal entry point for handling Activity.finish().
4066 *
4067 * @param token The Binder token referencing the Activity we want to finish.
4068 * @param resultCode Result code, if any, from this Activity.
4069 * @param resultData Result data (Intent), if any, from this Activity.
4070 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004071 * @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 -08004072 */
4073 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4074 // Refuse possible leaked file descriptors
4075 if (resultData != null && resultData.hasFileDescriptors() == true) {
4076 throw new IllegalArgumentException("File descriptors passed in Intent");
4077 }
4078
4079 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004080 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 // Find the first activity that is not finishing.
4082 HistoryRecord next = topRunningActivityLocked(token, 0);
4083 if (next != null) {
4084 // ask watcher if this is allowed
4085 boolean resumeOK = true;
4086 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004087 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004089 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 }
4091
4092 if (!resumeOK) {
4093 return false;
4094 }
4095 }
4096 }
4097 final long origId = Binder.clearCallingIdentity();
4098 boolean res = requestFinishActivityLocked(token, resultCode,
4099 resultData, "app-request");
4100 Binder.restoreCallingIdentity(origId);
4101 return res;
4102 }
4103 }
4104
4105 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4106 String resultWho, int requestCode, int resultCode, Intent data) {
4107
4108 if (callingUid > 0) {
4109 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4110 data, r);
4111 }
4112
The Android Open Source Project10592532009-03-18 17:39:46 -07004113 if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
4114 + " : who=" + resultWho + " req=" + requestCode
4115 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4117 try {
4118 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4119 list.add(new ResultInfo(resultWho, requestCode,
4120 resultCode, data));
4121 r.app.thread.scheduleSendResult(r, list);
4122 return;
4123 } catch (Exception e) {
4124 Log.w(TAG, "Exception thrown sending result to " + r, e);
4125 }
4126 }
4127
4128 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4129 }
4130
4131 public final void finishSubActivity(IBinder token, String resultWho,
4132 int requestCode) {
4133 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004134 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135 if (index < 0) {
4136 return;
4137 }
4138 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4139
4140 final long origId = Binder.clearCallingIdentity();
4141
4142 int i;
4143 for (i=mHistory.size()-1; i>=0; i--) {
4144 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4145 if (r.resultTo == self && r.requestCode == requestCode) {
4146 if ((r.resultWho == null && resultWho == null) ||
4147 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4148 finishActivityLocked(r, i,
4149 Activity.RESULT_CANCELED, null, "request-sub");
4150 }
4151 }
4152 }
4153
4154 Binder.restoreCallingIdentity(origId);
4155 }
4156 }
4157
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004158 public void overridePendingTransition(IBinder token, String packageName,
4159 int enterAnim, int exitAnim) {
4160 synchronized(this) {
4161 int index = indexOfTokenLocked(token);
4162 if (index < 0) {
4163 return;
4164 }
4165 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4166
4167 final long origId = Binder.clearCallingIdentity();
4168
4169 if (self.state == ActivityState.RESUMED
4170 || self.state == ActivityState.PAUSING) {
4171 mWindowManager.overridePendingAppTransition(packageName,
4172 enterAnim, exitAnim);
4173 }
4174
4175 Binder.restoreCallingIdentity(origId);
4176 }
4177 }
4178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 /**
4180 * Perform clean-up of service connections in an activity record.
4181 */
4182 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4183 // Throw away any services that have been bound by this activity.
4184 if (r.connections != null) {
4185 Iterator<ConnectionRecord> it = r.connections.iterator();
4186 while (it.hasNext()) {
4187 ConnectionRecord c = it.next();
4188 removeConnectionLocked(c, null, r);
4189 }
4190 r.connections = null;
4191 }
4192 }
4193
4194 /**
4195 * Perform the common clean-up of an activity record. This is called both
4196 * as part of destroyActivityLocked() (when destroying the client-side
4197 * representation) and cleaning things up as a result of its hosting
4198 * processing going away, in which case there is no remaining client-side
4199 * state to destroy so only the cleanup here is needed.
4200 */
4201 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4202 if (mResumedActivity == r) {
4203 mResumedActivity = null;
4204 }
4205 if (mFocusedActivity == r) {
4206 mFocusedActivity = null;
4207 }
4208
4209 r.configDestroy = false;
4210 r.frozenBeforeDestroy = false;
4211
4212 // Make sure this record is no longer in the pending finishes list.
4213 // This could happen, for example, if we are trimming activities
4214 // down to the max limit while they are still waiting to finish.
4215 mFinishingActivities.remove(r);
4216 mWaitingVisibleActivities.remove(r);
4217
4218 // Remove any pending results.
4219 if (r.finishing && r.pendingResults != null) {
4220 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4221 PendingIntentRecord rec = apr.get();
4222 if (rec != null) {
4223 cancelIntentSenderLocked(rec, false);
4224 }
4225 }
4226 r.pendingResults = null;
4227 }
4228
4229 if (cleanServices) {
4230 cleanUpActivityServicesLocked(r);
4231 }
4232
4233 if (mPendingThumbnails.size() > 0) {
4234 // There are clients waiting to receive thumbnails so, in case
4235 // this is an activity that someone is waiting for, add it
4236 // to the pending list so we can correctly update the clients.
4237 mCancelledThumbnails.add(r);
4238 }
4239
4240 // Get rid of any pending idle timeouts.
4241 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4242 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4243 }
4244
4245 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4246 if (r.state != ActivityState.DESTROYED) {
4247 mHistory.remove(r);
4248 r.inHistory = false;
4249 r.state = ActivityState.DESTROYED;
4250 mWindowManager.removeAppToken(r);
4251 if (VALIDATE_TOKENS) {
4252 mWindowManager.validateAppTokens(mHistory);
4253 }
4254 cleanUpActivityServicesLocked(r);
4255 removeActivityUriPermissionsLocked(r);
4256 }
4257 }
4258
4259 /**
4260 * Destroy the current CLIENT SIDE instance of an activity. This may be
4261 * called both when actually finishing an activity, or when performing
4262 * a configuration switch where we destroy the current client-side object
4263 * but then create a new client-side object for this same HistoryRecord.
4264 */
4265 private final boolean destroyActivityLocked(HistoryRecord r,
4266 boolean removeFromApp) {
4267 if (DEBUG_SWITCH) Log.v(
4268 TAG, "Removing activity: token=" + r
4269 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004270 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 System.identityHashCode(r),
4272 r.task.taskId, r.shortComponentName);
4273
4274 boolean removedFromHistory = false;
4275
4276 cleanUpActivityLocked(r, false);
4277
Dianne Hackborn03abb812010-01-04 18:43:19 -08004278 final boolean hadApp = r.app != null;
4279
4280 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 if (removeFromApp) {
4282 int idx = r.app.activities.indexOf(r);
4283 if (idx >= 0) {
4284 r.app.activities.remove(idx);
4285 }
4286 if (r.persistent) {
4287 decPersistentCountLocked(r.app);
4288 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004289 if (r.app.activities.size() == 0) {
4290 // No longer have activities, so update location in
4291 // LRU list.
4292 updateLruProcessLocked(r.app, true, false);
4293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 }
4295
4296 boolean skipDestroy = false;
4297
4298 try {
4299 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
4300 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4301 r.configChangeFlags);
4302 } catch (Exception e) {
4303 // We can just ignore exceptions here... if the process
4304 // has crashed, our death notification will clean things
4305 // up.
4306 //Log.w(TAG, "Exception thrown during finish", e);
4307 if (r.finishing) {
4308 removeActivityFromHistoryLocked(r);
4309 removedFromHistory = true;
4310 skipDestroy = true;
4311 }
4312 }
4313
4314 r.app = null;
4315 r.nowVisible = false;
4316
4317 if (r.finishing && !skipDestroy) {
4318 r.state = ActivityState.DESTROYING;
4319 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4320 msg.obj = r;
4321 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4322 } else {
4323 r.state = ActivityState.DESTROYED;
4324 }
4325 } else {
4326 // remove this record from the history.
4327 if (r.finishing) {
4328 removeActivityFromHistoryLocked(r);
4329 removedFromHistory = true;
4330 } else {
4331 r.state = ActivityState.DESTROYED;
4332 }
4333 }
4334
4335 r.configChangeFlags = 0;
4336
Dianne Hackborn03abb812010-01-04 18:43:19 -08004337 if (!mLRUActivities.remove(r) && hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4339 }
4340
4341 return removedFromHistory;
4342 }
4343
Dianne Hackborn03abb812010-01-04 18:43:19 -08004344 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 int i = list.size();
4346 if (localLOGV) Log.v(
4347 TAG, "Removing app " + app + " from list " + list
4348 + " with " + i + " entries");
4349 while (i > 0) {
4350 i--;
4351 HistoryRecord r = (HistoryRecord)list.get(i);
4352 if (localLOGV) Log.v(
4353 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4354 if (r.app == app) {
4355 if (localLOGV) Log.v(TAG, "Removing this entry!");
4356 list.remove(i);
4357 }
4358 }
4359 }
4360
4361 /**
4362 * Main function for removing an existing process from the activity manager
4363 * as a result of that process going away. Clears out all connections
4364 * to the process.
4365 */
4366 private final void handleAppDiedLocked(ProcessRecord app,
4367 boolean restarting) {
4368 cleanUpApplicationRecordLocked(app, restarting, -1);
4369 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004370 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 }
4372
4373 // Just in case...
4374 if (mPausingActivity != null && mPausingActivity.app == app) {
4375 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
4376 mPausingActivity = null;
4377 }
4378 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4379 mLastPausedActivity = null;
4380 }
4381
4382 // Remove this application's activities from active lists.
4383 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4384 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4385 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4386 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4387
4388 boolean atTop = true;
4389 boolean hasVisibleActivities = false;
4390
4391 // Clean out the history list.
4392 int i = mHistory.size();
4393 if (localLOGV) Log.v(
4394 TAG, "Removing app " + app + " from history with " + i + " entries");
4395 while (i > 0) {
4396 i--;
4397 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4398 if (localLOGV) Log.v(
4399 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4400 if (r.app == app) {
4401 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4402 if (localLOGV) Log.v(
4403 TAG, "Removing this entry! frozen=" + r.haveState
4404 + " finishing=" + r.finishing);
4405 mHistory.remove(i);
4406
4407 r.inHistory = false;
4408 mWindowManager.removeAppToken(r);
4409 if (VALIDATE_TOKENS) {
4410 mWindowManager.validateAppTokens(mHistory);
4411 }
4412 removeActivityUriPermissionsLocked(r);
4413
4414 } else {
4415 // We have the current state for this activity, so
4416 // it can be restarted later when needed.
4417 if (localLOGV) Log.v(
4418 TAG, "Keeping entry, setting app to null");
4419 if (r.visible) {
4420 hasVisibleActivities = true;
4421 }
4422 r.app = null;
4423 r.nowVisible = false;
4424 if (!r.haveState) {
4425 r.icicle = null;
4426 }
4427 }
4428
4429 cleanUpActivityLocked(r, true);
4430 r.state = ActivityState.STOPPED;
4431 }
4432 atTop = false;
4433 }
4434
4435 app.activities.clear();
4436
4437 if (app.instrumentationClass != null) {
4438 Log.w(TAG, "Crash of app " + app.processName
4439 + " running instrumentation " + app.instrumentationClass);
4440 Bundle info = new Bundle();
4441 info.putString("shortMsg", "Process crashed.");
4442 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4443 }
4444
4445 if (!restarting) {
4446 if (!resumeTopActivityLocked(null)) {
4447 // If there was nothing to resume, and we are not already
4448 // restarting this process, but there is a visible activity that
4449 // is hosted by the process... then make sure all visible
4450 // activities are running, taking care of restarting this
4451 // process.
4452 if (hasVisibleActivities) {
4453 ensureActivitiesVisibleLocked(null, 0);
4454 }
4455 }
4456 }
4457 }
4458
4459 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4460 IBinder threadBinder = thread.asBinder();
4461
4462 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004463 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4464 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4466 return i;
4467 }
4468 }
4469 return -1;
4470 }
4471
4472 private final ProcessRecord getRecordForAppLocked(
4473 IApplicationThread thread) {
4474 if (thread == null) {
4475 return null;
4476 }
4477
4478 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004479 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 }
4481
4482 private final void appDiedLocked(ProcessRecord app, int pid,
4483 IApplicationThread thread) {
4484
4485 mProcDeaths[0]++;
4486
4487 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4488 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4489 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004490 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 if (localLOGV) Log.v(
4492 TAG, "Dying app: " + app + ", pid: " + pid
4493 + ", thread: " + thread.asBinder());
4494 boolean doLowMem = app.instrumentationClass == null;
4495 handleAppDiedLocked(app, false);
4496
4497 if (doLowMem) {
4498 // If there are no longer any background processes running,
4499 // and the app that died was not running instrumentation,
4500 // then tell everyone we are now low on memory.
4501 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004502 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4503 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4505 haveBg = true;
4506 break;
4507 }
4508 }
4509
4510 if (!haveBg) {
4511 Log.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004512 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004513 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004514 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4515 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004516 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004517 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4518 // The low memory report is overriding any current
4519 // state for a GC request. Make sure to do
4520 // visible/foreground processes first.
4521 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4522 rec.lastRequestedGc = 0;
4523 } else {
4524 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004526 rec.reportLowMemory = true;
4527 rec.lastLowMemory = now;
4528 mProcessesToGc.remove(rec);
4529 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 }
4531 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004532 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 }
4534 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004535 } else if (DEBUG_PROCESSES) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 Log.d(TAG, "Received spurious death notification for thread "
4537 + thread.asBinder());
4538 }
4539 }
4540
Dan Egnor42471dd2010-01-07 17:25:22 -08004541 /**
4542 * If a stack trace dump file is configured, dump process stack traces.
4543 * @param pids of dalvik VM processes to dump stack traces for
4544 * @return file containing stack traces, or null if no dump file is configured
4545 */
4546 private static File dumpStackTraces(ArrayList<Integer> pids) {
4547 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4548 if (tracesPath == null || tracesPath.length() == 0) {
4549 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004551
4552 File tracesFile = new File(tracesPath);
4553 try {
4554 File tracesDir = tracesFile.getParentFile();
4555 if (!tracesDir.exists()) tracesFile.mkdirs();
4556 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4557
4558 if (tracesFile.exists()) tracesFile.delete();
4559 tracesFile.createNewFile();
4560 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4561 } catch (IOException e) {
4562 Log.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
4563 return null;
4564 }
4565
4566 // Use a FileObserver to detect when traces finish writing.
4567 // The order of traces is considered important to maintain for legibility.
4568 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4569 public synchronized void onEvent(int event, String path) { notify(); }
4570 };
4571
4572 try {
4573 observer.startWatching();
4574 int num = pids.size();
4575 for (int i = 0; i < num; i++) {
4576 synchronized (observer) {
4577 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4578 observer.wait(200); // Wait for write-close, give up after 200msec
4579 }
4580 }
4581 } catch (InterruptedException e) {
4582 Log.wtf(TAG, e);
4583 } finally {
4584 observer.stopWatching();
4585 }
4586
4587 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 }
4589
Dan Egnor42471dd2010-01-07 17:25:22 -08004590 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4591 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 if (app.notResponding || app.crashing) {
4593 return;
4594 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004597 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4598 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599
Dan Egnor42471dd2010-01-07 17:25:22 -08004600 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4601 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4602 pids.add(app.pid);
4603
4604 int parentPid = app.pid;
4605 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4606 if (parentPid != app.pid) pids.add(parentPid);
4607
4608 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4609
4610 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4611 ProcessRecord r = mLruProcesses.get(i);
4612 if (r != null && r.thread != null) {
4613 int pid = r.pid;
4614 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 }
4616 }
4617
Dan Egnor42471dd2010-01-07 17:25:22 -08004618 File tracesFile = dumpStackTraces(pids);
4619
4620 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004621 StringBuilder info = mStringBuilder;
4622 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004623 info.append("ANR in ").append(app.processName);
4624 if (activity != null && activity.shortComponentName != null) {
4625 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004626 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004627 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004629 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004631 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004632 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634
Dan Egnor42471dd2010-01-07 17:25:22 -08004635 String cpuInfo = null;
4636 if (MONITOR_CPU_USAGE) {
4637 updateCpuStatsNow();
4638 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4639 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 }
4641
Dan Egnor42471dd2010-01-07 17:25:22 -08004642 Log.e(TAG, info.toString());
4643 if (tracesFile == null) {
4644 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4645 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4646 }
4647
4648 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4649
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004650 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004652 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4653 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004655 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4656 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 }
4658 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004659 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004660 }
4661 }
4662
Dan Egnor42471dd2010-01-07 17:25:22 -08004663 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4664 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4665 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4666 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4667 Process.killProcess(app.pid);
4668 return;
4669 }
4670
4671 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 makeAppNotRespondingLocked(app,
4673 activity != null ? activity.shortComponentName : null,
4674 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004675 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004676
4677 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 Message msg = Message.obtain();
4679 HashMap map = new HashMap();
4680 msg.what = SHOW_NOT_RESPONDING_MSG;
4681 msg.obj = map;
4682 map.put("app", app);
4683 if (activity != null) {
4684 map.put("activity", activity);
4685 }
4686
4687 mHandler.sendMessage(msg);
4688 return;
4689 }
4690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 private final void decPersistentCountLocked(ProcessRecord app)
4692 {
4693 app.persistentActivities--;
4694 if (app.persistentActivities > 0) {
4695 // Still more of 'em...
4696 return;
4697 }
4698 if (app.persistent) {
4699 // Ah, but the application itself is persistent. Whatever!
4700 return;
4701 }
4702
4703 // App is no longer persistent... make sure it and the ones
4704 // following it in the LRU list have the correc oom_adj.
4705 updateOomAdjLocked();
4706 }
4707
4708 public void setPersistent(IBinder token, boolean isPersistent) {
4709 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4710 != PackageManager.PERMISSION_GRANTED) {
4711 String msg = "Permission Denial: setPersistent() from pid="
4712 + Binder.getCallingPid()
4713 + ", uid=" + Binder.getCallingUid()
4714 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4715 Log.w(TAG, msg);
4716 throw new SecurityException(msg);
4717 }
4718
4719 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004720 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 if (index < 0) {
4722 return;
4723 }
4724 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4725 ProcessRecord app = r.app;
4726
4727 if (localLOGV) Log.v(
4728 TAG, "Setting persistence " + isPersistent + ": " + r);
4729
4730 if (isPersistent) {
4731 if (r.persistent) {
4732 // Okay okay, I heard you already!
4733 if (localLOGV) Log.v(TAG, "Already persistent!");
4734 return;
4735 }
4736 r.persistent = true;
4737 app.persistentActivities++;
4738 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4739 if (app.persistentActivities > 1) {
4740 // We aren't the first...
4741 if (localLOGV) Log.v(TAG, "Not the first!");
4742 return;
4743 }
4744 if (app.persistent) {
4745 // This would be redundant.
4746 if (localLOGV) Log.v(TAG, "App is persistent!");
4747 return;
4748 }
4749
4750 // App is now persistent... make sure it and the ones
4751 // following it now have the correct oom_adj.
4752 final long origId = Binder.clearCallingIdentity();
4753 updateOomAdjLocked();
4754 Binder.restoreCallingIdentity(origId);
4755
4756 } else {
4757 if (!r.persistent) {
4758 // Okay okay, I heard you already!
4759 return;
4760 }
4761 r.persistent = false;
4762 final long origId = Binder.clearCallingIdentity();
4763 decPersistentCountLocked(app);
4764 Binder.restoreCallingIdentity(origId);
4765
4766 }
4767 }
4768 }
4769
4770 public boolean clearApplicationUserData(final String packageName,
4771 final IPackageDataObserver observer) {
4772 int uid = Binder.getCallingUid();
4773 int pid = Binder.getCallingPid();
4774 long callingId = Binder.clearCallingIdentity();
4775 try {
4776 IPackageManager pm = ActivityThread.getPackageManager();
4777 int pkgUid = -1;
4778 synchronized(this) {
4779 try {
4780 pkgUid = pm.getPackageUid(packageName);
4781 } catch (RemoteException e) {
4782 }
4783 if (pkgUid == -1) {
4784 Log.w(TAG, "Invalid packageName:" + packageName);
4785 return false;
4786 }
4787 if (uid == pkgUid || checkComponentPermission(
4788 android.Manifest.permission.CLEAR_APP_USER_DATA,
4789 pid, uid, -1)
4790 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004791 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 } else {
4793 throw new SecurityException(pid+" does not have permission:"+
4794 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4795 "for process:"+packageName);
4796 }
4797 }
4798
4799 try {
4800 //clear application user data
4801 pm.clearApplicationUserData(packageName, observer);
4802 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4803 Uri.fromParts("package", packageName, null));
4804 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4805 broadcastIntentLocked(null, null, intent,
4806 null, null, 0, null, null, null,
4807 false, false, MY_PID, Process.SYSTEM_UID);
4808 } catch (RemoteException e) {
4809 }
4810 } finally {
4811 Binder.restoreCallingIdentity(callingId);
4812 }
4813 return true;
4814 }
4815
Dianne Hackborn03abb812010-01-04 18:43:19 -08004816 public void killBackgroundProcesses(final String packageName) {
4817 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4818 != PackageManager.PERMISSION_GRANTED &&
4819 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4820 != PackageManager.PERMISSION_GRANTED) {
4821 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 + Binder.getCallingPid()
4823 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004824 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004825 Log.w(TAG, msg);
4826 throw new SecurityException(msg);
4827 }
4828
4829 long callingId = Binder.clearCallingIdentity();
4830 try {
4831 IPackageManager pm = ActivityThread.getPackageManager();
4832 int pkgUid = -1;
4833 synchronized(this) {
4834 try {
4835 pkgUid = pm.getPackageUid(packageName);
4836 } catch (RemoteException e) {
4837 }
4838 if (pkgUid == -1) {
4839 Log.w(TAG, "Invalid packageName: " + packageName);
4840 return;
4841 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004842 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004843 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004844 }
4845 } finally {
4846 Binder.restoreCallingIdentity(callingId);
4847 }
4848 }
4849
4850 public void forceStopPackage(final String packageName) {
4851 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4852 != PackageManager.PERMISSION_GRANTED) {
4853 String msg = "Permission Denial: forceStopPackage() from pid="
4854 + Binder.getCallingPid()
4855 + ", uid=" + Binder.getCallingUid()
4856 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4857 Log.w(TAG, msg);
4858 throw new SecurityException(msg);
4859 }
4860
4861 long callingId = Binder.clearCallingIdentity();
4862 try {
4863 IPackageManager pm = ActivityThread.getPackageManager();
4864 int pkgUid = -1;
4865 synchronized(this) {
4866 try {
4867 pkgUid = pm.getPackageUid(packageName);
4868 } catch (RemoteException e) {
4869 }
4870 if (pkgUid == -1) {
4871 Log.w(TAG, "Invalid packageName: " + packageName);
4872 return;
4873 }
4874 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004875 }
4876 } finally {
4877 Binder.restoreCallingIdentity(callingId);
4878 }
4879 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004880
4881 /*
4882 * The pkg name and uid have to be specified.
4883 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4884 */
4885 public void killApplicationWithUid(String pkg, int uid) {
4886 if (pkg == null) {
4887 return;
4888 }
4889 // Make sure the uid is valid.
4890 if (uid < 0) {
4891 Log.w(TAG, "Invalid uid specified for pkg : " + pkg);
4892 return;
4893 }
4894 int callerUid = Binder.getCallingUid();
4895 // Only the system server can kill an application
4896 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004897 // Post an aysnc message to kill the application
4898 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4899 msg.arg1 = uid;
4900 msg.arg2 = 0;
4901 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004902 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004903 } else {
4904 throw new SecurityException(callerUid + " cannot kill pkg: " +
4905 pkg);
4906 }
4907 }
4908
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004909 public void closeSystemDialogs(String reason) {
4910 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
4911 if (reason != null) {
4912 intent.putExtra("reason", reason);
4913 }
4914
4915 final int uid = Binder.getCallingUid();
4916 final long origId = Binder.clearCallingIdentity();
4917 synchronized (this) {
4918 int i = mWatchers.beginBroadcast();
4919 while (i > 0) {
4920 i--;
4921 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4922 if (w != null) {
4923 try {
4924 w.closingSystemDialogs(reason);
4925 } catch (RemoteException e) {
4926 }
4927 }
4928 }
4929 mWatchers.finishBroadcast();
4930
Dianne Hackbornffa42482009-09-23 22:20:11 -07004931 mWindowManager.closeSystemDialogs(reason);
4932
4933 for (i=mHistory.size()-1; i>=0; i--) {
4934 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4935 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4936 finishActivityLocked(r, i,
4937 Activity.RESULT_CANCELED, null, "close-sys");
4938 }
4939 }
4940
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004941 broadcastIntentLocked(null, null, intent, null,
4942 null, 0, null, null, null, false, false, -1, uid);
4943 }
4944 Binder.restoreCallingIdentity(origId);
4945 }
4946
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004947 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004948 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004949 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4950 for (int i=pids.length-1; i>=0; i--) {
4951 infos[i] = new Debug.MemoryInfo();
4952 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004953 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004954 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004955 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004956
4957 public void killApplicationProcess(String processName, int uid) {
4958 if (processName == null) {
4959 return;
4960 }
4961
4962 int callerUid = Binder.getCallingUid();
4963 // Only the system server can kill an application
4964 if (callerUid == Process.SYSTEM_UID) {
4965 synchronized (this) {
4966 ProcessRecord app = getProcessRecordLocked(processName, uid);
4967 if (app != null) {
4968 try {
4969 app.thread.scheduleSuicide();
4970 } catch (RemoteException e) {
4971 // If the other end already died, then our work here is done.
4972 }
4973 } else {
4974 Log.w(TAG, "Process/uid not found attempting kill of "
4975 + processName + " / " + uid);
4976 }
4977 }
4978 } else {
4979 throw new SecurityException(callerUid + " cannot kill app process: " +
4980 processName);
4981 }
4982 }
4983
Dianne Hackborn03abb812010-01-04 18:43:19 -08004984 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004985 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4987 Uri.fromParts("package", packageName, null));
4988 intent.putExtra(Intent.EXTRA_UID, uid);
4989 broadcastIntentLocked(null, null, intent,
4990 null, null, 0, null, null, null,
4991 false, false, MY_PID, Process.SYSTEM_UID);
4992 }
4993
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004994 private final boolean killPackageProcessesLocked(String packageName, int uid,
4995 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004996 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997
Dianne Hackborn03abb812010-01-04 18:43:19 -08004998 // Remove all processes this package may have touched: all with the
4999 // same UID (except for the system or root user), and all whose name
5000 // matches the package name.
5001 final String procNamePrefix = packageName + ":";
5002 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5003 final int NA = apps.size();
5004 for (int ia=0; ia<NA; ia++) {
5005 ProcessRecord app = apps.valueAt(ia);
5006 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005007 if (doit) {
5008 procs.add(app);
5009 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005010 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5011 || app.processName.equals(packageName)
5012 || app.processName.startsWith(procNamePrefix)) {
5013 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005014 if (!doit) {
5015 return true;
5016 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005017 app.removed = true;
5018 procs.add(app);
5019 }
5020 }
5021 }
5022 }
5023
5024 int N = procs.size();
5025 for (int i=0; i<N; i++) {
5026 removeProcessLocked(procs.get(i), callerWillRestart);
5027 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005028 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005029 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005030
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005031 private final boolean forceStopPackageLocked(String name, int uid,
5032 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 int i, N;
5034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 if (uid < 0) {
5036 try {
5037 uid = ActivityThread.getPackageManager().getPackageUid(name);
5038 } catch (RemoteException e) {
5039 }
5040 }
5041
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005042 if (doit) {
5043 Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005044
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005045 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5046 while (badApps.hasNext()) {
5047 SparseArray<Long> ba = badApps.next();
5048 if (ba.get(uid) != null) {
5049 badApps.remove();
5050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 }
5052 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005053
5054 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5055 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056
5057 for (i=mHistory.size()-1; i>=0; i--) {
5058 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5059 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005060 if (!doit) {
5061 return true;
5062 }
5063 didSomething = true;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005064 Log.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 if (r.app != null) {
5066 r.app.removed = true;
5067 }
5068 r.app = null;
5069 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5070 }
5071 }
5072
5073 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5074 for (ServiceRecord service : mServices.values()) {
5075 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005076 if (!doit) {
5077 return true;
5078 }
5079 didSomething = true;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005080 Log.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 if (service.app != null) {
5082 service.app.removed = true;
5083 }
5084 service.app = null;
5085 services.add(service);
5086 }
5087 }
5088
5089 N = services.size();
5090 for (i=0; i<N; i++) {
5091 bringDownServiceLocked(services.get(i), true);
5092 }
5093
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005094 if (doit) {
5095 if (purgeCache) {
5096 AttributeCache ac = AttributeCache.instance();
5097 if (ac != null) {
5098 ac.removePackage(name);
5099 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005100 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005101 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005102 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005103
5104 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 }
5106
5107 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5108 final String name = app.processName;
5109 final int uid = app.info.uid;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005110 if (DEBUG_PROCESSES) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005111 TAG, "Force removing process " + app + " (" + name
5112 + "/" + uid + ")");
5113
5114 mProcessNames.remove(name, uid);
5115 boolean needRestart = false;
5116 if (app.pid > 0 && app.pid != MY_PID) {
5117 int pid = app.pid;
5118 synchronized (mPidsSelfLocked) {
5119 mPidsSelfLocked.remove(pid);
5120 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5121 }
5122 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005123 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 Process.killProcess(pid);
5125
5126 if (app.persistent) {
5127 if (!callerWillRestart) {
5128 addAppLocked(app.info);
5129 } else {
5130 needRestart = true;
5131 }
5132 }
5133 } else {
5134 mRemovedProcesses.add(app);
5135 }
5136
5137 return needRestart;
5138 }
5139
5140 private final void processStartTimedOutLocked(ProcessRecord app) {
5141 final int pid = app.pid;
5142 boolean gone = false;
5143 synchronized (mPidsSelfLocked) {
5144 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5145 if (knownApp != null && knownApp.thread == null) {
5146 mPidsSelfLocked.remove(pid);
5147 gone = true;
5148 }
5149 }
5150
5151 if (gone) {
5152 Log.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005153 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005154 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005156 // Take care of any launching providers waiting for this process.
5157 checkAppInLaunchingProvidersLocked(app, true);
5158 // Take care of any services that are waiting for the process.
5159 for (int i=0; i<mPendingServices.size(); i++) {
5160 ServiceRecord sr = mPendingServices.get(i);
5161 if (app.info.uid == sr.appInfo.uid
5162 && app.processName.equals(sr.processName)) {
5163 Log.w(TAG, "Forcing bringing down service: " + sr);
5164 mPendingServices.remove(i);
5165 i--;
5166 bringDownServiceLocked(sr, true);
5167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005169 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005170 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
5171 Log.w(TAG, "Unattached app died before backup, skipping");
5172 try {
5173 IBackupManager bm = IBackupManager.Stub.asInterface(
5174 ServiceManager.getService(Context.BACKUP_SERVICE));
5175 bm.agentDisconnected(app.info.packageName);
5176 } catch (RemoteException e) {
5177 // Can't happen; the backup manager is local
5178 }
5179 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005180 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
5181 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
5182 mPendingBroadcast = null;
5183 scheduleBroadcastsLocked();
5184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 } else {
5186 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
5187 }
5188 }
5189
5190 private final boolean attachApplicationLocked(IApplicationThread thread,
5191 int pid) {
5192
5193 // Find the application record that is being attached... either via
5194 // the pid if we are running in multiple processes, or just pull the
5195 // next app record if we are emulating process with anonymous threads.
5196 ProcessRecord app;
5197 if (pid != MY_PID && pid >= 0) {
5198 synchronized (mPidsSelfLocked) {
5199 app = mPidsSelfLocked.get(pid);
5200 }
5201 } else if (mStartingProcesses.size() > 0) {
5202 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005203 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 } else {
5205 app = null;
5206 }
5207
5208 if (app == null) {
5209 Log.w(TAG, "No pending application record for pid " + pid
5210 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005211 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 if (pid > 0 && pid != MY_PID) {
5213 Process.killProcess(pid);
5214 } else {
5215 try {
5216 thread.scheduleExit();
5217 } catch (Exception e) {
5218 // Ignore exceptions.
5219 }
5220 }
5221 return false;
5222 }
5223
5224 // If this application record is still attached to a previous
5225 // process, clean it up now.
5226 if (app.thread != null) {
5227 handleAppDiedLocked(app, true);
5228 }
5229
5230 // Tell the process all about itself.
5231
5232 if (localLOGV) Log.v(
5233 TAG, "Binding process pid " + pid + " to record " + app);
5234
5235 String processName = app.processName;
5236 try {
5237 thread.asBinder().linkToDeath(new AppDeathRecipient(
5238 app, pid, thread), 0);
5239 } catch (RemoteException e) {
5240 app.resetPackageList();
5241 startProcessLocked(app, "link fail", processName);
5242 return false;
5243 }
5244
Doug Zongker2bec3d42009-12-04 12:52:44 -08005245 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246
5247 app.thread = thread;
5248 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005249 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5250 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 app.forcingToForeground = null;
5252 app.foregroundServices = false;
5253 app.debugging = false;
5254
5255 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5256
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005257 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5258 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005260 if (!normalMode) {
5261 Log.i(TAG, "Launching preboot mode app: " + app);
5262 }
5263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 if (localLOGV) Log.v(
5265 TAG, "New app record " + app
5266 + " thread=" + thread.asBinder() + " pid=" + pid);
5267 try {
5268 int testMode = IApplicationThread.DEBUG_OFF;
5269 if (mDebugApp != null && mDebugApp.equals(processName)) {
5270 testMode = mWaitForDebugger
5271 ? IApplicationThread.DEBUG_WAIT
5272 : IApplicationThread.DEBUG_ON;
5273 app.debugging = true;
5274 if (mDebugTransient) {
5275 mDebugApp = mOrigDebugApp;
5276 mWaitForDebugger = mOrigWaitForDebugger;
5277 }
5278 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005279
Christopher Tate181fafa2009-05-14 11:12:14 -07005280 // If the app is being launched for restore or full backup, set it up specially
5281 boolean isRestrictedBackupMode = false;
5282 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5283 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5284 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5285 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005286
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005287 ensurePackageDexOpt(app.instrumentationInfo != null
5288 ? app.instrumentationInfo.packageName
5289 : app.info.packageName);
5290 if (app.instrumentationClass != null) {
5291 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005292 }
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005293 if (DEBUG_CONFIGURATION) Log.v(TAG, "Binding proc "
5294 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005295 thread.bindApplication(processName, app.instrumentationInfo != null
5296 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 app.instrumentationClass, app.instrumentationProfileFile,
5298 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005299 isRestrictedBackupMode || !normalMode,
5300 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005301 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005302 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 } catch (Exception e) {
5304 // todo: Yikes! What should we do? For now we will try to
5305 // start another process, but that could easily get us in
5306 // an infinite loop of restarting processes...
5307 Log.w(TAG, "Exception thrown during bind!", e);
5308
5309 app.resetPackageList();
5310 startProcessLocked(app, "bind fail", processName);
5311 return false;
5312 }
5313
5314 // Remove this record from the list of starting applications.
5315 mPersistentStartingProcesses.remove(app);
5316 mProcessesOnHold.remove(app);
5317
5318 boolean badApp = false;
5319 boolean didSomething = false;
5320
5321 // See if the top visible activity is waiting to run in this process...
5322 HistoryRecord hr = topRunningActivityLocked(null);
5323 if (hr != null) {
5324 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5325 && processName.equals(hr.processName)) {
5326 try {
5327 if (realStartActivityLocked(hr, app, true, true)) {
5328 didSomething = true;
5329 }
5330 } catch (Exception e) {
5331 Log.w(TAG, "Exception in new application when starting activity "
5332 + hr.intent.getComponent().flattenToShortString(), e);
5333 badApp = true;
5334 }
5335 } else {
5336 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5337 }
5338 }
5339
5340 // Find any services that should be running in this process...
5341 if (!badApp && mPendingServices.size() > 0) {
5342 ServiceRecord sr = null;
5343 try {
5344 for (int i=0; i<mPendingServices.size(); i++) {
5345 sr = mPendingServices.get(i);
5346 if (app.info.uid != sr.appInfo.uid
5347 || !processName.equals(sr.processName)) {
5348 continue;
5349 }
5350
5351 mPendingServices.remove(i);
5352 i--;
5353 realStartServiceLocked(sr, app);
5354 didSomething = true;
5355 }
5356 } catch (Exception e) {
5357 Log.w(TAG, "Exception in new application when starting service "
5358 + sr.shortName, e);
5359 badApp = true;
5360 }
5361 }
5362
5363 // Check if the next broadcast receiver is in this process...
5364 BroadcastRecord br = mPendingBroadcast;
5365 if (!badApp && br != null && br.curApp == app) {
5366 try {
5367 mPendingBroadcast = null;
5368 processCurBroadcastLocked(br, app);
5369 didSomething = true;
5370 } catch (Exception e) {
5371 Log.w(TAG, "Exception in new application when starting receiver "
5372 + br.curComponent.flattenToShortString(), e);
5373 badApp = true;
5374 logBroadcastReceiverDiscard(br);
5375 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5376 br.resultExtras, br.resultAbort, true);
5377 scheduleBroadcastsLocked();
5378 }
5379 }
5380
Christopher Tate181fafa2009-05-14 11:12:14 -07005381 // Check whether the next backup agent is in this process...
5382 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
5383 if (DEBUG_BACKUP) Log.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005384 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005385 try {
5386 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5387 } catch (Exception e) {
5388 Log.w(TAG, "Exception scheduling backup agent creation: ");
5389 e.printStackTrace();
5390 }
5391 }
5392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 if (badApp) {
5394 // todo: Also need to kill application to deal with all
5395 // kinds of exceptions.
5396 handleAppDiedLocked(app, false);
5397 return false;
5398 }
5399
5400 if (!didSomething) {
5401 updateOomAdjLocked();
5402 }
5403
5404 return true;
5405 }
5406
5407 public final void attachApplication(IApplicationThread thread) {
5408 synchronized (this) {
5409 int callingPid = Binder.getCallingPid();
5410 final long origId = Binder.clearCallingIdentity();
5411 attachApplicationLocked(thread, callingPid);
5412 Binder.restoreCallingIdentity(origId);
5413 }
5414 }
5415
Dianne Hackborne88846e2009-09-30 21:34:25 -07005416 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005418 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 Binder.restoreCallingIdentity(origId);
5420 }
5421
5422 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5423 boolean remove) {
5424 int N = mStoppingActivities.size();
5425 if (N <= 0) return null;
5426
5427 ArrayList<HistoryRecord> stops = null;
5428
5429 final boolean nowVisible = mResumedActivity != null
5430 && mResumedActivity.nowVisible
5431 && !mResumedActivity.waitingVisible;
5432 for (int i=0; i<N; i++) {
5433 HistoryRecord s = mStoppingActivities.get(i);
5434 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
5435 + nowVisible + " waitingVisible=" + s.waitingVisible
5436 + " finishing=" + s.finishing);
5437 if (s.waitingVisible && nowVisible) {
5438 mWaitingVisibleActivities.remove(s);
5439 s.waitingVisible = false;
5440 if (s.finishing) {
5441 // If this activity is finishing, it is sitting on top of
5442 // everyone else but we now know it is no longer needed...
5443 // so get rid of it. Otherwise, we need to go through the
5444 // normal flow and hide it once we determine that it is
5445 // hidden by the activities in front of it.
5446 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
5447 mWindowManager.setAppVisibility(s, false);
5448 }
5449 }
5450 if (!s.waitingVisible && remove) {
5451 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
5452 if (stops == null) {
5453 stops = new ArrayList<HistoryRecord>();
5454 }
5455 stops.add(s);
5456 mStoppingActivities.remove(i);
5457 N--;
5458 i--;
5459 }
5460 }
5461
5462 return stops;
5463 }
5464
5465 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005466 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005467 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 mWindowManager.enableScreenAfterBoot();
5469 }
5470
Dianne Hackborne88846e2009-09-30 21:34:25 -07005471 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5472 Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
5474
5475 ArrayList<HistoryRecord> stops = null;
5476 ArrayList<HistoryRecord> finishes = null;
5477 ArrayList<HistoryRecord> thumbnails = null;
5478 int NS = 0;
5479 int NF = 0;
5480 int NT = 0;
5481 IApplicationThread sendThumbnail = null;
5482 boolean booting = false;
5483 boolean enableScreen = false;
5484
5485 synchronized (this) {
5486 if (token != null) {
5487 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5488 }
5489
5490 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005491 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 if (index >= 0) {
5493 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5494
Dianne Hackborne88846e2009-09-30 21:34:25 -07005495 // This is a hack to semi-deal with a race condition
5496 // in the client where it can be constructed with a
5497 // newer configuration from when we asked it to launch.
5498 // We'll update with whatever configuration it now says
5499 // it used to launch.
5500 if (config != null) {
5501 r.configuration = config;
5502 }
5503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 // No longer need to keep the device awake.
5505 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5506 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5507 mLaunchingActivity.release();
5508 }
5509
5510 // We are now idle. If someone is waiting for a thumbnail from
5511 // us, we can now deliver.
5512 r.idle = true;
5513 scheduleAppGcsLocked();
5514 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5515 sendThumbnail = r.app.thread;
5516 r.thumbnailNeeded = false;
5517 }
5518
5519 // If this activity is fullscreen, set up to hide those under it.
5520
5521 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
5522 ensureActivitiesVisibleLocked(null, 0);
5523
5524 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
5525 if (!mBooted && !fromTimeout) {
5526 mBooted = true;
5527 enableScreen = true;
5528 }
5529 }
5530
5531 // Atomically retrieve all of the other things to do.
5532 stops = processStoppingActivitiesLocked(true);
5533 NS = stops != null ? stops.size() : 0;
5534 if ((NF=mFinishingActivities.size()) > 0) {
5535 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5536 mFinishingActivities.clear();
5537 }
5538 if ((NT=mCancelledThumbnails.size()) > 0) {
5539 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5540 mCancelledThumbnails.clear();
5541 }
5542
5543 booting = mBooting;
5544 mBooting = false;
5545 }
5546
5547 int i;
5548
5549 // Send thumbnail if requested.
5550 if (sendThumbnail != null) {
5551 try {
5552 sendThumbnail.requestThumbnail(token);
5553 } catch (Exception e) {
5554 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5555 sendPendingThumbnail(null, token, null, null, true);
5556 }
5557 }
5558
5559 // Stop any activities that are scheduled to do so but have been
5560 // waiting for the next one to start.
5561 for (i=0; i<NS; i++) {
5562 HistoryRecord r = (HistoryRecord)stops.get(i);
5563 synchronized (this) {
5564 if (r.finishing) {
5565 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5566 } else {
5567 stopActivityLocked(r);
5568 }
5569 }
5570 }
5571
5572 // Finish any activities that are scheduled to do so but have been
5573 // waiting for the next one to start.
5574 for (i=0; i<NF; i++) {
5575 HistoryRecord r = (HistoryRecord)finishes.get(i);
5576 synchronized (this) {
5577 destroyActivityLocked(r, true);
5578 }
5579 }
5580
5581 // Report back to any thumbnail receivers.
5582 for (i=0; i<NT; i++) {
5583 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5584 sendPendingThumbnail(r, null, null, null, true);
5585 }
5586
5587 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005588 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 }
5590
5591 trimApplications();
5592 //dump();
5593 //mWindowManager.dump();
5594
5595 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 enableScreenAfterBoot();
5597 }
5598 }
5599
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005600 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005601 IntentFilter pkgFilter = new IntentFilter();
5602 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5603 pkgFilter.addDataScheme("package");
5604 mContext.registerReceiver(new BroadcastReceiver() {
5605 @Override
5606 public void onReceive(Context context, Intent intent) {
5607 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5608 if (pkgs != null) {
5609 for (String pkg : pkgs) {
5610 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5611 setResultCode(Activity.RESULT_OK);
5612 return;
5613 }
5614 }
5615 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005616 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005617 }, pkgFilter);
5618
5619 synchronized (this) {
5620 // Ensure that any processes we had put on hold are now started
5621 // up.
5622 final int NP = mProcessesOnHold.size();
5623 if (NP > 0) {
5624 ArrayList<ProcessRecord> procs =
5625 new ArrayList<ProcessRecord>(mProcessesOnHold);
5626 for (int ip=0; ip<NP; ip++) {
5627 this.startProcessLocked(procs.get(ip), "on-hold", null);
5628 }
5629 }
5630
5631 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5632 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005633 broadcastIntentLocked(null, null,
5634 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5635 null, null, 0, null, null,
5636 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5637 false, false, MY_PID, Process.SYSTEM_UID);
5638 }
5639 }
5640 }
5641
5642 final void ensureBootCompleted() {
5643 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005644 boolean enableScreen;
5645 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005646 booting = mBooting;
5647 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005648 enableScreen = !mBooted;
5649 mBooted = true;
5650 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005651
5652 if (booting) {
5653 finishBooting();
5654 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005655
5656 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005657 enableScreenAfterBoot();
5658 }
5659 }
5660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 public final void activityPaused(IBinder token, Bundle icicle) {
5662 // Refuse possible leaked file descriptors
5663 if (icicle != null && icicle.hasFileDescriptors()) {
5664 throw new IllegalArgumentException("File descriptors passed in Bundle");
5665 }
5666
5667 final long origId = Binder.clearCallingIdentity();
5668 activityPaused(token, icicle, false);
5669 Binder.restoreCallingIdentity(origId);
5670 }
5671
5672 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
5673 if (DEBUG_PAUSE) Log.v(
5674 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5675 + ", timeout=" + timeout);
5676
5677 HistoryRecord r = null;
5678
5679 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005680 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005681 if (index >= 0) {
5682 r = (HistoryRecord)mHistory.get(index);
5683 if (!timeout) {
5684 r.icicle = icicle;
5685 r.haveState = true;
5686 }
5687 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5688 if (mPausingActivity == r) {
5689 r.state = ActivityState.PAUSED;
5690 completePauseLocked();
5691 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005692 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 System.identityHashCode(r), r.shortComponentName,
5694 mPausingActivity != null
5695 ? mPausingActivity.shortComponentName : "(none)");
5696 }
5697 }
5698 }
5699 }
5700
5701 public final void activityStopped(IBinder token, Bitmap thumbnail,
5702 CharSequence description) {
5703 if (localLOGV) Log.v(
5704 TAG, "Activity stopped: token=" + token);
5705
5706 HistoryRecord r = null;
5707
5708 final long origId = Binder.clearCallingIdentity();
5709
5710 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005711 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 if (index >= 0) {
5713 r = (HistoryRecord)mHistory.get(index);
5714 r.thumbnail = thumbnail;
5715 r.description = description;
5716 r.stopped = true;
5717 r.state = ActivityState.STOPPED;
5718 if (!r.finishing) {
5719 if (r.configDestroy) {
5720 destroyActivityLocked(r, true);
5721 resumeTopActivityLocked(null);
5722 }
5723 }
5724 }
5725 }
5726
5727 if (r != null) {
5728 sendPendingThumbnail(r, null, null, null, false);
5729 }
5730
5731 trimApplications();
5732
5733 Binder.restoreCallingIdentity(origId);
5734 }
5735
5736 public final void activityDestroyed(IBinder token) {
5737 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
5738 synchronized (this) {
5739 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5740
Dianne Hackborn75b03852009-06-12 15:43:26 -07005741 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005742 if (index >= 0) {
5743 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5744 if (r.state == ActivityState.DESTROYING) {
5745 final long origId = Binder.clearCallingIdentity();
5746 removeActivityFromHistoryLocked(r);
5747 Binder.restoreCallingIdentity(origId);
5748 }
5749 }
5750 }
5751 }
5752
5753 public String getCallingPackage(IBinder token) {
5754 synchronized (this) {
5755 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005756 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 }
5758 }
5759
5760 public ComponentName getCallingActivity(IBinder token) {
5761 synchronized (this) {
5762 HistoryRecord r = getCallingRecordLocked(token);
5763 return r != null ? r.intent.getComponent() : null;
5764 }
5765 }
5766
5767 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005768 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 if (index >= 0) {
5770 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5771 if (r != null) {
5772 return r.resultTo;
5773 }
5774 }
5775 return null;
5776 }
5777
5778 public ComponentName getActivityClassForToken(IBinder token) {
5779 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005780 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 if (index >= 0) {
5782 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5783 return r.intent.getComponent();
5784 }
5785 return null;
5786 }
5787 }
5788
5789 public String getPackageForToken(IBinder token) {
5790 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005791 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005792 if (index >= 0) {
5793 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5794 return r.packageName;
5795 }
5796 return null;
5797 }
5798 }
5799
5800 public IIntentSender getIntentSender(int type,
5801 String packageName, IBinder token, String resultWho,
5802 int requestCode, Intent intent, String resolvedType, int flags) {
5803 // Refuse possible leaked file descriptors
5804 if (intent != null && intent.hasFileDescriptors() == true) {
5805 throw new IllegalArgumentException("File descriptors passed in Intent");
5806 }
5807
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005808 if (type == INTENT_SENDER_BROADCAST) {
5809 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5810 throw new IllegalArgumentException(
5811 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5812 }
5813 }
5814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 synchronized(this) {
5816 int callingUid = Binder.getCallingUid();
5817 try {
5818 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5819 Process.supportsProcesses()) {
5820 int uid = ActivityThread.getPackageManager()
5821 .getPackageUid(packageName);
5822 if (uid != Binder.getCallingUid()) {
5823 String msg = "Permission Denial: getIntentSender() from pid="
5824 + Binder.getCallingPid()
5825 + ", uid=" + Binder.getCallingUid()
5826 + ", (need uid=" + uid + ")"
5827 + " is not allowed to send as package " + packageName;
5828 Log.w(TAG, msg);
5829 throw new SecurityException(msg);
5830 }
5831 }
5832 } catch (RemoteException e) {
5833 throw new SecurityException(e);
5834 }
5835 HistoryRecord activity = null;
5836 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005837 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 if (index < 0) {
5839 return null;
5840 }
5841 activity = (HistoryRecord)mHistory.get(index);
5842 if (activity.finishing) {
5843 return null;
5844 }
5845 }
5846
5847 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5848 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5849 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5850 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5851 |PendingIntent.FLAG_UPDATE_CURRENT);
5852
5853 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5854 type, packageName, activity, resultWho,
5855 requestCode, intent, resolvedType, flags);
5856 WeakReference<PendingIntentRecord> ref;
5857 ref = mIntentSenderRecords.get(key);
5858 PendingIntentRecord rec = ref != null ? ref.get() : null;
5859 if (rec != null) {
5860 if (!cancelCurrent) {
5861 if (updateCurrent) {
5862 rec.key.requestIntent.replaceExtras(intent);
5863 }
5864 return rec;
5865 }
5866 rec.canceled = true;
5867 mIntentSenderRecords.remove(key);
5868 }
5869 if (noCreate) {
5870 return rec;
5871 }
5872 rec = new PendingIntentRecord(this, key, callingUid);
5873 mIntentSenderRecords.put(key, rec.ref);
5874 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5875 if (activity.pendingResults == null) {
5876 activity.pendingResults
5877 = new HashSet<WeakReference<PendingIntentRecord>>();
5878 }
5879 activity.pendingResults.add(rec.ref);
5880 }
5881 return rec;
5882 }
5883 }
5884
5885 public void cancelIntentSender(IIntentSender sender) {
5886 if (!(sender instanceof PendingIntentRecord)) {
5887 return;
5888 }
5889 synchronized(this) {
5890 PendingIntentRecord rec = (PendingIntentRecord)sender;
5891 try {
5892 int uid = ActivityThread.getPackageManager()
5893 .getPackageUid(rec.key.packageName);
5894 if (uid != Binder.getCallingUid()) {
5895 String msg = "Permission Denial: cancelIntentSender() from pid="
5896 + Binder.getCallingPid()
5897 + ", uid=" + Binder.getCallingUid()
5898 + " is not allowed to cancel packges "
5899 + rec.key.packageName;
5900 Log.w(TAG, msg);
5901 throw new SecurityException(msg);
5902 }
5903 } catch (RemoteException e) {
5904 throw new SecurityException(e);
5905 }
5906 cancelIntentSenderLocked(rec, true);
5907 }
5908 }
5909
5910 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5911 rec.canceled = true;
5912 mIntentSenderRecords.remove(rec.key);
5913 if (cleanActivity && rec.key.activity != null) {
5914 rec.key.activity.pendingResults.remove(rec.ref);
5915 }
5916 }
5917
5918 public String getPackageForIntentSender(IIntentSender pendingResult) {
5919 if (!(pendingResult instanceof PendingIntentRecord)) {
5920 return null;
5921 }
5922 synchronized(this) {
5923 try {
5924 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5925 return res.key.packageName;
5926 } catch (ClassCastException e) {
5927 }
5928 }
5929 return null;
5930 }
5931
5932 public void setProcessLimit(int max) {
5933 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5934 "setProcessLimit()");
5935 mProcessLimit = max;
5936 }
5937
5938 public int getProcessLimit() {
5939 return mProcessLimit;
5940 }
5941
5942 void foregroundTokenDied(ForegroundToken token) {
5943 synchronized (ActivityManagerService.this) {
5944 synchronized (mPidsSelfLocked) {
5945 ForegroundToken cur
5946 = mForegroundProcesses.get(token.pid);
5947 if (cur != token) {
5948 return;
5949 }
5950 mForegroundProcesses.remove(token.pid);
5951 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5952 if (pr == null) {
5953 return;
5954 }
5955 pr.forcingToForeground = null;
5956 pr.foregroundServices = false;
5957 }
5958 updateOomAdjLocked();
5959 }
5960 }
5961
5962 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5963 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5964 "setProcessForeground()");
5965 synchronized(this) {
5966 boolean changed = false;
5967
5968 synchronized (mPidsSelfLocked) {
5969 ProcessRecord pr = mPidsSelfLocked.get(pid);
5970 if (pr == null) {
5971 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5972 return;
5973 }
5974 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5975 if (oldToken != null) {
5976 oldToken.token.unlinkToDeath(oldToken, 0);
5977 mForegroundProcesses.remove(pid);
5978 pr.forcingToForeground = null;
5979 changed = true;
5980 }
5981 if (isForeground && token != null) {
5982 ForegroundToken newToken = new ForegroundToken() {
5983 public void binderDied() {
5984 foregroundTokenDied(this);
5985 }
5986 };
5987 newToken.pid = pid;
5988 newToken.token = token;
5989 try {
5990 token.linkToDeath(newToken, 0);
5991 mForegroundProcesses.put(pid, newToken);
5992 pr.forcingToForeground = token;
5993 changed = true;
5994 } catch (RemoteException e) {
5995 // If the process died while doing this, we will later
5996 // do the cleanup with the process death link.
5997 }
5998 }
5999 }
6000
6001 if (changed) {
6002 updateOomAdjLocked();
6003 }
6004 }
6005 }
6006
6007 // =========================================================
6008 // PERMISSIONS
6009 // =========================================================
6010
6011 static class PermissionController extends IPermissionController.Stub {
6012 ActivityManagerService mActivityManagerService;
6013 PermissionController(ActivityManagerService activityManagerService) {
6014 mActivityManagerService = activityManagerService;
6015 }
6016
6017 public boolean checkPermission(String permission, int pid, int uid) {
6018 return mActivityManagerService.checkPermission(permission, pid,
6019 uid) == PackageManager.PERMISSION_GRANTED;
6020 }
6021 }
6022
6023 /**
6024 * This can be called with or without the global lock held.
6025 */
6026 int checkComponentPermission(String permission, int pid, int uid,
6027 int reqUid) {
6028 // We might be performing an operation on behalf of an indirect binder
6029 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6030 // client identity accordingly before proceeding.
6031 Identity tlsIdentity = sCallerIdentity.get();
6032 if (tlsIdentity != null) {
6033 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
6034 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6035 uid = tlsIdentity.uid;
6036 pid = tlsIdentity.pid;
6037 }
6038
6039 // Root, system server and our own process get to do everything.
6040 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6041 !Process.supportsProcesses()) {
6042 return PackageManager.PERMISSION_GRANTED;
6043 }
6044 // If the target requires a specific UID, always fail for others.
6045 if (reqUid >= 0 && uid != reqUid) {
root0369a7c2009-03-23 15:20:47 +01006046 Log.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 return PackageManager.PERMISSION_DENIED;
6048 }
6049 if (permission == null) {
6050 return PackageManager.PERMISSION_GRANTED;
6051 }
6052 try {
6053 return ActivityThread.getPackageManager()
6054 .checkUidPermission(permission, uid);
6055 } catch (RemoteException e) {
6056 // Should never happen, but if it does... deny!
6057 Log.e(TAG, "PackageManager is dead?!?", e);
6058 }
6059 return PackageManager.PERMISSION_DENIED;
6060 }
6061
6062 /**
6063 * As the only public entry point for permissions checking, this method
6064 * can enforce the semantic that requesting a check on a null global
6065 * permission is automatically denied. (Internally a null permission
6066 * string is used when calling {@link #checkComponentPermission} in cases
6067 * when only uid-based security is needed.)
6068 *
6069 * This can be called with or without the global lock held.
6070 */
6071 public int checkPermission(String permission, int pid, int uid) {
6072 if (permission == null) {
6073 return PackageManager.PERMISSION_DENIED;
6074 }
6075 return checkComponentPermission(permission, pid, uid, -1);
6076 }
6077
6078 /**
6079 * Binder IPC calls go through the public entry point.
6080 * This can be called with or without the global lock held.
6081 */
6082 int checkCallingPermission(String permission) {
6083 return checkPermission(permission,
6084 Binder.getCallingPid(),
6085 Binder.getCallingUid());
6086 }
6087
6088 /**
6089 * This can be called with or without the global lock held.
6090 */
6091 void enforceCallingPermission(String permission, String func) {
6092 if (checkCallingPermission(permission)
6093 == PackageManager.PERMISSION_GRANTED) {
6094 return;
6095 }
6096
6097 String msg = "Permission Denial: " + func + " from pid="
6098 + Binder.getCallingPid()
6099 + ", uid=" + Binder.getCallingUid()
6100 + " requires " + permission;
6101 Log.w(TAG, msg);
6102 throw new SecurityException(msg);
6103 }
6104
6105 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6106 ProviderInfo pi, int uid, int modeFlags) {
6107 try {
6108 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6109 if ((pi.readPermission != null) &&
6110 (pm.checkUidPermission(pi.readPermission, uid)
6111 != PackageManager.PERMISSION_GRANTED)) {
6112 return false;
6113 }
6114 }
6115 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6116 if ((pi.writePermission != null) &&
6117 (pm.checkUidPermission(pi.writePermission, uid)
6118 != PackageManager.PERMISSION_GRANTED)) {
6119 return false;
6120 }
6121 }
6122 return true;
6123 } catch (RemoteException e) {
6124 return false;
6125 }
6126 }
6127
6128 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6129 int modeFlags) {
6130 // Root gets to do everything.
6131 if (uid == 0 || !Process.supportsProcesses()) {
6132 return true;
6133 }
6134 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6135 if (perms == null) return false;
6136 UriPermission perm = perms.get(uri);
6137 if (perm == null) return false;
6138 return (modeFlags&perm.modeFlags) == modeFlags;
6139 }
6140
6141 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6142 // Another redirected-binder-call permissions check as in
6143 // {@link checkComponentPermission}.
6144 Identity tlsIdentity = sCallerIdentity.get();
6145 if (tlsIdentity != null) {
6146 uid = tlsIdentity.uid;
6147 pid = tlsIdentity.pid;
6148 }
6149
6150 // Our own process gets to do everything.
6151 if (pid == MY_PID) {
6152 return PackageManager.PERMISSION_GRANTED;
6153 }
6154 synchronized(this) {
6155 return checkUriPermissionLocked(uri, uid, modeFlags)
6156 ? PackageManager.PERMISSION_GRANTED
6157 : PackageManager.PERMISSION_DENIED;
6158 }
6159 }
6160
6161 private void grantUriPermissionLocked(int callingUid,
6162 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6163 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6164 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6165 if (modeFlags == 0) {
6166 return;
6167 }
6168
6169 final IPackageManager pm = ActivityThread.getPackageManager();
6170
6171 // If this is not a content: uri, we can't do anything with it.
6172 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
6173 return;
6174 }
6175
6176 String name = uri.getAuthority();
6177 ProviderInfo pi = null;
6178 ContentProviderRecord cpr
6179 = (ContentProviderRecord)mProvidersByName.get(name);
6180 if (cpr != null) {
6181 pi = cpr.info;
6182 } else {
6183 try {
6184 pi = pm.resolveContentProvider(name,
6185 PackageManager.GET_URI_PERMISSION_PATTERNS);
6186 } catch (RemoteException ex) {
6187 }
6188 }
6189 if (pi == null) {
6190 Log.w(TAG, "No content provider found for: " + name);
6191 return;
6192 }
6193
6194 int targetUid;
6195 try {
6196 targetUid = pm.getPackageUid(targetPkg);
6197 if (targetUid < 0) {
6198 return;
6199 }
6200 } catch (RemoteException ex) {
6201 return;
6202 }
6203
6204 // First... does the target actually need this permission?
6205 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6206 // No need to grant the target this permission.
6207 return;
6208 }
6209
6210 // Second... maybe someone else has already granted the
6211 // permission?
6212 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
6213 // No need to grant the target this permission.
6214 return;
6215 }
6216
6217 // Third... is the provider allowing granting of URI permissions?
6218 if (!pi.grantUriPermissions) {
6219 throw new SecurityException("Provider " + pi.packageName
6220 + "/" + pi.name
6221 + " does not allow granting of Uri permissions (uri "
6222 + uri + ")");
6223 }
6224 if (pi.uriPermissionPatterns != null) {
6225 final int N = pi.uriPermissionPatterns.length;
6226 boolean allowed = false;
6227 for (int i=0; i<N; i++) {
6228 if (pi.uriPermissionPatterns[i] != null
6229 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6230 allowed = true;
6231 break;
6232 }
6233 }
6234 if (!allowed) {
6235 throw new SecurityException("Provider " + pi.packageName
6236 + "/" + pi.name
6237 + " does not allow granting of permission to path of Uri "
6238 + uri);
6239 }
6240 }
6241
6242 // Fourth... does the caller itself have permission to access
6243 // this uri?
6244 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6245 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6246 throw new SecurityException("Uid " + callingUid
6247 + " does not have permission to uri " + uri);
6248 }
6249 }
6250
6251 // Okay! So here we are: the caller has the assumed permission
6252 // to the uri, and the target doesn't. Let's now give this to
6253 // the target.
6254
6255 HashMap<Uri, UriPermission> targetUris
6256 = mGrantedUriPermissions.get(targetUid);
6257 if (targetUris == null) {
6258 targetUris = new HashMap<Uri, UriPermission>();
6259 mGrantedUriPermissions.put(targetUid, targetUris);
6260 }
6261
6262 UriPermission perm = targetUris.get(uri);
6263 if (perm == null) {
6264 perm = new UriPermission(targetUid, uri);
6265 targetUris.put(uri, perm);
6266
6267 }
6268 perm.modeFlags |= modeFlags;
6269 if (activity == null) {
6270 perm.globalModeFlags |= modeFlags;
6271 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6272 perm.readActivities.add(activity);
6273 if (activity.readUriPermissions == null) {
6274 activity.readUriPermissions = new HashSet<UriPermission>();
6275 }
6276 activity.readUriPermissions.add(perm);
6277 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6278 perm.writeActivities.add(activity);
6279 if (activity.writeUriPermissions == null) {
6280 activity.writeUriPermissions = new HashSet<UriPermission>();
6281 }
6282 activity.writeUriPermissions.add(perm);
6283 }
6284 }
6285
6286 private void grantUriPermissionFromIntentLocked(int callingUid,
6287 String targetPkg, Intent intent, HistoryRecord activity) {
6288 if (intent == null) {
6289 return;
6290 }
6291 Uri data = intent.getData();
6292 if (data == null) {
6293 return;
6294 }
6295 grantUriPermissionLocked(callingUid, targetPkg, data,
6296 intent.getFlags(), activity);
6297 }
6298
6299 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6300 Uri uri, int modeFlags) {
6301 synchronized(this) {
6302 final ProcessRecord r = getRecordForAppLocked(caller);
6303 if (r == null) {
6304 throw new SecurityException("Unable to find app for caller "
6305 + caller
6306 + " when granting permission to uri " + uri);
6307 }
6308 if (targetPkg == null) {
6309 Log.w(TAG, "grantUriPermission: null target");
6310 return;
6311 }
6312 if (uri == null) {
6313 Log.w(TAG, "grantUriPermission: null uri");
6314 return;
6315 }
6316
6317 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6318 null);
6319 }
6320 }
6321
6322 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6323 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6324 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6325 HashMap<Uri, UriPermission> perms
6326 = mGrantedUriPermissions.get(perm.uid);
6327 if (perms != null) {
6328 perms.remove(perm.uri);
6329 if (perms.size() == 0) {
6330 mGrantedUriPermissions.remove(perm.uid);
6331 }
6332 }
6333 }
6334 }
6335
6336 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6337 if (activity.readUriPermissions != null) {
6338 for (UriPermission perm : activity.readUriPermissions) {
6339 perm.readActivities.remove(activity);
6340 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6341 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6342 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6343 removeUriPermissionIfNeededLocked(perm);
6344 }
6345 }
6346 }
6347 if (activity.writeUriPermissions != null) {
6348 for (UriPermission perm : activity.writeUriPermissions) {
6349 perm.writeActivities.remove(activity);
6350 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6351 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6352 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6353 removeUriPermissionIfNeededLocked(perm);
6354 }
6355 }
6356 }
6357 }
6358
6359 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6360 int modeFlags) {
6361 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6362 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6363 if (modeFlags == 0) {
6364 return;
6365 }
6366
6367 final IPackageManager pm = ActivityThread.getPackageManager();
6368
6369 final String authority = uri.getAuthority();
6370 ProviderInfo pi = null;
6371 ContentProviderRecord cpr
6372 = (ContentProviderRecord)mProvidersByName.get(authority);
6373 if (cpr != null) {
6374 pi = cpr.info;
6375 } else {
6376 try {
6377 pi = pm.resolveContentProvider(authority,
6378 PackageManager.GET_URI_PERMISSION_PATTERNS);
6379 } catch (RemoteException ex) {
6380 }
6381 }
6382 if (pi == null) {
6383 Log.w(TAG, "No content provider found for: " + authority);
6384 return;
6385 }
6386
6387 // Does the caller have this permission on the URI?
6388 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6389 // Right now, if you are not the original owner of the permission,
6390 // you are not allowed to revoke it.
6391 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6392 throw new SecurityException("Uid " + callingUid
6393 + " does not have permission to uri " + uri);
6394 //}
6395 }
6396
6397 // Go through all of the permissions and remove any that match.
6398 final List<String> SEGMENTS = uri.getPathSegments();
6399 if (SEGMENTS != null) {
6400 final int NS = SEGMENTS.size();
6401 int N = mGrantedUriPermissions.size();
6402 for (int i=0; i<N; i++) {
6403 HashMap<Uri, UriPermission> perms
6404 = mGrantedUriPermissions.valueAt(i);
6405 Iterator<UriPermission> it = perms.values().iterator();
6406 toploop:
6407 while (it.hasNext()) {
6408 UriPermission perm = it.next();
6409 Uri targetUri = perm.uri;
6410 if (!authority.equals(targetUri.getAuthority())) {
6411 continue;
6412 }
6413 List<String> targetSegments = targetUri.getPathSegments();
6414 if (targetSegments == null) {
6415 continue;
6416 }
6417 if (targetSegments.size() < NS) {
6418 continue;
6419 }
6420 for (int j=0; j<NS; j++) {
6421 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6422 continue toploop;
6423 }
6424 }
6425 perm.clearModes(modeFlags);
6426 if (perm.modeFlags == 0) {
6427 it.remove();
6428 }
6429 }
6430 if (perms.size() == 0) {
6431 mGrantedUriPermissions.remove(
6432 mGrantedUriPermissions.keyAt(i));
6433 N--;
6434 i--;
6435 }
6436 }
6437 }
6438 }
6439
6440 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6441 int modeFlags) {
6442 synchronized(this) {
6443 final ProcessRecord r = getRecordForAppLocked(caller);
6444 if (r == null) {
6445 throw new SecurityException("Unable to find app for caller "
6446 + caller
6447 + " when revoking permission to uri " + uri);
6448 }
6449 if (uri == null) {
6450 Log.w(TAG, "revokeUriPermission: null uri");
6451 return;
6452 }
6453
6454 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6455 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6456 if (modeFlags == 0) {
6457 return;
6458 }
6459
6460 final IPackageManager pm = ActivityThread.getPackageManager();
6461
6462 final String authority = uri.getAuthority();
6463 ProviderInfo pi = null;
6464 ContentProviderRecord cpr
6465 = (ContentProviderRecord)mProvidersByName.get(authority);
6466 if (cpr != null) {
6467 pi = cpr.info;
6468 } else {
6469 try {
6470 pi = pm.resolveContentProvider(authority,
6471 PackageManager.GET_URI_PERMISSION_PATTERNS);
6472 } catch (RemoteException ex) {
6473 }
6474 }
6475 if (pi == null) {
6476 Log.w(TAG, "No content provider found for: " + authority);
6477 return;
6478 }
6479
6480 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6481 }
6482 }
6483
6484 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6485 synchronized (this) {
6486 ProcessRecord app =
6487 who != null ? getRecordForAppLocked(who) : null;
6488 if (app == null) return;
6489
6490 Message msg = Message.obtain();
6491 msg.what = WAIT_FOR_DEBUGGER_MSG;
6492 msg.obj = app;
6493 msg.arg1 = waiting ? 1 : 0;
6494 mHandler.sendMessage(msg);
6495 }
6496 }
6497
6498 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6499 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006500 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006502 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 }
6504
6505 // =========================================================
6506 // TASK MANAGEMENT
6507 // =========================================================
6508
6509 public List getTasks(int maxNum, int flags,
6510 IThumbnailReceiver receiver) {
6511 ArrayList list = new ArrayList();
6512
6513 PendingThumbnailsRecord pending = null;
6514 IApplicationThread topThumbnail = null;
6515 HistoryRecord topRecord = null;
6516
6517 synchronized(this) {
6518 if (localLOGV) Log.v(
6519 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6520 + ", receiver=" + receiver);
6521
6522 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6523 != PackageManager.PERMISSION_GRANTED) {
6524 if (receiver != null) {
6525 // If the caller wants to wait for pending thumbnails,
6526 // it ain't gonna get them.
6527 try {
6528 receiver.finished();
6529 } catch (RemoteException ex) {
6530 }
6531 }
6532 String msg = "Permission Denial: getTasks() from pid="
6533 + Binder.getCallingPid()
6534 + ", uid=" + Binder.getCallingUid()
6535 + " requires " + android.Manifest.permission.GET_TASKS;
6536 Log.w(TAG, msg);
6537 throw new SecurityException(msg);
6538 }
6539
6540 int pos = mHistory.size()-1;
6541 HistoryRecord next =
6542 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6543 HistoryRecord top = null;
6544 CharSequence topDescription = null;
6545 TaskRecord curTask = null;
6546 int numActivities = 0;
6547 int numRunning = 0;
6548 while (pos >= 0 && maxNum > 0) {
6549 final HistoryRecord r = next;
6550 pos--;
6551 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6552
6553 // Initialize state for next task if needed.
6554 if (top == null ||
6555 (top.state == ActivityState.INITIALIZING
6556 && top.task == r.task)) {
6557 top = r;
6558 topDescription = r.description;
6559 curTask = r.task;
6560 numActivities = numRunning = 0;
6561 }
6562
6563 // Add 'r' into the current task.
6564 numActivities++;
6565 if (r.app != null && r.app.thread != null) {
6566 numRunning++;
6567 }
6568 if (topDescription == null) {
6569 topDescription = r.description;
6570 }
6571
6572 if (localLOGV) Log.v(
6573 TAG, r.intent.getComponent().flattenToShortString()
6574 + ": task=" + r.task);
6575
6576 // If the next one is a different task, generate a new
6577 // TaskInfo entry for what we have.
6578 if (next == null || next.task != curTask) {
6579 ActivityManager.RunningTaskInfo ci
6580 = new ActivityManager.RunningTaskInfo();
6581 ci.id = curTask.taskId;
6582 ci.baseActivity = r.intent.getComponent();
6583 ci.topActivity = top.intent.getComponent();
6584 ci.thumbnail = top.thumbnail;
6585 ci.description = topDescription;
6586 ci.numActivities = numActivities;
6587 ci.numRunning = numRunning;
6588 //System.out.println(
6589 // "#" + maxNum + ": " + " descr=" + ci.description);
6590 if (ci.thumbnail == null && receiver != null) {
6591 if (localLOGV) Log.v(
6592 TAG, "State=" + top.state + "Idle=" + top.idle
6593 + " app=" + top.app
6594 + " thr=" + (top.app != null ? top.app.thread : null));
6595 if (top.state == ActivityState.RESUMED
6596 || top.state == ActivityState.PAUSING) {
6597 if (top.idle && top.app != null
6598 && top.app.thread != null) {
6599 topRecord = top;
6600 topThumbnail = top.app.thread;
6601 } else {
6602 top.thumbnailNeeded = true;
6603 }
6604 }
6605 if (pending == null) {
6606 pending = new PendingThumbnailsRecord(receiver);
6607 }
6608 pending.pendingRecords.add(top);
6609 }
6610 list.add(ci);
6611 maxNum--;
6612 top = null;
6613 }
6614 }
6615
6616 if (pending != null) {
6617 mPendingThumbnails.add(pending);
6618 }
6619 }
6620
6621 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
6622
6623 if (topThumbnail != null) {
6624 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
6625 try {
6626 topThumbnail.requestThumbnail(topRecord);
6627 } catch (Exception e) {
6628 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
6629 sendPendingThumbnail(null, topRecord, null, null, true);
6630 }
6631 }
6632
6633 if (pending == null && receiver != null) {
6634 // In this case all thumbnails were available and the client
6635 // is being asked to be told when the remaining ones come in...
6636 // which is unusually, since the top-most currently running
6637 // activity should never have a canned thumbnail! Oh well.
6638 try {
6639 receiver.finished();
6640 } catch (RemoteException ex) {
6641 }
6642 }
6643
6644 return list;
6645 }
6646
6647 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6648 int flags) {
6649 synchronized (this) {
6650 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6651 "getRecentTasks()");
6652
6653 final int N = mRecentTasks.size();
6654 ArrayList<ActivityManager.RecentTaskInfo> res
6655 = new ArrayList<ActivityManager.RecentTaskInfo>(
6656 maxNum < N ? maxNum : N);
6657 for (int i=0; i<N && maxNum > 0; i++) {
6658 TaskRecord tr = mRecentTasks.get(i);
6659 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6660 || (tr.intent == null)
6661 || ((tr.intent.getFlags()
6662 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6663 ActivityManager.RecentTaskInfo rti
6664 = new ActivityManager.RecentTaskInfo();
6665 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6666 rti.baseIntent = new Intent(
6667 tr.intent != null ? tr.intent : tr.affinityIntent);
6668 rti.origActivity = tr.origActivity;
6669 res.add(rti);
6670 maxNum--;
6671 }
6672 }
6673 return res;
6674 }
6675 }
6676
6677 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6678 int j;
6679 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6680 TaskRecord jt = startTask;
6681
6682 // First look backwards
6683 for (j=startIndex-1; j>=0; j--) {
6684 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6685 if (r.task != jt) {
6686 jt = r.task;
6687 if (affinity.equals(jt.affinity)) {
6688 return j;
6689 }
6690 }
6691 }
6692
6693 // Now look forwards
6694 final int N = mHistory.size();
6695 jt = startTask;
6696 for (j=startIndex+1; j<N; j++) {
6697 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6698 if (r.task != jt) {
6699 if (affinity.equals(jt.affinity)) {
6700 return j;
6701 }
6702 jt = r.task;
6703 }
6704 }
6705
6706 // Might it be at the top?
6707 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6708 return N-1;
6709 }
6710
6711 return -1;
6712 }
6713
6714 /**
6715 * Perform a reset of the given task, if needed as part of launching it.
6716 * Returns the new HistoryRecord at the top of the task.
6717 */
6718 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6719 HistoryRecord newActivity) {
6720 boolean forceReset = (newActivity.info.flags
6721 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6722 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6723 if ((newActivity.info.flags
6724 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6725 forceReset = true;
6726 }
6727 }
6728
6729 final TaskRecord task = taskTop.task;
6730
6731 // We are going to move through the history list so that we can look
6732 // at each activity 'target' with 'below' either the interesting
6733 // activity immediately below it in the stack or null.
6734 HistoryRecord target = null;
6735 int targetI = 0;
6736 int taskTopI = -1;
6737 int replyChainEnd = -1;
6738 int lastReparentPos = -1;
6739 for (int i=mHistory.size()-1; i>=-1; i--) {
6740 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6741
6742 if (below != null && below.finishing) {
6743 continue;
6744 }
6745 if (target == null) {
6746 target = below;
6747 targetI = i;
6748 // If we were in the middle of a reply chain before this
6749 // task, it doesn't appear like the root of the chain wants
6750 // anything interesting, so drop it.
6751 replyChainEnd = -1;
6752 continue;
6753 }
6754
6755 final int flags = target.info.flags;
6756
6757 final boolean finishOnTaskLaunch =
6758 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6759 final boolean allowTaskReparenting =
6760 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6761
6762 if (target.task == task) {
6763 // We are inside of the task being reset... we'll either
6764 // finish this activity, push it out for another task,
6765 // or leave it as-is. We only do this
6766 // for activities that are not the root of the task (since
6767 // if we finish the root, we may no longer have the task!).
6768 if (taskTopI < 0) {
6769 taskTopI = targetI;
6770 }
6771 if (below != null && below.task == task) {
6772 final boolean clearWhenTaskReset =
6773 (target.intent.getFlags()
6774 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006775 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 // If this activity is sending a reply to a previous
6777 // activity, we can't do anything with it now until
6778 // we reach the start of the reply chain.
6779 // XXX note that we are assuming the result is always
6780 // to the previous activity, which is almost always
6781 // the case but we really shouldn't count on.
6782 if (replyChainEnd < 0) {
6783 replyChainEnd = targetI;
6784 }
Ed Heyl73798232009-03-24 21:32:21 -07006785 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 && target.taskAffinity != null
6787 && !target.taskAffinity.equals(task.affinity)) {
6788 // If this activity has an affinity for another
6789 // task, then we need to move it out of here. We will
6790 // move it as far out of the way as possible, to the
6791 // bottom of the activity stack. This also keeps it
6792 // correctly ordered with any activities we previously
6793 // moved.
6794 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6795 if (target.taskAffinity != null
6796 && target.taskAffinity.equals(p.task.affinity)) {
6797 // If the activity currently at the bottom has the
6798 // same task affinity as the one we are moving,
6799 // then merge it into the same task.
6800 target.task = p.task;
6801 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6802 + " out to bottom task " + p.task);
6803 } else {
6804 mCurTask++;
6805 if (mCurTask <= 0) {
6806 mCurTask = 1;
6807 }
6808 target.task = new TaskRecord(mCurTask, target.info, null,
6809 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6810 target.task.affinityIntent = target.intent;
6811 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6812 + " out to new task " + target.task);
6813 }
6814 mWindowManager.setAppGroupId(target, task.taskId);
6815 if (replyChainEnd < 0) {
6816 replyChainEnd = targetI;
6817 }
6818 int dstPos = 0;
6819 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6820 p = (HistoryRecord)mHistory.get(srcPos);
6821 if (p.finishing) {
6822 continue;
6823 }
6824 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6825 + " out to target's task " + target.task);
6826 task.numActivities--;
6827 p.task = target.task;
6828 target.task.numActivities++;
6829 mHistory.remove(srcPos);
6830 mHistory.add(dstPos, p);
6831 mWindowManager.moveAppToken(dstPos, p);
6832 mWindowManager.setAppGroupId(p, p.task.taskId);
6833 dstPos++;
6834 if (VALIDATE_TOKENS) {
6835 mWindowManager.validateAppTokens(mHistory);
6836 }
6837 i++;
6838 }
6839 if (taskTop == p) {
6840 taskTop = below;
6841 }
6842 if (taskTopI == replyChainEnd) {
6843 taskTopI = -1;
6844 }
6845 replyChainEnd = -1;
6846 addRecentTask(target.task);
6847 } else if (forceReset || finishOnTaskLaunch
6848 || clearWhenTaskReset) {
6849 // If the activity should just be removed -- either
6850 // because it asks for it, or the task should be
6851 // cleared -- then finish it and anything that is
6852 // part of its reply chain.
6853 if (clearWhenTaskReset) {
6854 // In this case, we want to finish this activity
6855 // and everything above it, so be sneaky and pretend
6856 // like these are all in the reply chain.
6857 replyChainEnd = targetI+1;
6858 while (replyChainEnd < mHistory.size() &&
6859 ((HistoryRecord)mHistory.get(
6860 replyChainEnd)).task == task) {
6861 replyChainEnd++;
6862 }
6863 replyChainEnd--;
6864 } else if (replyChainEnd < 0) {
6865 replyChainEnd = targetI;
6866 }
6867 HistoryRecord p = null;
6868 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6869 p = (HistoryRecord)mHistory.get(srcPos);
6870 if (p.finishing) {
6871 continue;
6872 }
6873 if (finishActivityLocked(p, srcPos,
6874 Activity.RESULT_CANCELED, null, "reset")) {
6875 replyChainEnd--;
6876 srcPos--;
6877 }
6878 }
6879 if (taskTop == p) {
6880 taskTop = below;
6881 }
6882 if (taskTopI == replyChainEnd) {
6883 taskTopI = -1;
6884 }
6885 replyChainEnd = -1;
6886 } else {
6887 // If we were in the middle of a chain, well the
6888 // activity that started it all doesn't want anything
6889 // special, so leave it all as-is.
6890 replyChainEnd = -1;
6891 }
6892 } else {
6893 // Reached the bottom of the task -- any reply chain
6894 // should be left as-is.
6895 replyChainEnd = -1;
6896 }
6897
6898 } else if (target.resultTo != null) {
6899 // If this activity is sending a reply to a previous
6900 // activity, we can't do anything with it now until
6901 // we reach the start of the reply chain.
6902 // XXX note that we are assuming the result is always
6903 // to the previous activity, which is almost always
6904 // the case but we really shouldn't count on.
6905 if (replyChainEnd < 0) {
6906 replyChainEnd = targetI;
6907 }
6908
6909 } else if (taskTopI >= 0 && allowTaskReparenting
6910 && task.affinity != null
6911 && task.affinity.equals(target.taskAffinity)) {
6912 // We are inside of another task... if this activity has
6913 // an affinity for our task, then either remove it if we are
6914 // clearing or move it over to our task. Note that
6915 // we currently punt on the case where we are resetting a
6916 // task that is not at the top but who has activities above
6917 // with an affinity to it... this is really not a normal
6918 // case, and we will need to later pull that task to the front
6919 // and usually at that point we will do the reset and pick
6920 // up those remaining activities. (This only happens if
6921 // someone starts an activity in a new task from an activity
6922 // in a task that is not currently on top.)
6923 if (forceReset || finishOnTaskLaunch) {
6924 if (replyChainEnd < 0) {
6925 replyChainEnd = targetI;
6926 }
6927 HistoryRecord p = null;
6928 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6929 p = (HistoryRecord)mHistory.get(srcPos);
6930 if (p.finishing) {
6931 continue;
6932 }
6933 if (finishActivityLocked(p, srcPos,
6934 Activity.RESULT_CANCELED, null, "reset")) {
6935 taskTopI--;
6936 lastReparentPos--;
6937 replyChainEnd--;
6938 srcPos--;
6939 }
6940 }
6941 replyChainEnd = -1;
6942 } else {
6943 if (replyChainEnd < 0) {
6944 replyChainEnd = targetI;
6945 }
6946 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6947 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6948 if (p.finishing) {
6949 continue;
6950 }
6951 if (lastReparentPos < 0) {
6952 lastReparentPos = taskTopI;
6953 taskTop = p;
6954 } else {
6955 lastReparentPos--;
6956 }
6957 mHistory.remove(srcPos);
6958 p.task.numActivities--;
6959 p.task = task;
6960 mHistory.add(lastReparentPos, p);
6961 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6962 + " in to resetting task " + task);
6963 task.numActivities++;
6964 mWindowManager.moveAppToken(lastReparentPos, p);
6965 mWindowManager.setAppGroupId(p, p.task.taskId);
6966 if (VALIDATE_TOKENS) {
6967 mWindowManager.validateAppTokens(mHistory);
6968 }
6969 }
6970 replyChainEnd = -1;
6971
6972 // Now we've moved it in to place... but what if this is
6973 // a singleTop activity and we have put it on top of another
6974 // instance of the same activity? Then we drop the instance
6975 // below so it remains singleTop.
6976 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6977 for (int j=lastReparentPos-1; j>=0; j--) {
6978 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6979 if (p.finishing) {
6980 continue;
6981 }
6982 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6983 if (finishActivityLocked(p, j,
6984 Activity.RESULT_CANCELED, null, "replace")) {
6985 taskTopI--;
6986 lastReparentPos--;
6987 }
6988 }
6989 }
6990 }
6991 }
6992 }
6993
6994 target = below;
6995 targetI = i;
6996 }
6997
6998 return taskTop;
6999 }
7000
7001 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007002 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007003 */
7004 public void moveTaskToFront(int task) {
7005 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7006 "moveTaskToFront()");
7007
7008 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007009 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7010 Binder.getCallingUid(), "Task to front")) {
7011 return;
7012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 final long origId = Binder.clearCallingIdentity();
7014 try {
7015 int N = mRecentTasks.size();
7016 for (int i=0; i<N; i++) {
7017 TaskRecord tr = mRecentTasks.get(i);
7018 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007019 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 return;
7021 }
7022 }
7023 for (int i=mHistory.size()-1; i>=0; i--) {
7024 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7025 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007026 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 return;
7028 }
7029 }
7030 } finally {
7031 Binder.restoreCallingIdentity(origId);
7032 }
7033 }
7034 }
7035
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007036 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
7038
7039 final int task = tr.taskId;
7040 int top = mHistory.size()-1;
7041
7042 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7043 // nothing to do!
7044 return;
7045 }
7046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 ArrayList moved = new ArrayList();
7048
7049 // Applying the affinities may have removed entries from the history,
7050 // so get the size again.
7051 top = mHistory.size()-1;
7052 int pos = top;
7053
7054 // Shift all activities with this task up to the top
7055 // of the stack, keeping them in the same internal order.
7056 while (pos >= 0) {
7057 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7058 if (localLOGV) Log.v(
7059 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7060 boolean first = true;
7061 if (r.task.taskId == task) {
7062 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
7063 mHistory.remove(pos);
7064 mHistory.add(top, r);
7065 moved.add(0, r);
7066 top--;
7067 if (first) {
7068 addRecentTask(r.task);
7069 first = false;
7070 }
7071 }
7072 pos--;
7073 }
7074
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007075 if (DEBUG_TRANSITION) Log.v(TAG,
7076 "Prepare to front transition: task=" + tr);
7077 if (reason != null &&
7078 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7079 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7080 HistoryRecord r = topRunningActivityLocked(null);
7081 if (r != null) {
7082 mNoAnimActivities.add(r);
7083 }
7084 } else {
7085 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7086 }
7087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088 mWindowManager.moveAppTokensToTop(moved);
7089 if (VALIDATE_TOKENS) {
7090 mWindowManager.validateAppTokens(mHistory);
7091 }
7092
7093 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007094 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007095 }
7096
7097 private final void finishTaskMove(int task) {
7098 resumeTopActivityLocked(null);
7099 }
7100
7101 public void moveTaskToBack(int task) {
7102 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7103 "moveTaskToBack()");
7104
7105 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007106 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7107 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7108 Binder.getCallingUid(), "Task to back")) {
7109 return;
7110 }
7111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007112 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007113 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 Binder.restoreCallingIdentity(origId);
7115 }
7116 }
7117
7118 /**
7119 * Moves an activity, and all of the other activities within the same task, to the bottom
7120 * of the history stack. The activity's order within the task is unchanged.
7121 *
7122 * @param token A reference to the activity we wish to move
7123 * @param nonRoot If false then this only works if the activity is the root
7124 * of a task; if true it will work for any activity in a task.
7125 * @return Returns true if the move completed, false if not.
7126 */
7127 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7128 synchronized(this) {
7129 final long origId = Binder.clearCallingIdentity();
7130 int taskId = getTaskForActivityLocked(token, !nonRoot);
7131 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007132 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007133 }
7134 Binder.restoreCallingIdentity(origId);
7135 }
7136 return false;
7137 }
7138
7139 /**
7140 * Worker method for rearranging history stack. Implements the function of moving all
7141 * activities for a specific task (gathering them if disjoint) into a single group at the
7142 * bottom of the stack.
7143 *
7144 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7145 * to premeptively cancel the move.
7146 *
7147 * @param task The taskId to collect and move to the bottom.
7148 * @return Returns true if the move completed, false if not.
7149 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007150 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 Log.i(TAG, "moveTaskToBack: " + task);
7152
7153 // If we have a watcher, preflight the move before committing to it. First check
7154 // for *other* available tasks, but if none are available, then try again allowing the
7155 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007156 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 HistoryRecord next = topRunningActivityLocked(null, task);
7158 if (next == null) {
7159 next = topRunningActivityLocked(null, 0);
7160 }
7161 if (next != null) {
7162 // ask watcher if this is allowed
7163 boolean moveOK = true;
7164 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007165 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007166 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007167 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168 }
7169 if (!moveOK) {
7170 return false;
7171 }
7172 }
7173 }
7174
7175 ArrayList moved = new ArrayList();
7176
7177 if (DEBUG_TRANSITION) Log.v(TAG,
7178 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007179
7180 final int N = mHistory.size();
7181 int bottom = 0;
7182 int pos = 0;
7183
7184 // Shift all activities with this task down to the bottom
7185 // of the stack, keeping them in the same internal order.
7186 while (pos < N) {
7187 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7188 if (localLOGV) Log.v(
7189 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7190 if (r.task.taskId == task) {
7191 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
7192 mHistory.remove(pos);
7193 mHistory.add(bottom, r);
7194 moved.add(r);
7195 bottom++;
7196 }
7197 pos++;
7198 }
7199
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007200 if (reason != null &&
7201 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7202 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7203 HistoryRecord r = topRunningActivityLocked(null);
7204 if (r != null) {
7205 mNoAnimActivities.add(r);
7206 }
7207 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007208 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210 mWindowManager.moveAppTokensToBottom(moved);
7211 if (VALIDATE_TOKENS) {
7212 mWindowManager.validateAppTokens(mHistory);
7213 }
7214
7215 finishTaskMove(task);
7216 return true;
7217 }
7218
7219 public void moveTaskBackwards(int task) {
7220 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7221 "moveTaskBackwards()");
7222
7223 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007224 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7225 Binder.getCallingUid(), "Task backwards")) {
7226 return;
7227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 final long origId = Binder.clearCallingIdentity();
7229 moveTaskBackwardsLocked(task);
7230 Binder.restoreCallingIdentity(origId);
7231 }
7232 }
7233
7234 private final void moveTaskBackwardsLocked(int task) {
7235 Log.e(TAG, "moveTaskBackwards not yet implemented!");
7236 }
7237
7238 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7239 synchronized(this) {
7240 return getTaskForActivityLocked(token, onlyRoot);
7241 }
7242 }
7243
7244 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7245 final int N = mHistory.size();
7246 TaskRecord lastTask = null;
7247 for (int i=0; i<N; i++) {
7248 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7249 if (r == token) {
7250 if (!onlyRoot || lastTask != r.task) {
7251 return r.task.taskId;
7252 }
7253 return -1;
7254 }
7255 lastTask = r.task;
7256 }
7257
7258 return -1;
7259 }
7260
7261 /**
7262 * Returns the top activity in any existing task matching the given
7263 * Intent. Returns null if no such task is found.
7264 */
7265 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7266 ComponentName cls = intent.getComponent();
7267 if (info.targetActivity != null) {
7268 cls = new ComponentName(info.packageName, info.targetActivity);
7269 }
7270
7271 TaskRecord cp = null;
7272
7273 final int N = mHistory.size();
7274 for (int i=(N-1); i>=0; i--) {
7275 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7276 if (!r.finishing && r.task != cp
7277 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7278 cp = r.task;
7279 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
7280 // + "/aff=" + r.task.affinity + " to new cls="
7281 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7282 if (r.task.affinity != null) {
7283 if (r.task.affinity.equals(info.taskAffinity)) {
7284 //Log.i(TAG, "Found matching affinity!");
7285 return r;
7286 }
7287 } else if (r.task.intent != null
7288 && r.task.intent.getComponent().equals(cls)) {
7289 //Log.i(TAG, "Found matching class!");
7290 //dump();
7291 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7292 return r;
7293 } else if (r.task.affinityIntent != null
7294 && r.task.affinityIntent.getComponent().equals(cls)) {
7295 //Log.i(TAG, "Found matching class!");
7296 //dump();
7297 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7298 return r;
7299 }
7300 }
7301 }
7302
7303 return null;
7304 }
7305
7306 /**
7307 * Returns the first activity (starting from the top of the stack) that
7308 * is the same as the given activity. Returns null if no such activity
7309 * is found.
7310 */
7311 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7312 ComponentName cls = intent.getComponent();
7313 if (info.targetActivity != null) {
7314 cls = new ComponentName(info.packageName, info.targetActivity);
7315 }
7316
7317 final int N = mHistory.size();
7318 for (int i=(N-1); i>=0; i--) {
7319 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7320 if (!r.finishing) {
7321 if (r.intent.getComponent().equals(cls)) {
7322 //Log.i(TAG, "Found matching class!");
7323 //dump();
7324 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7325 return r;
7326 }
7327 }
7328 }
7329
7330 return null;
7331 }
7332
7333 public void finishOtherInstances(IBinder token, ComponentName className) {
7334 synchronized(this) {
7335 final long origId = Binder.clearCallingIdentity();
7336
7337 int N = mHistory.size();
7338 TaskRecord lastTask = null;
7339 for (int i=0; i<N; i++) {
7340 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7341 if (r.realActivity.equals(className)
7342 && r != token && lastTask != r.task) {
7343 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7344 null, "others")) {
7345 i--;
7346 N--;
7347 }
7348 }
7349 lastTask = r.task;
7350 }
7351
7352 Binder.restoreCallingIdentity(origId);
7353 }
7354 }
7355
7356 // =========================================================
7357 // THUMBNAILS
7358 // =========================================================
7359
7360 public void reportThumbnail(IBinder token,
7361 Bitmap thumbnail, CharSequence description) {
7362 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7363 final long origId = Binder.clearCallingIdentity();
7364 sendPendingThumbnail(null, token, thumbnail, description, true);
7365 Binder.restoreCallingIdentity(origId);
7366 }
7367
7368 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7369 Bitmap thumbnail, CharSequence description, boolean always) {
7370 TaskRecord task = null;
7371 ArrayList receivers = null;
7372
7373 //System.out.println("Send pending thumbnail: " + r);
7374
7375 synchronized(this) {
7376 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007377 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 if (index < 0) {
7379 return;
7380 }
7381 r = (HistoryRecord)mHistory.get(index);
7382 }
7383 if (thumbnail == null) {
7384 thumbnail = r.thumbnail;
7385 description = r.description;
7386 }
7387 if (thumbnail == null && !always) {
7388 // If there is no thumbnail, and this entry is not actually
7389 // going away, then abort for now and pick up the next
7390 // thumbnail we get.
7391 return;
7392 }
7393 task = r.task;
7394
7395 int N = mPendingThumbnails.size();
7396 int i=0;
7397 while (i<N) {
7398 PendingThumbnailsRecord pr =
7399 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7400 //System.out.println("Looking in " + pr.pendingRecords);
7401 if (pr.pendingRecords.remove(r)) {
7402 if (receivers == null) {
7403 receivers = new ArrayList();
7404 }
7405 receivers.add(pr);
7406 if (pr.pendingRecords.size() == 0) {
7407 pr.finished = true;
7408 mPendingThumbnails.remove(i);
7409 N--;
7410 continue;
7411 }
7412 }
7413 i++;
7414 }
7415 }
7416
7417 if (receivers != null) {
7418 final int N = receivers.size();
7419 for (int i=0; i<N; i++) {
7420 try {
7421 PendingThumbnailsRecord pr =
7422 (PendingThumbnailsRecord)receivers.get(i);
7423 pr.receiver.newThumbnail(
7424 task != null ? task.taskId : -1, thumbnail, description);
7425 if (pr.finished) {
7426 pr.receiver.finished();
7427 }
7428 } catch (Exception e) {
7429 Log.w(TAG, "Exception thrown when sending thumbnail", e);
7430 }
7431 }
7432 }
7433 }
7434
7435 // =========================================================
7436 // CONTENT PROVIDERS
7437 // =========================================================
7438
7439 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7440 List providers = null;
7441 try {
7442 providers = ActivityThread.getPackageManager().
7443 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007444 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007445 } catch (RemoteException ex) {
7446 }
7447 if (providers != null) {
7448 final int N = providers.size();
7449 for (int i=0; i<N; i++) {
7450 ProviderInfo cpi =
7451 (ProviderInfo)providers.get(i);
7452 ContentProviderRecord cpr =
7453 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7454 if (cpr == null) {
7455 cpr = new ContentProviderRecord(cpi, app.info);
7456 mProvidersByClass.put(cpi.name, cpr);
7457 }
7458 app.pubProviders.put(cpi.name, cpr);
7459 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007460 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 }
7462 }
7463 return providers;
7464 }
7465
7466 private final String checkContentProviderPermissionLocked(
7467 ProviderInfo cpi, ProcessRecord r, int mode) {
7468 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7469 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7470 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7471 cpi.exported ? -1 : cpi.applicationInfo.uid)
7472 == PackageManager.PERMISSION_GRANTED
7473 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7474 return null;
7475 }
7476 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7477 cpi.exported ? -1 : cpi.applicationInfo.uid)
7478 == PackageManager.PERMISSION_GRANTED) {
7479 return null;
7480 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007481
7482 PathPermission[] pps = cpi.pathPermissions;
7483 if (pps != null) {
7484 int i = pps.length;
7485 while (i > 0) {
7486 i--;
7487 PathPermission pp = pps[i];
7488 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7489 cpi.exported ? -1 : cpi.applicationInfo.uid)
7490 == PackageManager.PERMISSION_GRANTED
7491 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7492 return null;
7493 }
7494 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7495 cpi.exported ? -1 : cpi.applicationInfo.uid)
7496 == PackageManager.PERMISSION_GRANTED) {
7497 return null;
7498 }
7499 }
7500 }
7501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 String msg = "Permission Denial: opening provider " + cpi.name
7503 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7504 + ", uid=" + callingUid + ") requires "
7505 + cpi.readPermission + " or " + cpi.writePermission;
7506 Log.w(TAG, msg);
7507 return msg;
7508 }
7509
7510 private final ContentProviderHolder getContentProviderImpl(
7511 IApplicationThread caller, String name) {
7512 ContentProviderRecord cpr;
7513 ProviderInfo cpi = null;
7514
7515 synchronized(this) {
7516 ProcessRecord r = null;
7517 if (caller != null) {
7518 r = getRecordForAppLocked(caller);
7519 if (r == null) {
7520 throw new SecurityException(
7521 "Unable to find app for caller " + caller
7522 + " (pid=" + Binder.getCallingPid()
7523 + ") when getting content provider " + name);
7524 }
7525 }
7526
7527 // First check if this content provider has been published...
7528 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7529 if (cpr != null) {
7530 cpi = cpr.info;
7531 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7532 return new ContentProviderHolder(cpi,
7533 cpi.readPermission != null
7534 ? cpi.readPermission : cpi.writePermission);
7535 }
7536
7537 if (r != null && cpr.canRunHere(r)) {
7538 // This provider has been published or is in the process
7539 // of being published... but it is also allowed to run
7540 // in the caller's process, so don't make a connection
7541 // and just let the caller instantiate its own instance.
7542 if (cpr.provider != null) {
7543 // don't give caller the provider object, it needs
7544 // to make its own.
7545 cpr = new ContentProviderRecord(cpr);
7546 }
7547 return cpr;
7548 }
7549
7550 final long origId = Binder.clearCallingIdentity();
7551
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007552 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553 // return it right away.
7554 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007555 if (DEBUG_PROVIDER) Log.v(TAG,
7556 "Adding provider requested by "
7557 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007558 + cpr.info.processName);
7559 Integer cnt = r.conProviders.get(cpr);
7560 if (cnt == null) {
7561 r.conProviders.put(cpr, new Integer(1));
7562 } else {
7563 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 cpr.clients.add(r);
7566 } else {
7567 cpr.externals++;
7568 }
7569
7570 if (cpr.app != null) {
7571 updateOomAdjLocked(cpr.app);
7572 }
7573
7574 Binder.restoreCallingIdentity(origId);
7575
7576 } else {
7577 try {
7578 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007579 resolveContentProvider(name,
7580 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 } catch (RemoteException ex) {
7582 }
7583 if (cpi == null) {
7584 return null;
7585 }
7586
7587 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7588 return new ContentProviderHolder(cpi,
7589 cpi.readPermission != null
7590 ? cpi.readPermission : cpi.writePermission);
7591 }
7592
7593 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7594 final boolean firstClass = cpr == null;
7595 if (firstClass) {
7596 try {
7597 ApplicationInfo ai =
7598 ActivityThread.getPackageManager().
7599 getApplicationInfo(
7600 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007601 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 if (ai == null) {
7603 Log.w(TAG, "No package info for content provider "
7604 + cpi.name);
7605 return null;
7606 }
7607 cpr = new ContentProviderRecord(cpi, ai);
7608 } catch (RemoteException ex) {
7609 // pm is in same process, this will never happen.
7610 }
7611 }
7612
7613 if (r != null && cpr.canRunHere(r)) {
7614 // If this is a multiprocess provider, then just return its
7615 // info and allow the caller to instantiate it. Only do
7616 // this if the provider is the same user as the caller's
7617 // process, or can run as root (so can be in any process).
7618 return cpr;
7619 }
7620
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007621 if (DEBUG_PROVIDER) {
7622 RuntimeException e = new RuntimeException("here");
7623 Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
7624 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 }
7626
7627 // This is single process, and our app is now connecting to it.
7628 // See if we are already in the process of launching this
7629 // provider.
7630 final int N = mLaunchingProviders.size();
7631 int i;
7632 for (i=0; i<N; i++) {
7633 if (mLaunchingProviders.get(i) == cpr) {
7634 break;
7635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 }
7637
7638 // If the provider is not already being launched, then get it
7639 // started.
7640 if (i >= N) {
7641 final long origId = Binder.clearCallingIdentity();
7642 ProcessRecord proc = startProcessLocked(cpi.processName,
7643 cpr.appInfo, false, 0, "content provider",
7644 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007645 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 if (proc == null) {
7647 Log.w(TAG, "Unable to launch app "
7648 + cpi.applicationInfo.packageName + "/"
7649 + cpi.applicationInfo.uid + " for provider "
7650 + name + ": process is bad");
7651 return null;
7652 }
7653 cpr.launchingApp = proc;
7654 mLaunchingProviders.add(cpr);
7655 Binder.restoreCallingIdentity(origId);
7656 }
7657
7658 // Make sure the provider is published (the same provider class
7659 // may be published under multiple names).
7660 if (firstClass) {
7661 mProvidersByClass.put(cpi.name, cpr);
7662 }
7663 mProvidersByName.put(name, cpr);
7664
7665 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007666 if (DEBUG_PROVIDER) Log.v(TAG,
7667 "Adding provider requested by "
7668 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007669 + cpr.info.processName);
7670 Integer cnt = r.conProviders.get(cpr);
7671 if (cnt == null) {
7672 r.conProviders.put(cpr, new Integer(1));
7673 } else {
7674 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 cpr.clients.add(r);
7677 } else {
7678 cpr.externals++;
7679 }
7680 }
7681 }
7682
7683 // Wait for the provider to be published...
7684 synchronized (cpr) {
7685 while (cpr.provider == null) {
7686 if (cpr.launchingApp == null) {
7687 Log.w(TAG, "Unable to launch app "
7688 + cpi.applicationInfo.packageName + "/"
7689 + cpi.applicationInfo.uid + " for provider "
7690 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007691 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 cpi.applicationInfo.packageName,
7693 cpi.applicationInfo.uid, name);
7694 return null;
7695 }
7696 try {
7697 cpr.wait();
7698 } catch (InterruptedException ex) {
7699 }
7700 }
7701 }
7702 return cpr;
7703 }
7704
7705 public final ContentProviderHolder getContentProvider(
7706 IApplicationThread caller, String name) {
7707 if (caller == null) {
7708 String msg = "null IApplicationThread when getting content provider "
7709 + name;
7710 Log.w(TAG, msg);
7711 throw new SecurityException(msg);
7712 }
7713
7714 return getContentProviderImpl(caller, name);
7715 }
7716
7717 private ContentProviderHolder getContentProviderExternal(String name) {
7718 return getContentProviderImpl(null, name);
7719 }
7720
7721 /**
7722 * Drop a content provider from a ProcessRecord's bookkeeping
7723 * @param cpr
7724 */
7725 public void removeContentProvider(IApplicationThread caller, String name) {
7726 synchronized (this) {
7727 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7728 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007729 // remove from mProvidersByClass
7730 if (DEBUG_PROVIDER) Log.v(TAG, name +
7731 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 return;
7733 }
7734 final ProcessRecord r = getRecordForAppLocked(caller);
7735 if (r == null) {
7736 throw new SecurityException(
7737 "Unable to find app for caller " + caller +
7738 " when removing content provider " + name);
7739 }
7740 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007741 ContentProviderRecord localCpr = (ContentProviderRecord)
7742 mProvidersByClass.get(cpr.info.name);
7743 if (DEBUG_PROVIDER) Log.v(TAG, "Removing provider requested by "
7744 + r.info.processName + " from process "
7745 + localCpr.appInfo.processName);
7746 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007747 //should not happen. taken care of as a local provider
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007748 Log.w(TAG, "removeContentProvider called on local provider: "
7749 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 return;
7751 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007752 Integer cnt = r.conProviders.get(localCpr);
7753 if (cnt == null || cnt.intValue() <= 1) {
7754 localCpr.clients.remove(r);
7755 r.conProviders.remove(localCpr);
7756 } else {
7757 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007759 }
7760 updateOomAdjLocked();
7761 }
7762 }
7763
7764 private void removeContentProviderExternal(String name) {
7765 synchronized (this) {
7766 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7767 if(cpr == null) {
7768 //remove from mProvidersByClass
7769 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
7770 return;
7771 }
7772
7773 //update content provider record entry info
7774 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7775 localCpr.externals--;
7776 if (localCpr.externals < 0) {
7777 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
7778 }
7779 updateOomAdjLocked();
7780 }
7781 }
7782
7783 public final void publishContentProviders(IApplicationThread caller,
7784 List<ContentProviderHolder> providers) {
7785 if (providers == null) {
7786 return;
7787 }
7788
7789 synchronized(this) {
7790 final ProcessRecord r = getRecordForAppLocked(caller);
7791 if (r == null) {
7792 throw new SecurityException(
7793 "Unable to find app for caller " + caller
7794 + " (pid=" + Binder.getCallingPid()
7795 + ") when publishing content providers");
7796 }
7797
7798 final long origId = Binder.clearCallingIdentity();
7799
7800 final int N = providers.size();
7801 for (int i=0; i<N; i++) {
7802 ContentProviderHolder src = providers.get(i);
7803 if (src == null || src.info == null || src.provider == null) {
7804 continue;
7805 }
7806 ContentProviderRecord dst =
7807 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7808 if (dst != null) {
7809 mProvidersByClass.put(dst.info.name, dst);
7810 String names[] = dst.info.authority.split(";");
7811 for (int j = 0; j < names.length; j++) {
7812 mProvidersByName.put(names[j], dst);
7813 }
7814
7815 int NL = mLaunchingProviders.size();
7816 int j;
7817 for (j=0; j<NL; j++) {
7818 if (mLaunchingProviders.get(j) == dst) {
7819 mLaunchingProviders.remove(j);
7820 j--;
7821 NL--;
7822 }
7823 }
7824 synchronized (dst) {
7825 dst.provider = src.provider;
7826 dst.app = r;
7827 dst.notifyAll();
7828 }
7829 updateOomAdjLocked(r);
7830 }
7831 }
7832
7833 Binder.restoreCallingIdentity(origId);
7834 }
7835 }
7836
7837 public static final void installSystemProviders() {
7838 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7839 List providers = mSelf.generateApplicationProvidersLocked(app);
7840 mSystemThread.installSystemProviders(providers);
7841 }
7842
7843 // =========================================================
7844 // GLOBAL MANAGEMENT
7845 // =========================================================
7846
7847 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7848 ApplicationInfo info, String customProcess) {
7849 String proc = customProcess != null ? customProcess : info.processName;
7850 BatteryStatsImpl.Uid.Proc ps = null;
7851 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7852 synchronized (stats) {
7853 ps = stats.getProcessStatsLocked(info.uid, proc);
7854 }
7855 return new ProcessRecord(ps, thread, info, proc);
7856 }
7857
7858 final ProcessRecord addAppLocked(ApplicationInfo info) {
7859 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7860
7861 if (app == null) {
7862 app = newProcessRecordLocked(null, info, null);
7863 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007864 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 }
7866
7867 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7868 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7869 app.persistent = true;
7870 app.maxAdj = CORE_SERVER_ADJ;
7871 }
7872 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7873 mPersistentStartingProcesses.add(app);
7874 startProcessLocked(app, "added application", app.processName);
7875 }
7876
7877 return app;
7878 }
7879
7880 public void unhandledBack() {
7881 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7882 "unhandledBack()");
7883
7884 synchronized(this) {
7885 int count = mHistory.size();
Dianne Hackborn03abb812010-01-04 18:43:19 -08007886 if (DEBUG_SWITCH) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 TAG, "Performing unhandledBack(): stack size = " + count);
7888 if (count > 1) {
7889 final long origId = Binder.clearCallingIdentity();
7890 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7891 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7892 Binder.restoreCallingIdentity(origId);
7893 }
7894 }
7895 }
7896
7897 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7898 String name = uri.getAuthority();
7899 ContentProviderHolder cph = getContentProviderExternal(name);
7900 ParcelFileDescriptor pfd = null;
7901 if (cph != null) {
7902 // We record the binder invoker's uid in thread-local storage before
7903 // going to the content provider to open the file. Later, in the code
7904 // that handles all permissions checks, we look for this uid and use
7905 // that rather than the Activity Manager's own uid. The effect is that
7906 // we do the check against the caller's permissions even though it looks
7907 // to the content provider like the Activity Manager itself is making
7908 // the request.
7909 sCallerIdentity.set(new Identity(
7910 Binder.getCallingPid(), Binder.getCallingUid()));
7911 try {
7912 pfd = cph.provider.openFile(uri, "r");
7913 } catch (FileNotFoundException e) {
7914 // do nothing; pfd will be returned null
7915 } finally {
7916 // Ensure that whatever happens, we clean up the identity state
7917 sCallerIdentity.remove();
7918 }
7919
7920 // We've got the fd now, so we're done with the provider.
7921 removeContentProviderExternal(name);
7922 } else {
7923 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7924 }
7925 return pfd;
7926 }
7927
7928 public void goingToSleep() {
7929 synchronized(this) {
7930 mSleeping = true;
7931 mWindowManager.setEventDispatching(false);
7932
7933 if (mResumedActivity != null) {
7934 pauseIfSleepingLocked();
7935 } else {
7936 Log.w(TAG, "goingToSleep with no resumed activity!");
7937 }
7938 }
7939 }
7940
Dianne Hackborn55280a92009-05-07 15:53:46 -07007941 public boolean shutdown(int timeout) {
7942 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7943 != PackageManager.PERMISSION_GRANTED) {
7944 throw new SecurityException("Requires permission "
7945 + android.Manifest.permission.SHUTDOWN);
7946 }
7947
7948 boolean timedout = false;
7949
7950 synchronized(this) {
7951 mShuttingDown = true;
7952 mWindowManager.setEventDispatching(false);
7953
7954 if (mResumedActivity != null) {
7955 pauseIfSleepingLocked();
7956 final long endTime = System.currentTimeMillis() + timeout;
7957 while (mResumedActivity != null || mPausingActivity != null) {
7958 long delay = endTime - System.currentTimeMillis();
7959 if (delay <= 0) {
7960 Log.w(TAG, "Activity manager shutdown timed out");
7961 timedout = true;
7962 break;
7963 }
7964 try {
7965 this.wait();
7966 } catch (InterruptedException e) {
7967 }
7968 }
7969 }
7970 }
7971
7972 mUsageStatsService.shutdown();
7973 mBatteryStatsService.shutdown();
7974
7975 return timedout;
7976 }
7977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007978 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007979 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 if (!mGoingToSleep.isHeld()) {
7981 mGoingToSleep.acquire();
7982 if (mLaunchingActivity.isHeld()) {
7983 mLaunchingActivity.release();
7984 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7985 }
7986 }
7987
7988 // If we are not currently pausing an activity, get the current
7989 // one to pause. If we are pausing one, we will just let that stuff
7990 // run and release the wake lock when all done.
7991 if (mPausingActivity == null) {
7992 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7993 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7994 startPausingLocked(false, true);
7995 }
7996 }
7997 }
7998
7999 public void wakingUp() {
8000 synchronized(this) {
8001 if (mGoingToSleep.isHeld()) {
8002 mGoingToSleep.release();
8003 }
8004 mWindowManager.setEventDispatching(true);
8005 mSleeping = false;
8006 resumeTopActivityLocked(null);
8007 }
8008 }
8009
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008010 public void stopAppSwitches() {
8011 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8012 != PackageManager.PERMISSION_GRANTED) {
8013 throw new SecurityException("Requires permission "
8014 + android.Manifest.permission.STOP_APP_SWITCHES);
8015 }
8016
8017 synchronized(this) {
8018 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8019 + APP_SWITCH_DELAY_TIME;
8020 mDidAppSwitch = false;
8021 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8022 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8023 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8024 }
8025 }
8026
8027 public void resumeAppSwitches() {
8028 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8029 != PackageManager.PERMISSION_GRANTED) {
8030 throw new SecurityException("Requires permission "
8031 + android.Manifest.permission.STOP_APP_SWITCHES);
8032 }
8033
8034 synchronized(this) {
8035 // Note that we don't execute any pending app switches... we will
8036 // let those wait until either the timeout, or the next start
8037 // activity request.
8038 mAppSwitchesAllowedTime = 0;
8039 }
8040 }
8041
8042 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8043 String name) {
8044 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8045 return true;
8046 }
8047
8048 final int perm = checkComponentPermission(
8049 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8050 callingUid, -1);
8051 if (perm == PackageManager.PERMISSION_GRANTED) {
8052 return true;
8053 }
8054
8055 Log.w(TAG, name + " request from " + callingUid + " stopped");
8056 return false;
8057 }
8058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059 public void setDebugApp(String packageName, boolean waitForDebugger,
8060 boolean persistent) {
8061 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8062 "setDebugApp()");
8063
8064 // Note that this is not really thread safe if there are multiple
8065 // callers into it at the same time, but that's not a situation we
8066 // care about.
8067 if (persistent) {
8068 final ContentResolver resolver = mContext.getContentResolver();
8069 Settings.System.putString(
8070 resolver, Settings.System.DEBUG_APP,
8071 packageName);
8072 Settings.System.putInt(
8073 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8074 waitForDebugger ? 1 : 0);
8075 }
8076
8077 synchronized (this) {
8078 if (!persistent) {
8079 mOrigDebugApp = mDebugApp;
8080 mOrigWaitForDebugger = mWaitForDebugger;
8081 }
8082 mDebugApp = packageName;
8083 mWaitForDebugger = waitForDebugger;
8084 mDebugTransient = !persistent;
8085 if (packageName != null) {
8086 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008087 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008088 Binder.restoreCallingIdentity(origId);
8089 }
8090 }
8091 }
8092
8093 public void setAlwaysFinish(boolean enabled) {
8094 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8095 "setAlwaysFinish()");
8096
8097 Settings.System.putInt(
8098 mContext.getContentResolver(),
8099 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8100
8101 synchronized (this) {
8102 mAlwaysFinishActivities = enabled;
8103 }
8104 }
8105
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008106 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008108 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008110 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008111 }
8112 }
8113
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008114 public boolean isUserAMonkey() {
8115 // For now the fact that there is a controller implies
8116 // we have a monkey.
8117 synchronized (this) {
8118 return mController != null;
8119 }
8120 }
8121
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008122 public void registerActivityWatcher(IActivityWatcher watcher) {
8123 mWatchers.register(watcher);
8124 }
8125
8126 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8127 mWatchers.unregister(watcher);
8128 }
8129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130 public final void enterSafeMode() {
8131 synchronized(this) {
8132 // It only makes sense to do this before the system is ready
8133 // and started launching other packages.
8134 if (!mSystemReady) {
8135 try {
8136 ActivityThread.getPackageManager().enterSafeMode();
8137 } catch (RemoteException e) {
8138 }
8139
8140 View v = LayoutInflater.from(mContext).inflate(
8141 com.android.internal.R.layout.safe_mode, null);
8142 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8143 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8144 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8145 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8146 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8147 lp.format = v.getBackground().getOpacity();
8148 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8149 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8150 ((WindowManager)mContext.getSystemService(
8151 Context.WINDOW_SERVICE)).addView(v, lp);
8152 }
8153 }
8154 }
8155
8156 public void noteWakeupAlarm(IIntentSender sender) {
8157 if (!(sender instanceof PendingIntentRecord)) {
8158 return;
8159 }
8160 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8161 synchronized (stats) {
8162 if (mBatteryStatsService.isOnBattery()) {
8163 mBatteryStatsService.enforceCallingPermission();
8164 PendingIntentRecord rec = (PendingIntentRecord)sender;
8165 int MY_UID = Binder.getCallingUid();
8166 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8167 BatteryStatsImpl.Uid.Pkg pkg =
8168 stats.getPackageStatsLocked(uid, rec.key.packageName);
8169 pkg.incWakeupsLocked();
8170 }
8171 }
8172 }
8173
8174 public boolean killPidsForMemory(int[] pids) {
8175 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8176 throw new SecurityException("killPidsForMemory only available to the system");
8177 }
8178
8179 // XXX Note: don't acquire main activity lock here, because the window
8180 // manager calls in with its locks held.
8181
8182 boolean killed = false;
8183 synchronized (mPidsSelfLocked) {
8184 int[] types = new int[pids.length];
8185 int worstType = 0;
8186 for (int i=0; i<pids.length; i++) {
8187 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8188 if (proc != null) {
8189 int type = proc.setAdj;
8190 types[i] = type;
8191 if (type > worstType) {
8192 worstType = type;
8193 }
8194 }
8195 }
8196
8197 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8198 // then constrain it so we will kill all hidden procs.
8199 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8200 worstType = HIDDEN_APP_MIN_ADJ;
8201 }
8202 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
8203 for (int i=0; i<pids.length; i++) {
8204 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8205 if (proc == null) {
8206 continue;
8207 }
8208 int adj = proc.setAdj;
8209 if (adj >= worstType) {
8210 Log.w(TAG, "Killing for memory: " + proc + " (adj "
8211 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008212 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008213 proc.processName, adj);
8214 killed = true;
8215 Process.killProcess(pids[i]);
8216 }
8217 }
8218 }
8219 return killed;
8220 }
8221
8222 public void reportPss(IApplicationThread caller, int pss) {
8223 Watchdog.PssRequestor req;
8224 String name;
8225 ProcessRecord callerApp;
8226 synchronized (this) {
8227 if (caller == null) {
8228 return;
8229 }
8230 callerApp = getRecordForAppLocked(caller);
8231 if (callerApp == null) {
8232 return;
8233 }
8234 callerApp.lastPss = pss;
8235 req = callerApp;
8236 name = callerApp.processName;
8237 }
8238 Watchdog.getInstance().reportPss(req, name, pss);
8239 if (!callerApp.persistent) {
8240 removeRequestedPss(callerApp);
8241 }
8242 }
8243
8244 public void requestPss(Runnable completeCallback) {
8245 ArrayList<ProcessRecord> procs;
8246 synchronized (this) {
8247 mRequestPssCallback = completeCallback;
8248 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008249 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8250 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008251 if (!proc.persistent) {
8252 mRequestPssList.add(proc);
8253 }
8254 }
8255 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8256 }
8257
8258 int oldPri = Process.getThreadPriority(Process.myTid());
8259 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8260 for (int i=procs.size()-1; i>=0; i--) {
8261 ProcessRecord proc = procs.get(i);
8262 proc.lastPss = 0;
8263 proc.requestPss();
8264 }
8265 Process.setThreadPriority(oldPri);
8266 }
8267
8268 void removeRequestedPss(ProcessRecord proc) {
8269 Runnable callback = null;
8270 synchronized (this) {
8271 if (mRequestPssList.remove(proc)) {
8272 if (mRequestPssList.size() == 0) {
8273 callback = mRequestPssCallback;
8274 mRequestPssCallback = null;
8275 }
8276 }
8277 }
8278
8279 if (callback != null) {
8280 callback.run();
8281 }
8282 }
8283
8284 public void collectPss(Watchdog.PssStats stats) {
8285 stats.mEmptyPss = 0;
8286 stats.mEmptyCount = 0;
8287 stats.mBackgroundPss = 0;
8288 stats.mBackgroundCount = 0;
8289 stats.mServicePss = 0;
8290 stats.mServiceCount = 0;
8291 stats.mVisiblePss = 0;
8292 stats.mVisibleCount = 0;
8293 stats.mForegroundPss = 0;
8294 stats.mForegroundCount = 0;
8295 stats.mNoPssCount = 0;
8296 synchronized (this) {
8297 int i;
8298 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8299 ? mProcDeaths.length : stats.mProcDeaths.length;
8300 int aggr = 0;
8301 for (i=0; i<NPD; i++) {
8302 aggr += mProcDeaths[i];
8303 stats.mProcDeaths[i] = aggr;
8304 }
8305 while (i<stats.mProcDeaths.length) {
8306 stats.mProcDeaths[i] = 0;
8307 i++;
8308 }
8309
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008310 for (i=mLruProcesses.size()-1; i>=0; i--) {
8311 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 if (proc.persistent) {
8313 continue;
8314 }
8315 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
8316 if (proc.lastPss == 0) {
8317 stats.mNoPssCount++;
8318 continue;
8319 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008320 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8321 if (proc.empty) {
8322 stats.mEmptyPss += proc.lastPss;
8323 stats.mEmptyCount++;
8324 } else {
8325 stats.mBackgroundPss += proc.lastPss;
8326 stats.mBackgroundCount++;
8327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8329 stats.mVisiblePss += proc.lastPss;
8330 stats.mVisibleCount++;
8331 } else {
8332 stats.mForegroundPss += proc.lastPss;
8333 stats.mForegroundCount++;
8334 }
8335 }
8336 }
8337 }
8338
8339 public final void startRunning(String pkg, String cls, String action,
8340 String data) {
8341 synchronized(this) {
8342 if (mStartRunning) {
8343 return;
8344 }
8345 mStartRunning = true;
8346 mTopComponent = pkg != null && cls != null
8347 ? new ComponentName(pkg, cls) : null;
8348 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8349 mTopData = data;
8350 if (!mSystemReady) {
8351 return;
8352 }
8353 }
8354
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008355 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 }
8357
8358 private void retrieveSettings() {
8359 final ContentResolver resolver = mContext.getContentResolver();
8360 String debugApp = Settings.System.getString(
8361 resolver, Settings.System.DEBUG_APP);
8362 boolean waitForDebugger = Settings.System.getInt(
8363 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8364 boolean alwaysFinishActivities = Settings.System.getInt(
8365 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8366
8367 Configuration configuration = new Configuration();
8368 Settings.System.getConfiguration(resolver, configuration);
8369
8370 synchronized (this) {
8371 mDebugApp = mOrigDebugApp = debugApp;
8372 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8373 mAlwaysFinishActivities = alwaysFinishActivities;
8374 // This happens before any activities are started, so we can
8375 // change mConfiguration in-place.
8376 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008377 mConfigurationSeq = mConfiguration.seq = 1;
Dianne Hackborndc6b6352009-09-30 14:20:09 -07008378 if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379 }
8380 }
8381
8382 public boolean testIsSystemReady() {
8383 // no need to synchronize(this) just to read & return the value
8384 return mSystemReady;
8385 }
8386
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008387 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 // In the simulator, startRunning will never have been called, which
8389 // normally sets a few crucial variables. Do it here instead.
8390 if (!Process.supportsProcesses()) {
8391 mStartRunning = true;
8392 mTopAction = Intent.ACTION_MAIN;
8393 }
8394
8395 synchronized(this) {
8396 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008397 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 return;
8399 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008400
8401 // Check to see if there are any update receivers to run.
8402 if (!mDidUpdate) {
8403 if (mWaitingUpdate) {
8404 return;
8405 }
8406 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8407 List<ResolveInfo> ris = null;
8408 try {
8409 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8410 intent, null, 0);
8411 } catch (RemoteException e) {
8412 }
8413 if (ris != null) {
8414 for (int i=ris.size()-1; i>=0; i--) {
8415 if ((ris.get(i).activityInfo.applicationInfo.flags
8416 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8417 ris.remove(i);
8418 }
8419 }
8420 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8421 for (int i=0; i<ris.size(); i++) {
8422 ActivityInfo ai = ris.get(i).activityInfo;
8423 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8424 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008425 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008426 finisher = new IIntentReceiver.Stub() {
8427 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008428 String data, Bundle extras, boolean ordered,
8429 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008430 throws RemoteException {
8431 synchronized (ActivityManagerService.this) {
8432 mDidUpdate = true;
8433 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008434 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008435 }
8436 };
8437 }
8438 Log.i(TAG, "Sending system update to: " + intent.getComponent());
8439 broadcastIntentLocked(null, null, intent, null, finisher,
8440 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008441 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008442 mWaitingUpdate = true;
8443 }
8444 }
8445 }
8446 if (mWaitingUpdate) {
8447 return;
8448 }
8449 mDidUpdate = true;
8450 }
8451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 mSystemReady = true;
8453 if (!mStartRunning) {
8454 return;
8455 }
8456 }
8457
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008458 ArrayList<ProcessRecord> procsToKill = null;
8459 synchronized(mPidsSelfLocked) {
8460 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8461 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8462 if (!isAllowedWhileBooting(proc.info)){
8463 if (procsToKill == null) {
8464 procsToKill = new ArrayList<ProcessRecord>();
8465 }
8466 procsToKill.add(proc);
8467 }
8468 }
8469 }
8470
8471 if (procsToKill != null) {
8472 synchronized(this) {
8473 for (int i=procsToKill.size()-1; i>=0; i--) {
8474 ProcessRecord proc = procsToKill.get(i);
8475 Log.i(TAG, "Removing system update proc: " + proc);
8476 removeProcessLocked(proc, true);
8477 }
8478 }
8479 }
8480
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008481 Log.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008482 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 SystemClock.uptimeMillis());
8484
8485 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008486 // Make sure we have no pre-ready processes sitting around.
8487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008488 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8489 ResolveInfo ri = mContext.getPackageManager()
8490 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008491 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 CharSequence errorMsg = null;
8493 if (ri != null) {
8494 ActivityInfo ai = ri.activityInfo;
8495 ApplicationInfo app = ai.applicationInfo;
8496 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8497 mTopAction = Intent.ACTION_FACTORY_TEST;
8498 mTopData = null;
8499 mTopComponent = new ComponentName(app.packageName,
8500 ai.name);
8501 } else {
8502 errorMsg = mContext.getResources().getText(
8503 com.android.internal.R.string.factorytest_not_system);
8504 }
8505 } else {
8506 errorMsg = mContext.getResources().getText(
8507 com.android.internal.R.string.factorytest_no_action);
8508 }
8509 if (errorMsg != null) {
8510 mTopAction = null;
8511 mTopData = null;
8512 mTopComponent = null;
8513 Message msg = Message.obtain();
8514 msg.what = SHOW_FACTORY_ERROR_MSG;
8515 msg.getData().putCharSequence("msg", errorMsg);
8516 mHandler.sendMessage(msg);
8517 }
8518 }
8519 }
8520
8521 retrieveSettings();
8522
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008523 if (goingCallback != null) goingCallback.run();
8524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008525 synchronized (this) {
8526 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8527 try {
8528 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008529 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 if (apps != null) {
8531 int N = apps.size();
8532 int i;
8533 for (i=0; i<N; i++) {
8534 ApplicationInfo info
8535 = (ApplicationInfo)apps.get(i);
8536 if (info != null &&
8537 !info.packageName.equals("android")) {
8538 addAppLocked(info);
8539 }
8540 }
8541 }
8542 } catch (RemoteException ex) {
8543 // pm is in same process, this will never happen.
8544 }
8545 }
8546
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008547 // Start up initial activity.
8548 mBooting = true;
8549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 try {
8551 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8552 Message msg = Message.obtain();
8553 msg.what = SHOW_UID_ERROR_MSG;
8554 mHandler.sendMessage(msg);
8555 }
8556 } catch (RemoteException e) {
8557 }
8558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008559 resumeTopActivityLocked(null);
8560 }
8561 }
8562
Dan Egnorb7f03672009-12-09 16:22:32 -08008563 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008564 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008566 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008567 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 startAppProblemLocked(app);
8569 app.stopFreezingAllLocked();
8570 return handleAppCrashLocked(app);
8571 }
8572
Dan Egnorb7f03672009-12-09 16:22:32 -08008573 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008574 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008576 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008577 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8578 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 startAppProblemLocked(app);
8580 app.stopFreezingAllLocked();
8581 }
8582
8583 /**
8584 * Generate a process error record, suitable for attachment to a ProcessRecord.
8585 *
8586 * @param app The ProcessRecord in which the error occurred.
8587 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8588 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008589 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008590 * @param shortMsg Short message describing the crash.
8591 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008592 * @param stackTrace Full crash stack trace, may be null.
8593 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 * @return Returns a fully-formed AppErrorStateInfo record.
8595 */
8596 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008597 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008598 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008600 report.condition = condition;
8601 report.processName = app.processName;
8602 report.pid = app.pid;
8603 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008604 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 report.shortMsg = shortMsg;
8606 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008607 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008608
8609 return report;
8610 }
8611
Dan Egnor42471dd2010-01-07 17:25:22 -08008612 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 synchronized (this) {
8614 app.crashing = false;
8615 app.crashingReport = null;
8616 app.notResponding = false;
8617 app.notRespondingReport = null;
8618 if (app.anrDialog == fromDialog) {
8619 app.anrDialog = null;
8620 }
8621 if (app.waitDialog == fromDialog) {
8622 app.waitDialog = null;
8623 }
8624 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008625 handleAppCrashLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 Log.i(ActivityManagerService.TAG, "Killing process "
8627 + app.processName
8628 + " (pid=" + app.pid + ") at user's request");
8629 Process.killProcess(app.pid);
8630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 }
8632 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008633
Dan Egnorb7f03672009-12-09 16:22:32 -08008634 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 long now = SystemClock.uptimeMillis();
8636
8637 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8638 app.info.uid);
8639 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8640 // This process loses!
8641 Log.w(TAG, "Process " + app.info.processName
8642 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008643 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 app.info.processName, app.info.uid);
8645 killServicesLocked(app, false);
8646 for (int i=mHistory.size()-1; i>=0; i--) {
8647 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8648 if (r.app == app) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08008649 Log.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 + r.intent.getComponent().flattenToShortString());
8651 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8652 }
8653 }
8654 if (!app.persistent) {
8655 // We don't want to start this process again until the user
8656 // explicitly does so... but for persistent process, we really
8657 // need to keep it running. If a persistent process is actually
8658 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008659 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 app.info.processName);
8661 mBadProcesses.put(app.info.processName, app.info.uid, now);
8662 app.bad = true;
8663 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8664 app.removed = true;
8665 removeProcessLocked(app, false);
8666 return false;
8667 }
8668 }
8669
8670 // Bump up the crash count of any services currently running in the proc.
8671 if (app.services.size() != 0) {
8672 // Any services running in the application need to be placed
8673 // back in the pending list.
8674 Iterator it = app.services.iterator();
8675 while (it.hasNext()) {
8676 ServiceRecord sr = (ServiceRecord)it.next();
8677 sr.crashCount++;
8678 }
8679 }
8680
8681 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8682 return true;
8683 }
8684
8685 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008686 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8687 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008688 skipCurrentReceiverLocked(app);
8689 }
8690
8691 void skipCurrentReceiverLocked(ProcessRecord app) {
8692 boolean reschedule = false;
8693 BroadcastRecord r = app.curReceiver;
8694 if (r != null) {
8695 // The current broadcast is waiting for this app's receiver
8696 // to be finished. Looks like that's not going to happen, so
8697 // let the broadcast continue.
8698 logBroadcastReceiverDiscard(r);
8699 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8700 r.resultExtras, r.resultAbort, true);
8701 reschedule = true;
8702 }
8703 r = mPendingBroadcast;
8704 if (r != null && r.curApp == app) {
8705 if (DEBUG_BROADCAST) Log.v(TAG,
8706 "skip & discard pending app " + r);
8707 logBroadcastReceiverDiscard(r);
8708 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8709 r.resultExtras, r.resultAbort, true);
8710 reschedule = true;
8711 }
8712 if (reschedule) {
8713 scheduleBroadcastsLocked();
8714 }
8715 }
8716
Dan Egnor60d87622009-12-16 16:32:58 -08008717 /**
8718 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8719 * The application process will exit immediately after this call returns.
8720 * @param app object of the crashing app, null for the system server
8721 * @param crashInfo describing the exception
8722 */
8723 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8724 ProcessRecord r = findAppProcess(app);
8725
8726 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8727 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008728 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008729 crashInfo.exceptionClassName,
8730 crashInfo.exceptionMessage,
8731 crashInfo.throwFileName,
8732 crashInfo.throwLineNumber);
8733
Dan Egnor42471dd2010-01-07 17:25:22 -08008734 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008735
8736 crashApplication(r, crashInfo);
8737 }
8738
8739 /**
8740 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8741 * @param app object of the crashing app, null for the system server
8742 * @param tag reported by the caller
8743 * @param crashInfo describing the context of the error
8744 * @return true if the process should exit immediately (WTF is fatal)
8745 */
8746 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008747 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008748 ProcessRecord r = findAppProcess(app);
8749
8750 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8751 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008752 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008753 tag, crashInfo.exceptionMessage);
8754
Dan Egnor42471dd2010-01-07 17:25:22 -08008755 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008756
Doug Zongker43866e02010-01-07 12:09:54 -08008757 if (Settings.Secure.getInt(mContext.getContentResolver(),
8758 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008759 crashApplication(r, crashInfo);
8760 return true;
8761 } else {
8762 return false;
8763 }
8764 }
8765
8766 /**
8767 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8768 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8769 */
8770 private ProcessRecord findAppProcess(IBinder app) {
8771 if (app == null) {
8772 return null;
8773 }
8774
8775 synchronized (this) {
8776 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8777 final int NA = apps.size();
8778 for (int ia=0; ia<NA; ia++) {
8779 ProcessRecord p = apps.valueAt(ia);
8780 if (p.thread != null && p.thread.asBinder() == app) {
8781 return p;
8782 }
8783 }
8784 }
8785
8786 Log.w(TAG, "Can't find mystery application: " + app);
8787 return null;
8788 }
8789 }
8790
8791 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008792 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008793 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008794 * @param process which caused the error, null means the system server
8795 * @param activity which triggered the error, null if unknown
8796 * @param parent activity related to the error, null if unknown
8797 * @param subject line related to the error, null if absent
8798 * @param report in long form describing the error, null if absent
8799 * @param logFile to include in the report, null if none
8800 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008801 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008802 private void addErrorToDropBox(String eventType,
8803 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8804 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008805 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008806 String dropboxTag;
8807 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008808 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008809 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008810 dropboxTag = "system_app_" + eventType;
8811 } else {
8812 dropboxTag = "data_app_" + eventType;
8813 }
8814
8815 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8816 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8817 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008818 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008819 sb.append("Process: system_server\n");
8820 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008821 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008822 }
8823 if (process != null) {
8824 int flags = process.info.flags;
8825 IPackageManager pm = ActivityThread.getPackageManager();
8826 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8827 for (String pkg : process.pkgList) {
8828 sb.append("Package: ").append(pkg);
8829 try {
8830 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8831 if (pi != null) {
8832 sb.append(" v").append(pi.versionCode);
8833 if (pi.versionName != null) {
8834 sb.append(" (").append(pi.versionName).append(")");
8835 }
8836 }
8837 } catch (RemoteException e) {
8838 Log.e(TAG, "Error getting package info: " + pkg, e);
8839 }
8840 sb.append("\n");
8841 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008842 }
8843 if (activity != null) {
8844 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8845 }
8846 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8847 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8848 }
8849 if (parent != null && parent != activity) {
8850 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8851 }
8852 if (subject != null) {
8853 sb.append("Subject: ").append(subject).append("\n");
8854 }
8855 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8856 sb.append("\n");
8857 if (report != null) {
8858 sb.append(report);
8859 }
8860 if (logFile != null) {
8861 try {
8862 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8863 } catch (IOException e) {
8864 Log.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008865 }
8866 }
Dan Egnor60d87622009-12-16 16:32:58 -08008867 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008868 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08008869 }
8870 dbox.addText(dropboxTag, sb.toString());
8871 }
8872 }
8873
8874 /**
8875 * Bring up the "unexpected error" dialog box for a crashing app.
8876 * Deal with edge cases (intercepts from instrumented applications,
8877 * ActivityController, error intent receivers, that sort of thing).
8878 * @param r the application crashing
8879 * @param crashInfo describing the failure
8880 */
8881 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008882 long timeMillis = System.currentTimeMillis();
8883 String shortMsg = crashInfo.exceptionClassName;
8884 String longMsg = crashInfo.exceptionMessage;
8885 String stackTrace = crashInfo.stackTrace;
8886 if (shortMsg != null && longMsg != null) {
8887 longMsg = shortMsg + ": " + longMsg;
8888 } else if (shortMsg != null) {
8889 longMsg = shortMsg;
8890 }
8891
Dan Egnor60d87622009-12-16 16:32:58 -08008892 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008894 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 try {
8896 String name = r != null ? r.processName : null;
8897 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008898 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008899 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 Log.w(TAG, "Force-killing crashed app " + name
8901 + " at watcher's request");
8902 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008903 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 }
8905 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008906 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008907 }
8908 }
8909
8910 final long origId = Binder.clearCallingIdentity();
8911
8912 // If this process is running instrumentation, finish it.
8913 if (r != null && r.instrumentationClass != null) {
8914 Log.w(TAG, "Error in app " + r.processName
8915 + " running instrumentation " + r.instrumentationClass + ":");
8916 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
8917 if (longMsg != null) Log.w(TAG, " " + longMsg);
8918 Bundle info = new Bundle();
8919 info.putString("shortMsg", shortMsg);
8920 info.putString("longMsg", longMsg);
8921 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8922 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008923 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 }
8925
Dan Egnor60d87622009-12-16 16:32:58 -08008926 // If we can't identify the process or it's already exceeded its crash quota,
8927 // quit right away without showing a crash dialog.
8928 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008929 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008930 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 }
8932
8933 Message msg = Message.obtain();
8934 msg.what = SHOW_ERROR_MSG;
8935 HashMap data = new HashMap();
8936 data.put("result", result);
8937 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938 msg.obj = data;
8939 mHandler.sendMessage(msg);
8940
8941 Binder.restoreCallingIdentity(origId);
8942 }
8943
8944 int res = result.get();
8945
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008946 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 synchronized (this) {
8948 if (r != null) {
8949 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8950 SystemClock.uptimeMillis());
8951 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008952 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008953 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008954 }
8955 }
8956
8957 if (appErrorIntent != null) {
8958 try {
8959 mContext.startActivity(appErrorIntent);
8960 } catch (ActivityNotFoundException e) {
8961 Log.w(TAG, "bug report receiver dissappeared", e);
8962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 }
Dan Egnorb7f03672009-12-09 16:22:32 -08008965
8966 Intent createAppErrorIntentLocked(ProcessRecord r,
8967 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
8968 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008969 if (report == null) {
8970 return null;
8971 }
8972 Intent result = new Intent(Intent.ACTION_APP_ERROR);
8973 result.setComponent(r.errorReportReceiver);
8974 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
8975 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8976 return result;
8977 }
8978
Dan Egnorb7f03672009-12-09 16:22:32 -08008979 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
8980 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008981 if (r.errorReportReceiver == null) {
8982 return null;
8983 }
8984
8985 if (!r.crashing && !r.notResponding) {
8986 return null;
8987 }
8988
Dan Egnorb7f03672009-12-09 16:22:32 -08008989 ApplicationErrorReport report = new ApplicationErrorReport();
8990 report.packageName = r.info.packageName;
8991 report.installerPackageName = r.errorReportReceiver.getPackageName();
8992 report.processName = r.processName;
8993 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01008994 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008995
Dan Egnorb7f03672009-12-09 16:22:32 -08008996 if (r.crashing) {
8997 report.type = ApplicationErrorReport.TYPE_CRASH;
8998 report.crashInfo = crashInfo;
8999 } else if (r.notResponding) {
9000 report.type = ApplicationErrorReport.TYPE_ANR;
9001 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009002
Dan Egnorb7f03672009-12-09 16:22:32 -08009003 report.anrInfo.activity = r.notRespondingReport.tag;
9004 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9005 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009006 }
9007
Dan Egnorb7f03672009-12-09 16:22:32 -08009008 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009009 }
9010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009011 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9012 // assume our apps are happy - lazy create the list
9013 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9014
9015 synchronized (this) {
9016
9017 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009018 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9019 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9021 // This one's in trouble, so we'll generate a report for it
9022 // crashes are higher priority (in case there's a crash *and* an anr)
9023 ActivityManager.ProcessErrorStateInfo report = null;
9024 if (app.crashing) {
9025 report = app.crashingReport;
9026 } else if (app.notResponding) {
9027 report = app.notRespondingReport;
9028 }
9029
9030 if (report != null) {
9031 if (errList == null) {
9032 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9033 }
9034 errList.add(report);
9035 } else {
9036 Log.w(TAG, "Missing app error report, app = " + app.processName +
9037 " crashing = " + app.crashing +
9038 " notResponding = " + app.notResponding);
9039 }
9040 }
9041 }
9042 }
9043
9044 return errList;
9045 }
9046
9047 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9048 // Lazy instantiation of list
9049 List<ActivityManager.RunningAppProcessInfo> runList = null;
9050 synchronized (this) {
9051 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009052 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9053 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9055 // Generate process state info for running application
9056 ActivityManager.RunningAppProcessInfo currApp =
9057 new ActivityManager.RunningAppProcessInfo(app.processName,
9058 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009059 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009060 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009061 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9063 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9064 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009065 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9066 } else if (adj >= HOME_APP_ADJ) {
9067 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9068 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 } else if (adj >= SECONDARY_SERVER_ADJ) {
9070 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9071 } else if (adj >= VISIBLE_APP_ADJ) {
9072 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9073 } else {
9074 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9075 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009076 currApp.importanceReasonCode = app.adjTypeCode;
9077 if (app.adjSource instanceof ProcessRecord) {
9078 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9079 } else if (app.adjSource instanceof HistoryRecord) {
9080 HistoryRecord r = (HistoryRecord)app.adjSource;
9081 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9082 }
9083 if (app.adjTarget instanceof ComponentName) {
9084 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
9087 // + " lru=" + currApp.lru);
9088 if (runList == null) {
9089 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9090 }
9091 runList.add(currApp);
9092 }
9093 }
9094 }
9095 return runList;
9096 }
9097
9098 @Override
9099 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009100 if (checkCallingPermission(android.Manifest.permission.DUMP)
9101 != PackageManager.PERMISSION_GRANTED) {
9102 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9103 + Binder.getCallingPid()
9104 + ", uid=" + Binder.getCallingUid()
9105 + " without permission "
9106 + android.Manifest.permission.DUMP);
9107 return;
9108 }
9109
9110 boolean dumpAll = false;
9111
9112 int opti = 0;
9113 while (opti < args.length) {
9114 String opt = args[opti];
9115 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9116 break;
9117 }
9118 opti++;
9119 if ("-a".equals(opt)) {
9120 dumpAll = true;
9121 } else if ("-h".equals(opt)) {
9122 pw.println("Activity manager dump options:");
9123 pw.println(" [-a] [h- [cmd] ...");
9124 pw.println(" cmd may be one of:");
9125 pw.println(" activities: activity stack state");
9126 pw.println(" broadcasts: broadcast state");
9127 pw.println(" intents: pending intent state");
9128 pw.println(" processes: process state");
9129 pw.println(" providers: content provider state");
9130 pw.println(" services: service state");
9131 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009133 } else {
9134 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009136 }
9137
9138 // Is the caller requesting to dump a particular piece of data?
9139 if (opti < args.length) {
9140 String cmd = args[opti];
9141 opti++;
9142 if ("activities".equals(cmd) || "a".equals(cmd)) {
9143 synchronized (this) {
9144 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009146 return;
9147 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9148 synchronized (this) {
9149 dumpBroadcastsLocked(fd, pw, args, opti, true);
9150 }
9151 return;
9152 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9153 synchronized (this) {
9154 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9155 }
9156 return;
9157 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9158 synchronized (this) {
9159 dumpProcessesLocked(fd, pw, args, opti, true);
9160 }
9161 return;
9162 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9163 synchronized (this) {
9164 dumpProvidersLocked(fd, pw, args, opti, true);
9165 }
9166 return;
9167 } else if ("service".equals(cmd)) {
9168 dumpService(fd, pw, args, opti, true);
9169 return;
9170 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9171 synchronized (this) {
9172 dumpServicesLocked(fd, pw, args, opti, true);
9173 }
9174 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009176 }
9177
9178 // No piece of data specified, dump everything.
9179 synchronized (this) {
9180 boolean needSep;
9181 if (dumpAll) {
9182 pw.println("Providers in Current Activity Manager State:");
9183 }
9184 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9185 if (needSep) {
9186 pw.println(" ");
9187 }
9188 if (dumpAll) {
9189 pw.println("-------------------------------------------------------------------------------");
9190 pw.println("Broadcasts in Current Activity Manager State:");
9191 }
9192 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9193 if (needSep) {
9194 pw.println(" ");
9195 }
9196 if (dumpAll) {
9197 pw.println("-------------------------------------------------------------------------------");
9198 pw.println("Services in Current Activity Manager State:");
9199 }
9200 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9201 if (needSep) {
9202 pw.println(" ");
9203 }
9204 if (dumpAll) {
9205 pw.println("-------------------------------------------------------------------------------");
9206 pw.println("PendingIntents in Current Activity Manager State:");
9207 }
9208 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9209 if (needSep) {
9210 pw.println(" ");
9211 }
9212 if (dumpAll) {
9213 pw.println("-------------------------------------------------------------------------------");
9214 pw.println("Activities in Current Activity Manager State:");
9215 }
9216 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9217 if (needSep) {
9218 pw.println(" ");
9219 }
9220 if (dumpAll) {
9221 pw.println("-------------------------------------------------------------------------------");
9222 pw.println("Processes in Current Activity Manager State:");
9223 }
9224 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9225 }
9226 }
9227
9228 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9229 int opti, boolean dumpAll, boolean needHeader) {
9230 if (needHeader) {
9231 pw.println(" Activity stack:");
9232 }
9233 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9234 pw.println(" ");
9235 pw.println(" Running activities (most recent first):");
9236 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9237 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009238 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009239 pw.println(" Activities waiting for another to become visible:");
9240 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9241 }
9242 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009244 pw.println(" Activities waiting to stop:");
9245 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9246 }
9247 if (mFinishingActivities.size() > 0) {
9248 pw.println(" ");
9249 pw.println(" Activities waiting to finish:");
9250 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009253 pw.println(" ");
9254 pw.println(" mPausingActivity: " + mPausingActivity);
9255 pw.println(" mResumedActivity: " + mResumedActivity);
9256 pw.println(" mFocusedActivity: " + mFocusedActivity);
9257 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009259 if (dumpAll && mRecentTasks.size() > 0) {
9260 pw.println(" ");
9261 pw.println("Recent tasks in Current Activity Manager State:");
9262
9263 final int N = mRecentTasks.size();
9264 for (int i=0; i<N; i++) {
9265 TaskRecord tr = mRecentTasks.get(i);
9266 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9267 pw.println(tr);
9268 mRecentTasks.get(i).dump(pw, " ");
9269 }
9270 }
9271
9272 pw.println(" ");
9273 pw.println(" mCurTask: " + mCurTask);
9274
9275 return true;
9276 }
9277
9278 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9279 int opti, boolean dumpAll) {
9280 boolean needSep = false;
9281 int numPers = 0;
9282
9283 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009284 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9285 final int NA = procs.size();
9286 for (int ia=0; ia<NA; ia++) {
9287 if (!needSep) {
9288 pw.println(" All known processes:");
9289 needSep = true;
9290 }
9291 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009292 pw.print(r.persistent ? " *PERS*" : " *APP*");
9293 pw.print(" UID "); pw.print(procs.keyAt(ia));
9294 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 r.dump(pw, " ");
9296 if (r.persistent) {
9297 numPers++;
9298 }
9299 }
9300 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009301 }
9302
9303 if (mLruProcesses.size() > 0) {
9304 if (needSep) pw.println(" ");
9305 needSep = true;
9306 pw.println(" Running processes (most recent first):");
9307 dumpProcessList(pw, this, mLruProcesses, " ",
9308 "App ", "PERS", true);
9309 needSep = true;
9310 }
9311
9312 synchronized (mPidsSelfLocked) {
9313 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 if (needSep) pw.println(" ");
9315 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009316 pw.println(" PID mappings:");
9317 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9318 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9319 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 }
9321 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009322 }
9323
9324 if (mForegroundProcesses.size() > 0) {
9325 if (needSep) pw.println(" ");
9326 needSep = true;
9327 pw.println(" Foreground Processes:");
9328 for (int i=0; i<mForegroundProcesses.size(); i++) {
9329 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9330 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009332 }
9333
9334 if (mPersistentStartingProcesses.size() > 0) {
9335 if (needSep) pw.println(" ");
9336 needSep = true;
9337 pw.println(" Persisent processes that are starting:");
9338 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9339 "Starting Norm", "Restarting PERS", false);
9340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009342 if (mStartingProcesses.size() > 0) {
9343 if (needSep) pw.println(" ");
9344 needSep = true;
9345 pw.println(" Processes that are starting:");
9346 dumpProcessList(pw, this, mStartingProcesses, " ",
9347 "Starting Norm", "Starting PERS", false);
9348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009350 if (mRemovedProcesses.size() > 0) {
9351 if (needSep) pw.println(" ");
9352 needSep = true;
9353 pw.println(" Processes that are being removed:");
9354 dumpProcessList(pw, this, mRemovedProcesses, " ",
9355 "Removed Norm", "Removed PERS", false);
9356 }
9357
9358 if (mProcessesOnHold.size() > 0) {
9359 if (needSep) pw.println(" ");
9360 needSep = true;
9361 pw.println(" Processes that are on old until the system is ready:");
9362 dumpProcessList(pw, this, mProcessesOnHold, " ",
9363 "OnHold Norm", "OnHold PERS", false);
9364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009366 if (mProcessesToGc.size() > 0) {
9367 if (needSep) pw.println(" ");
9368 needSep = true;
9369 pw.println(" Processes that are waiting to GC:");
9370 long now = SystemClock.uptimeMillis();
9371 for (int i=0; i<mProcessesToGc.size(); i++) {
9372 ProcessRecord proc = mProcessesToGc.get(i);
9373 pw.print(" Process "); pw.println(proc);
9374 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9375 pw.print(", last gced=");
9376 pw.print(now-proc.lastRequestedGc);
9377 pw.print(" ms ago, last lowMem=");
9378 pw.print(now-proc.lastLowMemory);
9379 pw.println(" ms ago");
9380
9381 }
9382 }
9383
9384 if (mProcessCrashTimes.getMap().size() > 0) {
9385 if (needSep) pw.println(" ");
9386 needSep = true;
9387 pw.println(" Time since processes crashed:");
9388 long now = SystemClock.uptimeMillis();
9389 for (Map.Entry<String, SparseArray<Long>> procs
9390 : mProcessCrashTimes.getMap().entrySet()) {
9391 SparseArray<Long> uids = procs.getValue();
9392 final int N = uids.size();
9393 for (int i=0; i<N; i++) {
9394 pw.print(" Process "); pw.print(procs.getKey());
9395 pw.print(" uid "); pw.print(uids.keyAt(i));
9396 pw.print(": last crashed ");
9397 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009398 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009399 }
9400 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009403 if (mBadProcesses.getMap().size() > 0) {
9404 if (needSep) pw.println(" ");
9405 needSep = true;
9406 pw.println(" Bad processes:");
9407 for (Map.Entry<String, SparseArray<Long>> procs
9408 : mBadProcesses.getMap().entrySet()) {
9409 SparseArray<Long> uids = procs.getValue();
9410 final int N = uids.size();
9411 for (int i=0; i<N; i++) {
9412 pw.print(" Bad process "); pw.print(procs.getKey());
9413 pw.print(" uid "); pw.print(uids.keyAt(i));
9414 pw.print(": crashed at time ");
9415 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 }
9417 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009420 pw.println(" ");
9421 pw.println(" mHomeProcess: " + mHomeProcess);
9422 pw.println(" mConfiguration: " + mConfiguration);
9423 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9424 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9425 || mOrigWaitForDebugger) {
9426 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9427 + " mDebugTransient=" + mDebugTransient
9428 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9429 }
9430 if (mAlwaysFinishActivities || mController != null) {
9431 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9432 + " mController=" + mController);
9433 }
9434 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009435 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 pw.println(" mStartRunning=" + mStartRunning
9437 + " mSystemReady=" + mSystemReady
9438 + " mBooting=" + mBooting
9439 + " mBooted=" + mBooted
9440 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009441 pw.println(" mGoingToSleep=" + mGoingToSleep);
9442 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009444
9445 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 }
9447
9448 /**
9449 * There are three ways to call this:
9450 * - no service specified: dump all the services
9451 * - a flattened component name that matched an existing service was specified as the
9452 * first arg: dump that one service
9453 * - the first arg isn't the flattened component name of an existing service:
9454 * dump all services whose component contains the first arg as a substring
9455 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009456 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9457 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009458 String[] newArgs;
9459 String componentNameString;
9460 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009461 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 componentNameString = null;
9463 newArgs = EMPTY_STRING_ARRAY;
9464 r = null;
9465 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009466 componentNameString = args[opti];
9467 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9469 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009470 newArgs = new String[args.length - opti];
9471 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009472 }
9473
9474 if (r != null) {
9475 dumpService(fd, pw, r, newArgs);
9476 } else {
9477 for (ServiceRecord r1 : mServices.values()) {
9478 if (componentNameString == null
9479 || r1.name.flattenToString().contains(componentNameString)) {
9480 dumpService(fd, pw, r1, newArgs);
9481 }
9482 }
9483 }
9484 }
9485
9486 /**
9487 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9488 * there is a thread associated with the service.
9489 */
9490 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9491 pw.println(" Service " + r.name.flattenToString());
9492 if (r.app != null && r.app.thread != null) {
9493 try {
9494 // flush anything that is already in the PrintWriter since the thread is going
9495 // to write to the file descriptor directly
9496 pw.flush();
9497 r.app.thread.dumpService(fd, r, args);
9498 pw.print("\n");
9499 } catch (RemoteException e) {
9500 pw.println("got a RemoteException while dumping the service");
9501 }
9502 }
9503 }
9504
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009505 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9506 int opti, boolean dumpAll) {
9507 boolean needSep = false;
9508
9509 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009510 if (mRegisteredReceivers.size() > 0) {
9511 pw.println(" ");
9512 pw.println(" Registered Receivers:");
9513 Iterator it = mRegisteredReceivers.values().iterator();
9514 while (it.hasNext()) {
9515 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009516 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 r.dump(pw, " ");
9518 }
9519 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 pw.println(" ");
9522 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009523 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009524 needSep = true;
9525 }
9526
9527 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9528 || mPendingBroadcast != null) {
9529 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009530 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009531 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009532 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009533 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9534 pw.println(" Broadcast #" + i + ":");
9535 mParallelBroadcasts.get(i).dump(pw, " ");
9536 }
9537 if (mOrderedBroadcasts.size() > 0) {
9538 pw.println(" ");
9539 pw.println(" Active serialized broadcasts:");
9540 }
9541 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9542 pw.println(" Serialized Broadcast #" + i + ":");
9543 mOrderedBroadcasts.get(i).dump(pw, " ");
9544 }
9545 pw.println(" ");
9546 pw.println(" Pending broadcast:");
9547 if (mPendingBroadcast != null) {
9548 mPendingBroadcast.dump(pw, " ");
9549 } else {
9550 pw.println(" (null)");
9551 }
9552 needSep = true;
9553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009555 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009557 pw.println(" Historical broadcasts:");
9558 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9559 BroadcastRecord r = mBroadcastHistory[i];
9560 if (r == null) {
9561 break;
9562 }
9563 pw.println(" Historical Broadcast #" + i + ":");
9564 r.dump(pw, " ");
9565 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009566 needSep = true;
9567 }
9568
9569 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009570 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009571 pw.println(" Sticky broadcasts:");
9572 StringBuilder sb = new StringBuilder(128);
9573 for (Map.Entry<String, ArrayList<Intent>> ent
9574 : mStickyBroadcasts.entrySet()) {
9575 pw.print(" * Sticky action "); pw.print(ent.getKey());
9576 pw.println(":");
9577 ArrayList<Intent> intents = ent.getValue();
9578 final int N = intents.size();
9579 for (int i=0; i<N; i++) {
9580 sb.setLength(0);
9581 sb.append(" Intent: ");
9582 intents.get(i).toShortString(sb, true, false);
9583 pw.println(sb.toString());
9584 Bundle bundle = intents.get(i).getExtras();
9585 if (bundle != null) {
9586 pw.print(" ");
9587 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 }
9589 }
9590 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009591 needSep = true;
9592 }
9593
9594 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009595 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009596 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 pw.println(" mHandler:");
9598 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009599 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009601
9602 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 }
9604
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009605 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9606 int opti, boolean dumpAll) {
9607 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009609 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610 if (mServices.size() > 0) {
9611 pw.println(" Active services:");
9612 Iterator<ServiceRecord> it = mServices.values().iterator();
9613 while (it.hasNext()) {
9614 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009615 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 r.dump(pw, " ");
9617 }
9618 needSep = true;
9619 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009622 if (mPendingServices.size() > 0) {
9623 if (needSep) pw.println(" ");
9624 pw.println(" Pending services:");
9625 for (int i=0; i<mPendingServices.size(); i++) {
9626 ServiceRecord r = mPendingServices.get(i);
9627 pw.print(" * Pending "); pw.println(r);
9628 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009629 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009630 needSep = true;
9631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009633 if (mRestartingServices.size() > 0) {
9634 if (needSep) pw.println(" ");
9635 pw.println(" Restarting services:");
9636 for (int i=0; i<mRestartingServices.size(); i++) {
9637 ServiceRecord r = mRestartingServices.get(i);
9638 pw.print(" * Restarting "); pw.println(r);
9639 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009640 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009641 needSep = true;
9642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009644 if (mStoppingServices.size() > 0) {
9645 if (needSep) pw.println(" ");
9646 pw.println(" Stopping services:");
9647 for (int i=0; i<mStoppingServices.size(); i++) {
9648 ServiceRecord r = mStoppingServices.get(i);
9649 pw.print(" * Stopping "); pw.println(r);
9650 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009651 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009652 needSep = true;
9653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009655 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656 if (mServiceConnections.size() > 0) {
9657 if (needSep) pw.println(" ");
9658 pw.println(" Connection bindings to services:");
9659 Iterator<ConnectionRecord> it
9660 = mServiceConnections.values().iterator();
9661 while (it.hasNext()) {
9662 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009663 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 r.dump(pw, " ");
9665 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009666 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 }
9668 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009669
9670 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 }
9672
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009673 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9674 int opti, boolean dumpAll) {
9675 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009677 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678 if (mProvidersByClass.size() > 0) {
9679 if (needSep) pw.println(" ");
9680 pw.println(" Published content providers (by class):");
9681 Iterator it = mProvidersByClass.entrySet().iterator();
9682 while (it.hasNext()) {
9683 Map.Entry e = (Map.Entry)it.next();
9684 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009685 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 r.dump(pw, " ");
9687 }
9688 needSep = true;
9689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009690
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009691 if (mProvidersByName.size() > 0) {
9692 pw.println(" ");
9693 pw.println(" Authority to provider mappings:");
9694 Iterator it = mProvidersByName.entrySet().iterator();
9695 while (it.hasNext()) {
9696 Map.Entry e = (Map.Entry)it.next();
9697 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9698 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9699 pw.println(r);
9700 }
9701 needSep = true;
9702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009704
9705 if (mLaunchingProviders.size() > 0) {
9706 if (needSep) pw.println(" ");
9707 pw.println(" Launching content providers:");
9708 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9709 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9710 pw.println(mLaunchingProviders.get(i));
9711 }
9712 needSep = true;
9713 }
9714
9715 if (mGrantedUriPermissions.size() > 0) {
9716 pw.println();
9717 pw.println("Granted Uri Permissions:");
9718 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9719 int uid = mGrantedUriPermissions.keyAt(i);
9720 HashMap<Uri, UriPermission> perms
9721 = mGrantedUriPermissions.valueAt(i);
9722 pw.print(" * UID "); pw.print(uid);
9723 pw.println(" holds:");
9724 for (UriPermission perm : perms.values()) {
9725 pw.print(" "); pw.println(perm);
9726 perm.dump(pw, " ");
9727 }
9728 }
9729 needSep = true;
9730 }
9731
9732 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 }
9734
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009735 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9736 int opti, boolean dumpAll) {
9737 boolean needSep = false;
9738
9739 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 if (this.mIntentSenderRecords.size() > 0) {
9741 Iterator<WeakReference<PendingIntentRecord>> it
9742 = mIntentSenderRecords.values().iterator();
9743 while (it.hasNext()) {
9744 WeakReference<PendingIntentRecord> ref = it.next();
9745 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009746 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009748 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 rec.dump(pw, " ");
9750 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009751 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 }
9753 }
9754 }
9755 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009756
9757 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 }
9759
9760 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009761 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 TaskRecord lastTask = null;
9763 for (int i=list.size()-1; i>=0; i--) {
9764 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009765 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 if (lastTask != r.task) {
9767 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009768 pw.print(prefix);
9769 pw.print(full ? "* " : " ");
9770 pw.println(lastTask);
9771 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009772 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009775 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9776 pw.print(" #"); pw.print(i); pw.print(": ");
9777 pw.println(r);
9778 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009779 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 }
9782 }
9783
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009784 private static String buildOomTag(String prefix, String space, int val, int base) {
9785 if (val == base) {
9786 if (space == null) return prefix;
9787 return prefix + " ";
9788 }
9789 return prefix + "+" + Integer.toString(val-base);
9790 }
9791
9792 private static final int dumpProcessList(PrintWriter pw,
9793 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 String prefix, String normalLabel, String persistentLabel,
9795 boolean inclOomAdj) {
9796 int numPers = 0;
9797 for (int i=list.size()-1; i>=0; i--) {
9798 ProcessRecord r = (ProcessRecord)list.get(i);
9799 if (false) {
9800 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9801 + " #" + i + ":");
9802 r.dump(pw, prefix + " ");
9803 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009804 String oomAdj;
9805 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009806 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009807 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009808 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9809 } else if (r.setAdj >= HOME_APP_ADJ) {
9810 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9811 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9812 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9813 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9814 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9815 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9816 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9817 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9818 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009819 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009820 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009821 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009822 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009823 } else {
9824 oomAdj = Integer.toString(r.setAdj);
9825 }
9826 String schedGroup;
9827 switch (r.setSchedGroup) {
9828 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9829 schedGroup = "B";
9830 break;
9831 case Process.THREAD_GROUP_DEFAULT:
9832 schedGroup = "F";
9833 break;
9834 default:
9835 schedGroup = Integer.toString(r.setSchedGroup);
9836 break;
9837 }
9838 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009840 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009841 if (r.adjSource != null || r.adjTarget != null) {
9842 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009843 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 } else {
9846 pw.println(String.format("%s%s #%2d: %s",
9847 prefix, (r.persistent ? persistentLabel : normalLabel),
9848 i, r.toString()));
9849 }
9850 if (r.persistent) {
9851 numPers++;
9852 }
9853 }
9854 return numPers;
9855 }
9856
9857 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
9858 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009859 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 long uptime = SystemClock.uptimeMillis();
9861 long realtime = SystemClock.elapsedRealtime();
9862
9863 if (isCheckinRequest) {
9864 // short checkin version
9865 pw.println(uptime + "," + realtime);
9866 pw.flush();
9867 } else {
9868 pw.println("Applications Memory Usage (kB):");
9869 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9870 }
9871 for (int i = list.size() - 1 ; i >= 0 ; i--) {
9872 ProcessRecord r = (ProcessRecord)list.get(i);
9873 if (r.thread != null) {
9874 if (!isCheckinRequest) {
9875 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9876 pw.flush();
9877 }
9878 try {
9879 r.thread.asBinder().dump(fd, args);
9880 } catch (RemoteException e) {
9881 if (!isCheckinRequest) {
9882 pw.println("Got RemoteException!");
9883 pw.flush();
9884 }
9885 }
9886 }
9887 }
9888 }
9889
9890 /**
9891 * Searches array of arguments for the specified string
9892 * @param args array of argument strings
9893 * @param value value to search for
9894 * @return true if the value is contained in the array
9895 */
9896 private static boolean scanArgs(String[] args, String value) {
9897 if (args != null) {
9898 for (String arg : args) {
9899 if (value.equals(arg)) {
9900 return true;
9901 }
9902 }
9903 }
9904 return false;
9905 }
9906
Dianne Hackborn75b03852009-06-12 15:43:26 -07009907 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908 int count = mHistory.size();
9909
9910 // convert the token to an entry in the history.
9911 HistoryRecord r = null;
9912 int index = -1;
9913 for (int i=count-1; i>=0; i--) {
9914 Object o = mHistory.get(i);
9915 if (o == token) {
9916 r = (HistoryRecord)o;
9917 index = i;
9918 break;
9919 }
9920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921
9922 return index;
9923 }
9924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 private final void killServicesLocked(ProcessRecord app,
9926 boolean allowRestart) {
9927 // Report disconnected services.
9928 if (false) {
9929 // XXX we are letting the client link to the service for
9930 // death notifications.
9931 if (app.services.size() > 0) {
9932 Iterator it = app.services.iterator();
9933 while (it.hasNext()) {
9934 ServiceRecord r = (ServiceRecord)it.next();
9935 if (r.connections.size() > 0) {
9936 Iterator<ConnectionRecord> jt
9937 = r.connections.values().iterator();
9938 while (jt.hasNext()) {
9939 ConnectionRecord c = jt.next();
9940 if (c.binding.client != app) {
9941 try {
9942 //c.conn.connected(r.className, null);
9943 } catch (Exception e) {
9944 // todo: this should be asynchronous!
9945 Log.w(TAG, "Exception thrown disconnected servce "
9946 + r.shortName
9947 + " from app " + app.processName, e);
9948 }
9949 }
9950 }
9951 }
9952 }
9953 }
9954 }
9955
9956 // Clean up any connections this application has to other services.
9957 if (app.connections.size() > 0) {
9958 Iterator<ConnectionRecord> it = app.connections.iterator();
9959 while (it.hasNext()) {
9960 ConnectionRecord r = it.next();
9961 removeConnectionLocked(r, app, null);
9962 }
9963 }
9964 app.connections.clear();
9965
9966 if (app.services.size() != 0) {
9967 // Any services running in the application need to be placed
9968 // back in the pending list.
9969 Iterator it = app.services.iterator();
9970 while (it.hasNext()) {
9971 ServiceRecord sr = (ServiceRecord)it.next();
9972 synchronized (sr.stats.getBatteryStats()) {
9973 sr.stats.stopLaunchedLocked();
9974 }
9975 sr.app = null;
9976 sr.executeNesting = 0;
9977 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009978
9979 boolean hasClients = sr.bindings.size() > 0;
9980 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 Iterator<IntentBindRecord> bindings
9982 = sr.bindings.values().iterator();
9983 while (bindings.hasNext()) {
9984 IntentBindRecord b = bindings.next();
9985 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
9986 + ": shouldUnbind=" + b.hasBound);
9987 b.binder = null;
9988 b.requested = b.received = b.hasBound = false;
9989 }
9990 }
9991
9992 if (sr.crashCount >= 2) {
9993 Log.w(TAG, "Service crashed " + sr.crashCount
9994 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009995 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 sr.crashCount, sr.shortName, app.pid);
9997 bringDownServiceLocked(sr, true);
9998 } else if (!allowRestart) {
9999 bringDownServiceLocked(sr, true);
10000 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010001 boolean canceled = scheduleServiceRestartLocked(sr, true);
10002
10003 // Should the service remain running? Note that in the
10004 // extreme case of so many attempts to deliver a command
10005 // that it failed, that we also will stop it here.
10006 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10007 if (sr.pendingStarts.size() == 0) {
10008 sr.startRequested = false;
10009 if (!hasClients) {
10010 // Whoops, no reason to restart!
10011 bringDownServiceLocked(sr, true);
10012 }
10013 }
10014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 }
10016 }
10017
10018 if (!allowRestart) {
10019 app.services.clear();
10020 }
10021 }
10022
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010023 // Make sure we have no more records on the stopping list.
10024 int i = mStoppingServices.size();
10025 while (i > 0) {
10026 i--;
10027 ServiceRecord sr = mStoppingServices.get(i);
10028 if (sr.app == app) {
10029 mStoppingServices.remove(i);
10030 }
10031 }
10032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 app.executingServices.clear();
10034 }
10035
10036 private final void removeDyingProviderLocked(ProcessRecord proc,
10037 ContentProviderRecord cpr) {
10038 synchronized (cpr) {
10039 cpr.launchingApp = null;
10040 cpr.notifyAll();
10041 }
10042
10043 mProvidersByClass.remove(cpr.info.name);
10044 String names[] = cpr.info.authority.split(";");
10045 for (int j = 0; j < names.length; j++) {
10046 mProvidersByName.remove(names[j]);
10047 }
10048
10049 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10050 while (cit.hasNext()) {
10051 ProcessRecord capp = cit.next();
10052 if (!capp.persistent && capp.thread != null
10053 && capp.pid != 0
10054 && capp.pid != MY_PID) {
10055 Log.i(TAG, "Killing app " + capp.processName
10056 + " (pid " + capp.pid
10057 + ") because provider " + cpr.info.name
10058 + " is in dying process " + proc.processName);
10059 Process.killProcess(capp.pid);
10060 }
10061 }
10062
10063 mLaunchingProviders.remove(cpr);
10064 }
10065
10066 /**
10067 * Main code for cleaning up a process when it has gone away. This is
10068 * called both as a result of the process dying, or directly when stopping
10069 * a process when running in single process mode.
10070 */
10071 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10072 boolean restarting, int index) {
10073 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010074 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 }
10076
Dianne Hackborn36124872009-10-08 16:22:03 -070010077 mProcessesToGc.remove(app);
10078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010079 // Dismiss any open dialogs.
10080 if (app.crashDialog != null) {
10081 app.crashDialog.dismiss();
10082 app.crashDialog = null;
10083 }
10084 if (app.anrDialog != null) {
10085 app.anrDialog.dismiss();
10086 app.anrDialog = null;
10087 }
10088 if (app.waitDialog != null) {
10089 app.waitDialog.dismiss();
10090 app.waitDialog = null;
10091 }
10092
10093 app.crashing = false;
10094 app.notResponding = false;
10095
10096 app.resetPackageList();
10097 app.thread = null;
10098 app.forcingToForeground = null;
10099 app.foregroundServices = false;
10100
10101 killServicesLocked(app, true);
10102
10103 boolean restart = false;
10104
10105 int NL = mLaunchingProviders.size();
10106
10107 // Remove published content providers.
10108 if (!app.pubProviders.isEmpty()) {
10109 Iterator it = app.pubProviders.values().iterator();
10110 while (it.hasNext()) {
10111 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10112 cpr.provider = null;
10113 cpr.app = null;
10114
10115 // See if someone is waiting for this provider... in which
10116 // case we don't remove it, but just let it restart.
10117 int i = 0;
10118 if (!app.bad) {
10119 for (; i<NL; i++) {
10120 if (mLaunchingProviders.get(i) == cpr) {
10121 restart = true;
10122 break;
10123 }
10124 }
10125 } else {
10126 i = NL;
10127 }
10128
10129 if (i >= NL) {
10130 removeDyingProviderLocked(app, cpr);
10131 NL = mLaunchingProviders.size();
10132 }
10133 }
10134 app.pubProviders.clear();
10135 }
10136
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010137 // Take care of any launching providers waiting for this process.
10138 if (checkAppInLaunchingProvidersLocked(app, false)) {
10139 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 // Unregister from connected content providers.
10143 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010144 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010145 while (it.hasNext()) {
10146 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10147 cpr.clients.remove(app);
10148 }
10149 app.conProviders.clear();
10150 }
10151
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010152 // At this point there may be remaining entries in mLaunchingProviders
10153 // where we were the only one waiting, so they are no longer of use.
10154 // Look for these and clean up if found.
10155 // XXX Commented out for now. Trying to figure out a way to reproduce
10156 // the actual situation to identify what is actually going on.
10157 if (false) {
10158 for (int i=0; i<NL; i++) {
10159 ContentProviderRecord cpr = (ContentProviderRecord)
10160 mLaunchingProviders.get(i);
10161 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10162 synchronized (cpr) {
10163 cpr.launchingApp = null;
10164 cpr.notifyAll();
10165 }
10166 }
10167 }
10168 }
10169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 skipCurrentReceiverLocked(app);
10171
10172 // Unregister any receivers.
10173 if (app.receivers.size() > 0) {
10174 Iterator<ReceiverList> it = app.receivers.iterator();
10175 while (it.hasNext()) {
10176 removeReceiverLocked(it.next());
10177 }
10178 app.receivers.clear();
10179 }
10180
Christopher Tate181fafa2009-05-14 11:12:14 -070010181 // If the app is undergoing backup, tell the backup manager about it
10182 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
10183 if (DEBUG_BACKUP) Log.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
10184 try {
10185 IBackupManager bm = IBackupManager.Stub.asInterface(
10186 ServiceManager.getService(Context.BACKUP_SERVICE));
10187 bm.agentDisconnected(app.info.packageName);
10188 } catch (RemoteException e) {
10189 // can't happen; backup manager is local
10190 }
10191 }
10192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 // If the caller is restarting this app, then leave it in its
10194 // current lists and let the caller take care of it.
10195 if (restarting) {
10196 return;
10197 }
10198
10199 if (!app.persistent) {
10200 if (DEBUG_PROCESSES) Log.v(TAG,
10201 "Removing non-persistent process during cleanup: " + app);
10202 mProcessNames.remove(app.processName, app.info.uid);
10203 } else if (!app.removed) {
10204 // This app is persistent, so we need to keep its record around.
10205 // If it is not already on the pending app list, add it there
10206 // and start a new process for it.
10207 app.thread = null;
10208 app.forcingToForeground = null;
10209 app.foregroundServices = false;
10210 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10211 mPersistentStartingProcesses.add(app);
10212 restart = true;
10213 }
10214 }
10215 mProcessesOnHold.remove(app);
10216
The Android Open Source Project4df24232009-03-05 14:34:35 -080010217 if (app == mHomeProcess) {
10218 mHomeProcess = null;
10219 }
10220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 if (restart) {
10222 // We have components that still need to be running in the
10223 // process, so re-launch it.
10224 mProcessNames.put(app.processName, app.info.uid, app);
10225 startProcessLocked(app, "restart", app.processName);
10226 } else if (app.pid > 0 && app.pid != MY_PID) {
10227 // Goodbye!
10228 synchronized (mPidsSelfLocked) {
10229 mPidsSelfLocked.remove(app.pid);
10230 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10231 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010232 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010233 }
10234 }
10235
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010236 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10237 // Look through the content providers we are waiting to have launched,
10238 // and if any run in this process then either schedule a restart of
10239 // the process or kill the client waiting for it if this process has
10240 // gone bad.
10241 int NL = mLaunchingProviders.size();
10242 boolean restart = false;
10243 for (int i=0; i<NL; i++) {
10244 ContentProviderRecord cpr = (ContentProviderRecord)
10245 mLaunchingProviders.get(i);
10246 if (cpr.launchingApp == app) {
10247 if (!alwaysBad && !app.bad) {
10248 restart = true;
10249 } else {
10250 removeDyingProviderLocked(app, cpr);
10251 NL = mLaunchingProviders.size();
10252 }
10253 }
10254 }
10255 return restart;
10256 }
10257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 // =========================================================
10259 // SERVICES
10260 // =========================================================
10261
10262 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10263 ActivityManager.RunningServiceInfo info =
10264 new ActivityManager.RunningServiceInfo();
10265 info.service = r.name;
10266 if (r.app != null) {
10267 info.pid = r.app.pid;
10268 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010269 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010270 info.process = r.processName;
10271 info.foreground = r.isForeground;
10272 info.activeSince = r.createTime;
10273 info.started = r.startRequested;
10274 info.clientCount = r.connections.size();
10275 info.crashCount = r.crashCount;
10276 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010277 if (r.isForeground) {
10278 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10279 }
10280 if (r.startRequested) {
10281 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10282 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010283 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010284 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10285 }
10286 if (r.app != null && r.app.persistent) {
10287 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10288 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010289 for (ConnectionRecord conn : r.connections.values()) {
10290 if (conn.clientLabel != 0) {
10291 info.clientPackage = conn.binding.client.info.packageName;
10292 info.clientLabel = conn.clientLabel;
10293 break;
10294 }
10295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 return info;
10297 }
10298
10299 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10300 int flags) {
10301 synchronized (this) {
10302 ArrayList<ActivityManager.RunningServiceInfo> res
10303 = new ArrayList<ActivityManager.RunningServiceInfo>();
10304
10305 if (mServices.size() > 0) {
10306 Iterator<ServiceRecord> it = mServices.values().iterator();
10307 while (it.hasNext() && res.size() < maxNum) {
10308 res.add(makeRunningServiceInfoLocked(it.next()));
10309 }
10310 }
10311
10312 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10313 ServiceRecord r = mRestartingServices.get(i);
10314 ActivityManager.RunningServiceInfo info =
10315 makeRunningServiceInfoLocked(r);
10316 info.restarting = r.nextRestartTime;
10317 res.add(info);
10318 }
10319
10320 return res;
10321 }
10322 }
10323
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010324 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10325 synchronized (this) {
10326 ServiceRecord r = mServices.get(name);
10327 if (r != null) {
10328 for (ConnectionRecord conn : r.connections.values()) {
10329 if (conn.clientIntent != null) {
10330 return conn.clientIntent;
10331 }
10332 }
10333 }
10334 }
10335 return null;
10336 }
10337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 private final ServiceRecord findServiceLocked(ComponentName name,
10339 IBinder token) {
10340 ServiceRecord r = mServices.get(name);
10341 return r == token ? r : null;
10342 }
10343
10344 private final class ServiceLookupResult {
10345 final ServiceRecord record;
10346 final String permission;
10347
10348 ServiceLookupResult(ServiceRecord _record, String _permission) {
10349 record = _record;
10350 permission = _permission;
10351 }
10352 };
10353
10354 private ServiceLookupResult findServiceLocked(Intent service,
10355 String resolvedType) {
10356 ServiceRecord r = null;
10357 if (service.getComponent() != null) {
10358 r = mServices.get(service.getComponent());
10359 }
10360 if (r == null) {
10361 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10362 r = mServicesByIntent.get(filter);
10363 }
10364
10365 if (r == null) {
10366 try {
10367 ResolveInfo rInfo =
10368 ActivityThread.getPackageManager().resolveService(
10369 service, resolvedType, 0);
10370 ServiceInfo sInfo =
10371 rInfo != null ? rInfo.serviceInfo : null;
10372 if (sInfo == null) {
10373 return null;
10374 }
10375
10376 ComponentName name = new ComponentName(
10377 sInfo.applicationInfo.packageName, sInfo.name);
10378 r = mServices.get(name);
10379 } catch (RemoteException ex) {
10380 // pm is in same process, this will never happen.
10381 }
10382 }
10383 if (r != null) {
10384 int callingPid = Binder.getCallingPid();
10385 int callingUid = Binder.getCallingUid();
10386 if (checkComponentPermission(r.permission,
10387 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10388 != PackageManager.PERMISSION_GRANTED) {
10389 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10390 + " from pid=" + callingPid
10391 + ", uid=" + callingUid
10392 + " requires " + r.permission);
10393 return new ServiceLookupResult(null, r.permission);
10394 }
10395 return new ServiceLookupResult(r, null);
10396 }
10397 return null;
10398 }
10399
10400 private class ServiceRestarter implements Runnable {
10401 private ServiceRecord mService;
10402
10403 void setService(ServiceRecord service) {
10404 mService = service;
10405 }
10406
10407 public void run() {
10408 synchronized(ActivityManagerService.this) {
10409 performServiceRestartLocked(mService);
10410 }
10411 }
10412 }
10413
10414 private ServiceLookupResult retrieveServiceLocked(Intent service,
10415 String resolvedType, int callingPid, int callingUid) {
10416 ServiceRecord r = null;
10417 if (service.getComponent() != null) {
10418 r = mServices.get(service.getComponent());
10419 }
10420 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10421 r = mServicesByIntent.get(filter);
10422 if (r == null) {
10423 try {
10424 ResolveInfo rInfo =
10425 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010426 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 ServiceInfo sInfo =
10428 rInfo != null ? rInfo.serviceInfo : null;
10429 if (sInfo == null) {
10430 Log.w(TAG, "Unable to start service " + service +
10431 ": not found");
10432 return null;
10433 }
10434
10435 ComponentName name = new ComponentName(
10436 sInfo.applicationInfo.packageName, sInfo.name);
10437 r = mServices.get(name);
10438 if (r == null) {
10439 filter = new Intent.FilterComparison(service.cloneFilter());
10440 ServiceRestarter res = new ServiceRestarter();
10441 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10442 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10443 synchronized (stats) {
10444 ss = stats.getServiceStatsLocked(
10445 sInfo.applicationInfo.uid, sInfo.packageName,
10446 sInfo.name);
10447 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010448 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 res.setService(r);
10450 mServices.put(name, r);
10451 mServicesByIntent.put(filter, r);
10452
10453 // Make sure this component isn't in the pending list.
10454 int N = mPendingServices.size();
10455 for (int i=0; i<N; i++) {
10456 ServiceRecord pr = mPendingServices.get(i);
10457 if (pr.name.equals(name)) {
10458 mPendingServices.remove(i);
10459 i--;
10460 N--;
10461 }
10462 }
10463 }
10464 } catch (RemoteException ex) {
10465 // pm is in same process, this will never happen.
10466 }
10467 }
10468 if (r != null) {
10469 if (checkComponentPermission(r.permission,
10470 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10471 != PackageManager.PERMISSION_GRANTED) {
10472 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10473 + " from pid=" + Binder.getCallingPid()
10474 + ", uid=" + Binder.getCallingUid()
10475 + " requires " + r.permission);
10476 return new ServiceLookupResult(null, r.permission);
10477 }
10478 return new ServiceLookupResult(r, null);
10479 }
10480 return null;
10481 }
10482
10483 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10484 long now = SystemClock.uptimeMillis();
10485 if (r.executeNesting == 0 && r.app != null) {
10486 if (r.app.executingServices.size() == 0) {
10487 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10488 msg.obj = r.app;
10489 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10490 }
10491 r.app.executingServices.add(r);
10492 }
10493 r.executeNesting++;
10494 r.executingStart = now;
10495 }
10496
10497 private final void sendServiceArgsLocked(ServiceRecord r,
10498 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010499 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 if (N == 0) {
10501 return;
10502 }
10503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010504 int i = 0;
10505 while (i < N) {
10506 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010507 ServiceRecord.StartItem si = r.pendingStarts.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010509 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010510 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010511 // If somehow we got a dummy start at the front, then
10512 // just drop it here.
10513 i++;
10514 continue;
10515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 bumpServiceExecutingLocked(r);
10517 if (!oomAdjusted) {
10518 oomAdjusted = true;
10519 updateOomAdjLocked(r.app);
10520 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010521 int flags = 0;
10522 if (si.deliveryCount > 0) {
10523 flags |= Service.START_FLAG_RETRY;
10524 }
10525 if (si.doneExecutingCount > 0) {
10526 flags |= Service.START_FLAG_REDELIVERY;
10527 }
10528 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10529 si.deliveredTime = SystemClock.uptimeMillis();
10530 r.deliveredStarts.add(si);
10531 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010533 } catch (RemoteException e) {
10534 // Remote process gone... we'll let the normal cleanup take
10535 // care of this.
10536 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010537 } catch (Exception e) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010538 Log.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 break;
10540 }
10541 }
10542 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010543 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 } else {
10545 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010547 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 }
10549 }
10550 }
10551
10552 private final boolean requestServiceBindingLocked(ServiceRecord r,
10553 IntentBindRecord i, boolean rebind) {
10554 if (r.app == null || r.app.thread == null) {
10555 // If service is not currently running, can't yet bind.
10556 return false;
10557 }
10558 if ((!i.requested || rebind) && i.apps.size() > 0) {
10559 try {
10560 bumpServiceExecutingLocked(r);
10561 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
10562 + ": shouldUnbind=" + i.hasBound);
10563 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10564 if (!rebind) {
10565 i.requested = true;
10566 }
10567 i.hasBound = true;
10568 i.doRebind = false;
10569 } catch (RemoteException e) {
10570 return false;
10571 }
10572 }
10573 return true;
10574 }
10575
10576 private final void requestServiceBindingsLocked(ServiceRecord r) {
10577 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10578 while (bindings.hasNext()) {
10579 IntentBindRecord i = bindings.next();
10580 if (!requestServiceBindingLocked(r, i, false)) {
10581 break;
10582 }
10583 }
10584 }
10585
10586 private final void realStartServiceLocked(ServiceRecord r,
10587 ProcessRecord app) throws RemoteException {
10588 if (app.thread == null) {
10589 throw new RemoteException();
10590 }
10591
10592 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010593 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594
10595 app.services.add(r);
10596 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010597 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010598
10599 boolean created = false;
10600 try {
10601 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
10602 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010603 mStringBuilder.setLength(0);
10604 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010605 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010606 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010607 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 synchronized (r.stats.getBatteryStats()) {
10609 r.stats.startLaunchedLocked();
10610 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010611 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010613 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 created = true;
10615 } finally {
10616 if (!created) {
10617 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010618 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010619 }
10620 }
10621
10622 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010623
10624 // If the service is in the started state, and there are no
10625 // pending arguments, then fake up one so its onStartCommand() will
10626 // be called.
10627 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10628 r.lastStartId++;
10629 if (r.lastStartId < 1) {
10630 r.lastStartId = 1;
10631 }
10632 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10633 }
10634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 sendServiceArgsLocked(r, true);
10636 }
10637
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010638 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10639 boolean allowCancel) {
10640 boolean canceled = false;
10641
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010642 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010643 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010644 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010645
10646 // Any delivered but not yet finished starts should be put back
10647 // on the pending list.
10648 final int N = r.deliveredStarts.size();
10649 if (N > 0) {
10650 for (int i=N-1; i>=0; i--) {
10651 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10652 if (si.intent == null) {
10653 // We'll generate this again if needed.
10654 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10655 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10656 r.pendingStarts.add(0, si);
10657 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10658 dur *= 2;
10659 if (minDuration < dur) minDuration = dur;
10660 if (resetTime < dur) resetTime = dur;
10661 } else {
10662 Log.w(TAG, "Canceling start item " + si.intent + " in service "
10663 + r.name);
10664 canceled = true;
10665 }
10666 }
10667 r.deliveredStarts.clear();
10668 }
10669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 r.totalRestartCount++;
10671 if (r.restartDelay == 0) {
10672 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010673 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010674 } else {
10675 // If it has been a "reasonably long time" since the service
10676 // was started, then reset our restart duration back to
10677 // the beginning, so we don't infinitely increase the duration
10678 // on a service that just occasionally gets killed (which is
10679 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010680 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010681 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010682 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010683 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010684 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010685 if (r.restartDelay < minDuration) {
10686 r.restartDelay = minDuration;
10687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 }
10689 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010690
10691 r.nextRestartTime = now + r.restartDelay;
10692
10693 // Make sure that we don't end up restarting a bunch of services
10694 // all at the same time.
10695 boolean repeat;
10696 do {
10697 repeat = false;
10698 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10699 ServiceRecord r2 = mRestartingServices.get(i);
10700 if (r2 != r && r.nextRestartTime
10701 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10702 && r.nextRestartTime
10703 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10704 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10705 r.restartDelay = r.nextRestartTime - now;
10706 repeat = true;
10707 break;
10708 }
10709 }
10710 } while (repeat);
10711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 if (!mRestartingServices.contains(r)) {
10713 mRestartingServices.add(r);
10714 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010715
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010716 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010719 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
10721 Log.w(TAG, "Scheduling restart of crashed service "
10722 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010723 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 r.shortName, r.restartDelay);
10725
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010726 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010727 }
10728
10729 final void performServiceRestartLocked(ServiceRecord r) {
10730 if (!mRestartingServices.contains(r)) {
10731 return;
10732 }
10733 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10734 }
10735
10736 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10737 if (r.restartDelay == 0) {
10738 return false;
10739 }
10740 r.resetRestartCounter();
10741 mRestartingServices.remove(r);
10742 mHandler.removeCallbacks(r.restarter);
10743 return true;
10744 }
10745
10746 private final boolean bringUpServiceLocked(ServiceRecord r,
10747 int intentFlags, boolean whileRestarting) {
10748 //Log.i(TAG, "Bring up service:");
10749 //r.dump(" ");
10750
Dianne Hackborn36124872009-10-08 16:22:03 -070010751 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 sendServiceArgsLocked(r, false);
10753 return true;
10754 }
10755
10756 if (!whileRestarting && r.restartDelay > 0) {
10757 // If waiting for a restart, then do nothing.
10758 return true;
10759 }
10760
10761 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
10762 + " " + r.intent);
10763
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010764 // We are now bringing the service up, so no longer in the
10765 // restarting state.
10766 mRestartingServices.remove(r);
10767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 final String appName = r.processName;
10769 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10770 if (app != null && app.thread != null) {
10771 try {
10772 realStartServiceLocked(r, app);
10773 return true;
10774 } catch (RemoteException e) {
10775 Log.w(TAG, "Exception when starting service " + r.shortName, e);
10776 }
10777
10778 // If a dead object exception was thrown -- fall through to
10779 // restart the application.
10780 }
10781
Dianne Hackborn36124872009-10-08 16:22:03 -070010782 // Not running -- get it started, and enqueue this service record
10783 // to be executed when the app comes up.
10784 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10785 "service", r.name, false) == null) {
10786 Log.w(TAG, "Unable to launch app "
10787 + r.appInfo.packageName + "/"
10788 + r.appInfo.uid + " for service "
10789 + r.intent.getIntent() + ": process is bad");
10790 bringDownServiceLocked(r, true);
10791 return false;
10792 }
10793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 mPendingServices.add(r);
10796 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 return true;
10799 }
10800
10801 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
10802 //Log.i(TAG, "Bring down service:");
10803 //r.dump(" ");
10804
10805 // Does it still need to run?
10806 if (!force && r.startRequested) {
10807 return;
10808 }
10809 if (r.connections.size() > 0) {
10810 if (!force) {
10811 // XXX should probably keep a count of the number of auto-create
10812 // connections directly in the service.
10813 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10814 while (it.hasNext()) {
10815 ConnectionRecord cr = it.next();
10816 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10817 return;
10818 }
10819 }
10820 }
10821
10822 // Report to all of the connections that the service is no longer
10823 // available.
10824 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10825 while (it.hasNext()) {
10826 ConnectionRecord c = it.next();
10827 try {
10828 // todo: shouldn't be a synchronous call!
10829 c.conn.connected(r.name, null);
10830 } catch (Exception e) {
10831 Log.w(TAG, "Failure disconnecting service " + r.name +
10832 " to connection " + c.conn.asBinder() +
10833 " (in " + c.binding.client.processName + ")", e);
10834 }
10835 }
10836 }
10837
10838 // Tell the service that it has been unbound.
10839 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10840 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10841 while (it.hasNext()) {
10842 IntentBindRecord ibr = it.next();
10843 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
10844 + ": hasBound=" + ibr.hasBound);
10845 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10846 try {
10847 bumpServiceExecutingLocked(r);
10848 updateOomAdjLocked(r.app);
10849 ibr.hasBound = false;
10850 r.app.thread.scheduleUnbindService(r,
10851 ibr.intent.getIntent());
10852 } catch (Exception e) {
10853 Log.w(TAG, "Exception when unbinding service "
10854 + r.shortName, e);
10855 serviceDoneExecutingLocked(r, true);
10856 }
10857 }
10858 }
10859 }
10860
10861 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
10862 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010863 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 System.identityHashCode(r), r.shortName,
10865 (r.app != null) ? r.app.pid : -1);
10866
10867 mServices.remove(r.name);
10868 mServicesByIntent.remove(r.intent);
10869 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
10870 r.totalRestartCount = 0;
10871 unscheduleServiceRestartLocked(r);
10872
10873 // Also make sure it is not on the pending list.
10874 int N = mPendingServices.size();
10875 for (int i=0; i<N; i++) {
10876 if (mPendingServices.get(i) == r) {
10877 mPendingServices.remove(i);
10878 if (DEBUG_SERVICE) Log.v(
10879 TAG, "Removed pending service: " + r.shortName);
10880 i--;
10881 N--;
10882 }
10883 }
10884
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010885 r.cancelNotification();
10886 r.isForeground = false;
10887 r.foregroundId = 0;
10888 r.foregroundNoti = null;
10889
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010890 // Clear start entries.
10891 r.deliveredStarts.clear();
10892 r.pendingStarts.clear();
10893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 if (r.app != null) {
10895 synchronized (r.stats.getBatteryStats()) {
10896 r.stats.stopLaunchedLocked();
10897 }
10898 r.app.services.remove(r);
10899 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 try {
Dianne Hackborna1e989b2009-09-01 19:54:29 -070010901 if (DEBUG_SERVICE) Log.v(TAG,
10902 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 bumpServiceExecutingLocked(r);
10904 mStoppingServices.add(r);
10905 updateOomAdjLocked(r.app);
10906 r.app.thread.scheduleStopService(r);
10907 } catch (Exception e) {
10908 Log.w(TAG, "Exception when stopping service "
10909 + r.shortName, e);
10910 serviceDoneExecutingLocked(r, true);
10911 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010912 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 } else {
10914 if (DEBUG_SERVICE) Log.v(
10915 TAG, "Removed service that has no process: " + r.shortName);
10916 }
10917 } else {
10918 if (DEBUG_SERVICE) Log.v(
10919 TAG, "Removed service that is not running: " + r.shortName);
10920 }
10921 }
10922
10923 ComponentName startServiceLocked(IApplicationThread caller,
10924 Intent service, String resolvedType,
10925 int callingPid, int callingUid) {
10926 synchronized(this) {
10927 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
10928 + " type=" + resolvedType + " args=" + service.getExtras());
10929
10930 if (caller != null) {
10931 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10932 if (callerApp == null) {
10933 throw new SecurityException(
10934 "Unable to find app for caller " + caller
10935 + " (pid=" + Binder.getCallingPid()
10936 + ") when starting service " + service);
10937 }
10938 }
10939
10940 ServiceLookupResult res =
10941 retrieveServiceLocked(service, resolvedType,
10942 callingPid, callingUid);
10943 if (res == null) {
10944 return null;
10945 }
10946 if (res.record == null) {
10947 return new ComponentName("!", res.permission != null
10948 ? res.permission : "private to package");
10949 }
10950 ServiceRecord r = res.record;
10951 if (unscheduleServiceRestartLocked(r)) {
10952 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
10953 + r.shortName);
10954 }
10955 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010956 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 r.lastStartId++;
10958 if (r.lastStartId < 1) {
10959 r.lastStartId = 1;
10960 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010961 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 r.lastActivity = SystemClock.uptimeMillis();
10963 synchronized (r.stats.getBatteryStats()) {
10964 r.stats.startRunningLocked();
10965 }
10966 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10967 return new ComponentName("!", "Service process is bad");
10968 }
10969 return r.name;
10970 }
10971 }
10972
10973 public ComponentName startService(IApplicationThread caller, Intent service,
10974 String resolvedType) {
10975 // Refuse possible leaked file descriptors
10976 if (service != null && service.hasFileDescriptors() == true) {
10977 throw new IllegalArgumentException("File descriptors passed in Intent");
10978 }
10979
10980 synchronized(this) {
10981 final int callingPid = Binder.getCallingPid();
10982 final int callingUid = Binder.getCallingUid();
10983 final long origId = Binder.clearCallingIdentity();
10984 ComponentName res = startServiceLocked(caller, service,
10985 resolvedType, callingPid, callingUid);
10986 Binder.restoreCallingIdentity(origId);
10987 return res;
10988 }
10989 }
10990
10991 ComponentName startServiceInPackage(int uid,
10992 Intent service, String resolvedType) {
10993 synchronized(this) {
10994 final long origId = Binder.clearCallingIdentity();
10995 ComponentName res = startServiceLocked(null, service,
10996 resolvedType, -1, uid);
10997 Binder.restoreCallingIdentity(origId);
10998 return res;
10999 }
11000 }
11001
11002 public int stopService(IApplicationThread caller, Intent service,
11003 String resolvedType) {
11004 // Refuse possible leaked file descriptors
11005 if (service != null && service.hasFileDescriptors() == true) {
11006 throw new IllegalArgumentException("File descriptors passed in Intent");
11007 }
11008
11009 synchronized(this) {
11010 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
11011 + " type=" + resolvedType);
11012
11013 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11014 if (caller != null && callerApp == null) {
11015 throw new SecurityException(
11016 "Unable to find app for caller " + caller
11017 + " (pid=" + Binder.getCallingPid()
11018 + ") when stopping service " + service);
11019 }
11020
11021 // If this service is active, make sure it is stopped.
11022 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11023 if (r != null) {
11024 if (r.record != null) {
11025 synchronized (r.record.stats.getBatteryStats()) {
11026 r.record.stats.stopRunningLocked();
11027 }
11028 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011029 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 final long origId = Binder.clearCallingIdentity();
11031 bringDownServiceLocked(r.record, false);
11032 Binder.restoreCallingIdentity(origId);
11033 return 1;
11034 }
11035 return -1;
11036 }
11037 }
11038
11039 return 0;
11040 }
11041
11042 public IBinder peekService(Intent service, String resolvedType) {
11043 // Refuse possible leaked file descriptors
11044 if (service != null && service.hasFileDescriptors() == true) {
11045 throw new IllegalArgumentException("File descriptors passed in Intent");
11046 }
11047
11048 IBinder ret = null;
11049
11050 synchronized(this) {
11051 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11052
11053 if (r != null) {
11054 // r.record is null if findServiceLocked() failed the caller permission check
11055 if (r.record == null) {
11056 throw new SecurityException(
11057 "Permission Denial: Accessing service " + r.record.name
11058 + " from pid=" + Binder.getCallingPid()
11059 + ", uid=" + Binder.getCallingUid()
11060 + " requires " + r.permission);
11061 }
11062 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11063 if (ib != null) {
11064 ret = ib.binder;
11065 }
11066 }
11067 }
11068
11069 return ret;
11070 }
11071
11072 public boolean stopServiceToken(ComponentName className, IBinder token,
11073 int startId) {
11074 synchronized(this) {
11075 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
11076 + " " + token + " startId=" + startId);
11077 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011078 if (r != null) {
11079 if (startId >= 0) {
11080 // Asked to only stop if done with all work. Note that
11081 // to avoid leaks, we will take this as dropping all
11082 // start items up to and including this one.
11083 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11084 if (si != null) {
11085 while (r.deliveredStarts.size() > 0) {
11086 if (r.deliveredStarts.remove(0) == si) {
11087 break;
11088 }
11089 }
11090 }
11091
11092 if (r.lastStartId != startId) {
11093 return false;
11094 }
11095
11096 if (r.deliveredStarts.size() > 0) {
11097 Log.w(TAG, "stopServiceToken startId " + startId
11098 + " is last, but have " + r.deliveredStarts.size()
11099 + " remaining args");
11100 }
11101 }
11102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103 synchronized (r.stats.getBatteryStats()) {
11104 r.stats.stopRunningLocked();
11105 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011106 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 }
11108 final long origId = Binder.clearCallingIdentity();
11109 bringDownServiceLocked(r, false);
11110 Binder.restoreCallingIdentity(origId);
11111 return true;
11112 }
11113 }
11114 return false;
11115 }
11116
11117 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011118 int id, Notification notification, boolean removeNotification) {
11119 final long origId = Binder.clearCallingIdentity();
11120 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 synchronized(this) {
11122 ServiceRecord r = findServiceLocked(className, token);
11123 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011124 if (id != 0) {
11125 if (notification == null) {
11126 throw new IllegalArgumentException("null notification");
11127 }
11128 if (r.foregroundId != id) {
11129 r.cancelNotification();
11130 r.foregroundId = id;
11131 }
11132 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11133 r.foregroundNoti = notification;
11134 r.isForeground = true;
11135 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 if (r.app != null) {
11137 updateServiceForegroundLocked(r.app, true);
11138 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011139 } else {
11140 if (r.isForeground) {
11141 r.isForeground = false;
11142 if (r.app != null) {
11143 updateServiceForegroundLocked(r.app, true);
11144 }
11145 }
11146 if (removeNotification) {
11147 r.cancelNotification();
11148 r.foregroundId = 0;
11149 r.foregroundNoti = null;
11150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 }
11152 }
11153 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011154 } finally {
11155 Binder.restoreCallingIdentity(origId);
11156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011157 }
11158
11159 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11160 boolean anyForeground = false;
11161 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11162 if (sr.isForeground) {
11163 anyForeground = true;
11164 break;
11165 }
11166 }
11167 if (anyForeground != proc.foregroundServices) {
11168 proc.foregroundServices = anyForeground;
11169 if (oomAdj) {
11170 updateOomAdjLocked();
11171 }
11172 }
11173 }
11174
11175 public int bindService(IApplicationThread caller, IBinder token,
11176 Intent service, String resolvedType,
11177 IServiceConnection connection, int flags) {
11178 // Refuse possible leaked file descriptors
11179 if (service != null && service.hasFileDescriptors() == true) {
11180 throw new IllegalArgumentException("File descriptors passed in Intent");
11181 }
11182
11183 synchronized(this) {
11184 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
11185 + " type=" + resolvedType + " conn=" + connection.asBinder()
11186 + " flags=0x" + Integer.toHexString(flags));
11187 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11188 if (callerApp == null) {
11189 throw new SecurityException(
11190 "Unable to find app for caller " + caller
11191 + " (pid=" + Binder.getCallingPid()
11192 + ") when binding service " + service);
11193 }
11194
11195 HistoryRecord activity = null;
11196 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011197 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 if (aindex < 0) {
11199 Log.w(TAG, "Binding with unknown activity: " + token);
11200 return 0;
11201 }
11202 activity = (HistoryRecord)mHistory.get(aindex);
11203 }
11204
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011205 int clientLabel = 0;
11206 PendingIntent clientIntent = null;
11207
11208 if (callerApp.info.uid == Process.SYSTEM_UID) {
11209 // Hacky kind of thing -- allow system stuff to tell us
11210 // what they are, so we can report this elsewhere for
11211 // others to know why certain services are running.
11212 try {
11213 clientIntent = (PendingIntent)service.getParcelableExtra(
11214 Intent.EXTRA_CLIENT_INTENT);
11215 } catch (RuntimeException e) {
11216 }
11217 if (clientIntent != null) {
11218 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11219 if (clientLabel != 0) {
11220 // There are no useful extras in the intent, trash them.
11221 // System code calling with this stuff just needs to know
11222 // this will happen.
11223 service = service.cloneFilter();
11224 }
11225 }
11226 }
11227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 ServiceLookupResult res =
11229 retrieveServiceLocked(service, resolvedType,
11230 Binder.getCallingPid(), Binder.getCallingUid());
11231 if (res == null) {
11232 return 0;
11233 }
11234 if (res.record == null) {
11235 return -1;
11236 }
11237 ServiceRecord s = res.record;
11238
11239 final long origId = Binder.clearCallingIdentity();
11240
11241 if (unscheduleServiceRestartLocked(s)) {
11242 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
11243 + s.shortName);
11244 }
11245
11246 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11247 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011248 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249
11250 IBinder binder = connection.asBinder();
11251 s.connections.put(binder, c);
11252 b.connections.add(c);
11253 if (activity != null) {
11254 if (activity.connections == null) {
11255 activity.connections = new HashSet<ConnectionRecord>();
11256 }
11257 activity.connections.add(c);
11258 }
11259 b.client.connections.add(c);
11260 mServiceConnections.put(binder, c);
11261
11262 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11263 s.lastActivity = SystemClock.uptimeMillis();
11264 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11265 return 0;
11266 }
11267 }
11268
11269 if (s.app != null) {
11270 // This could have made the service more important.
11271 updateOomAdjLocked(s.app);
11272 }
11273
11274 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
11275 + ": received=" + b.intent.received
11276 + " apps=" + b.intent.apps.size()
11277 + " doRebind=" + b.intent.doRebind);
11278
11279 if (s.app != null && b.intent.received) {
11280 // Service is already running, so we can immediately
11281 // publish the connection.
11282 try {
11283 c.conn.connected(s.name, b.intent.binder);
11284 } catch (Exception e) {
11285 Log.w(TAG, "Failure sending service " + s.shortName
11286 + " to connection " + c.conn.asBinder()
11287 + " (in " + c.binding.client.processName + ")", e);
11288 }
11289
11290 // If this is the first app connected back to this binding,
11291 // and the service had previously asked to be told when
11292 // rebound, then do so.
11293 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11294 requestServiceBindingLocked(s, b.intent, true);
11295 }
11296 } else if (!b.intent.requested) {
11297 requestServiceBindingLocked(s, b.intent, false);
11298 }
11299
11300 Binder.restoreCallingIdentity(origId);
11301 }
11302
11303 return 1;
11304 }
11305
11306 private void removeConnectionLocked(
11307 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11308 IBinder binder = c.conn.asBinder();
11309 AppBindRecord b = c.binding;
11310 ServiceRecord s = b.service;
11311 s.connections.remove(binder);
11312 b.connections.remove(c);
11313 if (c.activity != null && c.activity != skipAct) {
11314 if (c.activity.connections != null) {
11315 c.activity.connections.remove(c);
11316 }
11317 }
11318 if (b.client != skipApp) {
11319 b.client.connections.remove(c);
11320 }
11321 mServiceConnections.remove(binder);
11322
11323 if (b.connections.size() == 0) {
11324 b.intent.apps.remove(b.client);
11325 }
11326
11327 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
11328 + ": shouldUnbind=" + b.intent.hasBound);
11329 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11330 && b.intent.hasBound) {
11331 try {
11332 bumpServiceExecutingLocked(s);
11333 updateOomAdjLocked(s.app);
11334 b.intent.hasBound = false;
11335 // Assume the client doesn't want to know about a rebind;
11336 // we will deal with that later if it asks for one.
11337 b.intent.doRebind = false;
11338 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11339 } catch (Exception e) {
11340 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
11341 serviceDoneExecutingLocked(s, true);
11342 }
11343 }
11344
11345 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11346 bringDownServiceLocked(s, false);
11347 }
11348 }
11349
11350 public boolean unbindService(IServiceConnection connection) {
11351 synchronized (this) {
11352 IBinder binder = connection.asBinder();
11353 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
11354 ConnectionRecord r = mServiceConnections.get(binder);
11355 if (r == null) {
11356 Log.w(TAG, "Unbind failed: could not find connection for "
11357 + connection.asBinder());
11358 return false;
11359 }
11360
11361 final long origId = Binder.clearCallingIdentity();
11362
11363 removeConnectionLocked(r, null, null);
11364
11365 if (r.binding.service.app != null) {
11366 // This could have made the service less important.
11367 updateOomAdjLocked(r.binding.service.app);
11368 }
11369
11370 Binder.restoreCallingIdentity(origId);
11371 }
11372
11373 return true;
11374 }
11375
11376 public void publishService(IBinder token, Intent intent, IBinder service) {
11377 // Refuse possible leaked file descriptors
11378 if (intent != null && intent.hasFileDescriptors() == true) {
11379 throw new IllegalArgumentException("File descriptors passed in Intent");
11380 }
11381
11382 synchronized(this) {
11383 if (!(token instanceof ServiceRecord)) {
11384 throw new IllegalArgumentException("Invalid service token");
11385 }
11386 ServiceRecord r = (ServiceRecord)token;
11387
11388 final long origId = Binder.clearCallingIdentity();
11389
11390 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
11391 + " " + intent + ": " + service);
11392 if (r != null) {
11393 Intent.FilterComparison filter
11394 = new Intent.FilterComparison(intent);
11395 IntentBindRecord b = r.bindings.get(filter);
11396 if (b != null && !b.received) {
11397 b.binder = service;
11398 b.requested = true;
11399 b.received = true;
11400 if (r.connections.size() > 0) {
11401 Iterator<ConnectionRecord> it
11402 = r.connections.values().iterator();
11403 while (it.hasNext()) {
11404 ConnectionRecord c = it.next();
11405 if (!filter.equals(c.binding.intent.intent)) {
11406 if (DEBUG_SERVICE) Log.v(
11407 TAG, "Not publishing to: " + c);
11408 if (DEBUG_SERVICE) Log.v(
11409 TAG, "Bound intent: " + c.binding.intent.intent);
11410 if (DEBUG_SERVICE) Log.v(
11411 TAG, "Published intent: " + intent);
11412 continue;
11413 }
11414 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
11415 try {
11416 c.conn.connected(r.name, service);
11417 } catch (Exception e) {
11418 Log.w(TAG, "Failure sending service " + r.name +
11419 " to connection " + c.conn.asBinder() +
11420 " (in " + c.binding.client.processName + ")", e);
11421 }
11422 }
11423 }
11424 }
11425
11426 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11427
11428 Binder.restoreCallingIdentity(origId);
11429 }
11430 }
11431 }
11432
11433 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11434 // Refuse possible leaked file descriptors
11435 if (intent != null && intent.hasFileDescriptors() == true) {
11436 throw new IllegalArgumentException("File descriptors passed in Intent");
11437 }
11438
11439 synchronized(this) {
11440 if (!(token instanceof ServiceRecord)) {
11441 throw new IllegalArgumentException("Invalid service token");
11442 }
11443 ServiceRecord r = (ServiceRecord)token;
11444
11445 final long origId = Binder.clearCallingIdentity();
11446
11447 if (r != null) {
11448 Intent.FilterComparison filter
11449 = new Intent.FilterComparison(intent);
11450 IntentBindRecord b = r.bindings.get(filter);
11451 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
11452 + " at " + b + ": apps="
11453 + (b != null ? b.apps.size() : 0));
11454 if (b != null) {
11455 if (b.apps.size() > 0) {
11456 // Applications have already bound since the last
11457 // unbind, so just rebind right here.
11458 requestServiceBindingLocked(r, b, true);
11459 } else {
11460 // Note to tell the service the next time there is
11461 // a new client.
11462 b.doRebind = true;
11463 }
11464 }
11465
11466 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11467
11468 Binder.restoreCallingIdentity(origId);
11469 }
11470 }
11471 }
11472
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011473 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 synchronized(this) {
11475 if (!(token instanceof ServiceRecord)) {
11476 throw new IllegalArgumentException("Invalid service token");
11477 }
11478 ServiceRecord r = (ServiceRecord)token;
11479 boolean inStopping = mStoppingServices.contains(token);
11480 if (r != null) {
11481 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
11482 + ": nesting=" + r.executeNesting
11483 + ", inStopping=" + inStopping);
11484 if (r != token) {
11485 Log.w(TAG, "Done executing service " + r.name
11486 + " with incorrect token: given " + token
11487 + ", expected " + r);
11488 return;
11489 }
11490
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011491 if (type == 1) {
11492 // This is a call from a service start... take care of
11493 // book-keeping.
11494 r.callStart = true;
11495 switch (res) {
11496 case Service.START_STICKY_COMPATIBILITY:
11497 case Service.START_STICKY: {
11498 // We are done with the associated start arguments.
11499 r.findDeliveredStart(startId, true);
11500 // Don't stop if killed.
11501 r.stopIfKilled = false;
11502 break;
11503 }
11504 case Service.START_NOT_STICKY: {
11505 // We are done with the associated start arguments.
11506 r.findDeliveredStart(startId, true);
11507 if (r.lastStartId == startId) {
11508 // There is no more work, and this service
11509 // doesn't want to hang around if killed.
11510 r.stopIfKilled = true;
11511 }
11512 break;
11513 }
11514 case Service.START_REDELIVER_INTENT: {
11515 // We'll keep this item until they explicitly
11516 // call stop for it, but keep track of the fact
11517 // that it was delivered.
11518 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11519 if (si != null) {
11520 si.deliveryCount = 0;
11521 si.doneExecutingCount++;
11522 // Don't stop if killed.
11523 r.stopIfKilled = true;
11524 }
11525 break;
11526 }
11527 default:
11528 throw new IllegalArgumentException(
11529 "Unknown service start result: " + res);
11530 }
11531 if (res == Service.START_STICKY_COMPATIBILITY) {
11532 r.callStart = false;
11533 }
11534 }
11535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 final long origId = Binder.clearCallingIdentity();
11537 serviceDoneExecutingLocked(r, inStopping);
11538 Binder.restoreCallingIdentity(origId);
11539 } else {
11540 Log.w(TAG, "Done executing unknown service " + r.name
11541 + " with token " + token);
11542 }
11543 }
11544 }
11545
11546 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11547 r.executeNesting--;
11548 if (r.executeNesting <= 0 && r.app != null) {
11549 r.app.executingServices.remove(r);
11550 if (r.app.executingServices.size() == 0) {
11551 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11552 }
11553 if (inStopping) {
11554 mStoppingServices.remove(r);
11555 }
11556 updateOomAdjLocked(r.app);
11557 }
11558 }
11559
11560 void serviceTimeout(ProcessRecord proc) {
11561 synchronized(this) {
11562 if (proc.executingServices.size() == 0 || proc.thread == null) {
11563 return;
11564 }
11565 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11566 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11567 ServiceRecord timeout = null;
11568 long nextTime = 0;
11569 while (it.hasNext()) {
11570 ServiceRecord sr = it.next();
11571 if (sr.executingStart < maxTime) {
11572 timeout = sr;
11573 break;
11574 }
11575 if (sr.executingStart > nextTime) {
11576 nextTime = sr.executingStart;
11577 }
11578 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011579 if (timeout != null && mLruProcesses.contains(proc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 Log.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011581 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 } else {
11583 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11584 msg.obj = proc;
11585 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11586 }
11587 }
11588 }
11589
11590 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011591 // BACKUP AND RESTORE
11592 // =========================================================
11593
11594 // Cause the target app to be launched if necessary and its backup agent
11595 // instantiated. The backup agent will invoke backupAgentCreated() on the
11596 // activity manager to announce its creation.
11597 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
11598 if (DEBUG_BACKUP) Log.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
11599 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11600
11601 synchronized(this) {
11602 // !!! TODO: currently no check here that we're already bound
11603 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11604 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11605 synchronized (stats) {
11606 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11607 }
11608
11609 BackupRecord r = new BackupRecord(ss, app, backupMode);
11610 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11611 // startProcessLocked() returns existing proc's record if it's already running
11612 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011613 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011614 if (proc == null) {
11615 Log.e(TAG, "Unable to start backup agent process " + r);
11616 return false;
11617 }
11618
11619 r.app = proc;
11620 mBackupTarget = r;
11621 mBackupAppName = app.packageName;
11622
Christopher Tate6fa95972009-06-05 18:43:55 -070011623 // Try not to kill the process during backup
11624 updateOomAdjLocked(proc);
11625
Christopher Tate181fafa2009-05-14 11:12:14 -070011626 // If the process is already attached, schedule the creation of the backup agent now.
11627 // If it is not yet live, this will be done when it attaches to the framework.
11628 if (proc.thread != null) {
11629 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc already running: " + proc);
11630 try {
11631 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11632 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011633 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011634 }
11635 } else {
11636 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc not running, waiting for attach");
11637 }
11638 // Invariants: at this point, the target app process exists and the application
11639 // is either already running or in the process of coming up. mBackupTarget and
11640 // mBackupAppName describe the app, so that when it binds back to the AM we
11641 // know that it's scheduled for a backup-agent operation.
11642 }
11643
11644 return true;
11645 }
11646
11647 // A backup agent has just come up
11648 public void backupAgentCreated(String agentPackageName, IBinder agent) {
11649 if (DEBUG_BACKUP) Log.v(TAG, "backupAgentCreated: " + agentPackageName
11650 + " = " + agent);
11651
11652 synchronized(this) {
11653 if (!agentPackageName.equals(mBackupAppName)) {
11654 Log.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
11655 return;
11656 }
11657
Christopher Tate043dadc2009-06-02 16:11:00 -070011658 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011659 try {
11660 IBackupManager bm = IBackupManager.Stub.asInterface(
11661 ServiceManager.getService(Context.BACKUP_SERVICE));
11662 bm.agentConnected(agentPackageName, agent);
11663 } catch (RemoteException e) {
11664 // can't happen; the backup manager service is local
11665 } catch (Exception e) {
11666 Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11667 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011668 } finally {
11669 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011670 }
11671 }
11672 }
11673
11674 // done with this agent
11675 public void unbindBackupAgent(ApplicationInfo appInfo) {
11676 if (DEBUG_BACKUP) Log.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011677 if (appInfo == null) {
11678 Log.w(TAG, "unbind backup agent for null app");
11679 return;
11680 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011681
11682 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011683 if (mBackupAppName == null) {
11684 Log.w(TAG, "Unbinding backup agent with no active backup");
11685 return;
11686 }
11687
Christopher Tate181fafa2009-05-14 11:12:14 -070011688 if (!mBackupAppName.equals(appInfo.packageName)) {
11689 Log.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
11690 return;
11691 }
11692
Christopher Tate6fa95972009-06-05 18:43:55 -070011693 ProcessRecord proc = mBackupTarget.app;
11694 mBackupTarget = null;
11695 mBackupAppName = null;
11696
11697 // Not backing this app up any more; reset its OOM adjustment
11698 updateOomAdjLocked(proc);
11699
Christopher Tatec7b31e32009-06-10 15:49:30 -070011700 // If the app crashed during backup, 'thread' will be null here
11701 if (proc.thread != null) {
11702 try {
11703 proc.thread.scheduleDestroyBackupAgent(appInfo);
11704 } catch (Exception e) {
11705 Log.e(TAG, "Exception when unbinding backup agent:");
11706 e.printStackTrace();
11707 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011708 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011709 }
11710 }
11711 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 // BROADCASTS
11713 // =========================================================
11714
11715 private final List getStickies(String action, IntentFilter filter,
11716 List cur) {
11717 final ContentResolver resolver = mContext.getContentResolver();
11718 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11719 if (list == null) {
11720 return cur;
11721 }
11722 int N = list.size();
11723 for (int i=0; i<N; i++) {
11724 Intent intent = list.get(i);
11725 if (filter.match(resolver, intent, true, TAG) >= 0) {
11726 if (cur == null) {
11727 cur = new ArrayList<Intent>();
11728 }
11729 cur.add(intent);
11730 }
11731 }
11732 return cur;
11733 }
11734
11735 private final void scheduleBroadcastsLocked() {
11736 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
11737 + mBroadcastsScheduled);
11738
11739 if (mBroadcastsScheduled) {
11740 return;
11741 }
11742 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11743 mBroadcastsScheduled = true;
11744 }
11745
11746 public Intent registerReceiver(IApplicationThread caller,
11747 IIntentReceiver receiver, IntentFilter filter, String permission) {
11748 synchronized(this) {
11749 ProcessRecord callerApp = null;
11750 if (caller != null) {
11751 callerApp = getRecordForAppLocked(caller);
11752 if (callerApp == null) {
11753 throw new SecurityException(
11754 "Unable to find app for caller " + caller
11755 + " (pid=" + Binder.getCallingPid()
11756 + ") when registering receiver " + receiver);
11757 }
11758 }
11759
11760 List allSticky = null;
11761
11762 // Look for any matching sticky broadcasts...
11763 Iterator actions = filter.actionsIterator();
11764 if (actions != null) {
11765 while (actions.hasNext()) {
11766 String action = (String)actions.next();
11767 allSticky = getStickies(action, filter, allSticky);
11768 }
11769 } else {
11770 allSticky = getStickies(null, filter, allSticky);
11771 }
11772
11773 // The first sticky in the list is returned directly back to
11774 // the client.
11775 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11776
11777 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
11778 + ": " + sticky);
11779
11780 if (receiver == null) {
11781 return sticky;
11782 }
11783
11784 ReceiverList rl
11785 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11786 if (rl == null) {
11787 rl = new ReceiverList(this, callerApp,
11788 Binder.getCallingPid(),
11789 Binder.getCallingUid(), receiver);
11790 if (rl.app != null) {
11791 rl.app.receivers.add(rl);
11792 } else {
11793 try {
11794 receiver.asBinder().linkToDeath(rl, 0);
11795 } catch (RemoteException e) {
11796 return sticky;
11797 }
11798 rl.linkedToDeath = true;
11799 }
11800 mRegisteredReceivers.put(receiver.asBinder(), rl);
11801 }
11802 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11803 rl.add(bf);
11804 if (!bf.debugCheck()) {
11805 Log.w(TAG, "==> For Dynamic broadast");
11806 }
11807 mReceiverResolver.addFilter(bf);
11808
11809 // Enqueue broadcasts for all existing stickies that match
11810 // this filter.
11811 if (allSticky != null) {
11812 ArrayList receivers = new ArrayList();
11813 receivers.add(bf);
11814
11815 int N = allSticky.size();
11816 for (int i=0; i<N; i++) {
11817 Intent intent = (Intent)allSticky.get(i);
11818 BroadcastRecord r = new BroadcastRecord(intent, null,
11819 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011820 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011821 if (mParallelBroadcasts.size() == 0) {
11822 scheduleBroadcastsLocked();
11823 }
11824 mParallelBroadcasts.add(r);
11825 }
11826 }
11827
11828 return sticky;
11829 }
11830 }
11831
11832 public void unregisterReceiver(IIntentReceiver receiver) {
11833 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
11834
11835 boolean doNext = false;
11836
11837 synchronized(this) {
11838 ReceiverList rl
11839 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11840 if (rl != null) {
11841 if (rl.curBroadcast != null) {
11842 BroadcastRecord r = rl.curBroadcast;
11843 doNext = finishReceiverLocked(
11844 receiver.asBinder(), r.resultCode, r.resultData,
11845 r.resultExtras, r.resultAbort, true);
11846 }
11847
11848 if (rl.app != null) {
11849 rl.app.receivers.remove(rl);
11850 }
11851 removeReceiverLocked(rl);
11852 if (rl.linkedToDeath) {
11853 rl.linkedToDeath = false;
11854 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11855 }
11856 }
11857 }
11858
11859 if (!doNext) {
11860 return;
11861 }
11862
11863 final long origId = Binder.clearCallingIdentity();
11864 processNextBroadcast(false);
11865 trimApplications();
11866 Binder.restoreCallingIdentity(origId);
11867 }
11868
11869 void removeReceiverLocked(ReceiverList rl) {
11870 mRegisteredReceivers.remove(rl.receiver.asBinder());
11871 int N = rl.size();
11872 for (int i=0; i<N; i++) {
11873 mReceiverResolver.removeFilter(rl.get(i));
11874 }
11875 }
11876
11877 private final int broadcastIntentLocked(ProcessRecord callerApp,
11878 String callerPackage, Intent intent, String resolvedType,
11879 IIntentReceiver resultTo, int resultCode, String resultData,
11880 Bundle map, String requiredPermission,
11881 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11882 intent = new Intent(intent);
11883
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011884 if (DEBUG_BROADCAST_LIGHT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11886 + " ordered=" + ordered);
11887 if ((resultTo != null) && !ordered) {
11888 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
11889 }
11890
11891 // Handle special intents: if this broadcast is from the package
11892 // manager about a package being removed, we need to remove all of
11893 // its activities from the history stack.
11894 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
11895 intent.getAction());
11896 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11897 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011898 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 || uidRemoved) {
11900 if (checkComponentPermission(
11901 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
11902 callingPid, callingUid, -1)
11903 == PackageManager.PERMISSION_GRANTED) {
11904 if (uidRemoved) {
11905 final Bundle intentExtras = intent.getExtras();
11906 final int uid = intentExtras != null
11907 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11908 if (uid >= 0) {
11909 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11910 synchronized (bs) {
11911 bs.removeUidStatsLocked(uid);
11912 }
11913 }
11914 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011915 // If resources are unvailble just force stop all
11916 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011917 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011918 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11919 if (list != null && (list.length > 0)) {
11920 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011921 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011922 }
11923 }
11924 } else {
11925 Uri data = intent.getData();
11926 String ssp;
11927 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11928 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11929 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011930 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011932 }
11933 }
11934 }
11935 } else {
11936 String msg = "Permission Denial: " + intent.getAction()
11937 + " broadcast from " + callerPackage + " (pid=" + callingPid
11938 + ", uid=" + callingUid + ")"
11939 + " requires "
11940 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
11941 Log.w(TAG, msg);
11942 throw new SecurityException(msg);
11943 }
11944 }
11945
11946 /*
11947 * If this is the time zone changed action, queue up a message that will reset the timezone
11948 * of all currently running processes. This message will get queued up before the broadcast
11949 * happens.
11950 */
11951 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11952 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11953 }
11954
Dianne Hackborn854060af2009-07-09 18:14:31 -070011955 /*
11956 * Prevent non-system code (defined here to be non-persistent
11957 * processes) from sending protected broadcasts.
11958 */
11959 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11960 || callingUid == Process.SHELL_UID || callingUid == 0) {
11961 // Always okay.
11962 } else if (callerApp == null || !callerApp.persistent) {
11963 try {
11964 if (ActivityThread.getPackageManager().isProtectedBroadcast(
11965 intent.getAction())) {
11966 String msg = "Permission Denial: not allowed to send broadcast "
11967 + intent.getAction() + " from pid="
11968 + callingPid + ", uid=" + callingUid;
11969 Log.w(TAG, msg);
11970 throw new SecurityException(msg);
11971 }
11972 } catch (RemoteException e) {
11973 Log.w(TAG, "Remote exception", e);
11974 return BROADCAST_SUCCESS;
11975 }
11976 }
11977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978 // Add to the sticky list if requested.
11979 if (sticky) {
11980 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11981 callingPid, callingUid)
11982 != PackageManager.PERMISSION_GRANTED) {
11983 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11984 + callingPid + ", uid=" + callingUid
11985 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
11986 Log.w(TAG, msg);
11987 throw new SecurityException(msg);
11988 }
11989 if (requiredPermission != null) {
11990 Log.w(TAG, "Can't broadcast sticky intent " + intent
11991 + " and enforce permission " + requiredPermission);
11992 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11993 }
11994 if (intent.getComponent() != null) {
11995 throw new SecurityException(
11996 "Sticky broadcasts can't target a specific component");
11997 }
11998 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11999 if (list == null) {
12000 list = new ArrayList<Intent>();
12001 mStickyBroadcasts.put(intent.getAction(), list);
12002 }
12003 int N = list.size();
12004 int i;
12005 for (i=0; i<N; i++) {
12006 if (intent.filterEquals(list.get(i))) {
12007 // This sticky already exists, replace it.
12008 list.set(i, new Intent(intent));
12009 break;
12010 }
12011 }
12012 if (i >= N) {
12013 list.add(new Intent(intent));
12014 }
12015 }
12016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 // Figure out who all will receive this broadcast.
12018 List receivers = null;
12019 List<BroadcastFilter> registeredReceivers = null;
12020 try {
12021 if (intent.getComponent() != null) {
12022 // Broadcast is going to one specific receiver class...
12023 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012024 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 if (ai != null) {
12026 receivers = new ArrayList();
12027 ResolveInfo ri = new ResolveInfo();
12028 ri.activityInfo = ai;
12029 receivers.add(ri);
12030 }
12031 } else {
12032 // Need to resolve the intent to interested receivers...
12033 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12034 == 0) {
12035 receivers =
12036 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012037 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012038 }
Mihai Preda074edef2009-05-18 17:13:31 +020012039 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012040 }
12041 } catch (RemoteException ex) {
12042 // pm is in same process, this will never happen.
12043 }
12044
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012045 final boolean replacePending =
12046 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12047
12048 if (DEBUG_BROADCAST) Log.v(TAG, "Enqueing broadcast: " + intent.getAction()
12049 + " replacePending=" + replacePending);
12050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012051 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12052 if (!ordered && NR > 0) {
12053 // If we are not serializing this broadcast, then send the
12054 // registered receivers separately so they don't wait for the
12055 // components to be launched.
12056 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12057 callerPackage, callingPid, callingUid, requiredPermission,
12058 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012059 ordered, sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012060 if (DEBUG_BROADCAST) Log.v(
12061 TAG, "Enqueueing parallel broadcast " + r
12062 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012063 boolean replaced = false;
12064 if (replacePending) {
12065 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12066 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
12067 if (DEBUG_BROADCAST) Log.v(TAG,
12068 "***** DROPPING PARALLEL: " + intent);
12069 mParallelBroadcasts.set(i, r);
12070 replaced = true;
12071 break;
12072 }
12073 }
12074 }
12075 if (!replaced) {
12076 mParallelBroadcasts.add(r);
12077 scheduleBroadcastsLocked();
12078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012079 registeredReceivers = null;
12080 NR = 0;
12081 }
12082
12083 // Merge into one list.
12084 int ir = 0;
12085 if (receivers != null) {
12086 // A special case for PACKAGE_ADDED: do not allow the package
12087 // being added to see this broadcast. This prevents them from
12088 // using this as a back door to get run as soon as they are
12089 // installed. Maybe in the future we want to have a special install
12090 // broadcast or such for apps, but we'd like to deliberately make
12091 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012092 String skipPackages[] = null;
12093 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12094 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12095 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12096 Uri data = intent.getData();
12097 if (data != null) {
12098 String pkgName = data.getSchemeSpecificPart();
12099 if (pkgName != null) {
12100 skipPackages = new String[] { pkgName };
12101 }
12102 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012103 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012104 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012105 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012106 if (skipPackages != null && (skipPackages.length > 0)) {
12107 for (String skipPackage : skipPackages) {
12108 if (skipPackage != null) {
12109 int NT = receivers.size();
12110 for (int it=0; it<NT; it++) {
12111 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12112 if (curt.activityInfo.packageName.equals(skipPackage)) {
12113 receivers.remove(it);
12114 it--;
12115 NT--;
12116 }
12117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 }
12119 }
12120 }
12121
12122 int NT = receivers != null ? receivers.size() : 0;
12123 int it = 0;
12124 ResolveInfo curt = null;
12125 BroadcastFilter curr = null;
12126 while (it < NT && ir < NR) {
12127 if (curt == null) {
12128 curt = (ResolveInfo)receivers.get(it);
12129 }
12130 if (curr == null) {
12131 curr = registeredReceivers.get(ir);
12132 }
12133 if (curr.getPriority() >= curt.priority) {
12134 // Insert this broadcast record into the final list.
12135 receivers.add(it, curr);
12136 ir++;
12137 curr = null;
12138 it++;
12139 NT++;
12140 } else {
12141 // Skip to the next ResolveInfo in the final list.
12142 it++;
12143 curt = null;
12144 }
12145 }
12146 }
12147 while (ir < NR) {
12148 if (receivers == null) {
12149 receivers = new ArrayList();
12150 }
12151 receivers.add(registeredReceivers.get(ir));
12152 ir++;
12153 }
12154
12155 if ((receivers != null && receivers.size() > 0)
12156 || resultTo != null) {
12157 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12158 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012159 receivers, resultTo, resultCode, resultData, map, ordered,
12160 sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012161 if (DEBUG_BROADCAST) Log.v(
12162 TAG, "Enqueueing ordered broadcast " + r
12163 + ": prev had " + mOrderedBroadcasts.size());
12164 if (DEBUG_BROADCAST) {
12165 int seq = r.intent.getIntExtra("seq", -1);
12166 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
12167 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012168 boolean replaced = false;
12169 if (replacePending) {
12170 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12171 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
12172 if (DEBUG_BROADCAST) Log.v(TAG,
12173 "***** DROPPING ORDERED: " + intent);
12174 mOrderedBroadcasts.set(i, r);
12175 replaced = true;
12176 break;
12177 }
12178 }
12179 }
12180 if (!replaced) {
12181 mOrderedBroadcasts.add(r);
12182 scheduleBroadcastsLocked();
12183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012184 }
12185
12186 return BROADCAST_SUCCESS;
12187 }
12188
12189 public final int broadcastIntent(IApplicationThread caller,
12190 Intent intent, String resolvedType, IIntentReceiver resultTo,
12191 int resultCode, String resultData, Bundle map,
12192 String requiredPermission, boolean serialized, boolean sticky) {
12193 // Refuse possible leaked file descriptors
12194 if (intent != null && intent.hasFileDescriptors() == true) {
12195 throw new IllegalArgumentException("File descriptors passed in Intent");
12196 }
12197
12198 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012199 int flags = intent.getFlags();
12200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012201 if (!mSystemReady) {
12202 // if the caller really truly claims to know what they're doing, go
12203 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012204 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12205 intent = new Intent(intent);
12206 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12207 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
12208 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12209 + " before boot completion");
12210 throw new IllegalStateException("Cannot broadcast before boot completed");
12211 }
12212 }
12213
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012214 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12215 throw new IllegalArgumentException(
12216 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12217 }
12218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012219 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12220 final int callingPid = Binder.getCallingPid();
12221 final int callingUid = Binder.getCallingUid();
12222 final long origId = Binder.clearCallingIdentity();
12223 int res = broadcastIntentLocked(callerApp,
12224 callerApp != null ? callerApp.info.packageName : null,
12225 intent, resolvedType, resultTo,
12226 resultCode, resultData, map, requiredPermission, serialized,
12227 sticky, callingPid, callingUid);
12228 Binder.restoreCallingIdentity(origId);
12229 return res;
12230 }
12231 }
12232
12233 int broadcastIntentInPackage(String packageName, int uid,
12234 Intent intent, String resolvedType, IIntentReceiver resultTo,
12235 int resultCode, String resultData, Bundle map,
12236 String requiredPermission, boolean serialized, boolean sticky) {
12237 synchronized(this) {
12238 final long origId = Binder.clearCallingIdentity();
12239 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12240 resultTo, resultCode, resultData, map, requiredPermission,
12241 serialized, sticky, -1, uid);
12242 Binder.restoreCallingIdentity(origId);
12243 return res;
12244 }
12245 }
12246
12247 public final void unbroadcastIntent(IApplicationThread caller,
12248 Intent intent) {
12249 // Refuse possible leaked file descriptors
12250 if (intent != null && intent.hasFileDescriptors() == true) {
12251 throw new IllegalArgumentException("File descriptors passed in Intent");
12252 }
12253
12254 synchronized(this) {
12255 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12256 != PackageManager.PERMISSION_GRANTED) {
12257 String msg = "Permission Denial: unbroadcastIntent() from pid="
12258 + Binder.getCallingPid()
12259 + ", uid=" + Binder.getCallingUid()
12260 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12261 Log.w(TAG, msg);
12262 throw new SecurityException(msg);
12263 }
12264 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12265 if (list != null) {
12266 int N = list.size();
12267 int i;
12268 for (i=0; i<N; i++) {
12269 if (intent.filterEquals(list.get(i))) {
12270 list.remove(i);
12271 break;
12272 }
12273 }
12274 }
12275 }
12276 }
12277
12278 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12279 String resultData, Bundle resultExtras, boolean resultAbort,
12280 boolean explicit) {
12281 if (mOrderedBroadcasts.size() == 0) {
12282 if (explicit) {
12283 Log.w(TAG, "finishReceiver called but no pending broadcasts");
12284 }
12285 return false;
12286 }
12287 BroadcastRecord r = mOrderedBroadcasts.get(0);
12288 if (r.receiver == null) {
12289 if (explicit) {
12290 Log.w(TAG, "finishReceiver called but none active");
12291 }
12292 return false;
12293 }
12294 if (r.receiver != receiver) {
12295 Log.w(TAG, "finishReceiver called but active receiver is different");
12296 return false;
12297 }
12298 int state = r.state;
12299 r.state = r.IDLE;
12300 if (state == r.IDLE) {
12301 if (explicit) {
12302 Log.w(TAG, "finishReceiver called but state is IDLE");
12303 }
12304 }
12305 r.receiver = null;
12306 r.intent.setComponent(null);
12307 if (r.curApp != null) {
12308 r.curApp.curReceiver = null;
12309 }
12310 if (r.curFilter != null) {
12311 r.curFilter.receiverList.curBroadcast = null;
12312 }
12313 r.curFilter = null;
12314 r.curApp = null;
12315 r.curComponent = null;
12316 r.curReceiver = null;
12317 mPendingBroadcast = null;
12318
12319 r.resultCode = resultCode;
12320 r.resultData = resultData;
12321 r.resultExtras = resultExtras;
12322 r.resultAbort = resultAbort;
12323
12324 // We will process the next receiver right now if this is finishing
12325 // an app receiver (which is always asynchronous) or after we have
12326 // come back from calling a receiver.
12327 return state == BroadcastRecord.APP_RECEIVE
12328 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12329 }
12330
12331 public void finishReceiver(IBinder who, int resultCode, String resultData,
12332 Bundle resultExtras, boolean resultAbort) {
12333 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
12334
12335 // Refuse possible leaked file descriptors
12336 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12337 throw new IllegalArgumentException("File descriptors passed in Bundle");
12338 }
12339
12340 boolean doNext;
12341
12342 final long origId = Binder.clearCallingIdentity();
12343
12344 synchronized(this) {
12345 doNext = finishReceiverLocked(
12346 who, resultCode, resultData, resultExtras, resultAbort, true);
12347 }
12348
12349 if (doNext) {
12350 processNextBroadcast(false);
12351 }
12352 trimApplications();
12353
12354 Binder.restoreCallingIdentity(origId);
12355 }
12356
12357 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12358 if (r.nextReceiver > 0) {
12359 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12360 if (curReceiver instanceof BroadcastFilter) {
12361 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012362 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 System.identityHashCode(r),
12364 r.intent.getAction(),
12365 r.nextReceiver - 1,
12366 System.identityHashCode(bf));
12367 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012368 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012369 System.identityHashCode(r),
12370 r.intent.getAction(),
12371 r.nextReceiver - 1,
12372 ((ResolveInfo)curReceiver).toString());
12373 }
12374 } else {
12375 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
12376 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012377 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012378 System.identityHashCode(r),
12379 r.intent.getAction(),
12380 r.nextReceiver,
12381 "NONE");
12382 }
12383 }
12384
12385 private final void broadcastTimeout() {
12386 synchronized (this) {
12387 if (mOrderedBroadcasts.size() == 0) {
12388 return;
12389 }
12390 long now = SystemClock.uptimeMillis();
12391 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012392 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012393 if (DEBUG_BROADCAST) Log.v(TAG,
12394 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012395 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012396 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012397 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012398 return;
12399 }
12400
12401 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012402 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 r.anrCount++;
12404
12405 // Current receiver has passed its expiration date.
12406 if (r.nextReceiver <= 0) {
12407 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12408 return;
12409 }
12410
12411 ProcessRecord app = null;
12412
12413 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12414 Log.w(TAG, "Receiver during timeout: " + curReceiver);
12415 logBroadcastReceiverDiscard(r);
12416 if (curReceiver instanceof BroadcastFilter) {
12417 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12418 if (bf.receiverList.pid != 0
12419 && bf.receiverList.pid != MY_PID) {
12420 synchronized (this.mPidsSelfLocked) {
12421 app = this.mPidsSelfLocked.get(
12422 bf.receiverList.pid);
12423 }
12424 }
12425 } else {
12426 app = r.curApp;
12427 }
12428
12429 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012430 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012431 }
12432
12433 if (mPendingBroadcast == r) {
12434 mPendingBroadcast = null;
12435 }
12436
12437 // Move on to the next receiver.
12438 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12439 r.resultExtras, r.resultAbort, true);
12440 scheduleBroadcastsLocked();
12441 }
12442 }
12443
12444 private final void processCurBroadcastLocked(BroadcastRecord r,
12445 ProcessRecord app) throws RemoteException {
12446 if (app.thread == null) {
12447 throw new RemoteException();
12448 }
12449 r.receiver = app.thread.asBinder();
12450 r.curApp = app;
12451 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012452 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012453
12454 // Tell the application to launch this receiver.
12455 r.intent.setComponent(r.curComponent);
12456
12457 boolean started = false;
12458 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012459 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012460 "Delivering to component " + r.curComponent
12461 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012462 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012463 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12464 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12465 started = true;
12466 } finally {
12467 if (!started) {
12468 r.receiver = null;
12469 r.curApp = null;
12470 app.curReceiver = null;
12471 }
12472 }
12473
12474 }
12475
12476 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012477 Intent intent, int resultCode, String data, Bundle extras,
12478 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012479 if (app != null && app.thread != null) {
12480 // If we have an app thread, do the call through that so it is
12481 // correctly ordered with other one-way calls.
12482 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012483 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012485 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012486 }
12487 }
12488
12489 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12490 BroadcastFilter filter, boolean ordered) {
12491 boolean skip = false;
12492 if (filter.requiredPermission != null) {
12493 int perm = checkComponentPermission(filter.requiredPermission,
12494 r.callingPid, r.callingUid, -1);
12495 if (perm != PackageManager.PERMISSION_GRANTED) {
12496 Log.w(TAG, "Permission Denial: broadcasting "
12497 + r.intent.toString()
12498 + " from " + r.callerPackage + " (pid="
12499 + r.callingPid + ", uid=" + r.callingUid + ")"
12500 + " requires " + filter.requiredPermission
12501 + " due to registered receiver " + filter);
12502 skip = true;
12503 }
12504 }
12505 if (r.requiredPermission != null) {
12506 int perm = checkComponentPermission(r.requiredPermission,
12507 filter.receiverList.pid, filter.receiverList.uid, -1);
12508 if (perm != PackageManager.PERMISSION_GRANTED) {
12509 Log.w(TAG, "Permission Denial: receiving "
12510 + r.intent.toString()
12511 + " to " + filter.receiverList.app
12512 + " (pid=" + filter.receiverList.pid
12513 + ", uid=" + filter.receiverList.uid + ")"
12514 + " requires " + r.requiredPermission
12515 + " due to sender " + r.callerPackage
12516 + " (uid " + r.callingUid + ")");
12517 skip = true;
12518 }
12519 }
12520
12521 if (!skip) {
12522 // If this is not being sent as an ordered broadcast, then we
12523 // don't want to touch the fields that keep track of the current
12524 // state of ordered broadcasts.
12525 if (ordered) {
12526 r.receiver = filter.receiverList.receiver.asBinder();
12527 r.curFilter = filter;
12528 filter.receiverList.curBroadcast = r;
12529 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012530 if (filter.receiverList.app != null) {
12531 // Bump hosting application to no longer be in background
12532 // scheduling class. Note that we can't do that if there
12533 // isn't an app... but we can only be in that case for
12534 // things that directly call the IActivityManager API, which
12535 // are already core system stuff so don't matter for this.
12536 r.curApp = filter.receiverList.app;
12537 filter.receiverList.app.curReceiver = r;
12538 updateOomAdjLocked();
12539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 }
12541 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012542 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012543 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012544 Log.i(TAG, "Delivering to " + filter.receiverList.app
12545 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012546 }
12547 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12548 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012549 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 if (ordered) {
12551 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12552 }
12553 } catch (RemoteException e) {
12554 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
12555 if (ordered) {
12556 r.receiver = null;
12557 r.curFilter = null;
12558 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012559 if (filter.receiverList.app != null) {
12560 filter.receiverList.app.curReceiver = null;
12561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012562 }
12563 }
12564 }
12565 }
12566
Dianne Hackborn12527f92009-11-11 17:39:50 -080012567 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12568 if (r.callingUid < 0) {
12569 // This was from a registerReceiver() call; ignore it.
12570 return;
12571 }
12572 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12573 MAX_BROADCAST_HISTORY-1);
12574 r.finishTime = SystemClock.uptimeMillis();
12575 mBroadcastHistory[0] = r;
12576 }
12577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 private final void processNextBroadcast(boolean fromMsg) {
12579 synchronized(this) {
12580 BroadcastRecord r;
12581
12582 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
12583 + mParallelBroadcasts.size() + " broadcasts, "
12584 + mOrderedBroadcasts.size() + " serialized broadcasts");
12585
12586 updateCpuStats();
12587
12588 if (fromMsg) {
12589 mBroadcastsScheduled = false;
12590 }
12591
12592 // First, deliver any non-serialized broadcasts right away.
12593 while (mParallelBroadcasts.size() > 0) {
12594 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012595 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012596 final int N = r.receivers.size();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012597 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing parallel broadcast "
12598 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 for (int i=0; i<N; i++) {
12600 Object target = r.receivers.get(i);
12601 if (DEBUG_BROADCAST) Log.v(TAG,
12602 "Delivering non-serialized to registered "
12603 + target + ": " + r);
12604 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12605 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012606 addBroadcastToHistoryLocked(r);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012607 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Done with parallel broadcast "
12608 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012609 }
12610
12611 // Now take care of the next serialized one...
12612
12613 // If we are waiting for a process to come up to handle the next
12614 // broadcast, then do nothing at this point. Just in case, we
12615 // check that the process we're waiting for still exists.
12616 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012617 if (DEBUG_BROADCAST_LIGHT) {
12618 Log.v(TAG, "processNextBroadcast: waiting for "
12619 + mPendingBroadcast.curApp);
12620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012621
12622 boolean isDead;
12623 synchronized (mPidsSelfLocked) {
12624 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12625 }
12626 if (!isDead) {
12627 // It's still alive, so keep waiting
12628 return;
12629 } else {
12630 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
12631 + " died before responding to broadcast");
12632 mPendingBroadcast = null;
12633 }
12634 }
12635
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012636 boolean looped = false;
12637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012638 do {
12639 if (mOrderedBroadcasts.size() == 0) {
12640 // No more broadcasts pending, so all done!
12641 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012642 if (looped) {
12643 // If we had finished the last ordered broadcast, then
12644 // make sure all processes have correct oom and sched
12645 // adjustments.
12646 updateOomAdjLocked();
12647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012648 return;
12649 }
12650 r = mOrderedBroadcasts.get(0);
12651 boolean forceReceive = false;
12652
12653 // Ensure that even if something goes awry with the timeout
12654 // detection, we catch "hung" broadcasts here, discard them,
12655 // and continue to make progress.
12656 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12657 long now = SystemClock.uptimeMillis();
12658 if (r.dispatchTime > 0) {
12659 if ((numReceivers > 0) &&
12660 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
12661 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
12662 + " now=" + now
12663 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012664 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 + " intent=" + r.intent
12666 + " numReceivers=" + numReceivers
12667 + " nextReceiver=" + r.nextReceiver
12668 + " state=" + r.state);
12669 broadcastTimeout(); // forcibly finish this broadcast
12670 forceReceive = true;
12671 r.state = BroadcastRecord.IDLE;
12672 }
12673 }
12674
12675 if (r.state != BroadcastRecord.IDLE) {
12676 if (DEBUG_BROADCAST) Log.d(TAG,
12677 "processNextBroadcast() called when not idle (state="
12678 + r.state + ")");
12679 return;
12680 }
12681
12682 if (r.receivers == null || r.nextReceiver >= numReceivers
12683 || r.resultAbort || forceReceive) {
12684 // No more receivers for this broadcast! Send the final
12685 // result if requested...
12686 if (r.resultTo != null) {
12687 try {
12688 if (DEBUG_BROADCAST) {
12689 int seq = r.intent.getIntExtra("seq", -1);
12690 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
12691 + " seq=" + seq + " app=" + r.callerApp);
12692 }
12693 performReceive(r.callerApp, r.resultTo,
12694 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012695 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012696 } catch (RemoteException e) {
12697 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
12698 }
12699 }
12700
12701 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
12702 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12703
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012704 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Finished with ordered broadcast "
12705 + r);
12706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012708 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012709 mOrderedBroadcasts.remove(0);
12710 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012711 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012712 continue;
12713 }
12714 } while (r == null);
12715
12716 // Get the next receiver...
12717 int recIdx = r.nextReceiver++;
12718
12719 // Keep track of when this receiver started, and make sure there
12720 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012721 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012723 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012724
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012725 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing ordered broadcast "
12726 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012727 if (DEBUG_BROADCAST) Log.v(TAG,
12728 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012729 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012730 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012731 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012732 }
12733
12734 Object nextReceiver = r.receivers.get(recIdx);
12735 if (nextReceiver instanceof BroadcastFilter) {
12736 // Simple case: this is a registered receiver who gets
12737 // a direct call.
12738 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
12739 if (DEBUG_BROADCAST) Log.v(TAG,
12740 "Delivering serialized to registered "
12741 + filter + ": " + r);
12742 deliverToRegisteredReceiver(r, filter, r.ordered);
12743 if (r.receiver == null || !r.ordered) {
12744 // The receiver has already finished, so schedule to
12745 // process the next one.
12746 r.state = BroadcastRecord.IDLE;
12747 scheduleBroadcastsLocked();
12748 }
12749 return;
12750 }
12751
12752 // Hard case: need to instantiate the receiver, possibly
12753 // starting its application process to host it.
12754
12755 ResolveInfo info =
12756 (ResolveInfo)nextReceiver;
12757
12758 boolean skip = false;
12759 int perm = checkComponentPermission(info.activityInfo.permission,
12760 r.callingPid, r.callingUid,
12761 info.activityInfo.exported
12762 ? -1 : info.activityInfo.applicationInfo.uid);
12763 if (perm != PackageManager.PERMISSION_GRANTED) {
12764 Log.w(TAG, "Permission Denial: broadcasting "
12765 + r.intent.toString()
12766 + " from " + r.callerPackage + " (pid=" + r.callingPid
12767 + ", uid=" + r.callingUid + ")"
12768 + " requires " + info.activityInfo.permission
12769 + " due to receiver " + info.activityInfo.packageName
12770 + "/" + info.activityInfo.name);
12771 skip = true;
12772 }
12773 if (r.callingUid != Process.SYSTEM_UID &&
12774 r.requiredPermission != null) {
12775 try {
12776 perm = ActivityThread.getPackageManager().
12777 checkPermission(r.requiredPermission,
12778 info.activityInfo.applicationInfo.packageName);
12779 } catch (RemoteException e) {
12780 perm = PackageManager.PERMISSION_DENIED;
12781 }
12782 if (perm != PackageManager.PERMISSION_GRANTED) {
12783 Log.w(TAG, "Permission Denial: receiving "
12784 + r.intent + " to "
12785 + info.activityInfo.applicationInfo.packageName
12786 + " requires " + r.requiredPermission
12787 + " due to sender " + r.callerPackage
12788 + " (uid " + r.callingUid + ")");
12789 skip = true;
12790 }
12791 }
12792 if (r.curApp != null && r.curApp.crashing) {
12793 // If the target process is crashing, just skip it.
12794 skip = true;
12795 }
12796
12797 if (skip) {
12798 r.receiver = null;
12799 r.curFilter = null;
12800 r.state = BroadcastRecord.IDLE;
12801 scheduleBroadcastsLocked();
12802 return;
12803 }
12804
12805 r.state = BroadcastRecord.APP_RECEIVE;
12806 String targetProcess = info.activityInfo.processName;
12807 r.curComponent = new ComponentName(
12808 info.activityInfo.applicationInfo.packageName,
12809 info.activityInfo.name);
12810 r.curReceiver = info.activityInfo;
12811
12812 // Is this receiver's application already running?
12813 ProcessRecord app = getProcessRecordLocked(targetProcess,
12814 info.activityInfo.applicationInfo.uid);
12815 if (app != null && app.thread != null) {
12816 try {
12817 processCurBroadcastLocked(r, app);
12818 return;
12819 } catch (RemoteException e) {
12820 Log.w(TAG, "Exception when sending broadcast to "
12821 + r.curComponent, e);
12822 }
12823
12824 // If a dead object exception was thrown -- fall through to
12825 // restart the application.
12826 }
12827
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012828 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 if ((r.curApp=startProcessLocked(targetProcess,
12830 info.activityInfo.applicationInfo, true,
12831 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012832 "broadcast", r.curComponent,
12833 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12834 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 // Ah, this recipient is unavailable. Finish it if necessary,
12836 // and mark the broadcast record as ready for the next.
12837 Log.w(TAG, "Unable to launch app "
12838 + info.activityInfo.applicationInfo.packageName + "/"
12839 + info.activityInfo.applicationInfo.uid + " for broadcast "
12840 + r.intent + ": process is bad");
12841 logBroadcastReceiverDiscard(r);
12842 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12843 r.resultExtras, r.resultAbort, true);
12844 scheduleBroadcastsLocked();
12845 r.state = BroadcastRecord.IDLE;
12846 return;
12847 }
12848
12849 mPendingBroadcast = r;
12850 }
12851 }
12852
12853 // =========================================================
12854 // INSTRUMENTATION
12855 // =========================================================
12856
12857 public boolean startInstrumentation(ComponentName className,
12858 String profileFile, int flags, Bundle arguments,
12859 IInstrumentationWatcher watcher) {
12860 // Refuse possible leaked file descriptors
12861 if (arguments != null && arguments.hasFileDescriptors()) {
12862 throw new IllegalArgumentException("File descriptors passed in Bundle");
12863 }
12864
12865 synchronized(this) {
12866 InstrumentationInfo ii = null;
12867 ApplicationInfo ai = null;
12868 try {
12869 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012870 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012872 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 } catch (PackageManager.NameNotFoundException e) {
12874 }
12875 if (ii == null) {
12876 reportStartInstrumentationFailure(watcher, className,
12877 "Unable to find instrumentation info for: " + className);
12878 return false;
12879 }
12880 if (ai == null) {
12881 reportStartInstrumentationFailure(watcher, className,
12882 "Unable to find instrumentation target package: " + ii.targetPackage);
12883 return false;
12884 }
12885
12886 int match = mContext.getPackageManager().checkSignatures(
12887 ii.targetPackage, ii.packageName);
12888 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12889 String msg = "Permission Denial: starting instrumentation "
12890 + className + " from pid="
12891 + Binder.getCallingPid()
12892 + ", uid=" + Binder.getCallingPid()
12893 + " not allowed because package " + ii.packageName
12894 + " does not have a signature matching the target "
12895 + ii.targetPackage;
12896 reportStartInstrumentationFailure(watcher, className, msg);
12897 throw new SecurityException(msg);
12898 }
12899
12900 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012901 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 ProcessRecord app = addAppLocked(ai);
12903 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012904 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905 app.instrumentationProfileFile = profileFile;
12906 app.instrumentationArguments = arguments;
12907 app.instrumentationWatcher = watcher;
12908 app.instrumentationResultClass = className;
12909 Binder.restoreCallingIdentity(origId);
12910 }
12911
12912 return true;
12913 }
12914
12915 /**
12916 * Report errors that occur while attempting to start Instrumentation. Always writes the
12917 * error to the logs, but if somebody is watching, send the report there too. This enables
12918 * the "am" command to report errors with more information.
12919 *
12920 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12921 * @param cn The component name of the instrumentation.
12922 * @param report The error report.
12923 */
12924 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12925 ComponentName cn, String report) {
12926 Log.w(TAG, report);
12927 try {
12928 if (watcher != null) {
12929 Bundle results = new Bundle();
12930 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12931 results.putString("Error", report);
12932 watcher.instrumentationStatus(cn, -1, results);
12933 }
12934 } catch (RemoteException e) {
12935 Log.w(TAG, e);
12936 }
12937 }
12938
12939 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12940 if (app.instrumentationWatcher != null) {
12941 try {
12942 // NOTE: IInstrumentationWatcher *must* be oneway here
12943 app.instrumentationWatcher.instrumentationFinished(
12944 app.instrumentationClass,
12945 resultCode,
12946 results);
12947 } catch (RemoteException e) {
12948 }
12949 }
12950 app.instrumentationWatcher = null;
12951 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012952 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012953 app.instrumentationProfileFile = null;
12954 app.instrumentationArguments = null;
12955
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012956 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 }
12958
12959 public void finishInstrumentation(IApplicationThread target,
12960 int resultCode, Bundle results) {
12961 // Refuse possible leaked file descriptors
12962 if (results != null && results.hasFileDescriptors()) {
12963 throw new IllegalArgumentException("File descriptors passed in Intent");
12964 }
12965
12966 synchronized(this) {
12967 ProcessRecord app = getRecordForAppLocked(target);
12968 if (app == null) {
12969 Log.w(TAG, "finishInstrumentation: no app for " + target);
12970 return;
12971 }
12972 final long origId = Binder.clearCallingIdentity();
12973 finishInstrumentationLocked(app, resultCode, results);
12974 Binder.restoreCallingIdentity(origId);
12975 }
12976 }
12977
12978 // =========================================================
12979 // CONFIGURATION
12980 // =========================================================
12981
12982 public ConfigurationInfo getDeviceConfigurationInfo() {
12983 ConfigurationInfo config = new ConfigurationInfo();
12984 synchronized (this) {
12985 config.reqTouchScreen = mConfiguration.touchscreen;
12986 config.reqKeyboardType = mConfiguration.keyboard;
12987 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012988 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12989 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012990 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12991 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012992 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12993 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012994 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12995 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012996 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 }
12998 return config;
12999 }
13000
13001 public Configuration getConfiguration() {
13002 Configuration ci;
13003 synchronized(this) {
13004 ci = new Configuration(mConfiguration);
13005 }
13006 return ci;
13007 }
13008
13009 public void updateConfiguration(Configuration values) {
13010 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13011 "updateConfiguration()");
13012
13013 synchronized(this) {
13014 if (values == null && mWindowManager != null) {
13015 // sentinel: fetch the current configuration from the window manager
13016 values = mWindowManager.computeNewConfiguration();
13017 }
13018
13019 final long origId = Binder.clearCallingIdentity();
13020 updateConfigurationLocked(values, null);
13021 Binder.restoreCallingIdentity(origId);
13022 }
13023 }
13024
13025 /**
13026 * Do either or both things: (1) change the current configuration, and (2)
13027 * make sure the given activity is running with the (now) current
13028 * configuration. Returns true if the activity has been left running, or
13029 * false if <var>starting</var> is being destroyed to match the new
13030 * configuration.
13031 */
13032 public boolean updateConfigurationLocked(Configuration values,
13033 HistoryRecord starting) {
13034 int changes = 0;
13035
13036 boolean kept = true;
13037
13038 if (values != null) {
13039 Configuration newConfig = new Configuration(mConfiguration);
13040 changes = newConfig.updateFrom(values);
13041 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013042 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013043 Log.i(TAG, "Updating configuration to: " + values);
13044 }
13045
Doug Zongker2bec3d42009-12-04 12:52:44 -080013046 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013047
13048 if (values.locale != null) {
13049 saveLocaleLocked(values.locale,
13050 !values.locale.equals(mConfiguration.locale),
13051 values.userSetLocale);
13052 }
13053
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013054 mConfigurationSeq++;
13055 if (mConfigurationSeq <= 0) {
13056 mConfigurationSeq = 1;
13057 }
13058 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013059 mConfiguration = newConfig;
Dianne Hackborna8f60182009-09-01 19:01:50 -070013060 Log.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013061
13062 AttributeCache ac = AttributeCache.instance();
13063 if (ac != null) {
13064 ac.updateConfiguration(mConfiguration);
13065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013066
13067 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13068 msg.obj = new Configuration(mConfiguration);
13069 mHandler.sendMessage(msg);
13070
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013071 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13072 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013073 try {
13074 if (app.thread != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013075 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending to proc "
13076 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013077 app.thread.scheduleConfigurationChanged(mConfiguration);
13078 }
13079 } catch (Exception e) {
13080 }
13081 }
13082 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013083 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13084 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013085 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13086 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013087 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13088 broadcastIntentLocked(null, null,
13089 new Intent(Intent.ACTION_LOCALE_CHANGED),
13090 null, null, 0, null, null,
13091 null, false, false, MY_PID, Process.SYSTEM_UID);
13092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013093 }
13094 }
13095
13096 if (changes != 0 && starting == null) {
13097 // If the configuration changed, and the caller is not already
13098 // in the process of starting an activity, then find the top
13099 // activity to check if its configuration needs to change.
13100 starting = topRunningActivityLocked(null);
13101 }
13102
13103 if (starting != null) {
13104 kept = ensureActivityConfigurationLocked(starting, changes);
13105 if (kept) {
13106 // If this didn't result in the starting activity being
13107 // destroyed, then we need to make sure at this point that all
13108 // other activities are made visible.
13109 if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
13110 + ", ensuring others are correct.");
13111 ensureActivitiesVisibleLocked(starting, changes);
13112 }
13113 }
13114
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013115 if (values != null && mWindowManager != null) {
13116 mWindowManager.setNewConfiguration(mConfiguration);
13117 }
13118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013119 return kept;
13120 }
13121
13122 private final boolean relaunchActivityLocked(HistoryRecord r,
13123 int changes, boolean andResume) {
13124 List<ResultInfo> results = null;
13125 List<Intent> newIntents = null;
13126 if (andResume) {
13127 results = r.results;
13128 newIntents = r.newIntents;
13129 }
13130 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
13131 + " with results=" + results + " newIntents=" + newIntents
13132 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013133 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13134 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013135 r.task.taskId, r.shortComponentName);
13136
13137 r.startFreezingScreenLocked(r.app, 0);
13138
13139 try {
13140 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
13141 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013142 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013143 // Note: don't need to call pauseIfSleepingLocked() here, because
13144 // the caller will only pass in 'andResume' if this activity is
13145 // currently resumed, which implies we aren't sleeping.
13146 } catch (RemoteException e) {
13147 return false;
13148 }
13149
13150 if (andResume) {
13151 r.results = null;
13152 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013153 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013154 }
13155
13156 return true;
13157 }
13158
13159 /**
13160 * Make sure the given activity matches the current configuration. Returns
13161 * false if the activity had to be destroyed. Returns true if the
13162 * configuration is the same, or the activity will remain running as-is
13163 * for whatever reason. Ensures the HistoryRecord is updated with the
13164 * correct configuration and all other bookkeeping is handled.
13165 */
13166 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13167 int globalChanges) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013168 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13169 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013170
13171 // Short circuit: if the two configurations are the exact same
13172 // object (the common case), then there is nothing to do.
13173 Configuration newConfig = mConfiguration;
13174 if (r.configuration == newConfig) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013175 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13176 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013177 return true;
13178 }
13179
13180 // We don't worry about activities that are finishing.
13181 if (r.finishing) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013182 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 "Configuration doesn't matter in finishing " + r);
13184 r.stopFreezingScreenLocked(false);
13185 return true;
13186 }
13187
13188 // Okay we now are going to make this activity have the new config.
13189 // But then we need to figure out how it needs to deal with that.
13190 Configuration oldConfig = r.configuration;
13191 r.configuration = newConfig;
13192
13193 // If the activity isn't currently running, just leave the new
13194 // configuration and it will pick that up next time it starts.
13195 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013196 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013197 "Configuration doesn't matter not running " + r);
13198 r.stopFreezingScreenLocked(false);
13199 return true;
13200 }
13201
13202 // If the activity isn't persistent, there is a chance we will
13203 // need to restart it.
13204 if (!r.persistent) {
13205
13206 // Figure out what has changed between the two configurations.
13207 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013208 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
13209 Log.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013211 + Integer.toHexString(r.info.configChanges)
13212 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013213 }
13214 if ((changes&(~r.info.configChanges)) != 0) {
13215 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13216 r.configChangeFlags |= changes;
13217 r.startFreezingScreenLocked(r.app, globalChanges);
13218 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013219 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13220 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013221 destroyActivityLocked(r, true);
13222 } else if (r.state == ActivityState.PAUSING) {
13223 // A little annoying: we are waiting for this activity to
13224 // finish pausing. Let's not do anything now, but just
13225 // flag that it needs to be restarted when done pausing.
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013226 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13227 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013228 r.configDestroy = true;
13229 return true;
13230 } else if (r.state == ActivityState.RESUMED) {
13231 // Try to optimize this case: the configuration is changing
13232 // and we need to restart the top, resumed activity.
13233 // Instead of doing the normal handshaking, just say
13234 // "restart!".
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013235 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13236 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013237 relaunchActivityLocked(r, r.configChangeFlags, true);
13238 r.configChangeFlags = 0;
13239 } else {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013240 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13241 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 relaunchActivityLocked(r, r.configChangeFlags, false);
13243 r.configChangeFlags = 0;
13244 }
13245
13246 // All done... tell the caller we weren't able to keep this
13247 // activity around.
13248 return false;
13249 }
13250 }
13251
13252 // Default case: the activity can handle this new configuration, so
13253 // hand it over. Note that we don't need to give it the new
13254 // configuration, since we always send configuration changes to all
13255 // process when they happen so it can just use whatever configuration
13256 // it last got.
13257 if (r.app != null && r.app.thread != null) {
13258 try {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013259 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013260 r.app.thread.scheduleActivityConfigurationChanged(r);
13261 } catch (RemoteException e) {
13262 // If process died, whatever.
13263 }
13264 }
13265 r.stopFreezingScreenLocked(false);
13266
13267 return true;
13268 }
13269
13270 /**
13271 * Save the locale. You must be inside a synchronized (this) block.
13272 */
13273 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13274 if(isDiff) {
13275 SystemProperties.set("user.language", l.getLanguage());
13276 SystemProperties.set("user.region", l.getCountry());
13277 }
13278
13279 if(isPersist) {
13280 SystemProperties.set("persist.sys.language", l.getLanguage());
13281 SystemProperties.set("persist.sys.country", l.getCountry());
13282 SystemProperties.set("persist.sys.localevar", l.getVariant());
13283 }
13284 }
13285
13286 // =========================================================
13287 // LIFETIME MANAGEMENT
13288 // =========================================================
13289
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013290 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13291 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013292 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013293 // This adjustment has already been computed. If we are calling
13294 // from the top, we may have already computed our adjustment with
13295 // an earlier hidden adjustment that isn't really for us... if
13296 // so, use the new hidden adjustment.
13297 if (!recursed && app.hidden) {
13298 app.curAdj = hiddenAdj;
13299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 return app.curAdj;
13301 }
13302
13303 if (app.thread == null) {
13304 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013305 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013306 return (app.curAdj=EMPTY_APP_ADJ);
13307 }
13308
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013309 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13310 // The max adjustment doesn't allow this app to be anything
13311 // below foreground, so it is not worth doing work for it.
13312 app.adjType = "fixed";
13313 app.adjSeq = mAdjSeq;
13314 app.curRawAdj = app.maxAdj;
13315 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13316 return (app.curAdj=app.maxAdj);
13317 }
13318
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013319 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013320 app.adjSource = null;
13321 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013322 app.empty = false;
13323 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013324
The Android Open Source Project4df24232009-03-05 14:34:35 -080013325 // Determine the importance of the process, starting with most
13326 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013327 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013328 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013330 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 // The last app on the list is the foreground app.
13332 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013333 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013334 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013335 } else if (app.instrumentationClass != null) {
13336 // Don't want to kill running instrumentation.
13337 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013338 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013339 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013340 } else if (app.persistentActivities > 0) {
13341 // Special persistent activities... shouldn't be used these days.
13342 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013343 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013344 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013345 } else if (app.curReceiver != null ||
13346 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13347 // An app that is currently receiving a broadcast also
13348 // counts as being in the foreground.
13349 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013350 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013351 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 } else if (app.executingServices.size() > 0) {
13353 // An app that is currently executing a service callback also
13354 // counts as being in the foreground.
13355 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013356 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013357 app.adjType = "exec-service";
13358 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013359 // The user is aware of this app, so make it visible.
13360 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013361 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013362 app.adjType = "foreground-service";
13363 } else if (app.forcingToForeground != null) {
13364 // The user is aware of this app, so make it visible.
13365 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013366 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013367 app.adjType = "force-foreground";
13368 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013369 } else if (app == mHomeProcess) {
13370 // This process is hosting what we currently consider to be the
13371 // home app, so we don't want to let it go into the background.
13372 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013373 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013374 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013375 } else if ((N=app.activities.size()) != 0) {
13376 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013377 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013379 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013380 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013381 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013382 for (int j=0; j<N; j++) {
13383 if (((HistoryRecord)app.activities.get(j)).visible) {
13384 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013385 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013386 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013387 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013388 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013389 break;
13390 }
13391 }
13392 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013393 // A very not-needed process. If this is lower in the lru list,
13394 // we will push it in to the empty bucket.
13395 app.hidden = true;
13396 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013397 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013398 adj = hiddenAdj;
13399 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013400 }
13401
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013402 //Log.i(TAG, "OOM " + app + ": initial adj=" + adj);
13403
The Android Open Source Project4df24232009-03-05 14:34:35 -080013404 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013405 // there are applications dependent on our services or providers, but
13406 // this gives us a baseline and makes sure we don't get into an
13407 // infinite recursion.
13408 app.adjSeq = mAdjSeq;
13409 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013410
Christopher Tate6fa95972009-06-05 18:43:55 -070013411 if (mBackupTarget != null && app == mBackupTarget.app) {
13412 // If possible we want to avoid killing apps while they're being backed up
13413 if (adj > BACKUP_APP_ADJ) {
13414 if (DEBUG_BACKUP) Log.v(TAG, "oom BACKUP_APP_ADJ for " + app);
13415 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013416 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013417 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013418 }
13419 }
13420
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013421 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13422 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013423 final long now = SystemClock.uptimeMillis();
13424 // This process is more important if the top activity is
13425 // bound to the service.
13426 Iterator jt = app.services.iterator();
13427 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13428 ServiceRecord s = (ServiceRecord)jt.next();
13429 if (s.startRequested) {
13430 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13431 // This service has seen some activity within
13432 // recent memory, so we will keep its process ahead
13433 // of the background processes.
13434 if (adj > SECONDARY_SERVER_ADJ) {
13435 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013436 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013437 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013438 }
13439 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013440 // If we have let the service slide into the background
13441 // state, still have some text describing what it is doing
13442 // even though the service no longer has an impact.
13443 if (adj > SECONDARY_SERVER_ADJ) {
13444 app.adjType = "started-bg-services";
13445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013446 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013447 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13448 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449 Iterator<ConnectionRecord> kt
13450 = s.connections.values().iterator();
13451 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13452 // XXX should compute this based on the max of
13453 // all connected clients.
13454 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013455 if (cr.binding.client == app) {
13456 // Binding to ourself is not interesting.
13457 continue;
13458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013459 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13460 ProcessRecord client = cr.binding.client;
13461 int myHiddenAdj = hiddenAdj;
13462 if (myHiddenAdj > client.hiddenAdj) {
13463 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13464 myHiddenAdj = client.hiddenAdj;
13465 } else {
13466 myHiddenAdj = VISIBLE_APP_ADJ;
13467 }
13468 }
13469 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013470 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013471 if (adj > clientAdj) {
13472 adj = clientAdj > VISIBLE_APP_ADJ
13473 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013474 if (!client.hidden) {
13475 app.hidden = false;
13476 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013477 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013478 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13479 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013480 app.adjSource = cr.binding.client;
13481 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013482 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013483 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13484 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13485 schedGroup = Process.THREAD_GROUP_DEFAULT;
13486 }
13487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013488 }
13489 HistoryRecord a = cr.activity;
13490 //if (a != null) {
13491 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
13492 //}
13493 if (a != null && adj > FOREGROUND_APP_ADJ &&
13494 (a.state == ActivityState.RESUMED
13495 || a.state == ActivityState.PAUSING)) {
13496 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013497 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013498 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013499 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013500 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13501 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013502 app.adjSource = a;
13503 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013504 }
13505 }
13506 }
13507 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013508
13509 // Finally, f this process has active services running in it, we
13510 // would like to avoid killing it unless it would prevent the current
13511 // application from running. By default we put the process in
13512 // with the rest of the background processes; as we scan through
13513 // its services we may bump it up from there.
13514 if (adj > hiddenAdj) {
13515 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013516 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013517 app.adjType = "bg-services";
13518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013519 }
13520
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013521 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13522 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013524 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13525 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13527 if (cpr.clients.size() != 0) {
13528 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13529 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13530 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013531 if (client == app) {
13532 // Being our own client is not interesting.
13533 continue;
13534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013535 int myHiddenAdj = hiddenAdj;
13536 if (myHiddenAdj > client.hiddenAdj) {
13537 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13538 myHiddenAdj = client.hiddenAdj;
13539 } else {
13540 myHiddenAdj = FOREGROUND_APP_ADJ;
13541 }
13542 }
13543 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013544 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 if (adj > clientAdj) {
13546 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013547 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013548 if (!client.hidden) {
13549 app.hidden = false;
13550 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013551 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013552 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13553 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013554 app.adjSource = client;
13555 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013557 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13558 schedGroup = Process.THREAD_GROUP_DEFAULT;
13559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013560 }
13561 }
13562 // If the provider has external (non-framework) process
13563 // dependencies, ensure that its adjustment is at least
13564 // FOREGROUND_APP_ADJ.
13565 if (cpr.externals != 0) {
13566 if (adj > FOREGROUND_APP_ADJ) {
13567 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013568 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013569 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013570 app.adjType = "provider";
13571 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013572 }
13573 }
13574 }
13575 }
13576
13577 app.curRawAdj = adj;
13578
13579 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
13580 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13581 if (adj > app.maxAdj) {
13582 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013583 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13584 schedGroup = Process.THREAD_GROUP_DEFAULT;
13585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013586 }
13587
13588 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013589 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013591 return adj;
13592 }
13593
13594 /**
13595 * Ask a given process to GC right now.
13596 */
13597 final void performAppGcLocked(ProcessRecord app) {
13598 try {
13599 app.lastRequestedGc = SystemClock.uptimeMillis();
13600 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013601 if (app.reportLowMemory) {
13602 app.reportLowMemory = false;
13603 app.thread.scheduleLowMemory();
13604 } else {
13605 app.thread.processInBackground();
13606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013607 }
13608 } catch (Exception e) {
13609 // whatever.
13610 }
13611 }
13612
13613 /**
13614 * Returns true if things are idle enough to perform GCs.
13615 */
13616 private final boolean canGcNow() {
13617 return mParallelBroadcasts.size() == 0
13618 && mOrderedBroadcasts.size() == 0
13619 && (mSleeping || (mResumedActivity != null &&
13620 mResumedActivity.idle));
13621 }
13622
13623 /**
13624 * Perform GCs on all processes that are waiting for it, but only
13625 * if things are idle.
13626 */
13627 final void performAppGcsLocked() {
13628 final int N = mProcessesToGc.size();
13629 if (N <= 0) {
13630 return;
13631 }
13632 if (canGcNow()) {
13633 while (mProcessesToGc.size() > 0) {
13634 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013635 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13636 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13637 <= SystemClock.uptimeMillis()) {
13638 // To avoid spamming the system, we will GC processes one
13639 // at a time, waiting a few seconds between each.
13640 performAppGcLocked(proc);
13641 scheduleAppGcsLocked();
13642 return;
13643 } else {
13644 // It hasn't been long enough since we last GCed this
13645 // process... put it in the list to wait for its time.
13646 addProcessToGcListLocked(proc);
13647 break;
13648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013649 }
13650 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013651
13652 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013653 }
13654 }
13655
13656 /**
13657 * If all looks good, perform GCs on all processes waiting for them.
13658 */
13659 final void performAppGcsIfAppropriateLocked() {
13660 if (canGcNow()) {
13661 performAppGcsLocked();
13662 return;
13663 }
13664 // Still not idle, wait some more.
13665 scheduleAppGcsLocked();
13666 }
13667
13668 /**
13669 * Schedule the execution of all pending app GCs.
13670 */
13671 final void scheduleAppGcsLocked() {
13672 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013673
13674 if (mProcessesToGc.size() > 0) {
13675 // Schedule a GC for the time to the next process.
13676 ProcessRecord proc = mProcessesToGc.get(0);
13677 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13678
13679 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13680 long now = SystemClock.uptimeMillis();
13681 if (when < (now+GC_TIMEOUT)) {
13682 when = now + GC_TIMEOUT;
13683 }
13684 mHandler.sendMessageAtTime(msg, when);
13685 }
13686 }
13687
13688 /**
13689 * Add a process to the array of processes waiting to be GCed. Keeps the
13690 * list in sorted order by the last GC time. The process can't already be
13691 * on the list.
13692 */
13693 final void addProcessToGcListLocked(ProcessRecord proc) {
13694 boolean added = false;
13695 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13696 if (mProcessesToGc.get(i).lastRequestedGc <
13697 proc.lastRequestedGc) {
13698 added = true;
13699 mProcessesToGc.add(i+1, proc);
13700 break;
13701 }
13702 }
13703 if (!added) {
13704 mProcessesToGc.add(0, proc);
13705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013706 }
13707
13708 /**
13709 * Set up to ask a process to GC itself. This will either do it
13710 * immediately, or put it on the list of processes to gc the next
13711 * time things are idle.
13712 */
13713 final void scheduleAppGcLocked(ProcessRecord app) {
13714 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013715 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013716 return;
13717 }
13718 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013719 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013720 scheduleAppGcsLocked();
13721 }
13722 }
13723
13724 private final boolean updateOomAdjLocked(
13725 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13726 app.hiddenAdj = hiddenAdj;
13727
13728 if (app.thread == null) {
13729 return true;
13730 }
13731
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013732 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013733
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013734 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013735 if (app.curRawAdj != app.setRawAdj) {
13736 if (app.curRawAdj > FOREGROUND_APP_ADJ
13737 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13738 // If this app is transitioning from foreground to
13739 // non-foreground, have it do a gc.
13740 scheduleAppGcLocked(app);
13741 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13742 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13743 // Likewise do a gc when an app is moving in to the
13744 // background (such as a service stopping).
13745 scheduleAppGcLocked(app);
13746 }
13747 app.setRawAdj = app.curRawAdj;
13748 }
13749 if (adj != app.setAdj) {
13750 if (Process.setOomAdj(app.pid, adj)) {
13751 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
13752 TAG, "Set app " + app.processName +
13753 " oom adj to " + adj);
13754 app.setAdj = adj;
13755 } else {
13756 return false;
13757 }
13758 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013759 if (app.setSchedGroup != app.curSchedGroup) {
13760 app.setSchedGroup = app.curSchedGroup;
13761 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG,
13762 "Setting process group of " + app.processName
13763 + " to " + app.curSchedGroup);
13764 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013765 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013766 try {
13767 Process.setProcessGroup(app.pid, app.curSchedGroup);
13768 } catch (Exception e) {
13769 Log.w(TAG, "Failed setting process group of " + app.pid
13770 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013771 e.printStackTrace();
13772 } finally {
13773 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013774 }
13775 }
13776 if (false) {
13777 if (app.thread != null) {
13778 try {
13779 app.thread.setSchedulingGroup(app.curSchedGroup);
13780 } catch (RemoteException e) {
13781 }
13782 }
13783 }
13784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013785 }
13786
13787 return true;
13788 }
13789
13790 private final HistoryRecord resumedAppLocked() {
13791 HistoryRecord resumedActivity = mResumedActivity;
13792 if (resumedActivity == null || resumedActivity.app == null) {
13793 resumedActivity = mPausingActivity;
13794 if (resumedActivity == null || resumedActivity.app == null) {
13795 resumedActivity = topRunningActivityLocked(null);
13796 }
13797 }
13798 return resumedActivity;
13799 }
13800
13801 private final boolean updateOomAdjLocked(ProcessRecord app) {
13802 final HistoryRecord TOP_ACT = resumedAppLocked();
13803 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13804 int curAdj = app.curAdj;
13805 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13806 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13807
13808 mAdjSeq++;
13809
13810 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13811 if (res) {
13812 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13813 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13814 if (nowHidden != wasHidden) {
13815 // Changed to/from hidden state, so apps after it in the LRU
13816 // list may also be changed.
13817 updateOomAdjLocked();
13818 }
13819 }
13820 return res;
13821 }
13822
13823 private final boolean updateOomAdjLocked() {
13824 boolean didOomAdj = true;
13825 final HistoryRecord TOP_ACT = resumedAppLocked();
13826 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13827
13828 if (false) {
13829 RuntimeException e = new RuntimeException();
13830 e.fillInStackTrace();
13831 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
13832 }
13833
13834 mAdjSeq++;
13835
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013836 // Let's determine how many processes we have running vs.
13837 // how many slots we have for background processes; we may want
13838 // to put multiple processes in a slot of there are enough of
13839 // them.
13840 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13841 int factor = (mLruProcesses.size()-4)/numSlots;
13842 if (factor < 1) factor = 1;
13843 int step = 0;
13844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013845 // First try updating the OOM adjustment for each of the
13846 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013847 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013848 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13849 while (i > 0) {
13850 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013851 ProcessRecord app = mLruProcesses.get(i);
13852 //Log.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013853 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013854 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013855 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013856 step++;
13857 if (step >= factor) {
13858 step = 0;
13859 curHiddenAdj++;
13860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013861 }
13862 } else {
13863 didOomAdj = false;
13864 }
13865 }
13866
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013867 // If we return false, we will fall back on killing processes to
13868 // have a fixed limit. Do this if a limit has been requested; else
13869 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013870 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13871 }
13872
13873 private final void trimApplications() {
13874 synchronized (this) {
13875 int i;
13876
13877 // First remove any unused application processes whose package
13878 // has been removed.
13879 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13880 final ProcessRecord app = mRemovedProcesses.get(i);
13881 if (app.activities.size() == 0
13882 && app.curReceiver == null && app.services.size() == 0) {
13883 Log.i(
13884 TAG, "Exiting empty application process "
13885 + app.processName + " ("
13886 + (app.thread != null ? app.thread.asBinder() : null)
13887 + ")\n");
13888 if (app.pid > 0 && app.pid != MY_PID) {
13889 Process.killProcess(app.pid);
13890 } else {
13891 try {
13892 app.thread.scheduleExit();
13893 } catch (Exception e) {
13894 // Ignore exceptions.
13895 }
13896 }
13897 cleanUpApplicationRecordLocked(app, false, -1);
13898 mRemovedProcesses.remove(i);
13899
13900 if (app.persistent) {
13901 if (app.persistent) {
13902 addAppLocked(app.info);
13903 }
13904 }
13905 }
13906 }
13907
13908 // Now try updating the OOM adjustment for each of the
13909 // application processes based on their current state.
13910 // If the setOomAdj() API is not supported, then go with our
13911 // back-up plan...
13912 if (!updateOomAdjLocked()) {
13913
13914 // Count how many processes are running services.
13915 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013916 for (i=mLruProcesses.size()-1; i>=0; i--) {
13917 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013918
13919 if (app.persistent || app.services.size() != 0
13920 || app.curReceiver != null
13921 || app.persistentActivities > 0) {
13922 // Don't count processes holding services against our
13923 // maximum process count.
13924 if (localLOGV) Log.v(
13925 TAG, "Not trimming app " + app + " with services: "
13926 + app.services);
13927 numServiceProcs++;
13928 }
13929 }
13930
13931 int curMaxProcs = mProcessLimit;
13932 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13933 if (mAlwaysFinishActivities) {
13934 curMaxProcs = 1;
13935 }
13936 curMaxProcs += numServiceProcs;
13937
13938 // Quit as many processes as we can to get down to the desired
13939 // process count. First remove any processes that no longer
13940 // have activites running in them.
13941 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013942 i<mLruProcesses.size()
13943 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013944 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013945 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013946 // Quit an application only if it is not currently
13947 // running any activities.
13948 if (!app.persistent && app.activities.size() == 0
13949 && app.curReceiver == null && app.services.size() == 0) {
13950 Log.i(
13951 TAG, "Exiting empty application process "
13952 + app.processName + " ("
13953 + (app.thread != null ? app.thread.asBinder() : null)
13954 + ")\n");
13955 if (app.pid > 0 && app.pid != MY_PID) {
13956 Process.killProcess(app.pid);
13957 } else {
13958 try {
13959 app.thread.scheduleExit();
13960 } catch (Exception e) {
13961 // Ignore exceptions.
13962 }
13963 }
13964 // todo: For now we assume the application is not buggy
13965 // or evil, and will quit as a result of our request.
13966 // Eventually we need to drive this off of the death
13967 // notification, and kill the process if it takes too long.
13968 cleanUpApplicationRecordLocked(app, false, i);
13969 i--;
13970 }
13971 }
13972
13973 // If we still have too many processes, now from the least
13974 // recently used process we start finishing activities.
13975 if (Config.LOGV) Log.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013976 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013977 " of " + curMaxProcs + " processes");
13978 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013979 i<mLruProcesses.size()
13980 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013981 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013982 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013983 // Quit the application only if we have a state saved for
13984 // all of its activities.
13985 boolean canQuit = !app.persistent && app.curReceiver == null
13986 && app.services.size() == 0
13987 && app.persistentActivities == 0;
13988 int NUMA = app.activities.size();
13989 int j;
13990 if (Config.LOGV) Log.v(
13991 TAG, "Looking to quit " + app.processName);
13992 for (j=0; j<NUMA && canQuit; j++) {
13993 HistoryRecord r = (HistoryRecord)app.activities.get(j);
13994 if (Config.LOGV) Log.v(
13995 TAG, " " + r.intent.getComponent().flattenToShortString()
13996 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13997 canQuit = (r.haveState || !r.stateNotNeeded)
13998 && !r.visible && r.stopped;
13999 }
14000 if (canQuit) {
14001 // Finish all of the activities, and then the app itself.
14002 for (j=0; j<NUMA; j++) {
14003 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14004 if (!r.finishing) {
14005 destroyActivityLocked(r, false);
14006 }
14007 r.resultTo = null;
14008 }
14009 Log.i(TAG, "Exiting application process "
14010 + app.processName + " ("
14011 + (app.thread != null ? app.thread.asBinder() : null)
14012 + ")\n");
14013 if (app.pid > 0 && app.pid != MY_PID) {
14014 Process.killProcess(app.pid);
14015 } else {
14016 try {
14017 app.thread.scheduleExit();
14018 } catch (Exception e) {
14019 // Ignore exceptions.
14020 }
14021 }
14022 // todo: For now we assume the application is not buggy
14023 // or evil, and will quit as a result of our request.
14024 // Eventually we need to drive this off of the death
14025 // notification, and kill the process if it takes too long.
14026 cleanUpApplicationRecordLocked(app, false, i);
14027 i--;
14028 //dump();
14029 }
14030 }
14031
14032 }
14033
14034 int curMaxActivities = MAX_ACTIVITIES;
14035 if (mAlwaysFinishActivities) {
14036 curMaxActivities = 1;
14037 }
14038
14039 // Finally, if there are too many activities now running, try to
14040 // finish as many as we can to get back down to the limit.
14041 for ( i=0;
14042 i<mLRUActivities.size()
14043 && mLRUActivities.size() > curMaxActivities;
14044 i++) {
14045 final HistoryRecord r
14046 = (HistoryRecord)mLRUActivities.get(i);
14047
14048 // We can finish this one if we have its icicle saved and
14049 // it is not persistent.
14050 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14051 && r.stopped && !r.persistent && !r.finishing) {
14052 final int origSize = mLRUActivities.size();
14053 destroyActivityLocked(r, true);
14054
14055 // This will remove it from the LRU list, so keep
14056 // our index at the same value. Note that this check to
14057 // see if the size changes is just paranoia -- if
14058 // something unexpected happens, we don't want to end up
14059 // in an infinite loop.
14060 if (origSize > mLRUActivities.size()) {
14061 i--;
14062 }
14063 }
14064 }
14065 }
14066 }
14067
14068 /** This method sends the specified signal to each of the persistent apps */
14069 public void signalPersistentProcesses(int sig) throws RemoteException {
14070 if (sig != Process.SIGNAL_USR1) {
14071 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14072 }
14073
14074 synchronized (this) {
14075 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14076 != PackageManager.PERMISSION_GRANTED) {
14077 throw new SecurityException("Requires permission "
14078 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14079 }
14080
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014081 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14082 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014083 if (r.thread != null && r.persistent) {
14084 Process.sendSignal(r.pid, sig);
14085 }
14086 }
14087 }
14088 }
14089
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014090 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014091 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014092
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014093 try {
14094 synchronized (this) {
14095 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14096 // its own permission.
14097 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14098 != PackageManager.PERMISSION_GRANTED) {
14099 throw new SecurityException("Requires permission "
14100 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014101 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014102
14103 if (start && fd == null) {
14104 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014105 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014106
14107 ProcessRecord proc = null;
14108 try {
14109 int pid = Integer.parseInt(process);
14110 synchronized (mPidsSelfLocked) {
14111 proc = mPidsSelfLocked.get(pid);
14112 }
14113 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014114 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014115
14116 if (proc == null) {
14117 HashMap<String, SparseArray<ProcessRecord>> all
14118 = mProcessNames.getMap();
14119 SparseArray<ProcessRecord> procs = all.get(process);
14120 if (procs != null && procs.size() > 0) {
14121 proc = procs.valueAt(0);
14122 }
14123 }
14124
14125 if (proc == null || proc.thread == null) {
14126 throw new IllegalArgumentException("Unknown process: " + process);
14127 }
14128
14129 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14130 if (isSecure) {
14131 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14132 throw new SecurityException("Process not debuggable: " + proc);
14133 }
14134 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014135
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014136 proc.thread.profilerControl(start, path, fd);
14137 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014138 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014139 }
14140 } catch (RemoteException e) {
14141 throw new IllegalStateException("Process disappeared");
14142 } finally {
14143 if (fd != null) {
14144 try {
14145 fd.close();
14146 } catch (IOException e) {
14147 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014148 }
14149 }
14150 }
14151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014152 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14153 public void monitor() {
14154 synchronized (this) { }
14155 }
14156}