blob: b1d77f58f1ebaefbc38215cf4298caae7158eba2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.app.IActivityWatcher;
39import android.app.IApplicationThread;
40import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IServiceConnection;
42import android.app.IThumbnailReceiver;
43import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070044import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.PendingIntent;
46import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070047import android.app.Service;
Christopher Tate181fafa2009-05-14 11:12:14 -070048import android.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020049import android.content.ActivityNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.ComponentName;
51import android.content.ContentResolver;
52import android.content.Context;
53import android.content.Intent;
54import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070055import android.content.IIntentReceiver;
56import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070057import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.pm.ActivityInfo;
59import android.content.pm.ApplicationInfo;
60import android.content.pm.ConfigurationInfo;
61import android.content.pm.IPackageDataObserver;
62import android.content.pm.IPackageManager;
63import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080064import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070066import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.ProviderInfo;
68import android.content.pm.ResolveInfo;
69import android.content.pm.ServiceInfo;
70import android.content.res.Configuration;
71import android.graphics.Bitmap;
72import android.net.Uri;
73import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080074import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080075import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070076import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080077import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080079import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.FileUtils;
81import android.os.Handler;
82import android.os.IBinder;
83import android.os.IPermissionController;
84import android.os.Looper;
85import android.os.Message;
86import android.os.Parcel;
87import android.os.ParcelFileDescriptor;
88import android.os.PowerManager;
89import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070090import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import android.os.RemoteException;
92import android.os.ServiceManager;
93import android.os.SystemClock;
94import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.provider.Settings;
96import android.text.TextUtils;
97import 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;
110import java.io.FileInputStream;
111import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200112import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.io.PrintWriter;
114import java.lang.IllegalStateException;
115import java.lang.ref.WeakReference;
116import java.util.ArrayList;
117import java.util.HashMap;
118import java.util.HashSet;
119import java.util.Iterator;
120import java.util.List;
121import java.util.Locale;
122import java.util.Map;
123
124public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
125 static final String TAG = "ActivityManager";
126 static final boolean DEBUG = false;
127 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
128 static final boolean DEBUG_SWITCH = localLOGV || false;
129 static final boolean DEBUG_TASKS = localLOGV || false;
130 static final boolean DEBUG_PAUSE = localLOGV || false;
131 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
132 static final boolean DEBUG_TRANSITION = localLOGV || false;
133 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700134 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 static final boolean DEBUG_SERVICE = localLOGV || false;
136 static final boolean DEBUG_VISBILITY = localLOGV || false;
137 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700138 static final boolean DEBUG_PROVIDER = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700140 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700141 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700142 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 static final boolean VALIDATE_TOKENS = false;
144 static final boolean SHOW_ACTIVITY_START_TIME = true;
145
146 // Control over CPU and battery monitoring.
147 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
148 static final boolean MONITOR_CPU_USAGE = true;
149 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
150 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
151 static final boolean MONITOR_THREAD_CPU_USAGE = false;
152
Dianne Hackborn1655be42009-05-08 14:29:01 -0700153 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700154 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 private static final String SYSTEM_SECURE = "ro.secure";
157
158 // This is the maximum number of application processes we would like
159 // to have running. Due to the asynchronous nature of things, we can
160 // temporarily go beyond this limit.
161 static final int MAX_PROCESSES = 2;
162
163 // Set to false to leave processes running indefinitely, relying on
164 // the kernel killing them as resources are required.
165 static final boolean ENFORCE_PROCESS_LIMIT = false;
166
167 // This is the maximum number of activities that we would like to have
168 // running at a given time.
169 static final int MAX_ACTIVITIES = 20;
170
171 // Maximum number of recent tasks that we can remember.
172 static final int MAX_RECENT_TASKS = 20;
173
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700174 // Amount of time after a call to stopAppSwitches() during which we will
175 // prevent further untrusted switches from happening.
176 static final long APP_SWITCH_DELAY_TIME = 5*1000;
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 // How long until we reset a task when the user returns to it. Currently
179 // 30 minutes.
180 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
181
182 // Set to true to disable the icon that is shown while a new activity
183 // is being started.
184 static final boolean SHOW_APP_STARTING_ICON = true;
185
186 // How long we wait until giving up on the last activity to pause. This
187 // is short because it directly impacts the responsiveness of starting the
188 // next activity.
189 static final int PAUSE_TIMEOUT = 500;
190
191 /**
192 * How long we can hold the launch wake lock before giving up.
193 */
194 static final int LAUNCH_TIMEOUT = 10*1000;
195
196 // How long we wait for a launched process to attach to the activity manager
197 // before we decide it's never going to come up for real.
198 static final int PROC_START_TIMEOUT = 10*1000;
199
200 // How long we wait until giving up on the last activity telling us it
201 // is idle.
202 static final int IDLE_TIMEOUT = 10*1000;
203
204 // How long to wait after going idle before forcing apps to GC.
205 static final int GC_TIMEOUT = 5*1000;
206
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700207 // The minimum amount of time between successive GC requests for a process.
208 static final int GC_MIN_INTERVAL = 60*1000;
209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 // How long we wait until giving up on an activity telling us it has
211 // finished destroying itself.
212 static final int DESTROY_TIMEOUT = 10*1000;
213
214 // How long we allow a receiver to run before giving up on it.
215 static final int BROADCAST_TIMEOUT = 10*1000;
216
217 // How long we wait for a service to finish executing.
218 static final int SERVICE_TIMEOUT = 20*1000;
219
220 // How long a service needs to be running until restarting its process
221 // is no longer considered to be a relaunch of the service.
222 static final int SERVICE_RESTART_DURATION = 5*1000;
223
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700224 // How long a service needs to be running until it will start back at
225 // SERVICE_RESTART_DURATION after being killed.
226 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
227
228 // Multiplying factor to increase restart duration time by, for each time
229 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
230 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
231
232 // The minimum amount of time between restarting services that we allow.
233 // That is, when multiple services are restarting, we won't allow each
234 // to restart less than this amount of time from the last one.
235 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 // Maximum amount of time for there to be no activity on a service before
238 // we consider it non-essential and allow its process to go on the
239 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700240 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241
242 // How long we wait until we timeout on key dispatching.
243 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
244
245 // The minimum time we allow between crashes, for us to consider this
246 // application to be bad and stop and its services and reject broadcasts.
247 static final int MIN_CRASH_INTERVAL = 60*1000;
248
249 // How long we wait until we timeout on key dispatching during instrumentation.
250 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
251
252 // OOM adjustments for processes in various states:
253
254 // This is a process without anything currently running in it. Definitely
255 // the first to go! Value set in system/rootdir/init.rc on startup.
256 // This value is initalized in the constructor, careful when refering to
257 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800258 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259
260 // This is a process only hosting activities that are not visible,
261 // so it can be killed without any disruption. Value set in
262 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800263 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 static int HIDDEN_APP_MIN_ADJ;
265
The Android Open Source Project4df24232009-03-05 14:34:35 -0800266 // This is a process holding the home application -- we want to try
267 // avoiding killing it, even if it would normally be in the background,
268 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800270
Christopher Tate6fa95972009-06-05 18:43:55 -0700271 // This is a process currently hosting a backup operation. Killing it
272 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800273 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 // This is a process holding a secondary server -- killing it will not
276 // have much of an impact as far as the user is concerned. Value set in
277 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
280 // This is a process only hosting activities that are visible to the
281 // user, so we'd prefer they don't disappear. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // This is the process running the current foreground app. We'd really
286 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // This is a process running a core server, such as telephony. Definitely
290 // don't want to kill it, but doing so is not completely fatal.
291 static final int CORE_SERVER_ADJ = -12;
292
293 // The system process runs at the default adjustment.
294 static final int SYSTEM_ADJ = -16;
295
296 // Memory pages are 4K.
297 static final int PAGE_SIZE = 4*1024;
298
Jacek Surazski82a73df2009-06-17 14:33:18 +0200299 // System property defining error report receiver for system apps
300 static final String SYSTEM_APPS_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.system.apps";
301
302 // System property defining default error report receiver
303 static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int EMPTY_APP_MEM;
307 static final int HIDDEN_APP_MEM;
308 static final int HOME_APP_MEM;
309 static final int BACKUP_APP_MEM;
310 static final int SECONDARY_SERVER_MEM;
311 static final int VISIBLE_APP_MEM;
312 static final int FOREGROUND_APP_MEM;
313
314 // The minimum number of hidden apps we want to be able to keep around,
315 // without empty apps being able to push them out of memory.
316 static final int MIN_HIDDEN_APPS = 2;
317
318 // We put empty content processes after any hidden processes that have
319 // been idle for less than 30 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
321
322 // We put empty content processes after any hidden processes that have
323 // been idle for less than 60 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
325
326 static {
327 // These values are set in system/rootdir/init.rc on startup.
328 FOREGROUND_APP_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
330 VISIBLE_APP_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
332 SECONDARY_SERVER_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
334 BACKUP_APP_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
336 HOME_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
338 HIDDEN_APP_MIN_ADJ =
339 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
340 EMPTY_APP_ADJ =
341 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
342 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
343 FOREGROUND_APP_MEM =
344 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
345 VISIBLE_APP_MEM =
346 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
347 SECONDARY_SERVER_MEM =
348 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
349 BACKUP_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
351 HOME_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
353 HIDDEN_APP_MEM =
354 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
355 EMPTY_APP_MEM =
356 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358
Dan Egnor42471dd2010-01-07 17:25:22 -0800359 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360
361 static final String[] EMPTY_STRING_ARRAY = new String[0];
362
363 enum ActivityState {
364 INITIALIZING,
365 RESUMED,
366 PAUSING,
367 PAUSED,
368 STOPPING,
369 STOPPED,
370 FINISHING,
371 DESTROYING,
372 DESTROYED
373 }
374
375 /**
376 * The back history of all previous (and possibly still
377 * running) activities. It contains HistoryRecord objects.
378 */
379 final ArrayList mHistory = new ArrayList();
380
381 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700382 * Description of a request to start a new activity, which has been held
383 * due to app switches being disabled.
384 */
385 class PendingActivityLaunch {
386 HistoryRecord r;
387 HistoryRecord sourceRecord;
388 Uri[] grantedUriPermissions;
389 int grantedMode;
390 boolean onlyIfNeeded;
391 }
392
393 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
394 = new ArrayList<PendingActivityLaunch>();
395
396 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 * List of all active broadcasts that are to be executed immediately
398 * (without waiting for another broadcast to finish). Currently this only
399 * contains broadcasts to registered receivers, to avoid spinning up
400 * a bunch of processes to execute IntentReceiver components.
401 */
402 final ArrayList<BroadcastRecord> mParallelBroadcasts
403 = new ArrayList<BroadcastRecord>();
404
405 /**
406 * List of all active broadcasts that are to be executed one at a time.
407 * The object at the top of the list is the currently activity broadcasts;
408 * those after it are waiting for the top to finish..
409 */
410 final ArrayList<BroadcastRecord> mOrderedBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800414 * Historical data of past broadcasts, for debugging.
415 */
416 static final int MAX_BROADCAST_HISTORY = 100;
417 final BroadcastRecord[] mBroadcastHistory
418 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
419
420 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 * Set when we current have a BROADCAST_INTENT_MSG in flight.
422 */
423 boolean mBroadcastsScheduled = false;
424
425 /**
426 * Set to indicate whether to issue an onUserLeaving callback when a
427 * newly launched activity is being brought in front of us.
428 */
429 boolean mUserLeaving = false;
430
431 /**
432 * When we are in the process of pausing an activity, before starting the
433 * next one, this variable holds the activity that is currently being paused.
434 */
435 HistoryRecord mPausingActivity = null;
436
437 /**
438 * Current activity that is resumed, or null if there is none.
439 */
440 HistoryRecord mResumedActivity = null;
441
442 /**
443 * Activity we have told the window manager to have key focus.
444 */
445 HistoryRecord mFocusedActivity = null;
446
447 /**
448 * This is the last activity that we put into the paused state. This is
449 * used to determine if we need to do an activity transition while sleeping,
450 * when we normally hold the top activity paused.
451 */
452 HistoryRecord mLastPausedActivity = null;
453
454 /**
455 * List of activities that are waiting for a new activity
456 * to become visible before completing whatever operation they are
457 * supposed to do.
458 */
459 final ArrayList mWaitingVisibleActivities = new ArrayList();
460
461 /**
462 * List of activities that are ready to be stopped, but waiting
463 * for the next activity to settle down before doing so. It contains
464 * HistoryRecord objects.
465 */
466 final ArrayList<HistoryRecord> mStoppingActivities
467 = new ArrayList<HistoryRecord>();
468
469 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700470 * Animations that for the current transition have requested not to
471 * be considered for the transition animation.
472 */
473 final ArrayList<HistoryRecord> mNoAnimActivities
474 = new ArrayList<HistoryRecord>();
475
476 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 * List of intents that were used to start the most recent tasks.
478 */
479 final ArrayList<TaskRecord> mRecentTasks
480 = new ArrayList<TaskRecord>();
481
482 /**
483 * List of activities that are ready to be finished, but waiting
484 * for the previous activity to settle down before doing so. It contains
485 * HistoryRecord objects.
486 */
487 final ArrayList mFinishingActivities = new ArrayList();
488
489 /**
490 * All of the applications we currently have running organized by name.
491 * The keys are strings of the application package name (as
492 * returned by the package manager), and the keys are ApplicationRecord
493 * objects.
494 */
495 final ProcessMap<ProcessRecord> mProcessNames
496 = new ProcessMap<ProcessRecord>();
497
498 /**
499 * The last time that various processes have crashed.
500 */
501 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
502
503 /**
504 * Set of applications that we consider to be bad, and will reject
505 * incoming broadcasts from (which the user has no control over).
506 * Processes are added to this set when they have crashed twice within
507 * a minimum amount of time; they are removed from it when they are
508 * later restarted (hopefully due to some user action). The value is the
509 * time it was added to the list.
510 */
511 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
512
513 /**
514 * All of the processes we currently have running organized by pid.
515 * The keys are the pid running the application.
516 *
517 * <p>NOTE: This object is protected by its own lock, NOT the global
518 * activity manager lock!
519 */
520 final SparseArray<ProcessRecord> mPidsSelfLocked
521 = new SparseArray<ProcessRecord>();
522
523 /**
524 * All of the processes that have been forced to be foreground. The key
525 * is the pid of the caller who requested it (we hold a death
526 * link on it).
527 */
528 abstract class ForegroundToken implements IBinder.DeathRecipient {
529 int pid;
530 IBinder token;
531 }
532 final SparseArray<ForegroundToken> mForegroundProcesses
533 = new SparseArray<ForegroundToken>();
534
535 /**
536 * List of records for processes that someone had tried to start before the
537 * system was ready. We don't start them at that point, but ensure they
538 * are started by the time booting is complete.
539 */
540 final ArrayList<ProcessRecord> mProcessesOnHold
541 = new ArrayList<ProcessRecord>();
542
543 /**
544 * List of records for processes that we have started and are waiting
545 * for them to call back. This is really only needed when running in
546 * single processes mode, in which case we do not have a unique pid for
547 * each process.
548 */
549 final ArrayList<ProcessRecord> mStartingProcesses
550 = new ArrayList<ProcessRecord>();
551
552 /**
553 * List of persistent applications that are in the process
554 * of being started.
555 */
556 final ArrayList<ProcessRecord> mPersistentStartingProcesses
557 = new ArrayList<ProcessRecord>();
558
559 /**
560 * Processes that are being forcibly torn down.
561 */
562 final ArrayList<ProcessRecord> mRemovedProcesses
563 = new ArrayList<ProcessRecord>();
564
565 /**
566 * List of running applications, sorted by recent usage.
567 * The first entry in the list is the least recently used.
568 * It contains ApplicationRecord objects. This list does NOT include
569 * any persistent application records (since we never want to exit them).
570 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800571 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 = new ArrayList<ProcessRecord>();
573
574 /**
575 * List of processes that should gc as soon as things are idle.
576 */
577 final ArrayList<ProcessRecord> mProcessesToGc
578 = new ArrayList<ProcessRecord>();
579
580 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800581 * This is the process holding what we currently consider to be
582 * the "home" activity.
583 */
584 private ProcessRecord mHomeProcess;
585
586 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 * List of running activities, sorted by recent usage.
588 * The first entry in the list is the least recently used.
589 * It contains HistoryRecord objects.
590 */
591 private final ArrayList mLRUActivities = new ArrayList();
592
593 /**
594 * Set of PendingResultRecord objects that are currently active.
595 */
596 final HashSet mPendingResultRecords = new HashSet();
597
598 /**
599 * Set of IntentSenderRecord objects that are currently active.
600 */
601 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
602 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
603
604 /**
605 * Intent broadcast that we have tried to start, but are
606 * waiting for its application's process to be created. We only
607 * need one (instead of a list) because we always process broadcasts
608 * one at a time, so no others can be started while waiting for this
609 * one.
610 */
611 BroadcastRecord mPendingBroadcast = null;
612
613 /**
614 * Keeps track of all IIntentReceivers that have been registered for
615 * broadcasts. Hash keys are the receiver IBinder, hash value is
616 * a ReceiverList.
617 */
618 final HashMap mRegisteredReceivers = new HashMap();
619
620 /**
621 * Resolver for broadcast intents to registered receivers.
622 * Holds BroadcastFilter (subclass of IntentFilter).
623 */
624 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
625 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
626 @Override
627 protected boolean allowFilterResult(
628 BroadcastFilter filter, List<BroadcastFilter> dest) {
629 IBinder target = filter.receiverList.receiver.asBinder();
630 for (int i=dest.size()-1; i>=0; i--) {
631 if (dest.get(i).receiverList.receiver.asBinder() == target) {
632 return false;
633 }
634 }
635 return true;
636 }
637 };
638
639 /**
640 * State of all active sticky broadcasts. Keys are the action of the
641 * sticky Intent, values are an ArrayList of all broadcasted intents with
642 * that action (which should usually be one).
643 */
644 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
645 new HashMap<String, ArrayList<Intent>>();
646
647 /**
648 * All currently running services.
649 */
650 final HashMap<ComponentName, ServiceRecord> mServices =
651 new HashMap<ComponentName, ServiceRecord>();
652
653 /**
654 * All currently running services indexed by the Intent used to start them.
655 */
656 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
657 new HashMap<Intent.FilterComparison, ServiceRecord>();
658
659 /**
660 * All currently bound service connections. Keys are the IBinder of
661 * the client's IServiceConnection.
662 */
663 final HashMap<IBinder, ConnectionRecord> mServiceConnections
664 = new HashMap<IBinder, ConnectionRecord>();
665
666 /**
667 * List of services that we have been asked to start,
668 * but haven't yet been able to. It is used to hold start requests
669 * while waiting for their corresponding application thread to get
670 * going.
671 */
672 final ArrayList<ServiceRecord> mPendingServices
673 = new ArrayList<ServiceRecord>();
674
675 /**
676 * List of services that are scheduled to restart following a crash.
677 */
678 final ArrayList<ServiceRecord> mRestartingServices
679 = new ArrayList<ServiceRecord>();
680
681 /**
682 * List of services that are in the process of being stopped.
683 */
684 final ArrayList<ServiceRecord> mStoppingServices
685 = new ArrayList<ServiceRecord>();
686
687 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700688 * Backup/restore process management
689 */
690 String mBackupAppName = null;
691 BackupRecord mBackupTarget = null;
692
693 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 * List of PendingThumbnailsRecord objects of clients who are still
695 * waiting to receive all of the thumbnails for a task.
696 */
697 final ArrayList mPendingThumbnails = new ArrayList();
698
699 /**
700 * List of HistoryRecord objects that have been finished and must
701 * still report back to a pending thumbnail receiver.
702 */
703 final ArrayList mCancelledThumbnails = new ArrayList();
704
705 /**
706 * All of the currently running global content providers. Keys are a
707 * string containing the provider name and values are a
708 * ContentProviderRecord object containing the data about it. Note
709 * that a single provider may be published under multiple names, so
710 * there may be multiple entries here for a single one in mProvidersByClass.
711 */
712 final HashMap mProvidersByName = new HashMap();
713
714 /**
715 * All of the currently running global content providers. Keys are a
716 * string containing the provider's implementation class and values are a
717 * ContentProviderRecord object containing the data about it.
718 */
719 final HashMap mProvidersByClass = new HashMap();
720
721 /**
722 * List of content providers who have clients waiting for them. The
723 * application is currently being launched and the provider will be
724 * removed from this list once it is published.
725 */
726 final ArrayList mLaunchingProviders = new ArrayList();
727
728 /**
729 * Global set of specific Uri permissions that have been granted.
730 */
731 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
732 = new SparseArray<HashMap<Uri, UriPermission>>();
733
734 /**
735 * Thread-local storage used to carry caller permissions over through
736 * indirect content-provider access.
737 * @see #ActivityManagerService.openContentUri()
738 */
739 private class Identity {
740 public int pid;
741 public int uid;
742
743 Identity(int _pid, int _uid) {
744 pid = _pid;
745 uid = _uid;
746 }
747 }
748 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
749
750 /**
751 * All information we have collected about the runtime performance of
752 * any user id that can impact battery performance.
753 */
754 final BatteryStatsService mBatteryStatsService;
755
756 /**
757 * information about component usage
758 */
759 final UsageStatsService mUsageStatsService;
760
761 /**
762 * Current configuration information. HistoryRecord objects are given
763 * a reference to this object to indicate which configuration they are
764 * currently running in, so this object must be kept immutable.
765 */
766 Configuration mConfiguration = new Configuration();
767
768 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700769 * Hardware-reported OpenGLES version.
770 */
771 final int GL_ES_VERSION;
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * List of initialization arguments to pass to all processes when binding applications to them.
775 * For example, references to the commonly used services.
776 */
777 HashMap<String, IBinder> mAppBindArgs;
778
779 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700780 * Temporary to avoid allocations. Protected by main lock.
781 */
782 final StringBuilder mStringBuilder = new StringBuilder(256);
783
784 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 * Used to control how we initialize the service.
786 */
787 boolean mStartRunning = false;
788 ComponentName mTopComponent;
789 String mTopAction;
790 String mTopData;
791 boolean mSystemReady = false;
792 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700793 boolean mWaitingUpdate = false;
794 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795
796 Context mContext;
797
798 int mFactoryTest;
799
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700800 boolean mCheckedForSetup;
801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700803 * The time at which we will allow normal application switches again,
804 * after a call to {@link #stopAppSwitches()}.
805 */
806 long mAppSwitchesAllowedTime;
807
808 /**
809 * This is set to true after the first switch after mAppSwitchesAllowedTime
810 * is set; any switches after that will clear the time.
811 */
812 boolean mDidAppSwitch;
813
814 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * Set while we are wanting to sleep, to prevent any
816 * activities from being started/resumed.
817 */
818 boolean mSleeping = false;
819
820 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700821 * Set if we are shutting down the system, similar to sleeping.
822 */
823 boolean mShuttingDown = false;
824
825 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 * Set when the system is going to sleep, until we have
827 * successfully paused the current activity and released our wake lock.
828 * At that point the system is allowed to actually sleep.
829 */
830 PowerManager.WakeLock mGoingToSleep;
831
832 /**
833 * We don't want to allow the device to go to sleep while in the process
834 * of launching an activity. This is primarily to allow alarm intent
835 * receivers to launch an activity and get that to run before the device
836 * goes back to sleep.
837 */
838 PowerManager.WakeLock mLaunchingActivity;
839
840 /**
841 * Task identifier that activities are currently being started
842 * in. Incremented each time a new task is created.
843 * todo: Replace this with a TokenSpace class that generates non-repeating
844 * integers that won't wrap.
845 */
846 int mCurTask = 1;
847
848 /**
849 * Current sequence id for oom_adj computation traversal.
850 */
851 int mAdjSeq = 0;
852
853 /**
854 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
855 * is set, indicating the user wants processes started in such a way
856 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
857 * running in each process (thus no pre-initialized process, etc).
858 */
859 boolean mSimpleProcessManagement = false;
860
861 /**
862 * System monitoring: number of processes that died since the last
863 * N procs were started.
864 */
865 int[] mProcDeaths = new int[20];
866
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700867 /**
868 * This is set if we had to do a delayed dexopt of an app before launching
869 * it, to increasing the ANR timeouts in that case.
870 */
871 boolean mDidDexOpt;
872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 String mDebugApp = null;
874 boolean mWaitForDebugger = false;
875 boolean mDebugTransient = false;
876 String mOrigDebugApp = null;
877 boolean mOrigWaitForDebugger = false;
878 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700879 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700881 final RemoteCallbackList<IActivityWatcher> mWatchers
882 = new RemoteCallbackList<IActivityWatcher>();
883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 /**
885 * Callback of last caller to {@link #requestPss}.
886 */
887 Runnable mRequestPssCallback;
888
889 /**
890 * Remaining processes for which we are waiting results from the last
891 * call to {@link #requestPss}.
892 */
893 final ArrayList<ProcessRecord> mRequestPssList
894 = new ArrayList<ProcessRecord>();
895
896 /**
897 * Runtime statistics collection thread. This object's lock is used to
898 * protect all related state.
899 */
900 final Thread mProcessStatsThread;
901
902 /**
903 * Used to collect process stats when showing not responding dialog.
904 * Protected by mProcessStatsThread.
905 */
906 final ProcessStats mProcessStats = new ProcessStats(
907 MONITOR_THREAD_CPU_USAGE);
908 long mLastCpuTime = 0;
909 long mLastWriteTime = 0;
910
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700911 long mInitialStartTime = 0;
912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 /**
914 * Set to true after the system has finished booting.
915 */
916 boolean mBooted = false;
917
918 int mProcessLimit = 0;
919
920 WindowManagerService mWindowManager;
921
922 static ActivityManagerService mSelf;
923 static ActivityThread mSystemThread;
924
925 private final class AppDeathRecipient implements IBinder.DeathRecipient {
926 final ProcessRecord mApp;
927 final int mPid;
928 final IApplicationThread mAppThread;
929
930 AppDeathRecipient(ProcessRecord app, int pid,
931 IApplicationThread thread) {
932 if (localLOGV) Log.v(
933 TAG, "New death recipient " + this
934 + " for thread " + thread.asBinder());
935 mApp = app;
936 mPid = pid;
937 mAppThread = thread;
938 }
939
940 public void binderDied() {
941 if (localLOGV) Log.v(
942 TAG, "Death received in " + this
943 + " for thread " + mAppThread.asBinder());
944 removeRequestedPss(mApp);
945 synchronized(ActivityManagerService.this) {
946 appDiedLocked(mApp, mPid, mAppThread);
947 }
948 }
949 }
950
951 static final int SHOW_ERROR_MSG = 1;
952 static final int SHOW_NOT_RESPONDING_MSG = 2;
953 static final int SHOW_FACTORY_ERROR_MSG = 3;
954 static final int UPDATE_CONFIGURATION_MSG = 4;
955 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
956 static final int WAIT_FOR_DEBUGGER_MSG = 6;
957 static final int BROADCAST_INTENT_MSG = 7;
958 static final int BROADCAST_TIMEOUT_MSG = 8;
959 static final int PAUSE_TIMEOUT_MSG = 9;
960 static final int IDLE_TIMEOUT_MSG = 10;
961 static final int IDLE_NOW_MSG = 11;
962 static final int SERVICE_TIMEOUT_MSG = 12;
963 static final int UPDATE_TIME_ZONE = 13;
964 static final int SHOW_UID_ERROR_MSG = 14;
965 static final int IM_FEELING_LUCKY_MSG = 15;
966 static final int LAUNCH_TIMEOUT_MSG = 16;
967 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 static final int RESUME_TOP_ACTIVITY_MSG = 19;
969 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700970 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700971 static final int KILL_APPLICATION_MSG = 22;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972
973 AlertDialog mUidAlert;
974
975 final Handler mHandler = new Handler() {
976 //public Handler() {
977 // if (localLOGV) Log.v(TAG, "Handler started!");
978 //}
979
980 public void handleMessage(Message msg) {
981 switch (msg.what) {
982 case SHOW_ERROR_MSG: {
983 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 synchronized (ActivityManagerService.this) {
985 ProcessRecord proc = (ProcessRecord)data.get("app");
986 if (proc != null && proc.crashDialog != null) {
987 Log.e(TAG, "App already has crash dialog: " + proc);
988 return;
989 }
990 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700991 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800992 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 d.show();
994 proc.crashDialog = d;
995 } else {
996 // The device is asleep, so just pretend that the user
997 // saw a crash dialog and hit "force quit".
998 res.set(0);
999 }
1000 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001001
1002 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 } break;
1004 case SHOW_NOT_RESPONDING_MSG: {
1005 synchronized (ActivityManagerService.this) {
1006 HashMap data = (HashMap) msg.obj;
1007 ProcessRecord proc = (ProcessRecord)data.get("app");
1008 if (proc != null && proc.anrDialog != null) {
1009 Log.e(TAG, "App already has anr dialog: " + proc);
1010 return;
1011 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001012
1013 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1014 null, null, 0, null, null, null,
1015 false, false, MY_PID, Process.SYSTEM_UID);
1016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1018 mContext, proc, (HistoryRecord)data.get("activity"));
1019 d.show();
1020 proc.anrDialog = d;
1021 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001022
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001023 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 } break;
1025 case SHOW_FACTORY_ERROR_MSG: {
1026 Dialog d = new FactoryErrorDialog(
1027 mContext, msg.getData().getCharSequence("msg"));
1028 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001029 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 } break;
1031 case UPDATE_CONFIGURATION_MSG: {
1032 final ContentResolver resolver = mContext.getContentResolver();
1033 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1034 } break;
1035 case GC_BACKGROUND_PROCESSES_MSG: {
1036 synchronized (ActivityManagerService.this) {
1037 performAppGcsIfAppropriateLocked();
1038 }
1039 } break;
1040 case WAIT_FOR_DEBUGGER_MSG: {
1041 synchronized (ActivityManagerService.this) {
1042 ProcessRecord app = (ProcessRecord)msg.obj;
1043 if (msg.arg1 != 0) {
1044 if (!app.waitedForDebugger) {
1045 Dialog d = new AppWaitingForDebuggerDialog(
1046 ActivityManagerService.this,
1047 mContext, app);
1048 app.waitDialog = d;
1049 app.waitedForDebugger = true;
1050 d.show();
1051 }
1052 } else {
1053 if (app.waitDialog != null) {
1054 app.waitDialog.dismiss();
1055 app.waitDialog = null;
1056 }
1057 }
1058 }
1059 } break;
1060 case BROADCAST_INTENT_MSG: {
1061 if (DEBUG_BROADCAST) Log.v(
1062 TAG, "Received BROADCAST_INTENT_MSG");
1063 processNextBroadcast(true);
1064 } break;
1065 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001066 if (mDidDexOpt) {
1067 mDidDexOpt = false;
1068 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1069 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1070 return;
1071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 broadcastTimeout();
1073 } break;
1074 case PAUSE_TIMEOUT_MSG: {
1075 IBinder token = (IBinder)msg.obj;
1076 // We don't at this point know if the activity is fullscreen,
1077 // so we need to be conservative and assume it isn't.
1078 Log.w(TAG, "Activity pause timeout for " + token);
1079 activityPaused(token, null, true);
1080 } break;
1081 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001082 if (mDidDexOpt) {
1083 mDidDexOpt = false;
1084 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1085 nmsg.obj = msg.obj;
1086 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1087 return;
1088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 // We don't at this point know if the activity is fullscreen,
1090 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001091 IBinder token = (IBinder)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 Log.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001093 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 } break;
1095 case DESTROY_TIMEOUT_MSG: {
1096 IBinder token = (IBinder)msg.obj;
1097 // We don't at this point know if the activity is fullscreen,
1098 // so we need to be conservative and assume it isn't.
1099 Log.w(TAG, "Activity destroy timeout for " + token);
1100 activityDestroyed(token);
1101 } break;
1102 case IDLE_NOW_MSG: {
1103 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001104 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 } break;
1106 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001107 if (mDidDexOpt) {
1108 mDidDexOpt = false;
1109 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1110 nmsg.obj = msg.obj;
1111 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1112 return;
1113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 serviceTimeout((ProcessRecord)msg.obj);
1115 } break;
1116 case UPDATE_TIME_ZONE: {
1117 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001118 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1119 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 if (r.thread != null) {
1121 try {
1122 r.thread.updateTimeZone();
1123 } catch (RemoteException ex) {
1124 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
1125 }
1126 }
1127 }
1128 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001129 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 case SHOW_UID_ERROR_MSG: {
1131 // XXX This is a temporary dialog, no need to localize.
1132 AlertDialog d = new BaseErrorDialog(mContext);
1133 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1134 d.setCancelable(false);
1135 d.setTitle("System UIDs Inconsistent");
1136 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1137 d.setButton("I'm Feeling Lucky",
1138 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1139 mUidAlert = d;
1140 d.show();
1141 } break;
1142 case IM_FEELING_LUCKY_MSG: {
1143 if (mUidAlert != null) {
1144 mUidAlert.dismiss();
1145 mUidAlert = null;
1146 }
1147 } break;
1148 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001149 if (mDidDexOpt) {
1150 mDidDexOpt = false;
1151 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1152 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1153 return;
1154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 synchronized (ActivityManagerService.this) {
1156 if (mLaunchingActivity.isHeld()) {
1157 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1158 mLaunchingActivity.release();
1159 }
1160 }
1161 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 case RESUME_TOP_ACTIVITY_MSG: {
1163 synchronized (ActivityManagerService.this) {
1164 resumeTopActivityLocked(null);
1165 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001166 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001168 if (mDidDexOpt) {
1169 mDidDexOpt = false;
1170 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1171 nmsg.obj = msg.obj;
1172 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1173 return;
1174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 ProcessRecord app = (ProcessRecord)msg.obj;
1176 synchronized (ActivityManagerService.this) {
1177 processStartTimedOutLocked(app);
1178 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001179 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001180 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1181 synchronized (ActivityManagerService.this) {
1182 doPendingActivityLaunchesLocked(true);
1183 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001184 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001185 case KILL_APPLICATION_MSG: {
1186 synchronized (ActivityManagerService.this) {
1187 int uid = msg.arg1;
1188 boolean restart = (msg.arg2 == 1);
1189 String pkg = (String) msg.obj;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08001190 forceStopPackageLocked(pkg, uid, restart, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001191 }
1192 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 }
1194 }
1195 };
1196
1197 public static void setSystemProcess() {
1198 try {
1199 ActivityManagerService m = mSelf;
1200
1201 ServiceManager.addService("activity", m);
1202 ServiceManager.addService("meminfo", new MemBinder(m));
1203 if (MONITOR_CPU_USAGE) {
1204 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 ServiceManager.addService("permission", new PermissionController(m));
1207
1208 ApplicationInfo info =
1209 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001210 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001211 mSystemThread.installSystemApplicationInfo(info);
1212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 synchronized (mSelf) {
1214 ProcessRecord app = mSelf.newProcessRecordLocked(
1215 mSystemThread.getApplicationThread(), info,
1216 info.processName);
1217 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001218 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 app.maxAdj = SYSTEM_ADJ;
1220 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1221 synchronized (mSelf.mPidsSelfLocked) {
1222 mSelf.mPidsSelfLocked.put(app.pid, app);
1223 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001224 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 }
1226 } catch (PackageManager.NameNotFoundException e) {
1227 throw new RuntimeException(
1228 "Unable to find android system package", e);
1229 }
1230 }
1231
1232 public void setWindowManager(WindowManagerService wm) {
1233 mWindowManager = wm;
1234 }
1235
1236 public static final Context main(int factoryTest) {
1237 AThread thr = new AThread();
1238 thr.start();
1239
1240 synchronized (thr) {
1241 while (thr.mService == null) {
1242 try {
1243 thr.wait();
1244 } catch (InterruptedException e) {
1245 }
1246 }
1247 }
1248
1249 ActivityManagerService m = thr.mService;
1250 mSelf = m;
1251 ActivityThread at = ActivityThread.systemMain();
1252 mSystemThread = at;
1253 Context context = at.getSystemContext();
1254 m.mContext = context;
1255 m.mFactoryTest = factoryTest;
1256 PowerManager pm =
1257 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1258 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1259 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1260 m.mLaunchingActivity.setReferenceCounted(false);
1261
1262 m.mBatteryStatsService.publish(context);
1263 m.mUsageStatsService.publish(context);
1264
1265 synchronized (thr) {
1266 thr.mReady = true;
1267 thr.notifyAll();
1268 }
1269
1270 m.startRunning(null, null, null, null);
1271
1272 return context;
1273 }
1274
1275 public static ActivityManagerService self() {
1276 return mSelf;
1277 }
1278
1279 static class AThread extends Thread {
1280 ActivityManagerService mService;
1281 boolean mReady = false;
1282
1283 public AThread() {
1284 super("ActivityManager");
1285 }
1286
1287 public void run() {
1288 Looper.prepare();
1289
1290 android.os.Process.setThreadPriority(
1291 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1292
1293 ActivityManagerService m = new ActivityManagerService();
1294
1295 synchronized (this) {
1296 mService = m;
1297 notifyAll();
1298 }
1299
1300 synchronized (this) {
1301 while (!mReady) {
1302 try {
1303 wait();
1304 } catch (InterruptedException e) {
1305 }
1306 }
1307 }
1308
1309 Looper.loop();
1310 }
1311 }
1312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 static class MemBinder extends Binder {
1314 ActivityManagerService mActivityManagerService;
1315 MemBinder(ActivityManagerService activityManagerService) {
1316 mActivityManagerService = activityManagerService;
1317 }
1318
1319 @Override
1320 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1321 ActivityManagerService service = mActivityManagerService;
1322 ArrayList<ProcessRecord> procs;
1323 synchronized (mActivityManagerService) {
1324 if (args != null && args.length > 0
1325 && args[0].charAt(0) != '-') {
1326 procs = new ArrayList<ProcessRecord>();
1327 int pid = -1;
1328 try {
1329 pid = Integer.parseInt(args[0]);
1330 } catch (NumberFormatException e) {
1331
1332 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001333 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1334 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 if (proc.pid == pid) {
1336 procs.add(proc);
1337 } else if (proc.processName.equals(args[0])) {
1338 procs.add(proc);
1339 }
1340 }
1341 if (procs.size() <= 0) {
1342 pw.println("No process found for: " + args[0]);
1343 return;
1344 }
1345 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001346 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 }
1348 }
1349 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1350 }
1351 }
1352
1353 static class CpuBinder extends Binder {
1354 ActivityManagerService mActivityManagerService;
1355 CpuBinder(ActivityManagerService activityManagerService) {
1356 mActivityManagerService = activityManagerService;
1357 }
1358
1359 @Override
1360 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1361 synchronized (mActivityManagerService.mProcessStatsThread) {
1362 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1363 }
1364 }
1365 }
1366
1367 private ActivityManagerService() {
1368 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1369 if (v != null && Integer.getInteger(v) != 0) {
1370 mSimpleProcessManagement = true;
1371 }
1372 v = System.getenv("ANDROID_DEBUG_APP");
1373 if (v != null) {
1374 mSimpleProcessManagement = true;
1375 }
1376
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001377 Log.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
1378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 File dataDir = Environment.getDataDirectory();
1380 File systemDir = new File(dataDir, "system");
1381 systemDir.mkdirs();
1382 mBatteryStatsService = new BatteryStatsService(new File(
1383 systemDir, "batterystats.bin").toString());
1384 mBatteryStatsService.getActiveStatistics().readLocked();
1385 mBatteryStatsService.getActiveStatistics().writeLocked();
1386
1387 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001388 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389
Jack Palevichb90d28c2009-07-22 15:35:24 -07001390 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1391 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 mConfiguration.makeDefault();
1394 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 Cheng23085b72010-02-08 16:06:32 -08001943 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0) {
1944 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1947 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1948 }
1949 if ("1".equals(SystemProperties.get("debug.assert"))) {
1950 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1951 }
1952 int pid = Process.start("android.app.ActivityThread",
1953 mSimpleProcessManagement ? app.processName : null, uid, uid,
1954 gids, debugFlags, null);
1955 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1956 synchronized (bs) {
1957 if (bs.isOnBattery()) {
1958 app.batteryStats.incStartsLocked();
1959 }
1960 }
1961
Doug Zongker2bec3d42009-12-04 12:52:44 -08001962 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 app.processName, hostingType,
1964 hostingNameStr != null ? hostingNameStr : "");
1965
1966 if (app.persistent) {
1967 Watchdog.getInstance().processStarted(app, app.processName, pid);
1968 }
1969
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001970 StringBuilder buf = mStringBuilder;
1971 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 buf.append("Start proc ");
1973 buf.append(app.processName);
1974 buf.append(" for ");
1975 buf.append(hostingType);
1976 if (hostingNameStr != null) {
1977 buf.append(" ");
1978 buf.append(hostingNameStr);
1979 }
1980 buf.append(": pid=");
1981 buf.append(pid);
1982 buf.append(" uid=");
1983 buf.append(uid);
1984 buf.append(" gids={");
1985 if (gids != null) {
1986 for (int gi=0; gi<gids.length; gi++) {
1987 if (gi != 0) buf.append(", ");
1988 buf.append(gids[gi]);
1989
1990 }
1991 }
1992 buf.append("}");
1993 Log.i(TAG, buf.toString());
1994 if (pid == 0 || pid == MY_PID) {
1995 // Processes are being emulated with threads.
1996 app.pid = MY_PID;
1997 app.removed = false;
1998 mStartingProcesses.add(app);
1999 } else if (pid > 0) {
2000 app.pid = pid;
2001 app.removed = false;
2002 synchronized (mPidsSelfLocked) {
2003 this.mPidsSelfLocked.put(pid, app);
2004 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2005 msg.obj = app;
2006 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2007 }
2008 } else {
2009 app.pid = 0;
2010 RuntimeException e = new RuntimeException(
2011 "Failure starting process " + app.processName
2012 + ": returned pid=" + pid);
2013 Log.e(TAG, e.getMessage(), e);
2014 }
2015 } catch (RuntimeException e) {
2016 // XXX do better error recovery.
2017 app.pid = 0;
2018 Log.e(TAG, "Failure starting process " + app.processName, e);
2019 }
2020 }
2021
2022 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2023 if (mPausingActivity != null) {
2024 RuntimeException e = new RuntimeException();
2025 Log.e(TAG, "Trying to pause when pause is already pending for "
2026 + mPausingActivity, e);
2027 }
2028 HistoryRecord prev = mResumedActivity;
2029 if (prev == null) {
2030 RuntimeException e = new RuntimeException();
2031 Log.e(TAG, "Trying to pause when nothing is resumed", e);
2032 resumeTopActivityLocked(null);
2033 return;
2034 }
2035 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
2036 mResumedActivity = null;
2037 mPausingActivity = prev;
2038 mLastPausedActivity = prev;
2039 prev.state = ActivityState.PAUSING;
2040 prev.task.touchActiveTime();
2041
2042 updateCpuStats();
2043
2044 if (prev.app != null && prev.app.thread != null) {
2045 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
2046 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002047 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 System.identityHashCode(prev),
2049 prev.shortComponentName);
2050 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2051 prev.configChangeFlags);
2052 updateUsageStats(prev, false);
2053 } catch (Exception e) {
2054 // Ignore exception, if process died other code will cleanup.
2055 Log.w(TAG, "Exception thrown during pause", e);
2056 mPausingActivity = null;
2057 mLastPausedActivity = null;
2058 }
2059 } else {
2060 mPausingActivity = null;
2061 mLastPausedActivity = null;
2062 }
2063
2064 // If we are not going to sleep, we want to ensure the device is
2065 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002066 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 mLaunchingActivity.acquire();
2068 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2069 // To be safe, don't allow the wake lock to be held for too long.
2070 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2071 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2072 }
2073 }
2074
2075
2076 if (mPausingActivity != null) {
2077 // Have the window manager pause its key dispatching until the new
2078 // activity has started. If we're pausing the activity just because
2079 // the screen is being turned off and the UI is sleeping, don't interrupt
2080 // key dispatch; the same activity will pick it up again on wakeup.
2081 if (!uiSleeping) {
2082 prev.pauseKeyDispatchingLocked();
2083 } else {
2084 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
2085 }
2086
2087 // Schedule a pause timeout in case the app doesn't respond.
2088 // We don't give it much time because this directly impacts the
2089 // responsiveness seen by the user.
2090 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2091 msg.obj = prev;
2092 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
2093 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
2094 } else {
2095 // This activity failed to schedule the
2096 // pause, so just treat it as being paused now.
2097 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
2098 resumeTopActivityLocked(null);
2099 }
2100 }
2101
2102 private final void completePauseLocked() {
2103 HistoryRecord prev = mPausingActivity;
2104 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
2105
2106 if (prev != null) {
2107 if (prev.finishing) {
2108 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
2109 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2110 } else if (prev.app != null) {
2111 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
2112 if (prev.waitingVisible) {
2113 prev.waitingVisible = false;
2114 mWaitingVisibleActivities.remove(prev);
2115 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
2116 TAG, "Complete pause, no longer waiting: " + prev);
2117 }
2118 if (prev.configDestroy) {
2119 // The previous is being paused because the configuration
2120 // is changing, which means it is actually stopping...
2121 // To juggle the fact that we are also starting a new
2122 // instance right now, we need to first completely stop
2123 // the current instance before starting the new one.
2124 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
2125 destroyActivityLocked(prev, true);
2126 } else {
2127 mStoppingActivities.add(prev);
2128 if (mStoppingActivities.size() > 3) {
2129 // If we already have a few activities waiting to stop,
2130 // then give up on things going idle and start clearing
2131 // them out.
2132 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
2133 Message msg = Message.obtain();
2134 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2135 mHandler.sendMessage(msg);
2136 }
2137 }
2138 } else {
2139 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
2140 prev = null;
2141 }
2142 mPausingActivity = null;
2143 }
2144
Dianne Hackborn55280a92009-05-07 15:53:46 -07002145 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 resumeTopActivityLocked(prev);
2147 } else {
2148 if (mGoingToSleep.isHeld()) {
2149 mGoingToSleep.release();
2150 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002151 if (mShuttingDown) {
2152 notifyAll();
2153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 }
2155
2156 if (prev != null) {
2157 prev.resumeKeyDispatchingLocked();
2158 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002159
2160 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2161 long diff = 0;
2162 synchronized (mProcessStatsThread) {
2163 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2164 }
2165 if (diff > 0) {
2166 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2167 synchronized (bsi) {
2168 BatteryStatsImpl.Uid.Proc ps =
2169 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2170 prev.info.packageName);
2171 if (ps != null) {
2172 ps.addForegroundTimeLocked(diff);
2173 }
2174 }
2175 }
2176 }
2177 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 }
2179
2180 /**
2181 * Once we know that we have asked an application to put an activity in
2182 * the resumed state (either by launching it or explicitly telling it),
2183 * this function updates the rest of our state to match that fact.
2184 */
2185 private final void completeResumeLocked(HistoryRecord next) {
2186 next.idle = false;
2187 next.results = null;
2188 next.newIntents = null;
2189
2190 // schedule an idle timeout in case the app doesn't do it for us.
2191 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2192 msg.obj = next;
2193 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2194
2195 if (false) {
2196 // The activity was never told to pause, so just keep
2197 // things going as-is. To maintain our own state,
2198 // we need to emulate it coming back and saying it is
2199 // idle.
2200 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2201 msg.obj = next;
2202 mHandler.sendMessage(msg);
2203 }
2204
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002205 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 next.thumbnail = null;
2208 setFocusedActivityLocked(next);
2209 next.resumeKeyDispatchingLocked();
2210 ensureActivitiesVisibleLocked(null, 0);
2211 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002212 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002213
2214 // Mark the point when the activity is resuming
2215 // TODO: To be more accurate, the mark should be before the onCreate,
2216 // not after the onResume. But for subsequent starts, onResume is fine.
2217 if (next.app != null) {
2218 synchronized (mProcessStatsThread) {
2219 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2220 }
2221 } else {
2222 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 }
2225
2226 /**
2227 * Make sure that all activities that need to be visible (that is, they
2228 * currently can be seen by the user) actually are.
2229 */
2230 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2231 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2232 if (DEBUG_VISBILITY) Log.v(
2233 TAG, "ensureActivitiesVisible behind " + top
2234 + " configChanges=0x" + Integer.toHexString(configChanges));
2235
2236 // If the top activity is not fullscreen, then we need to
2237 // make sure any activities under it are now visible.
2238 final int count = mHistory.size();
2239 int i = count-1;
2240 while (mHistory.get(i) != top) {
2241 i--;
2242 }
2243 HistoryRecord r;
2244 boolean behindFullscreen = false;
2245 for (; i>=0; i--) {
2246 r = (HistoryRecord)mHistory.get(i);
2247 if (DEBUG_VISBILITY) Log.v(
2248 TAG, "Make visible? " + r + " finishing=" + r.finishing
2249 + " state=" + r.state);
2250 if (r.finishing) {
2251 continue;
2252 }
2253
2254 final boolean doThisProcess = onlyThisProcess == null
2255 || onlyThisProcess.equals(r.processName);
2256
2257 // First: if this is not the current activity being started, make
2258 // sure it matches the current configuration.
2259 if (r != starting && doThisProcess) {
2260 ensureActivityConfigurationLocked(r, 0);
2261 }
2262
2263 if (r.app == null || r.app.thread == null) {
2264 if (onlyThisProcess == null
2265 || onlyThisProcess.equals(r.processName)) {
2266 // This activity needs to be visible, but isn't even
2267 // running... get it started, but don't resume it
2268 // at this point.
2269 if (DEBUG_VISBILITY) Log.v(
2270 TAG, "Start and freeze screen for " + r);
2271 if (r != starting) {
2272 r.startFreezingScreenLocked(r.app, configChanges);
2273 }
2274 if (!r.visible) {
2275 if (DEBUG_VISBILITY) Log.v(
2276 TAG, "Starting and making visible: " + r);
2277 mWindowManager.setAppVisibility(r, true);
2278 }
2279 if (r != starting) {
2280 startSpecificActivityLocked(r, false, false);
2281 }
2282 }
2283
2284 } else if (r.visible) {
2285 // If this activity is already visible, then there is nothing
2286 // else to do here.
2287 if (DEBUG_VISBILITY) Log.v(
2288 TAG, "Skipping: already visible at " + r);
2289 r.stopFreezingScreenLocked(false);
2290
2291 } else if (onlyThisProcess == null) {
2292 // This activity is not currently visible, but is running.
2293 // Tell it to become visible.
2294 r.visible = true;
2295 if (r.state != ActivityState.RESUMED && r != starting) {
2296 // If this activity is paused, tell it
2297 // to now show its window.
2298 if (DEBUG_VISBILITY) Log.v(
2299 TAG, "Making visible and scheduling visibility: " + r);
2300 try {
2301 mWindowManager.setAppVisibility(r, true);
2302 r.app.thread.scheduleWindowVisibility(r, true);
2303 r.stopFreezingScreenLocked(false);
2304 } catch (Exception e) {
2305 // Just skip on any failure; we'll make it
2306 // visible when it next restarts.
2307 Log.w(TAG, "Exception thrown making visibile: "
2308 + r.intent.getComponent(), e);
2309 }
2310 }
2311 }
2312
2313 // Aggregate current change flags.
2314 configChanges |= r.configChangeFlags;
2315
2316 if (r.fullscreen) {
2317 // At this point, nothing else needs to be shown
2318 if (DEBUG_VISBILITY) Log.v(
2319 TAG, "Stopping: fullscreen at " + r);
2320 behindFullscreen = true;
2321 i--;
2322 break;
2323 }
2324 }
2325
2326 // Now for any activities that aren't visible to the user, make
2327 // sure they no longer are keeping the screen frozen.
2328 while (i >= 0) {
2329 r = (HistoryRecord)mHistory.get(i);
2330 if (DEBUG_VISBILITY) Log.v(
2331 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2332 + " state=" + r.state
2333 + " behindFullscreen=" + behindFullscreen);
2334 if (!r.finishing) {
2335 if (behindFullscreen) {
2336 if (r.visible) {
2337 if (DEBUG_VISBILITY) Log.v(
2338 TAG, "Making invisible: " + r);
2339 r.visible = false;
2340 try {
2341 mWindowManager.setAppVisibility(r, false);
2342 if ((r.state == ActivityState.STOPPING
2343 || r.state == ActivityState.STOPPED)
2344 && r.app != null && r.app.thread != null) {
2345 if (DEBUG_VISBILITY) Log.v(
2346 TAG, "Scheduling invisibility: " + r);
2347 r.app.thread.scheduleWindowVisibility(r, false);
2348 }
2349 } catch (Exception e) {
2350 // Just skip on any failure; we'll make it
2351 // visible when it next restarts.
2352 Log.w(TAG, "Exception thrown making hidden: "
2353 + r.intent.getComponent(), e);
2354 }
2355 } else {
2356 if (DEBUG_VISBILITY) Log.v(
2357 TAG, "Already invisible: " + r);
2358 }
2359 } else if (r.fullscreen) {
2360 if (DEBUG_VISBILITY) Log.v(
2361 TAG, "Now behindFullscreen: " + r);
2362 behindFullscreen = true;
2363 }
2364 }
2365 i--;
2366 }
2367 }
2368
2369 /**
2370 * Version of ensureActivitiesVisible that can easily be called anywhere.
2371 */
2372 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2373 int configChanges) {
2374 HistoryRecord r = topRunningActivityLocked(null);
2375 if (r != null) {
2376 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2377 }
2378 }
2379
2380 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2381 if (resumed) {
2382 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2383 } else {
2384 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2385 }
2386 }
2387
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002388 private boolean startHomeActivityLocked() {
2389 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2390 && mTopAction == null) {
2391 // We are running in factory test mode, but unable to find
2392 // the factory test app, so just sit around displaying the
2393 // error message and don't try to start anything.
2394 return false;
2395 }
2396 Intent intent = new Intent(
2397 mTopAction,
2398 mTopData != null ? Uri.parse(mTopData) : null);
2399 intent.setComponent(mTopComponent);
2400 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2401 intent.addCategory(Intent.CATEGORY_HOME);
2402 }
2403 ActivityInfo aInfo =
2404 intent.resolveActivityInfo(mContext.getPackageManager(),
2405 STOCK_PM_FLAGS);
2406 if (aInfo != null) {
2407 intent.setComponent(new ComponentName(
2408 aInfo.applicationInfo.packageName, aInfo.name));
2409 // Don't do this if the home app is currently being
2410 // instrumented.
2411 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2412 aInfo.applicationInfo.uid);
2413 if (app == null || app.instrumentationClass == null) {
2414 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2415 startActivityLocked(null, intent, null, null, 0, aInfo,
2416 null, null, 0, 0, 0, false, false);
2417 }
2418 }
2419
2420
2421 return true;
2422 }
2423
2424 /**
2425 * Starts the "new version setup screen" if appropriate.
2426 */
2427 private void startSetupActivityLocked() {
2428 // Only do this once per boot.
2429 if (mCheckedForSetup) {
2430 return;
2431 }
2432
2433 // We will show this screen if the current one is a different
2434 // version than the last one shown, and we are not running in
2435 // low-level factory test mode.
2436 final ContentResolver resolver = mContext.getContentResolver();
2437 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2438 Settings.Secure.getInt(resolver,
2439 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2440 mCheckedForSetup = true;
2441
2442 // See if we should be showing the platform update setup UI.
2443 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2444 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2445 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2446
2447 // We don't allow third party apps to replace this.
2448 ResolveInfo ri = null;
2449 for (int i=0; ris != null && i<ris.size(); i++) {
2450 if ((ris.get(i).activityInfo.applicationInfo.flags
2451 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2452 ri = ris.get(i);
2453 break;
2454 }
2455 }
2456
2457 if (ri != null) {
2458 String vers = ri.activityInfo.metaData != null
2459 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2460 : null;
2461 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2462 vers = ri.activityInfo.applicationInfo.metaData.getString(
2463 Intent.METADATA_SETUP_VERSION);
2464 }
2465 String lastVers = Settings.Secure.getString(
2466 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2467 if (vers != null && !vers.equals(lastVers)) {
2468 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2469 intent.setComponent(new ComponentName(
2470 ri.activityInfo.packageName, ri.activityInfo.name));
2471 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2472 null, null, 0, 0, 0, false, false);
2473 }
2474 }
2475 }
2476 }
2477
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002478 private void reportResumedActivityLocked(HistoryRecord r) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002479 //Log.i(TAG, "**** REPORT RESUME: " + r);
2480
2481 final int identHash = System.identityHashCode(r);
2482 updateUsageStats(r, true);
2483
2484 int i = mWatchers.beginBroadcast();
2485 while (i > 0) {
2486 i--;
2487 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2488 if (w != null) {
2489 try {
2490 w.activityResuming(identHash);
2491 } catch (RemoteException e) {
2492 }
2493 }
2494 }
2495 mWatchers.finishBroadcast();
2496 }
2497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 /**
2499 * Ensure that the top activity in the stack is resumed.
2500 *
2501 * @param prev The previously resumed activity, for when in the process
2502 * of pausing; can be null to call from elsewhere.
2503 *
2504 * @return Returns true if something is being resumed, or false if
2505 * nothing happened.
2506 */
2507 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2508 // Find the first activity that is not finishing.
2509 HistoryRecord next = topRunningActivityLocked(null);
2510
2511 // Remember how we'll process this pause/resume situation, and ensure
2512 // that the state is reset however we wind up proceeding.
2513 final boolean userLeaving = mUserLeaving;
2514 mUserLeaving = false;
2515
2516 if (next == null) {
2517 // There are no more activities! Let's just start up the
2518 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002519 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 }
2521
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002522 next.delayedResume = false;
2523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 // If the top activity is the resumed one, nothing to do.
2525 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2526 // Make sure we have executed any pending transitions, since there
2527 // should be nothing left to do at this point.
2528 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002529 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 return false;
2531 }
2532
2533 // If we are sleeping, and there is no resumed activity, and the top
2534 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002535 if ((mSleeping || mShuttingDown)
2536 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 // Make sure we have executed any pending transitions, since there
2538 // should be nothing left to do at this point.
2539 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002540 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 return false;
2542 }
2543
2544 // The activity may be waiting for stop, but that is no longer
2545 // appropriate for it.
2546 mStoppingActivities.remove(next);
2547 mWaitingVisibleActivities.remove(next);
2548
2549 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2550
2551 // If we are currently pausing an activity, then don't do anything
2552 // until that is done.
2553 if (mPausingActivity != null) {
2554 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2555 return false;
2556 }
2557
2558 // We need to start pausing the current activity so the top one
2559 // can be resumed...
2560 if (mResumedActivity != null) {
2561 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2562 startPausingLocked(userLeaving, false);
2563 return true;
2564 }
2565
2566 if (prev != null && prev != next) {
2567 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2568 prev.waitingVisible = true;
2569 mWaitingVisibleActivities.add(prev);
2570 if (DEBUG_SWITCH) Log.v(
2571 TAG, "Resuming top, waiting visible to hide: " + prev);
2572 } else {
2573 // The next activity is already visible, so hide the previous
2574 // activity's windows right now so we can show the new one ASAP.
2575 // We only do this if the previous is finishing, which should mean
2576 // it is on top of the one being resumed so hiding it quickly
2577 // is good. Otherwise, we want to do the normal route of allowing
2578 // the resumed activity to be shown so we can decide if the
2579 // previous should actually be hidden depending on whether the
2580 // new one is found to be full-screen or not.
2581 if (prev.finishing) {
2582 mWindowManager.setAppVisibility(prev, false);
2583 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2584 + prev + ", waitingVisible="
2585 + (prev != null ? prev.waitingVisible : null)
2586 + ", nowVisible=" + next.nowVisible);
2587 } else {
2588 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2589 + prev + ", waitingVisible="
2590 + (prev != null ? prev.waitingVisible : null)
2591 + ", nowVisible=" + next.nowVisible);
2592 }
2593 }
2594 }
2595
2596 // We are starting up the next activity, so tell the window manager
2597 // that the previous one will be hidden soon. This way it can know
2598 // to ignore it when computing the desired screen orientation.
2599 if (prev != null) {
2600 if (prev.finishing) {
2601 if (DEBUG_TRANSITION) Log.v(TAG,
2602 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002603 if (mNoAnimActivities.contains(prev)) {
2604 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2605 } else {
2606 mWindowManager.prepareAppTransition(prev.task == next.task
2607 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2608 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 mWindowManager.setAppWillBeHidden(prev);
2611 mWindowManager.setAppVisibility(prev, false);
2612 } else {
2613 if (DEBUG_TRANSITION) Log.v(TAG,
2614 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002615 if (mNoAnimActivities.contains(next)) {
2616 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2617 } else {
2618 mWindowManager.prepareAppTransition(prev.task == next.task
2619 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2620 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
2623 if (false) {
2624 mWindowManager.setAppWillBeHidden(prev);
2625 mWindowManager.setAppVisibility(prev, false);
2626 }
2627 } else if (mHistory.size() > 1) {
2628 if (DEBUG_TRANSITION) Log.v(TAG,
2629 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002630 if (mNoAnimActivities.contains(next)) {
2631 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2632 } else {
2633 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 }
2636
2637 if (next.app != null && next.app.thread != null) {
2638 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2639
2640 // This activity is now becoming visible.
2641 mWindowManager.setAppVisibility(next, true);
2642
2643 HistoryRecord lastResumedActivity = mResumedActivity;
2644 ActivityState lastState = next.state;
2645
2646 updateCpuStats();
2647
2648 next.state = ActivityState.RESUMED;
2649 mResumedActivity = next;
2650 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002651 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 updateLRUListLocked(next);
2653
2654 // Have the window manager re-evaluate the orientation of
2655 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002656 boolean updated;
2657 synchronized (this) {
2658 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2659 mConfiguration,
2660 next.mayFreezeScreenLocked(next.app) ? next : null);
2661 if (config != null) {
2662 /*
2663 * Explicitly restore the locale to the one from the
2664 * old configuration, since the one that comes back from
2665 * the window manager has the default (boot) locale.
2666 *
2667 * It looks like previously the locale picker only worked
2668 * by coincidence: usually it would do its setting of
2669 * the locale after the activity transition, so it didn't
2670 * matter that this lost it. With the synchronized
2671 * block now keeping them from happening at the same time,
2672 * this one always would happen second and undo what the
2673 * locale picker had just done.
2674 */
2675 config.locale = mConfiguration.locale;
2676 next.frozenBeforeDestroy = true;
2677 }
2678 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002680 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 // The configuration update wasn't able to keep the existing
2682 // instance of the activity, and instead started a new one.
2683 // We should be all done, but let's just make sure our activity
2684 // is still at the top and schedule another run if something
2685 // weird happened.
2686 HistoryRecord nextNext = topRunningActivityLocked(null);
2687 if (DEBUG_SWITCH) Log.i(TAG,
2688 "Activity config changed during resume: " + next
2689 + ", new next: " + nextNext);
2690 if (nextNext != next) {
2691 // Do over!
2692 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2693 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002694 setFocusedActivityLocked(next);
2695 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002697 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 return true;
2699 }
2700
2701 try {
2702 // Deliver all pending results.
2703 ArrayList a = next.results;
2704 if (a != null) {
2705 final int N = a.size();
2706 if (!next.finishing && N > 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002707 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 TAG, "Delivering results to " + next
2709 + ": " + a);
2710 next.app.thread.scheduleSendResult(next, a);
2711 }
2712 }
2713
2714 if (next.newIntents != null) {
2715 next.app.thread.scheduleNewIntent(next.newIntents, next);
2716 }
2717
Doug Zongker2bec3d42009-12-04 12:52:44 -08002718 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 System.identityHashCode(next),
2720 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721
2722 next.app.thread.scheduleResumeActivity(next,
2723 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 pauseIfSleepingLocked();
2726
2727 } catch (Exception e) {
2728 // Whoops, need to restart this activity!
2729 next.state = lastState;
2730 mResumedActivity = lastResumedActivity;
Dianne Hackborn03abb812010-01-04 18:43:19 -08002731 Log.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 if (!next.hasBeenLaunched) {
2733 next.hasBeenLaunched = true;
2734 } else {
2735 if (SHOW_APP_STARTING_ICON) {
2736 mWindowManager.setAppStartingWindow(
2737 next, next.packageName, next.theme,
2738 next.nonLocalizedLabel,
2739 next.labelRes, next.icon, null, true);
2740 }
2741 }
2742 startSpecificActivityLocked(next, true, false);
2743 return true;
2744 }
2745
2746 // From this point on, if something goes wrong there is no way
2747 // to recover the activity.
2748 try {
2749 next.visible = true;
2750 completeResumeLocked(next);
2751 } catch (Exception e) {
2752 // If any exception gets thrown, toss away this
2753 // activity and try the next one.
2754 Log.w(TAG, "Exception thrown during resume of " + next, e);
2755 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2756 "resume-exception");
2757 return true;
2758 }
2759
2760 // Didn't need to use the icicle, and it is now out of date.
2761 next.icicle = null;
2762 next.haveState = false;
2763 next.stopped = false;
2764
2765 } else {
2766 // Whoops, need to restart this activity!
2767 if (!next.hasBeenLaunched) {
2768 next.hasBeenLaunched = true;
2769 } else {
2770 if (SHOW_APP_STARTING_ICON) {
2771 mWindowManager.setAppStartingWindow(
2772 next, next.packageName, next.theme,
2773 next.nonLocalizedLabel,
2774 next.labelRes, next.icon, null, true);
2775 }
2776 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2777 }
2778 startSpecificActivityLocked(next, true, true);
2779 }
2780
2781 return true;
2782 }
2783
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002784 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2785 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 final int NH = mHistory.size();
2787
2788 int addPos = -1;
2789
2790 if (!newTask) {
2791 // If starting in an existing task, find where that is...
2792 HistoryRecord next = null;
2793 boolean startIt = true;
2794 for (int i = NH-1; i >= 0; i--) {
2795 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2796 if (p.finishing) {
2797 continue;
2798 }
2799 if (p.task == r.task) {
2800 // Here it is! Now, if this is not yet visible to the
2801 // user, then just add it without starting; it will
2802 // get started when the user navigates back to it.
2803 addPos = i+1;
2804 if (!startIt) {
2805 mHistory.add(addPos, r);
2806 r.inHistory = true;
2807 r.task.numActivities++;
2808 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2809 r.info.screenOrientation, r.fullscreen);
2810 if (VALIDATE_TOKENS) {
2811 mWindowManager.validateAppTokens(mHistory);
2812 }
2813 return;
2814 }
2815 break;
2816 }
2817 if (p.fullscreen) {
2818 startIt = false;
2819 }
2820 next = p;
2821 }
2822 }
2823
2824 // Place a new activity at top of stack, so it is next to interact
2825 // with the user.
2826 if (addPos < 0) {
2827 addPos = mHistory.size();
2828 }
2829
2830 // If we are not placing the new activity frontmost, we do not want
2831 // to deliver the onUserLeaving callback to the actual frontmost
2832 // activity
2833 if (addPos < NH) {
2834 mUserLeaving = false;
2835 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2836 }
2837
2838 // Slot the activity into the history stack and proceed
2839 mHistory.add(addPos, r);
2840 r.inHistory = true;
2841 r.frontOfTask = newTask;
2842 r.task.numActivities++;
2843 if (NH > 0) {
2844 // We want to show the starting preview window if we are
2845 // switching to a new task, or the next activity's process is
2846 // not currently running.
2847 boolean showStartingIcon = newTask;
2848 ProcessRecord proc = r.app;
2849 if (proc == null) {
2850 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2851 }
2852 if (proc == null || proc.thread == null) {
2853 showStartingIcon = true;
2854 }
2855 if (DEBUG_TRANSITION) Log.v(TAG,
2856 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002857 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2858 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2859 mNoAnimActivities.add(r);
2860 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2861 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2862 mNoAnimActivities.remove(r);
2863 } else {
2864 mWindowManager.prepareAppTransition(newTask
2865 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2866 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2867 mNoAnimActivities.remove(r);
2868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 mWindowManager.addAppToken(
2870 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2871 boolean doShow = true;
2872 if (newTask) {
2873 // Even though this activity is starting fresh, we still need
2874 // to reset it to make sure we apply affinities to move any
2875 // existing activities from other tasks in to it.
2876 // If the caller has requested that the target task be
2877 // reset, then do so.
2878 if ((r.intent.getFlags()
2879 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2880 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002881 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002882 }
2883 }
2884 if (SHOW_APP_STARTING_ICON && doShow) {
2885 // Figure out if we are transitioning from another activity that is
2886 // "has the same starting icon" as the next one. This allows the
2887 // window manager to keep the previous window it had previously
2888 // created, if it still had one.
2889 HistoryRecord prev = mResumedActivity;
2890 if (prev != null) {
2891 // We don't want to reuse the previous starting preview if:
2892 // (1) The current activity is in a different task.
2893 if (prev.task != r.task) prev = null;
2894 // (2) The current activity is already displayed.
2895 else if (prev.nowVisible) prev = null;
2896 }
2897 mWindowManager.setAppStartingWindow(
2898 r, r.packageName, r.theme, r.nonLocalizedLabel,
2899 r.labelRes, r.icon, prev, showStartingIcon);
2900 }
2901 } else {
2902 // If this is the first activity, don't do any fancy animations,
2903 // because there is nothing for it to animate on top of.
2904 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2905 r.info.screenOrientation, r.fullscreen);
2906 }
2907 if (VALIDATE_TOKENS) {
2908 mWindowManager.validateAppTokens(mHistory);
2909 }
2910
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002911 if (doResume) {
2912 resumeTopActivityLocked(null);
2913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 }
2915
2916 /**
2917 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002918 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2919 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 * an instance of that activity in the stack and, if found, finish all
2921 * activities on top of it and return the instance.
2922 *
2923 * @param newR Description of the new activity being started.
2924 * @return Returns the old activity that should be continue to be used,
2925 * or null if none was found.
2926 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002927 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002928 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002930
2931 // First find the requested task.
2932 while (i > 0) {
2933 i--;
2934 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2935 if (r.task.taskId == taskId) {
2936 i++;
2937 break;
2938 }
2939 }
2940
2941 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 while (i > 0) {
2943 i--;
2944 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2945 if (r.finishing) {
2946 continue;
2947 }
2948 if (r.task.taskId != taskId) {
2949 return null;
2950 }
2951 if (r.realActivity.equals(newR.realActivity)) {
2952 // Here it is! Now finish everything in front...
2953 HistoryRecord ret = r;
2954 if (doClear) {
2955 while (i < (mHistory.size()-1)) {
2956 i++;
2957 r = (HistoryRecord)mHistory.get(i);
2958 if (r.finishing) {
2959 continue;
2960 }
2961 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2962 null, "clear")) {
2963 i--;
2964 }
2965 }
2966 }
2967
2968 // Finally, if this is a normal launch mode (that is, not
2969 // expecting onNewIntent()), then we will finish the current
2970 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002971 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2972 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002974 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 if (index >= 0) {
2976 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2977 null, "clear");
2978 }
2979 return null;
2980 }
2981 }
2982
2983 return ret;
2984 }
2985 }
2986
2987 return null;
2988 }
2989
2990 /**
2991 * Find the activity in the history stack within the given task. Returns
2992 * the index within the history at which it's found, or < 0 if not found.
2993 */
2994 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
2995 int i = mHistory.size();
2996 while (i > 0) {
2997 i--;
2998 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
2999 if (candidate.task.taskId != task) {
3000 break;
3001 }
3002 if (candidate.realActivity.equals(r.realActivity)) {
3003 return i;
3004 }
3005 }
3006
3007 return -1;
3008 }
3009
3010 /**
3011 * Reorder the history stack so that the activity at the given index is
3012 * brought to the front.
3013 */
3014 private final HistoryRecord moveActivityToFrontLocked(int where) {
3015 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3016 int top = mHistory.size();
3017 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3018 mHistory.add(top, newTop);
3019 oldTop.frontOfTask = false;
3020 newTop.frontOfTask = true;
3021 return newTop;
3022 }
3023
3024 /**
3025 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3026 * method will be called at the proper time.
3027 */
3028 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3029 boolean sent = false;
3030 if (r.state == ActivityState.RESUMED
3031 && r.app != null && r.app.thread != null) {
3032 try {
3033 ArrayList<Intent> ar = new ArrayList<Intent>();
3034 ar.add(new Intent(intent));
3035 r.app.thread.scheduleNewIntent(ar, r);
3036 sent = true;
3037 } catch (Exception e) {
3038 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
3039 }
3040 }
3041 if (!sent) {
3042 r.addNewIntentLocked(new Intent(intent));
3043 }
3044 }
3045
3046 private final void logStartActivity(int tag, HistoryRecord r,
3047 TaskRecord task) {
3048 EventLog.writeEvent(tag,
3049 System.identityHashCode(r), task.taskId,
3050 r.shortComponentName, r.intent.getAction(),
3051 r.intent.getType(), r.intent.getDataString(),
3052 r.intent.getFlags());
3053 }
3054
3055 private final int startActivityLocked(IApplicationThread caller,
3056 Intent intent, String resolvedType,
3057 Uri[] grantedUriPermissions,
3058 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3059 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003060 int callingPid, int callingUid, boolean onlyIfNeeded,
3061 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 Log.i(TAG, "Starting activity: " + intent);
3063
3064 HistoryRecord sourceRecord = null;
3065 HistoryRecord resultRecord = null;
3066 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003067 int index = indexOfTokenLocked(resultTo);
The Android Open Source Project10592532009-03-18 17:39:46 -07003068 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3070 if (index >= 0) {
3071 sourceRecord = (HistoryRecord)mHistory.get(index);
3072 if (requestCode >= 0 && !sourceRecord.finishing) {
3073 resultRecord = sourceRecord;
3074 }
3075 }
3076 }
3077
3078 int launchFlags = intent.getFlags();
3079
3080 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3081 && sourceRecord != null) {
3082 // Transfer the result target from the source activity to the new
3083 // one being started, including any failures.
3084 if (requestCode >= 0) {
3085 return START_FORWARD_AND_REQUEST_CONFLICT;
3086 }
3087 resultRecord = sourceRecord.resultTo;
3088 resultWho = sourceRecord.resultWho;
3089 requestCode = sourceRecord.requestCode;
3090 sourceRecord.resultTo = null;
3091 if (resultRecord != null) {
3092 resultRecord.removeResultsLocked(
3093 sourceRecord, resultWho, requestCode);
3094 }
3095 }
3096
3097 int err = START_SUCCESS;
3098
3099 if (intent.getComponent() == null) {
3100 // We couldn't find a class that can handle the given Intent.
3101 // That's the end of that!
3102 err = START_INTENT_NOT_RESOLVED;
3103 }
3104
3105 if (err == START_SUCCESS && aInfo == null) {
3106 // We couldn't find the specific class specified in the Intent.
3107 // Also the end of the line.
3108 err = START_CLASS_NOT_FOUND;
3109 }
3110
3111 ProcessRecord callerApp = null;
3112 if (err == START_SUCCESS && caller != null) {
3113 callerApp = getRecordForAppLocked(caller);
3114 if (callerApp != null) {
3115 callingPid = callerApp.pid;
3116 callingUid = callerApp.info.uid;
3117 } else {
3118 Log.w(TAG, "Unable to find app for caller " + caller
3119 + " (pid=" + callingPid + ") when starting: "
3120 + intent.toString());
3121 err = START_PERMISSION_DENIED;
3122 }
3123 }
3124
3125 if (err != START_SUCCESS) {
3126 if (resultRecord != null) {
3127 sendActivityResultLocked(-1,
3128 resultRecord, resultWho, requestCode,
3129 Activity.RESULT_CANCELED, null);
3130 }
3131 return err;
3132 }
3133
3134 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3135 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3136 if (perm != PackageManager.PERMISSION_GRANTED) {
3137 if (resultRecord != null) {
3138 sendActivityResultLocked(-1,
3139 resultRecord, resultWho, requestCode,
3140 Activity.RESULT_CANCELED, null);
3141 }
3142 String msg = "Permission Denial: starting " + intent.toString()
3143 + " from " + callerApp + " (pid=" + callingPid
3144 + ", uid=" + callingUid + ")"
3145 + " requires " + aInfo.permission;
3146 Log.w(TAG, msg);
3147 throw new SecurityException(msg);
3148 }
3149
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003150 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 boolean abort = false;
3152 try {
3153 // The Intent we give to the watcher has the extra data
3154 // stripped off, since it can contain private information.
3155 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003156 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 aInfo.applicationInfo.packageName);
3158 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003159 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 }
3161
3162 if (abort) {
3163 if (resultRecord != null) {
3164 sendActivityResultLocked(-1,
3165 resultRecord, resultWho, requestCode,
3166 Activity.RESULT_CANCELED, null);
3167 }
3168 // We pretend to the caller that it was really started, but
3169 // they will just get a cancel result.
3170 return START_SUCCESS;
3171 }
3172 }
3173
3174 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3175 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003176 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003178 if (mResumedActivity == null
3179 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3180 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3181 PendingActivityLaunch pal = new PendingActivityLaunch();
3182 pal.r = r;
3183 pal.sourceRecord = sourceRecord;
3184 pal.grantedUriPermissions = grantedUriPermissions;
3185 pal.grantedMode = grantedMode;
3186 pal.onlyIfNeeded = onlyIfNeeded;
3187 mPendingActivityLaunches.add(pal);
3188 return START_SWITCHES_CANCELED;
3189 }
3190 }
3191
3192 if (mDidAppSwitch) {
3193 // This is the second allowed switch since we stopped switches,
3194 // so now just generally allow switches. Use case: user presses
3195 // home (switches disabled, switch to home, mDidAppSwitch now true);
3196 // user taps a home icon (coming from home so allowed, we hit here
3197 // and now allow anyone to switch again).
3198 mAppSwitchesAllowedTime = 0;
3199 } else {
3200 mDidAppSwitch = true;
3201 }
3202
3203 doPendingActivityLaunchesLocked(false);
3204
3205 return startActivityUncheckedLocked(r, sourceRecord,
3206 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3207 }
3208
3209 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3210 final int N = mPendingActivityLaunches.size();
3211 if (N <= 0) {
3212 return;
3213 }
3214 for (int i=0; i<N; i++) {
3215 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3216 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3217 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3218 doResume && i == (N-1));
3219 }
3220 mPendingActivityLaunches.clear();
3221 }
3222
3223 private final int startActivityUncheckedLocked(HistoryRecord r,
3224 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3225 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3226 final Intent intent = r.intent;
3227 final int callingUid = r.launchedFromUid;
3228
3229 int launchFlags = intent.getFlags();
3230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 // We'll invoke onUserLeaving before onPause only if the launching
3232 // activity did not explicitly state that this is an automated launch.
3233 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
3234 if (DEBUG_USER_LEAVING) Log.v(TAG,
3235 "startActivity() => mUserLeaving=" + mUserLeaving);
3236
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003237 // If the caller has asked not to resume at this point, we make note
3238 // of this in the record so that we can skip it when trying to find
3239 // the top running activity.
3240 if (!doResume) {
3241 r.delayedResume = true;
3242 }
3243
3244 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3245 != 0 ? r : null;
3246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 // If the onlyIfNeeded flag is set, then we can do this if the activity
3248 // being launched is the same as the one making the call... or, as
3249 // a special case, if we do not know the caller then we count the
3250 // current top activity as the caller.
3251 if (onlyIfNeeded) {
3252 HistoryRecord checkedCaller = sourceRecord;
3253 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003254 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 }
3256 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3257 // Caller is not the same as launcher, so always needed.
3258 onlyIfNeeded = false;
3259 }
3260 }
3261
3262 if (grantedUriPermissions != null && callingUid > 0) {
3263 for (int i=0; i<grantedUriPermissions.length; i++) {
3264 grantUriPermissionLocked(callingUid, r.packageName,
3265 grantedUriPermissions[i], grantedMode, r);
3266 }
3267 }
3268
3269 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3270 intent, r);
3271
3272 if (sourceRecord == null) {
3273 // This activity is not being started from another... in this
3274 // case we -always- start a new task.
3275 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
3276 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
3277 + intent);
3278 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3279 }
3280 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3281 // The original activity who is starting us is running as a single
3282 // instance... this new activity it is starting must go on its
3283 // own task.
3284 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3285 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3286 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3287 // The activity being started is a single instance... it always
3288 // gets launched into its own task.
3289 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3290 }
3291
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003292 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 // For whatever reason this activity is being launched into a new
3294 // task... yet the caller has requested a result back. Well, that
3295 // is pretty messed up, so instead immediately send back a cancel
3296 // and let the new task continue launched as normal without a
3297 // dependency on its originator.
3298 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3299 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003300 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003301 Activity.RESULT_CANCELED, null);
3302 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 }
3304
3305 boolean addingToTask = false;
3306 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3307 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3308 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3309 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3310 // If bring to front is requested, and no result is requested, and
3311 // we can find a task that was started with this same
3312 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003313 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 // See if there is a task to bring to the front. If this is
3315 // a SINGLE_INSTANCE activity, there can be one and only one
3316 // instance of it in the history, and it is always in its own
3317 // unique task, so we do a special search.
3318 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3319 ? findTaskLocked(intent, r.info)
3320 : findActivityLocked(intent, r.info);
3321 if (taskTop != null) {
3322 if (taskTop.task.intent == null) {
3323 // This task was started because of movement of
3324 // the activity based on affinity... now that we
3325 // are actually launching it, we can assign the
3326 // base intent.
3327 taskTop.task.setIntent(intent, r.info);
3328 }
3329 // If the target task is not in the front, then we need
3330 // to bring it to the front... except... well, with
3331 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3332 // to have the same behavior as if a new instance was
3333 // being started, which means not bringing it to the front
3334 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003335 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 if (curTop.task != taskTop.task) {
3337 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3338 boolean callerAtFront = sourceRecord == null
3339 || curTop.task == sourceRecord.task;
3340 if (callerAtFront) {
3341 // We really do want to push this one into the
3342 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003343 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 }
3345 }
3346 // If the caller has requested that the target task be
3347 // reset, then do so.
3348 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3349 taskTop = resetTaskIfNeededLocked(taskTop, r);
3350 }
3351 if (onlyIfNeeded) {
3352 // We don't need to start a new activity, and
3353 // the client said not to do anything if that
3354 // is the case, so this is it! And for paranoia, make
3355 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003356 if (doResume) {
3357 resumeTopActivityLocked(null);
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 return START_RETURN_INTENT_TO_CALLER;
3360 }
3361 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3362 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3363 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3364 // In this situation we want to remove all activities
3365 // from the task up to the one being started. In most
3366 // cases this means we are resetting the task to its
3367 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003368 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003369 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 if (top != null) {
3371 if (top.frontOfTask) {
3372 // Activity aliases may mean we use different
3373 // intents for the top activity, so make sure
3374 // the task now has the identity of the new
3375 // intent.
3376 top.task.setIntent(r.intent, r.info);
3377 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003378 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 deliverNewIntentLocked(top, r.intent);
3380 } else {
3381 // A special case: we need to
3382 // start the activity because it is not currently
3383 // running, and the caller has asked to clear the
3384 // current task to have this activity at the top.
3385 addingToTask = true;
3386 // Now pretend like this activity is being started
3387 // by the top of its task, so it is put in the
3388 // right place.
3389 sourceRecord = taskTop;
3390 }
3391 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3392 // In this case the top activity on the task is the
3393 // same as the one being launched, so we take that
3394 // as a request to bring the task to the foreground.
3395 // If the top activity in the task is the root
3396 // activity, deliver this new intent to it if it
3397 // desires.
3398 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3399 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003400 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 if (taskTop.frontOfTask) {
3402 taskTop.task.setIntent(r.intent, r.info);
3403 }
3404 deliverNewIntentLocked(taskTop, r.intent);
3405 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3406 // In this case we are launching the root activity
3407 // of the task, but with a different intent. We
3408 // should start a new instance on top.
3409 addingToTask = true;
3410 sourceRecord = taskTop;
3411 }
3412 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3413 // In this case an activity is being launched in to an
3414 // existing task, without resetting that task. This
3415 // is typically the situation of launching an activity
3416 // from a notification or shortcut. We want to place
3417 // the new activity on top of the current task.
3418 addingToTask = true;
3419 sourceRecord = taskTop;
3420 } else if (!taskTop.task.rootWasReset) {
3421 // In this case we are launching in to an existing task
3422 // that has not yet been started from its front door.
3423 // The current task has been brought to the front.
3424 // Ideally, we'd probably like to place this new task
3425 // at the bottom of its stack, but that's a little hard
3426 // to do with the current organization of the code so
3427 // for now we'll just drop it.
3428 taskTop.task.setIntent(r.intent, r.info);
3429 }
3430 if (!addingToTask) {
3431 // We didn't do anything... but it was needed (a.k.a., client
3432 // don't use that intent!) And for paranoia, make
3433 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003434 if (doResume) {
3435 resumeTopActivityLocked(null);
3436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 return START_TASK_TO_FRONT;
3438 }
3439 }
3440 }
3441 }
3442
3443 //String uri = r.intent.toURI();
3444 //Intent intent2 = new Intent(uri);
3445 //Log.i(TAG, "Given intent: " + r.intent);
3446 //Log.i(TAG, "URI is: " + uri);
3447 //Log.i(TAG, "To intent: " + intent2);
3448
3449 if (r.packageName != null) {
3450 // If the activity being launched is the same as the one currently
3451 // at the top, then we need to check if it should only be launched
3452 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003453 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3454 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 if (top.realActivity.equals(r.realActivity)) {
3456 if (top.app != null && top.app.thread != null) {
3457 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3458 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3459 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003460 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 // For paranoia, make sure we have correctly
3462 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003463 if (doResume) {
3464 resumeTopActivityLocked(null);
3465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 if (onlyIfNeeded) {
3467 // We don't need to start a new activity, and
3468 // the client said not to do anything if that
3469 // is the case, so this is it!
3470 return START_RETURN_INTENT_TO_CALLER;
3471 }
3472 deliverNewIntentLocked(top, r.intent);
3473 return START_DELIVERED_TO_TOP;
3474 }
3475 }
3476 }
3477 }
3478
3479 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003480 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003482 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 Activity.RESULT_CANCELED, null);
3484 }
3485 return START_CLASS_NOT_FOUND;
3486 }
3487
3488 boolean newTask = false;
3489
3490 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003491 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3493 // todo: should do better management of integers.
3494 mCurTask++;
3495 if (mCurTask <= 0) {
3496 mCurTask = 1;
3497 }
3498 r.task = new TaskRecord(mCurTask, r.info, intent,
3499 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3500 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3501 + " in new task " + r.task);
3502 newTask = true;
3503 addRecentTask(r.task);
3504
3505 } else if (sourceRecord != null) {
3506 if (!addingToTask &&
3507 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3508 // In this case, we are adding the activity to an existing
3509 // task, but the caller has asked to clear that task if the
3510 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003511 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003512 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003514 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 deliverNewIntentLocked(top, r.intent);
3516 // For paranoia, make sure we have correctly
3517 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003518 if (doResume) {
3519 resumeTopActivityLocked(null);
3520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 return START_DELIVERED_TO_TOP;
3522 }
3523 } else if (!addingToTask &&
3524 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3525 // In this case, we are launching an activity in our own task
3526 // that may already be running somewhere in the history, and
3527 // we want to shuffle it to the front of the stack if so.
3528 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3529 if (where >= 0) {
3530 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003531 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003533 if (doResume) {
3534 resumeTopActivityLocked(null);
3535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 return START_DELIVERED_TO_TOP;
3537 }
3538 }
3539 // An existing activity is starting this new activity, so we want
3540 // to keep the new one in the same task as the one that is starting
3541 // it.
3542 r.task = sourceRecord.task;
3543 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3544 + " in existing task " + r.task);
3545
3546 } else {
3547 // This not being started from an existing activity, and not part
3548 // of a new task... just put it in the top task, though these days
3549 // this case should never happen.
3550 final int N = mHistory.size();
3551 HistoryRecord prev =
3552 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3553 r.task = prev != null
3554 ? prev.task
3555 : new TaskRecord(mCurTask, r.info, intent,
3556 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3557 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3558 + " in new guessed " + r.task);
3559 }
3560 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003561 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003563 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003564 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 return START_SUCCESS;
3566 }
3567
3568 public final int startActivity(IApplicationThread caller,
3569 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3570 int grantedMode, IBinder resultTo,
3571 String resultWho, int requestCode, boolean onlyIfNeeded,
3572 boolean debug) {
3573 // Refuse possible leaked file descriptors
3574 if (intent != null && intent.hasFileDescriptors()) {
3575 throw new IllegalArgumentException("File descriptors passed in Intent");
3576 }
3577
The Android Open Source Project4df24232009-03-05 14:34:35 -08003578 final boolean componentSpecified = intent.getComponent() != null;
3579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 // Don't modify the client's object!
3581 intent = new Intent(intent);
3582
3583 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 ActivityInfo aInfo;
3585 try {
3586 ResolveInfo rInfo =
3587 ActivityThread.getPackageManager().resolveIntent(
3588 intent, resolvedType,
3589 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003590 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 aInfo = rInfo != null ? rInfo.activityInfo : null;
3592 } catch (RemoteException e) {
3593 aInfo = null;
3594 }
3595
3596 if (aInfo != null) {
3597 // Store the found target back into the intent, because now that
3598 // we have it we never want to do this again. For example, if the
3599 // user navigates back to this point in the history, we should
3600 // always restart the exact same activity.
3601 intent.setComponent(new ComponentName(
3602 aInfo.applicationInfo.packageName, aInfo.name));
3603
3604 // Don't debug things in the system process
3605 if (debug) {
3606 if (!aInfo.processName.equals("system")) {
3607 setDebugApp(aInfo.processName, true, false);
3608 }
3609 }
3610 }
3611
3612 synchronized(this) {
3613 final long origId = Binder.clearCallingIdentity();
3614 int res = startActivityLocked(caller, intent, resolvedType,
3615 grantedUriPermissions, grantedMode, aInfo,
3616 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003617 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 Binder.restoreCallingIdentity(origId);
3619 return res;
3620 }
3621 }
3622
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003623 public int startActivityIntentSender(IApplicationThread caller,
3624 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003625 IBinder resultTo, String resultWho, int requestCode,
3626 int flagsMask, int flagsValues) {
3627 // Refuse possible leaked file descriptors
3628 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3629 throw new IllegalArgumentException("File descriptors passed in Intent");
3630 }
3631
3632 IIntentSender sender = intent.getTarget();
3633 if (!(sender instanceof PendingIntentRecord)) {
3634 throw new IllegalArgumentException("Bad PendingIntent object");
3635 }
3636
3637 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003638
3639 synchronized (this) {
3640 // If this is coming from the currently resumed activity, it is
3641 // effectively saying that app switches are allowed at this point.
3642 if (mResumedActivity != null
3643 && mResumedActivity.info.applicationInfo.uid ==
3644 Binder.getCallingUid()) {
3645 mAppSwitchesAllowedTime = 0;
3646 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003647 }
3648
3649 return pir.sendInner(0, fillInIntent, resolvedType,
3650 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3651 }
3652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 public boolean startNextMatchingActivity(IBinder callingActivity,
3654 Intent intent) {
3655 // Refuse possible leaked file descriptors
3656 if (intent != null && intent.hasFileDescriptors() == true) {
3657 throw new IllegalArgumentException("File descriptors passed in Intent");
3658 }
3659
3660 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003661 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 if (index < 0) {
3663 return false;
3664 }
3665 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3666 if (r.app == null || r.app.thread == null) {
3667 // The caller is not running... d'oh!
3668 return false;
3669 }
3670 intent = new Intent(intent);
3671 // The caller is not allowed to change the data.
3672 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3673 // And we are resetting to find the next component...
3674 intent.setComponent(null);
3675
3676 ActivityInfo aInfo = null;
3677 try {
3678 List<ResolveInfo> resolves =
3679 ActivityThread.getPackageManager().queryIntentActivities(
3680 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003681 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682
3683 // Look for the original activity in the list...
3684 final int N = resolves != null ? resolves.size() : 0;
3685 for (int i=0; i<N; i++) {
3686 ResolveInfo rInfo = resolves.get(i);
3687 if (rInfo.activityInfo.packageName.equals(r.packageName)
3688 && rInfo.activityInfo.name.equals(r.info.name)) {
3689 // We found the current one... the next matching is
3690 // after it.
3691 i++;
3692 if (i<N) {
3693 aInfo = resolves.get(i).activityInfo;
3694 }
3695 break;
3696 }
3697 }
3698 } catch (RemoteException e) {
3699 }
3700
3701 if (aInfo == null) {
3702 // Nobody who is next!
3703 return false;
3704 }
3705
3706 intent.setComponent(new ComponentName(
3707 aInfo.applicationInfo.packageName, aInfo.name));
3708 intent.setFlags(intent.getFlags()&~(
3709 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3710 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3711 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3712 Intent.FLAG_ACTIVITY_NEW_TASK));
3713
3714 // Okay now we need to start the new activity, replacing the
3715 // currently running activity. This is a little tricky because
3716 // we want to start the new one as if the current one is finished,
3717 // but not finish the current one first so that there is no flicker.
3718 // And thus...
3719 final boolean wasFinishing = r.finishing;
3720 r.finishing = true;
3721
3722 // Propagate reply information over to the new activity.
3723 final HistoryRecord resultTo = r.resultTo;
3724 final String resultWho = r.resultWho;
3725 final int requestCode = r.requestCode;
3726 r.resultTo = null;
3727 if (resultTo != null) {
3728 resultTo.removeResultsLocked(r, resultWho, requestCode);
3729 }
3730
3731 final long origId = Binder.clearCallingIdentity();
3732 // XXX we are not dealing with propagating grantedUriPermissions...
3733 // those are not yet exposed to user code, so there is no need.
3734 int res = startActivityLocked(r.app.thread, intent,
3735 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003736 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 Binder.restoreCallingIdentity(origId);
3738
3739 r.finishing = wasFinishing;
3740 if (res != START_SUCCESS) {
3741 return false;
3742 }
3743 return true;
3744 }
3745 }
3746
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003747 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003748 Intent intent, String resolvedType, IBinder resultTo,
3749 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003750
3751 // This is so super not safe, that only the system (or okay root)
3752 // can do it.
3753 final int callingUid = Binder.getCallingUid();
3754 if (callingUid != 0 && callingUid != Process.myUid()) {
3755 throw new SecurityException(
3756 "startActivityInPackage only available to the system");
3757 }
3758
The Android Open Source Project4df24232009-03-05 14:34:35 -08003759 final boolean componentSpecified = intent.getComponent() != null;
3760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 // Don't modify the client's object!
3762 intent = new Intent(intent);
3763
3764 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 ActivityInfo aInfo;
3766 try {
3767 ResolveInfo rInfo =
3768 ActivityThread.getPackageManager().resolveIntent(
3769 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003770 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 aInfo = rInfo != null ? rInfo.activityInfo : null;
3772 } catch (RemoteException e) {
3773 aInfo = null;
3774 }
3775
3776 if (aInfo != null) {
3777 // Store the found target back into the intent, because now that
3778 // we have it we never want to do this again. For example, if the
3779 // user navigates back to this point in the history, we should
3780 // always restart the exact same activity.
3781 intent.setComponent(new ComponentName(
3782 aInfo.applicationInfo.packageName, aInfo.name));
3783 }
3784
3785 synchronized(this) {
3786 return startActivityLocked(null, intent, resolvedType,
3787 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003788 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 }
3790 }
3791
3792 private final void addRecentTask(TaskRecord task) {
3793 // Remove any existing entries that are the same kind of task.
3794 int N = mRecentTasks.size();
3795 for (int i=0; i<N; i++) {
3796 TaskRecord tr = mRecentTasks.get(i);
3797 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3798 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3799 mRecentTasks.remove(i);
3800 i--;
3801 N--;
3802 if (task.intent == null) {
3803 // If the new recent task we are adding is not fully
3804 // specified, then replace it with the existing recent task.
3805 task = tr;
3806 }
3807 }
3808 }
3809 if (N >= MAX_RECENT_TASKS) {
3810 mRecentTasks.remove(N-1);
3811 }
3812 mRecentTasks.add(0, task);
3813 }
3814
3815 public void setRequestedOrientation(IBinder token,
3816 int requestedOrientation) {
3817 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003818 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 if (index < 0) {
3820 return;
3821 }
3822 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3823 final long origId = Binder.clearCallingIdentity();
3824 mWindowManager.setAppOrientation(r, requestedOrientation);
3825 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003826 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 r.mayFreezeScreenLocked(r.app) ? r : null);
3828 if (config != null) {
3829 r.frozenBeforeDestroy = true;
3830 if (!updateConfigurationLocked(config, r)) {
3831 resumeTopActivityLocked(null);
3832 }
3833 }
3834 Binder.restoreCallingIdentity(origId);
3835 }
3836 }
3837
3838 public int getRequestedOrientation(IBinder token) {
3839 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003840 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 if (index < 0) {
3842 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3843 }
3844 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3845 return mWindowManager.getAppOrientation(r);
3846 }
3847 }
3848
3849 private final void stopActivityLocked(HistoryRecord r) {
3850 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3851 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3852 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3853 if (!r.finishing) {
3854 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3855 "no-history");
3856 }
3857 } else if (r.app != null && r.app.thread != null) {
3858 if (mFocusedActivity == r) {
3859 setFocusedActivityLocked(topRunningActivityLocked(null));
3860 }
3861 r.resumeKeyDispatchingLocked();
3862 try {
3863 r.stopped = false;
3864 r.state = ActivityState.STOPPING;
3865 if (DEBUG_VISBILITY) Log.v(
3866 TAG, "Stopping visible=" + r.visible + " for " + r);
3867 if (!r.visible) {
3868 mWindowManager.setAppVisibility(r, false);
3869 }
3870 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3871 } catch (Exception e) {
3872 // Maybe just ignore exceptions here... if the process
3873 // has crashed, our death notification will clean things
3874 // up.
3875 Log.w(TAG, "Exception thrown during pause", e);
3876 // Just in case, assume it to be stopped.
3877 r.stopped = true;
3878 r.state = ActivityState.STOPPED;
3879 if (r.configDestroy) {
3880 destroyActivityLocked(r, true);
3881 }
3882 }
3883 }
3884 }
3885
3886 /**
3887 * @return Returns true if the activity is being finished, false if for
3888 * some reason it is being left as-is.
3889 */
3890 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3891 Intent resultData, String reason) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003892 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 TAG, "Finishing activity: token=" + token
3894 + ", result=" + resultCode + ", data=" + resultData);
3895
Dianne Hackborn75b03852009-06-12 15:43:26 -07003896 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 if (index < 0) {
3898 return false;
3899 }
3900 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3901
3902 // Is this the last activity left?
3903 boolean lastActivity = true;
3904 for (int i=mHistory.size()-1; i>=0; i--) {
3905 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3906 if (!p.finishing && p != r) {
3907 lastActivity = false;
3908 break;
3909 }
3910 }
3911
3912 // If this is the last activity, but it is the home activity, then
3913 // just don't finish it.
3914 if (lastActivity) {
3915 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3916 return false;
3917 }
3918 }
3919
3920 finishActivityLocked(r, index, resultCode, resultData, reason);
3921 return true;
3922 }
3923
3924 /**
3925 * @return Returns true if this activity has been removed from the history
3926 * list, or false if it is still in the list and will be removed later.
3927 */
3928 private final boolean finishActivityLocked(HistoryRecord r, int index,
3929 int resultCode, Intent resultData, String reason) {
3930 if (r.finishing) {
3931 Log.w(TAG, "Duplicate finish request for " + r);
3932 return false;
3933 }
3934
3935 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08003936 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 System.identityHashCode(r),
3938 r.task.taskId, r.shortComponentName, reason);
3939 r.task.numActivities--;
3940 if (r.frontOfTask && index < (mHistory.size()-1)) {
3941 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3942 if (next.task == r.task) {
3943 next.frontOfTask = true;
3944 }
3945 }
3946
3947 r.pauseKeyDispatchingLocked();
3948 if (mFocusedActivity == r) {
3949 setFocusedActivityLocked(topRunningActivityLocked(null));
3950 }
3951
3952 // send the result
3953 HistoryRecord resultTo = r.resultTo;
3954 if (resultTo != null) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003955 if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
3956 + " who=" + r.resultWho + " req=" + r.requestCode
3957 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 if (r.info.applicationInfo.uid > 0) {
3959 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3960 r.packageName, resultData, r);
3961 }
3962 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3963 resultData);
3964 r.resultTo = null;
3965 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003966 else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967
3968 // Make sure this HistoryRecord is not holding on to other resources,
3969 // because clients have remote IPC references to this object so we
3970 // can't assume that will go away and want to avoid circular IPC refs.
3971 r.results = null;
3972 r.pendingResults = null;
3973 r.newIntents = null;
3974 r.icicle = null;
3975
3976 if (mPendingThumbnails.size() > 0) {
3977 // There are clients waiting to receive thumbnails so, in case
3978 // this is an activity that someone is waiting for, add it
3979 // to the pending list so we can correctly update the clients.
3980 mCancelledThumbnails.add(r);
3981 }
3982
3983 if (mResumedActivity == r) {
3984 boolean endTask = index <= 0
3985 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3986 if (DEBUG_TRANSITION) Log.v(TAG,
3987 "Prepare close transition: finishing " + r);
3988 mWindowManager.prepareAppTransition(endTask
3989 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3990 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
3991
3992 // Tell window manager to prepare for this one to be removed.
3993 mWindowManager.setAppVisibility(r, false);
3994
3995 if (mPausingActivity == null) {
3996 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
3997 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
3998 startPausingLocked(false, false);
3999 }
4000
4001 } else if (r.state != ActivityState.PAUSING) {
4002 // If the activity is PAUSING, we will complete the finish once
4003 // it is done pausing; else we can just directly finish it here.
4004 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
4005 return finishCurrentActivityLocked(r, index,
4006 FINISH_AFTER_PAUSE) == null;
4007 } else {
4008 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
4009 }
4010
4011 return false;
4012 }
4013
4014 private static final int FINISH_IMMEDIATELY = 0;
4015 private static final int FINISH_AFTER_PAUSE = 1;
4016 private static final int FINISH_AFTER_VISIBLE = 2;
4017
4018 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4019 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004020 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 if (index < 0) {
4022 return null;
4023 }
4024
4025 return finishCurrentActivityLocked(r, index, mode);
4026 }
4027
4028 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4029 int index, int mode) {
4030 // First things first: if this activity is currently visible,
4031 // and the resumed activity is not yet visible, then hold off on
4032 // finishing until the resumed one becomes visible.
4033 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4034 if (!mStoppingActivities.contains(r)) {
4035 mStoppingActivities.add(r);
4036 if (mStoppingActivities.size() > 3) {
4037 // If we already have a few activities waiting to stop,
4038 // then give up on things going idle and start clearing
4039 // them out.
4040 Message msg = Message.obtain();
4041 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4042 mHandler.sendMessage(msg);
4043 }
4044 }
4045 r.state = ActivityState.STOPPING;
4046 updateOomAdjLocked();
4047 return r;
4048 }
4049
4050 // make sure the record is cleaned out of other places.
4051 mStoppingActivities.remove(r);
4052 mWaitingVisibleActivities.remove(r);
4053 if (mResumedActivity == r) {
4054 mResumedActivity = null;
4055 }
4056 final ActivityState prevState = r.state;
4057 r.state = ActivityState.FINISHING;
4058
4059 if (mode == FINISH_IMMEDIATELY
4060 || prevState == ActivityState.STOPPED
4061 || prevState == ActivityState.INITIALIZING) {
4062 // If this activity is already stopped, we can just finish
4063 // it right now.
4064 return destroyActivityLocked(r, true) ? null : r;
4065 } else {
4066 // Need to go through the full pause cycle to get this
4067 // activity into the stopped state and then finish it.
4068 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
4069 mFinishingActivities.add(r);
4070 resumeTopActivityLocked(null);
4071 }
4072 return r;
4073 }
4074
4075 /**
4076 * This is the internal entry point for handling Activity.finish().
4077 *
4078 * @param token The Binder token referencing the Activity we want to finish.
4079 * @param resultCode Result code, if any, from this Activity.
4080 * @param resultData Result data (Intent), if any, from this Activity.
4081 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004082 * @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 -08004083 */
4084 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4085 // Refuse possible leaked file descriptors
4086 if (resultData != null && resultData.hasFileDescriptors() == true) {
4087 throw new IllegalArgumentException("File descriptors passed in Intent");
4088 }
4089
4090 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004091 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 // Find the first activity that is not finishing.
4093 HistoryRecord next = topRunningActivityLocked(token, 0);
4094 if (next != null) {
4095 // ask watcher if this is allowed
4096 boolean resumeOK = true;
4097 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004098 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004100 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 }
4102
4103 if (!resumeOK) {
4104 return false;
4105 }
4106 }
4107 }
4108 final long origId = Binder.clearCallingIdentity();
4109 boolean res = requestFinishActivityLocked(token, resultCode,
4110 resultData, "app-request");
4111 Binder.restoreCallingIdentity(origId);
4112 return res;
4113 }
4114 }
4115
4116 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4117 String resultWho, int requestCode, int resultCode, Intent data) {
4118
4119 if (callingUid > 0) {
4120 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4121 data, r);
4122 }
4123
The Android Open Source Project10592532009-03-18 17:39:46 -07004124 if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
4125 + " : who=" + resultWho + " req=" + requestCode
4126 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4128 try {
4129 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4130 list.add(new ResultInfo(resultWho, requestCode,
4131 resultCode, data));
4132 r.app.thread.scheduleSendResult(r, list);
4133 return;
4134 } catch (Exception e) {
4135 Log.w(TAG, "Exception thrown sending result to " + r, e);
4136 }
4137 }
4138
4139 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4140 }
4141
4142 public final void finishSubActivity(IBinder token, String resultWho,
4143 int requestCode) {
4144 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004145 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 if (index < 0) {
4147 return;
4148 }
4149 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4150
4151 final long origId = Binder.clearCallingIdentity();
4152
4153 int i;
4154 for (i=mHistory.size()-1; i>=0; i--) {
4155 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4156 if (r.resultTo == self && r.requestCode == requestCode) {
4157 if ((r.resultWho == null && resultWho == null) ||
4158 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4159 finishActivityLocked(r, i,
4160 Activity.RESULT_CANCELED, null, "request-sub");
4161 }
4162 }
4163 }
4164
4165 Binder.restoreCallingIdentity(origId);
4166 }
4167 }
4168
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004169 public void overridePendingTransition(IBinder token, String packageName,
4170 int enterAnim, int exitAnim) {
4171 synchronized(this) {
4172 int index = indexOfTokenLocked(token);
4173 if (index < 0) {
4174 return;
4175 }
4176 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4177
4178 final long origId = Binder.clearCallingIdentity();
4179
4180 if (self.state == ActivityState.RESUMED
4181 || self.state == ActivityState.PAUSING) {
4182 mWindowManager.overridePendingAppTransition(packageName,
4183 enterAnim, exitAnim);
4184 }
4185
4186 Binder.restoreCallingIdentity(origId);
4187 }
4188 }
4189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 /**
4191 * Perform clean-up of service connections in an activity record.
4192 */
4193 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4194 // Throw away any services that have been bound by this activity.
4195 if (r.connections != null) {
4196 Iterator<ConnectionRecord> it = r.connections.iterator();
4197 while (it.hasNext()) {
4198 ConnectionRecord c = it.next();
4199 removeConnectionLocked(c, null, r);
4200 }
4201 r.connections = null;
4202 }
4203 }
4204
4205 /**
4206 * Perform the common clean-up of an activity record. This is called both
4207 * as part of destroyActivityLocked() (when destroying the client-side
4208 * representation) and cleaning things up as a result of its hosting
4209 * processing going away, in which case there is no remaining client-side
4210 * state to destroy so only the cleanup here is needed.
4211 */
4212 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4213 if (mResumedActivity == r) {
4214 mResumedActivity = null;
4215 }
4216 if (mFocusedActivity == r) {
4217 mFocusedActivity = null;
4218 }
4219
4220 r.configDestroy = false;
4221 r.frozenBeforeDestroy = false;
4222
4223 // Make sure this record is no longer in the pending finishes list.
4224 // This could happen, for example, if we are trimming activities
4225 // down to the max limit while they are still waiting to finish.
4226 mFinishingActivities.remove(r);
4227 mWaitingVisibleActivities.remove(r);
4228
4229 // Remove any pending results.
4230 if (r.finishing && r.pendingResults != null) {
4231 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4232 PendingIntentRecord rec = apr.get();
4233 if (rec != null) {
4234 cancelIntentSenderLocked(rec, false);
4235 }
4236 }
4237 r.pendingResults = null;
4238 }
4239
4240 if (cleanServices) {
4241 cleanUpActivityServicesLocked(r);
4242 }
4243
4244 if (mPendingThumbnails.size() > 0) {
4245 // There are clients waiting to receive thumbnails so, in case
4246 // this is an activity that someone is waiting for, add it
4247 // to the pending list so we can correctly update the clients.
4248 mCancelledThumbnails.add(r);
4249 }
4250
4251 // Get rid of any pending idle timeouts.
4252 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4253 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4254 }
4255
4256 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4257 if (r.state != ActivityState.DESTROYED) {
4258 mHistory.remove(r);
4259 r.inHistory = false;
4260 r.state = ActivityState.DESTROYED;
4261 mWindowManager.removeAppToken(r);
4262 if (VALIDATE_TOKENS) {
4263 mWindowManager.validateAppTokens(mHistory);
4264 }
4265 cleanUpActivityServicesLocked(r);
4266 removeActivityUriPermissionsLocked(r);
4267 }
4268 }
4269
4270 /**
4271 * Destroy the current CLIENT SIDE instance of an activity. This may be
4272 * called both when actually finishing an activity, or when performing
4273 * a configuration switch where we destroy the current client-side object
4274 * but then create a new client-side object for this same HistoryRecord.
4275 */
4276 private final boolean destroyActivityLocked(HistoryRecord r,
4277 boolean removeFromApp) {
4278 if (DEBUG_SWITCH) Log.v(
4279 TAG, "Removing activity: token=" + r
4280 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004281 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 System.identityHashCode(r),
4283 r.task.taskId, r.shortComponentName);
4284
4285 boolean removedFromHistory = false;
4286
4287 cleanUpActivityLocked(r, false);
4288
Dianne Hackborn03abb812010-01-04 18:43:19 -08004289 final boolean hadApp = r.app != null;
4290
4291 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 if (removeFromApp) {
4293 int idx = r.app.activities.indexOf(r);
4294 if (idx >= 0) {
4295 r.app.activities.remove(idx);
4296 }
4297 if (r.persistent) {
4298 decPersistentCountLocked(r.app);
4299 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004300 if (r.app.activities.size() == 0) {
4301 // No longer have activities, so update location in
4302 // LRU list.
4303 updateLruProcessLocked(r.app, true, false);
4304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004305 }
4306
4307 boolean skipDestroy = false;
4308
4309 try {
4310 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
4311 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4312 r.configChangeFlags);
4313 } catch (Exception e) {
4314 // We can just ignore exceptions here... if the process
4315 // has crashed, our death notification will clean things
4316 // up.
4317 //Log.w(TAG, "Exception thrown during finish", e);
4318 if (r.finishing) {
4319 removeActivityFromHistoryLocked(r);
4320 removedFromHistory = true;
4321 skipDestroy = true;
4322 }
4323 }
4324
4325 r.app = null;
4326 r.nowVisible = false;
4327
4328 if (r.finishing && !skipDestroy) {
4329 r.state = ActivityState.DESTROYING;
4330 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4331 msg.obj = r;
4332 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4333 } else {
4334 r.state = ActivityState.DESTROYED;
4335 }
4336 } else {
4337 // remove this record from the history.
4338 if (r.finishing) {
4339 removeActivityFromHistoryLocked(r);
4340 removedFromHistory = true;
4341 } else {
4342 r.state = ActivityState.DESTROYED;
4343 }
4344 }
4345
4346 r.configChangeFlags = 0;
4347
Dianne Hackborn03abb812010-01-04 18:43:19 -08004348 if (!mLRUActivities.remove(r) && hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4350 }
4351
4352 return removedFromHistory;
4353 }
4354
Dianne Hackborn03abb812010-01-04 18:43:19 -08004355 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 int i = list.size();
4357 if (localLOGV) Log.v(
4358 TAG, "Removing app " + app + " from list " + list
4359 + " with " + i + " entries");
4360 while (i > 0) {
4361 i--;
4362 HistoryRecord r = (HistoryRecord)list.get(i);
4363 if (localLOGV) Log.v(
4364 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4365 if (r.app == app) {
4366 if (localLOGV) Log.v(TAG, "Removing this entry!");
4367 list.remove(i);
4368 }
4369 }
4370 }
4371
4372 /**
4373 * Main function for removing an existing process from the activity manager
4374 * as a result of that process going away. Clears out all connections
4375 * to the process.
4376 */
4377 private final void handleAppDiedLocked(ProcessRecord app,
4378 boolean restarting) {
4379 cleanUpApplicationRecordLocked(app, restarting, -1);
4380 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004381 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 }
4383
4384 // Just in case...
4385 if (mPausingActivity != null && mPausingActivity.app == app) {
4386 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
4387 mPausingActivity = null;
4388 }
4389 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4390 mLastPausedActivity = null;
4391 }
4392
4393 // Remove this application's activities from active lists.
4394 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4395 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4396 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4397 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4398
4399 boolean atTop = true;
4400 boolean hasVisibleActivities = false;
4401
4402 // Clean out the history list.
4403 int i = mHistory.size();
4404 if (localLOGV) Log.v(
4405 TAG, "Removing app " + app + " from history with " + i + " entries");
4406 while (i > 0) {
4407 i--;
4408 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4409 if (localLOGV) Log.v(
4410 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4411 if (r.app == app) {
4412 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4413 if (localLOGV) Log.v(
4414 TAG, "Removing this entry! frozen=" + r.haveState
4415 + " finishing=" + r.finishing);
4416 mHistory.remove(i);
4417
4418 r.inHistory = false;
4419 mWindowManager.removeAppToken(r);
4420 if (VALIDATE_TOKENS) {
4421 mWindowManager.validateAppTokens(mHistory);
4422 }
4423 removeActivityUriPermissionsLocked(r);
4424
4425 } else {
4426 // We have the current state for this activity, so
4427 // it can be restarted later when needed.
4428 if (localLOGV) Log.v(
4429 TAG, "Keeping entry, setting app to null");
4430 if (r.visible) {
4431 hasVisibleActivities = true;
4432 }
4433 r.app = null;
4434 r.nowVisible = false;
4435 if (!r.haveState) {
4436 r.icicle = null;
4437 }
4438 }
4439
4440 cleanUpActivityLocked(r, true);
4441 r.state = ActivityState.STOPPED;
4442 }
4443 atTop = false;
4444 }
4445
4446 app.activities.clear();
4447
4448 if (app.instrumentationClass != null) {
4449 Log.w(TAG, "Crash of app " + app.processName
4450 + " running instrumentation " + app.instrumentationClass);
4451 Bundle info = new Bundle();
4452 info.putString("shortMsg", "Process crashed.");
4453 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4454 }
4455
4456 if (!restarting) {
4457 if (!resumeTopActivityLocked(null)) {
4458 // If there was nothing to resume, and we are not already
4459 // restarting this process, but there is a visible activity that
4460 // is hosted by the process... then make sure all visible
4461 // activities are running, taking care of restarting this
4462 // process.
4463 if (hasVisibleActivities) {
4464 ensureActivitiesVisibleLocked(null, 0);
4465 }
4466 }
4467 }
4468 }
4469
4470 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4471 IBinder threadBinder = thread.asBinder();
4472
4473 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004474 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4475 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4477 return i;
4478 }
4479 }
4480 return -1;
4481 }
4482
4483 private final ProcessRecord getRecordForAppLocked(
4484 IApplicationThread thread) {
4485 if (thread == null) {
4486 return null;
4487 }
4488
4489 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004490 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 }
4492
4493 private final void appDiedLocked(ProcessRecord app, int pid,
4494 IApplicationThread thread) {
4495
4496 mProcDeaths[0]++;
4497
4498 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4499 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4500 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004501 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 if (localLOGV) Log.v(
4503 TAG, "Dying app: " + app + ", pid: " + pid
4504 + ", thread: " + thread.asBinder());
4505 boolean doLowMem = app.instrumentationClass == null;
4506 handleAppDiedLocked(app, false);
4507
4508 if (doLowMem) {
4509 // If there are no longer any background processes running,
4510 // and the app that died was not running instrumentation,
4511 // then tell everyone we are now low on memory.
4512 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004513 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4514 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4516 haveBg = true;
4517 break;
4518 }
4519 }
4520
4521 if (!haveBg) {
4522 Log.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004523 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004524 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004525 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4526 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004527 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004528 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4529 // The low memory report is overriding any current
4530 // state for a GC request. Make sure to do
4531 // visible/foreground processes first.
4532 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4533 rec.lastRequestedGc = 0;
4534 } else {
4535 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004537 rec.reportLowMemory = true;
4538 rec.lastLowMemory = now;
4539 mProcessesToGc.remove(rec);
4540 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541 }
4542 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004543 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 }
4545 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004546 } else if (DEBUG_PROCESSES) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 Log.d(TAG, "Received spurious death notification for thread "
4548 + thread.asBinder());
4549 }
4550 }
4551
Dan Egnor42471dd2010-01-07 17:25:22 -08004552 /**
4553 * If a stack trace dump file is configured, dump process stack traces.
4554 * @param pids of dalvik VM processes to dump stack traces for
4555 * @return file containing stack traces, or null if no dump file is configured
4556 */
4557 private static File dumpStackTraces(ArrayList<Integer> pids) {
4558 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4559 if (tracesPath == null || tracesPath.length() == 0) {
4560 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004562
4563 File tracesFile = new File(tracesPath);
4564 try {
4565 File tracesDir = tracesFile.getParentFile();
4566 if (!tracesDir.exists()) tracesFile.mkdirs();
4567 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4568
4569 if (tracesFile.exists()) tracesFile.delete();
4570 tracesFile.createNewFile();
4571 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4572 } catch (IOException e) {
4573 Log.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
4574 return null;
4575 }
4576
4577 // Use a FileObserver to detect when traces finish writing.
4578 // The order of traces is considered important to maintain for legibility.
4579 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4580 public synchronized void onEvent(int event, String path) { notify(); }
4581 };
4582
4583 try {
4584 observer.startWatching();
4585 int num = pids.size();
4586 for (int i = 0; i < num; i++) {
4587 synchronized (observer) {
4588 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4589 observer.wait(200); // Wait for write-close, give up after 200msec
4590 }
4591 }
4592 } catch (InterruptedException e) {
4593 Log.wtf(TAG, e);
4594 } finally {
4595 observer.stopWatching();
4596 }
4597
4598 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 }
4600
Dan Egnor42471dd2010-01-07 17:25:22 -08004601 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4602 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 if (app.notResponding || app.crashing) {
4604 return;
4605 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004608 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4609 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610
Dan Egnor42471dd2010-01-07 17:25:22 -08004611 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4612 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4613 pids.add(app.pid);
4614
4615 int parentPid = app.pid;
4616 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4617 if (parentPid != app.pid) pids.add(parentPid);
4618
4619 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4620
4621 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4622 ProcessRecord r = mLruProcesses.get(i);
4623 if (r != null && r.thread != null) {
4624 int pid = r.pid;
4625 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626 }
4627 }
4628
Dan Egnor42471dd2010-01-07 17:25:22 -08004629 File tracesFile = dumpStackTraces(pids);
4630
4631 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004632 StringBuilder info = mStringBuilder;
4633 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004634 info.append("ANR in ").append(app.processName);
4635 if (activity != null && activity.shortComponentName != null) {
4636 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 if (annotation != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004639 info.append("\nReason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004641 if (parent != null && parent != activity) {
4642 info.append("\nParent: ").append(parent.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644
Dan Egnor42471dd2010-01-07 17:25:22 -08004645 String cpuInfo = null;
4646 if (MONITOR_CPU_USAGE) {
4647 updateCpuStatsNow();
4648 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4649 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 }
4651
Dan Egnor42471dd2010-01-07 17:25:22 -08004652 Log.e(TAG, info.toString());
4653 if (tracesFile == null) {
4654 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4655 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4656 }
4657
4658 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4659
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004660 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004662 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4663 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004665 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4666 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 }
4668 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004669 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
4671 }
4672
Dan Egnor42471dd2010-01-07 17:25:22 -08004673 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4674 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4675 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4676 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4677 Process.killProcess(app.pid);
4678 return;
4679 }
4680
4681 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 makeAppNotRespondingLocked(app,
4683 activity != null ? activity.shortComponentName : null,
4684 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004685 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004686
4687 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 Message msg = Message.obtain();
4689 HashMap map = new HashMap();
4690 msg.what = SHOW_NOT_RESPONDING_MSG;
4691 msg.obj = map;
4692 map.put("app", app);
4693 if (activity != null) {
4694 map.put("activity", activity);
4695 }
4696
4697 mHandler.sendMessage(msg);
4698 return;
4699 }
4700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701 private final void decPersistentCountLocked(ProcessRecord app)
4702 {
4703 app.persistentActivities--;
4704 if (app.persistentActivities > 0) {
4705 // Still more of 'em...
4706 return;
4707 }
4708 if (app.persistent) {
4709 // Ah, but the application itself is persistent. Whatever!
4710 return;
4711 }
4712
4713 // App is no longer persistent... make sure it and the ones
4714 // following it in the LRU list have the correc oom_adj.
4715 updateOomAdjLocked();
4716 }
4717
4718 public void setPersistent(IBinder token, boolean isPersistent) {
4719 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4720 != PackageManager.PERMISSION_GRANTED) {
4721 String msg = "Permission Denial: setPersistent() from pid="
4722 + Binder.getCallingPid()
4723 + ", uid=" + Binder.getCallingUid()
4724 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4725 Log.w(TAG, msg);
4726 throw new SecurityException(msg);
4727 }
4728
4729 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004730 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 if (index < 0) {
4732 return;
4733 }
4734 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4735 ProcessRecord app = r.app;
4736
4737 if (localLOGV) Log.v(
4738 TAG, "Setting persistence " + isPersistent + ": " + r);
4739
4740 if (isPersistent) {
4741 if (r.persistent) {
4742 // Okay okay, I heard you already!
4743 if (localLOGV) Log.v(TAG, "Already persistent!");
4744 return;
4745 }
4746 r.persistent = true;
4747 app.persistentActivities++;
4748 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4749 if (app.persistentActivities > 1) {
4750 // We aren't the first...
4751 if (localLOGV) Log.v(TAG, "Not the first!");
4752 return;
4753 }
4754 if (app.persistent) {
4755 // This would be redundant.
4756 if (localLOGV) Log.v(TAG, "App is persistent!");
4757 return;
4758 }
4759
4760 // App is now persistent... make sure it and the ones
4761 // following it now have the correct oom_adj.
4762 final long origId = Binder.clearCallingIdentity();
4763 updateOomAdjLocked();
4764 Binder.restoreCallingIdentity(origId);
4765
4766 } else {
4767 if (!r.persistent) {
4768 // Okay okay, I heard you already!
4769 return;
4770 }
4771 r.persistent = false;
4772 final long origId = Binder.clearCallingIdentity();
4773 decPersistentCountLocked(app);
4774 Binder.restoreCallingIdentity(origId);
4775
4776 }
4777 }
4778 }
4779
4780 public boolean clearApplicationUserData(final String packageName,
4781 final IPackageDataObserver observer) {
4782 int uid = Binder.getCallingUid();
4783 int pid = Binder.getCallingPid();
4784 long callingId = Binder.clearCallingIdentity();
4785 try {
4786 IPackageManager pm = ActivityThread.getPackageManager();
4787 int pkgUid = -1;
4788 synchronized(this) {
4789 try {
4790 pkgUid = pm.getPackageUid(packageName);
4791 } catch (RemoteException e) {
4792 }
4793 if (pkgUid == -1) {
4794 Log.w(TAG, "Invalid packageName:" + packageName);
4795 return false;
4796 }
4797 if (uid == pkgUid || checkComponentPermission(
4798 android.Manifest.permission.CLEAR_APP_USER_DATA,
4799 pid, uid, -1)
4800 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004801 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 } else {
4803 throw new SecurityException(pid+" does not have permission:"+
4804 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4805 "for process:"+packageName);
4806 }
4807 }
4808
4809 try {
4810 //clear application user data
4811 pm.clearApplicationUserData(packageName, observer);
4812 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4813 Uri.fromParts("package", packageName, null));
4814 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4815 broadcastIntentLocked(null, null, intent,
4816 null, null, 0, null, null, null,
4817 false, false, MY_PID, Process.SYSTEM_UID);
4818 } catch (RemoteException e) {
4819 }
4820 } finally {
4821 Binder.restoreCallingIdentity(callingId);
4822 }
4823 return true;
4824 }
4825
Dianne Hackborn03abb812010-01-04 18:43:19 -08004826 public void killBackgroundProcesses(final String packageName) {
4827 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4828 != PackageManager.PERMISSION_GRANTED &&
4829 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4830 != PackageManager.PERMISSION_GRANTED) {
4831 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 + Binder.getCallingPid()
4833 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004834 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 Log.w(TAG, msg);
4836 throw new SecurityException(msg);
4837 }
4838
4839 long callingId = Binder.clearCallingIdentity();
4840 try {
4841 IPackageManager pm = ActivityThread.getPackageManager();
4842 int pkgUid = -1;
4843 synchronized(this) {
4844 try {
4845 pkgUid = pm.getPackageUid(packageName);
4846 } catch (RemoteException e) {
4847 }
4848 if (pkgUid == -1) {
4849 Log.w(TAG, "Invalid packageName: " + packageName);
4850 return;
4851 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004852 killPackageProcessesLocked(packageName, pkgUid,
4853 SECONDARY_SERVER_ADJ, false);
4854 }
4855 } finally {
4856 Binder.restoreCallingIdentity(callingId);
4857 }
4858 }
4859
4860 public void forceStopPackage(final String packageName) {
4861 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4862 != PackageManager.PERMISSION_GRANTED) {
4863 String msg = "Permission Denial: forceStopPackage() from pid="
4864 + Binder.getCallingPid()
4865 + ", uid=" + Binder.getCallingUid()
4866 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4867 Log.w(TAG, msg);
4868 throw new SecurityException(msg);
4869 }
4870
4871 long callingId = Binder.clearCallingIdentity();
4872 try {
4873 IPackageManager pm = ActivityThread.getPackageManager();
4874 int pkgUid = -1;
4875 synchronized(this) {
4876 try {
4877 pkgUid = pm.getPackageUid(packageName);
4878 } catch (RemoteException e) {
4879 }
4880 if (pkgUid == -1) {
4881 Log.w(TAG, "Invalid packageName: " + packageName);
4882 return;
4883 }
4884 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 }
4886 } finally {
4887 Binder.restoreCallingIdentity(callingId);
4888 }
4889 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004890
4891 /*
4892 * The pkg name and uid have to be specified.
4893 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4894 */
4895 public void killApplicationWithUid(String pkg, int uid) {
4896 if (pkg == null) {
4897 return;
4898 }
4899 // Make sure the uid is valid.
4900 if (uid < 0) {
4901 Log.w(TAG, "Invalid uid specified for pkg : " + pkg);
4902 return;
4903 }
4904 int callerUid = Binder.getCallingUid();
4905 // Only the system server can kill an application
4906 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004907 // Post an aysnc message to kill the application
4908 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4909 msg.arg1 = uid;
4910 msg.arg2 = 0;
4911 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004912 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004913 } else {
4914 throw new SecurityException(callerUid + " cannot kill pkg: " +
4915 pkg);
4916 }
4917 }
4918
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004919 public void closeSystemDialogs(String reason) {
4920 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
4921 if (reason != null) {
4922 intent.putExtra("reason", reason);
4923 }
4924
4925 final int uid = Binder.getCallingUid();
4926 final long origId = Binder.clearCallingIdentity();
4927 synchronized (this) {
4928 int i = mWatchers.beginBroadcast();
4929 while (i > 0) {
4930 i--;
4931 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4932 if (w != null) {
4933 try {
4934 w.closingSystemDialogs(reason);
4935 } catch (RemoteException e) {
4936 }
4937 }
4938 }
4939 mWatchers.finishBroadcast();
4940
Dianne Hackbornffa42482009-09-23 22:20:11 -07004941 mWindowManager.closeSystemDialogs(reason);
4942
4943 for (i=mHistory.size()-1; i>=0; i--) {
4944 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4945 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4946 finishActivityLocked(r, i,
4947 Activity.RESULT_CANCELED, null, "close-sys");
4948 }
4949 }
4950
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004951 broadcastIntentLocked(null, null, intent, null,
4952 null, 0, null, null, null, false, false, -1, uid);
4953 }
4954 Binder.restoreCallingIdentity(origId);
4955 }
4956
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004957 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004958 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004959 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4960 for (int i=pids.length-1; i>=0; i--) {
4961 infos[i] = new Debug.MemoryInfo();
4962 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004963 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004964 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004965 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004966
4967 public void killApplicationProcess(String processName, int uid) {
4968 if (processName == null) {
4969 return;
4970 }
4971
4972 int callerUid = Binder.getCallingUid();
4973 // Only the system server can kill an application
4974 if (callerUid == Process.SYSTEM_UID) {
4975 synchronized (this) {
4976 ProcessRecord app = getProcessRecordLocked(processName, uid);
4977 if (app != null) {
4978 try {
4979 app.thread.scheduleSuicide();
4980 } catch (RemoteException e) {
4981 // If the other end already died, then our work here is done.
4982 }
4983 } else {
4984 Log.w(TAG, "Process/uid not found attempting kill of "
4985 + processName + " / " + uid);
4986 }
4987 }
4988 } else {
4989 throw new SecurityException(callerUid + " cannot kill app process: " +
4990 processName);
4991 }
4992 }
4993
Dianne Hackborn03abb812010-01-04 18:43:19 -08004994 private void forceStopPackageLocked(final String packageName, int uid) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004995 forceStopPackageLocked(packageName, uid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4997 Uri.fromParts("package", packageName, null));
4998 intent.putExtra(Intent.EXTRA_UID, uid);
4999 broadcastIntentLocked(null, null, intent,
5000 null, null, 0, null, null, null,
5001 false, false, MY_PID, Process.SYSTEM_UID);
5002 }
5003
Dianne Hackborn03abb812010-01-04 18:43:19 -08005004 private final void killPackageProcessesLocked(String packageName, int uid,
5005 int minOomAdj, boolean callerWillRestart) {
5006 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007
Dianne Hackborn03abb812010-01-04 18:43:19 -08005008 // Remove all processes this package may have touched: all with the
5009 // same UID (except for the system or root user), and all whose name
5010 // matches the package name.
5011 final String procNamePrefix = packageName + ":";
5012 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5013 final int NA = apps.size();
5014 for (int ia=0; ia<NA; ia++) {
5015 ProcessRecord app = apps.valueAt(ia);
5016 if (app.removed) {
5017 procs.add(app);
5018 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5019 || app.processName.equals(packageName)
5020 || app.processName.startsWith(procNamePrefix)) {
5021 if (app.setAdj >= minOomAdj) {
5022 app.removed = true;
5023 procs.add(app);
5024 }
5025 }
5026 }
5027 }
5028
5029 int N = procs.size();
5030 for (int i=0; i<N; i++) {
5031 removeProcessLocked(procs.get(i), callerWillRestart);
5032 }
5033 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005034
Dianne Hackborn03abb812010-01-04 18:43:19 -08005035 private final void forceStopPackageLocked(String name, int uid,
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005036 boolean callerWillRestart, boolean purgeCache) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 int i, N;
5038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 if (uid < 0) {
5040 try {
5041 uid = ActivityThread.getPackageManager().getPackageUid(name);
5042 } catch (RemoteException e) {
5043 }
5044 }
5045
Dianne Hackborn03abb812010-01-04 18:43:19 -08005046 Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
5047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5049 while (badApps.hasNext()) {
5050 SparseArray<Long> ba = badApps.next();
5051 if (ba.get(uid) != null) {
5052 badApps.remove();
5053 }
5054 }
5055
Dianne Hackborn03abb812010-01-04 18:43:19 -08005056 killPackageProcessesLocked(name, uid, -100, callerWillRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057
5058 for (i=mHistory.size()-1; i>=0; i--) {
5059 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5060 if (r.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005061 Log.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 if (r.app != null) {
5063 r.app.removed = true;
5064 }
5065 r.app = null;
5066 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5067 }
5068 }
5069
5070 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5071 for (ServiceRecord service : mServices.values()) {
5072 if (service.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005073 Log.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 if (service.app != null) {
5075 service.app.removed = true;
5076 }
5077 service.app = null;
5078 services.add(service);
5079 }
5080 }
5081
5082 N = services.size();
5083 for (i=0; i<N; i++) {
5084 bringDownServiceLocked(services.get(i), true);
5085 }
5086
5087 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005088 if (purgeCache) {
5089 AttributeCache ac = AttributeCache.instance();
5090 if (ac != null) {
5091 ac.removePackage(name);
5092 }
5093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 }
5095
5096 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5097 final String name = app.processName;
5098 final int uid = app.info.uid;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005099 if (DEBUG_PROCESSES) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 TAG, "Force removing process " + app + " (" + name
5101 + "/" + uid + ")");
5102
5103 mProcessNames.remove(name, uid);
5104 boolean needRestart = false;
5105 if (app.pid > 0 && app.pid != MY_PID) {
5106 int pid = app.pid;
5107 synchronized (mPidsSelfLocked) {
5108 mPidsSelfLocked.remove(pid);
5109 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5110 }
5111 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005112 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 Process.killProcess(pid);
5114
5115 if (app.persistent) {
5116 if (!callerWillRestart) {
5117 addAppLocked(app.info);
5118 } else {
5119 needRestart = true;
5120 }
5121 }
5122 } else {
5123 mRemovedProcesses.add(app);
5124 }
5125
5126 return needRestart;
5127 }
5128
5129 private final void processStartTimedOutLocked(ProcessRecord app) {
5130 final int pid = app.pid;
5131 boolean gone = false;
5132 synchronized (mPidsSelfLocked) {
5133 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5134 if (knownApp != null && knownApp.thread == null) {
5135 mPidsSelfLocked.remove(pid);
5136 gone = true;
5137 }
5138 }
5139
5140 if (gone) {
5141 Log.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005142 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005143 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005144 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005145 // Take care of any launching providers waiting for this process.
5146 checkAppInLaunchingProvidersLocked(app, true);
5147 // Take care of any services that are waiting for the process.
5148 for (int i=0; i<mPendingServices.size(); i++) {
5149 ServiceRecord sr = mPendingServices.get(i);
5150 if (app.info.uid == sr.appInfo.uid
5151 && app.processName.equals(sr.processName)) {
5152 Log.w(TAG, "Forcing bringing down service: " + sr);
5153 mPendingServices.remove(i);
5154 i--;
5155 bringDownServiceLocked(sr, true);
5156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005158 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005159 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
5160 Log.w(TAG, "Unattached app died before backup, skipping");
5161 try {
5162 IBackupManager bm = IBackupManager.Stub.asInterface(
5163 ServiceManager.getService(Context.BACKUP_SERVICE));
5164 bm.agentDisconnected(app.info.packageName);
5165 } catch (RemoteException e) {
5166 // Can't happen; the backup manager is local
5167 }
5168 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005169 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
5170 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
5171 mPendingBroadcast = null;
5172 scheduleBroadcastsLocked();
5173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005174 } else {
5175 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
5176 }
5177 }
5178
5179 private final boolean attachApplicationLocked(IApplicationThread thread,
5180 int pid) {
5181
5182 // Find the application record that is being attached... either via
5183 // the pid if we are running in multiple processes, or just pull the
5184 // next app record if we are emulating process with anonymous threads.
5185 ProcessRecord app;
5186 if (pid != MY_PID && pid >= 0) {
5187 synchronized (mPidsSelfLocked) {
5188 app = mPidsSelfLocked.get(pid);
5189 }
5190 } else if (mStartingProcesses.size() > 0) {
5191 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005192 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 } else {
5194 app = null;
5195 }
5196
5197 if (app == null) {
5198 Log.w(TAG, "No pending application record for pid " + pid
5199 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005200 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 if (pid > 0 && pid != MY_PID) {
5202 Process.killProcess(pid);
5203 } else {
5204 try {
5205 thread.scheduleExit();
5206 } catch (Exception e) {
5207 // Ignore exceptions.
5208 }
5209 }
5210 return false;
5211 }
5212
5213 // If this application record is still attached to a previous
5214 // process, clean it up now.
5215 if (app.thread != null) {
5216 handleAppDiedLocked(app, true);
5217 }
5218
5219 // Tell the process all about itself.
5220
5221 if (localLOGV) Log.v(
5222 TAG, "Binding process pid " + pid + " to record " + app);
5223
5224 String processName = app.processName;
5225 try {
5226 thread.asBinder().linkToDeath(new AppDeathRecipient(
5227 app, pid, thread), 0);
5228 } catch (RemoteException e) {
5229 app.resetPackageList();
5230 startProcessLocked(app, "link fail", processName);
5231 return false;
5232 }
5233
Doug Zongker2bec3d42009-12-04 12:52:44 -08005234 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235
5236 app.thread = thread;
5237 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005238 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5239 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 app.forcingToForeground = null;
5241 app.foregroundServices = false;
5242 app.debugging = false;
5243
5244 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5245
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005246 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5247 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005249 if (!normalMode) {
5250 Log.i(TAG, "Launching preboot mode app: " + app);
5251 }
5252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 if (localLOGV) Log.v(
5254 TAG, "New app record " + app
5255 + " thread=" + thread.asBinder() + " pid=" + pid);
5256 try {
5257 int testMode = IApplicationThread.DEBUG_OFF;
5258 if (mDebugApp != null && mDebugApp.equals(processName)) {
5259 testMode = mWaitForDebugger
5260 ? IApplicationThread.DEBUG_WAIT
5261 : IApplicationThread.DEBUG_ON;
5262 app.debugging = true;
5263 if (mDebugTransient) {
5264 mDebugApp = mOrigDebugApp;
5265 mWaitForDebugger = mOrigWaitForDebugger;
5266 }
5267 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005268
Christopher Tate181fafa2009-05-14 11:12:14 -07005269 // If the app is being launched for restore or full backup, set it up specially
5270 boolean isRestrictedBackupMode = false;
5271 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5272 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5273 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5274 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005275
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005276 ensurePackageDexOpt(app.instrumentationInfo != null
5277 ? app.instrumentationInfo.packageName
5278 : app.info.packageName);
5279 if (app.instrumentationClass != null) {
5280 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005281 }
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005282 if (DEBUG_CONFIGURATION) Log.v(TAG, "Binding proc "
5283 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005284 thread.bindApplication(processName, app.instrumentationInfo != null
5285 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 app.instrumentationClass, app.instrumentationProfileFile,
5287 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005288 isRestrictedBackupMode || !normalMode,
5289 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005290 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005291 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 } catch (Exception e) {
5293 // todo: Yikes! What should we do? For now we will try to
5294 // start another process, but that could easily get us in
5295 // an infinite loop of restarting processes...
5296 Log.w(TAG, "Exception thrown during bind!", e);
5297
5298 app.resetPackageList();
5299 startProcessLocked(app, "bind fail", processName);
5300 return false;
5301 }
5302
5303 // Remove this record from the list of starting applications.
5304 mPersistentStartingProcesses.remove(app);
5305 mProcessesOnHold.remove(app);
5306
5307 boolean badApp = false;
5308 boolean didSomething = false;
5309
5310 // See if the top visible activity is waiting to run in this process...
5311 HistoryRecord hr = topRunningActivityLocked(null);
5312 if (hr != null) {
5313 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5314 && processName.equals(hr.processName)) {
5315 try {
5316 if (realStartActivityLocked(hr, app, true, true)) {
5317 didSomething = true;
5318 }
5319 } catch (Exception e) {
5320 Log.w(TAG, "Exception in new application when starting activity "
5321 + hr.intent.getComponent().flattenToShortString(), e);
5322 badApp = true;
5323 }
5324 } else {
5325 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5326 }
5327 }
5328
5329 // Find any services that should be running in this process...
5330 if (!badApp && mPendingServices.size() > 0) {
5331 ServiceRecord sr = null;
5332 try {
5333 for (int i=0; i<mPendingServices.size(); i++) {
5334 sr = mPendingServices.get(i);
5335 if (app.info.uid != sr.appInfo.uid
5336 || !processName.equals(sr.processName)) {
5337 continue;
5338 }
5339
5340 mPendingServices.remove(i);
5341 i--;
5342 realStartServiceLocked(sr, app);
5343 didSomething = true;
5344 }
5345 } catch (Exception e) {
5346 Log.w(TAG, "Exception in new application when starting service "
5347 + sr.shortName, e);
5348 badApp = true;
5349 }
5350 }
5351
5352 // Check if the next broadcast receiver is in this process...
5353 BroadcastRecord br = mPendingBroadcast;
5354 if (!badApp && br != null && br.curApp == app) {
5355 try {
5356 mPendingBroadcast = null;
5357 processCurBroadcastLocked(br, app);
5358 didSomething = true;
5359 } catch (Exception e) {
5360 Log.w(TAG, "Exception in new application when starting receiver "
5361 + br.curComponent.flattenToShortString(), e);
5362 badApp = true;
5363 logBroadcastReceiverDiscard(br);
5364 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5365 br.resultExtras, br.resultAbort, true);
5366 scheduleBroadcastsLocked();
5367 }
5368 }
5369
Christopher Tate181fafa2009-05-14 11:12:14 -07005370 // Check whether the next backup agent is in this process...
5371 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
5372 if (DEBUG_BACKUP) Log.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005373 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005374 try {
5375 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5376 } catch (Exception e) {
5377 Log.w(TAG, "Exception scheduling backup agent creation: ");
5378 e.printStackTrace();
5379 }
5380 }
5381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 if (badApp) {
5383 // todo: Also need to kill application to deal with all
5384 // kinds of exceptions.
5385 handleAppDiedLocked(app, false);
5386 return false;
5387 }
5388
5389 if (!didSomething) {
5390 updateOomAdjLocked();
5391 }
5392
5393 return true;
5394 }
5395
5396 public final void attachApplication(IApplicationThread thread) {
5397 synchronized (this) {
5398 int callingPid = Binder.getCallingPid();
5399 final long origId = Binder.clearCallingIdentity();
5400 attachApplicationLocked(thread, callingPid);
5401 Binder.restoreCallingIdentity(origId);
5402 }
5403 }
5404
Dianne Hackborne88846e2009-09-30 21:34:25 -07005405 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005407 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 Binder.restoreCallingIdentity(origId);
5409 }
5410
5411 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5412 boolean remove) {
5413 int N = mStoppingActivities.size();
5414 if (N <= 0) return null;
5415
5416 ArrayList<HistoryRecord> stops = null;
5417
5418 final boolean nowVisible = mResumedActivity != null
5419 && mResumedActivity.nowVisible
5420 && !mResumedActivity.waitingVisible;
5421 for (int i=0; i<N; i++) {
5422 HistoryRecord s = mStoppingActivities.get(i);
5423 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
5424 + nowVisible + " waitingVisible=" + s.waitingVisible
5425 + " finishing=" + s.finishing);
5426 if (s.waitingVisible && nowVisible) {
5427 mWaitingVisibleActivities.remove(s);
5428 s.waitingVisible = false;
5429 if (s.finishing) {
5430 // If this activity is finishing, it is sitting on top of
5431 // everyone else but we now know it is no longer needed...
5432 // so get rid of it. Otherwise, we need to go through the
5433 // normal flow and hide it once we determine that it is
5434 // hidden by the activities in front of it.
5435 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
5436 mWindowManager.setAppVisibility(s, false);
5437 }
5438 }
5439 if (!s.waitingVisible && remove) {
5440 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
5441 if (stops == null) {
5442 stops = new ArrayList<HistoryRecord>();
5443 }
5444 stops.add(s);
5445 mStoppingActivities.remove(i);
5446 N--;
5447 i--;
5448 }
5449 }
5450
5451 return stops;
5452 }
5453
5454 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005455 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005456 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 mWindowManager.enableScreenAfterBoot();
5458 }
5459
Dianne Hackborne88846e2009-09-30 21:34:25 -07005460 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5461 Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
5463
5464 ArrayList<HistoryRecord> stops = null;
5465 ArrayList<HistoryRecord> finishes = null;
5466 ArrayList<HistoryRecord> thumbnails = null;
5467 int NS = 0;
5468 int NF = 0;
5469 int NT = 0;
5470 IApplicationThread sendThumbnail = null;
5471 boolean booting = false;
5472 boolean enableScreen = false;
5473
5474 synchronized (this) {
5475 if (token != null) {
5476 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5477 }
5478
5479 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005480 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 if (index >= 0) {
5482 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5483
Dianne Hackborne88846e2009-09-30 21:34:25 -07005484 // This is a hack to semi-deal with a race condition
5485 // in the client where it can be constructed with a
5486 // newer configuration from when we asked it to launch.
5487 // We'll update with whatever configuration it now says
5488 // it used to launch.
5489 if (config != null) {
5490 r.configuration = config;
5491 }
5492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 // No longer need to keep the device awake.
5494 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5495 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5496 mLaunchingActivity.release();
5497 }
5498
5499 // We are now idle. If someone is waiting for a thumbnail from
5500 // us, we can now deliver.
5501 r.idle = true;
5502 scheduleAppGcsLocked();
5503 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5504 sendThumbnail = r.app.thread;
5505 r.thumbnailNeeded = false;
5506 }
5507
5508 // If this activity is fullscreen, set up to hide those under it.
5509
5510 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
5511 ensureActivitiesVisibleLocked(null, 0);
5512
5513 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
5514 if (!mBooted && !fromTimeout) {
5515 mBooted = true;
5516 enableScreen = true;
5517 }
5518 }
5519
5520 // Atomically retrieve all of the other things to do.
5521 stops = processStoppingActivitiesLocked(true);
5522 NS = stops != null ? stops.size() : 0;
5523 if ((NF=mFinishingActivities.size()) > 0) {
5524 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5525 mFinishingActivities.clear();
5526 }
5527 if ((NT=mCancelledThumbnails.size()) > 0) {
5528 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5529 mCancelledThumbnails.clear();
5530 }
5531
5532 booting = mBooting;
5533 mBooting = false;
5534 }
5535
5536 int i;
5537
5538 // Send thumbnail if requested.
5539 if (sendThumbnail != null) {
5540 try {
5541 sendThumbnail.requestThumbnail(token);
5542 } catch (Exception e) {
5543 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5544 sendPendingThumbnail(null, token, null, null, true);
5545 }
5546 }
5547
5548 // Stop any activities that are scheduled to do so but have been
5549 // waiting for the next one to start.
5550 for (i=0; i<NS; i++) {
5551 HistoryRecord r = (HistoryRecord)stops.get(i);
5552 synchronized (this) {
5553 if (r.finishing) {
5554 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5555 } else {
5556 stopActivityLocked(r);
5557 }
5558 }
5559 }
5560
5561 // Finish any activities that are scheduled to do so but have been
5562 // waiting for the next one to start.
5563 for (i=0; i<NF; i++) {
5564 HistoryRecord r = (HistoryRecord)finishes.get(i);
5565 synchronized (this) {
5566 destroyActivityLocked(r, true);
5567 }
5568 }
5569
5570 // Report back to any thumbnail receivers.
5571 for (i=0; i<NT; i++) {
5572 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5573 sendPendingThumbnail(r, null, null, null, true);
5574 }
5575
5576 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005577 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 }
5579
5580 trimApplications();
5581 //dump();
5582 //mWindowManager.dump();
5583
5584 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 enableScreenAfterBoot();
5586 }
5587 }
5588
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005589 final void finishBooting() {
5590 // Ensure that any processes we had put on hold are now started
5591 // up.
5592 final int NP = mProcessesOnHold.size();
5593 if (NP > 0) {
5594 ArrayList<ProcessRecord> procs =
5595 new ArrayList<ProcessRecord>(mProcessesOnHold);
5596 for (int ip=0; ip<NP; ip++) {
5597 this.startProcessLocked(procs.get(ip), "on-hold", null);
5598 }
5599 }
5600 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5601 // Tell anyone interested that we are done booting!
5602 synchronized (this) {
5603 broadcastIntentLocked(null, null,
5604 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5605 null, null, 0, null, null,
5606 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5607 false, false, MY_PID, Process.SYSTEM_UID);
5608 }
5609 }
5610 }
5611
5612 final void ensureBootCompleted() {
5613 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005614 boolean enableScreen;
5615 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005616 booting = mBooting;
5617 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005618 enableScreen = !mBooted;
5619 mBooted = true;
5620 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005621
5622 if (booting) {
5623 finishBooting();
5624 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005625
5626 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005627 enableScreenAfterBoot();
5628 }
5629 }
5630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 public final void activityPaused(IBinder token, Bundle icicle) {
5632 // Refuse possible leaked file descriptors
5633 if (icicle != null && icicle.hasFileDescriptors()) {
5634 throw new IllegalArgumentException("File descriptors passed in Bundle");
5635 }
5636
5637 final long origId = Binder.clearCallingIdentity();
5638 activityPaused(token, icicle, false);
5639 Binder.restoreCallingIdentity(origId);
5640 }
5641
5642 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
5643 if (DEBUG_PAUSE) Log.v(
5644 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5645 + ", timeout=" + timeout);
5646
5647 HistoryRecord r = null;
5648
5649 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005650 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 if (index >= 0) {
5652 r = (HistoryRecord)mHistory.get(index);
5653 if (!timeout) {
5654 r.icicle = icicle;
5655 r.haveState = true;
5656 }
5657 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5658 if (mPausingActivity == r) {
5659 r.state = ActivityState.PAUSED;
5660 completePauseLocked();
5661 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005662 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 System.identityHashCode(r), r.shortComponentName,
5664 mPausingActivity != null
5665 ? mPausingActivity.shortComponentName : "(none)");
5666 }
5667 }
5668 }
5669 }
5670
5671 public final void activityStopped(IBinder token, Bitmap thumbnail,
5672 CharSequence description) {
5673 if (localLOGV) Log.v(
5674 TAG, "Activity stopped: token=" + token);
5675
5676 HistoryRecord r = null;
5677
5678 final long origId = Binder.clearCallingIdentity();
5679
5680 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005681 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 if (index >= 0) {
5683 r = (HistoryRecord)mHistory.get(index);
5684 r.thumbnail = thumbnail;
5685 r.description = description;
5686 r.stopped = true;
5687 r.state = ActivityState.STOPPED;
5688 if (!r.finishing) {
5689 if (r.configDestroy) {
5690 destroyActivityLocked(r, true);
5691 resumeTopActivityLocked(null);
5692 }
5693 }
5694 }
5695 }
5696
5697 if (r != null) {
5698 sendPendingThumbnail(r, null, null, null, false);
5699 }
5700
5701 trimApplications();
5702
5703 Binder.restoreCallingIdentity(origId);
5704 }
5705
5706 public final void activityDestroyed(IBinder token) {
5707 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
5708 synchronized (this) {
5709 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5710
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 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5714 if (r.state == ActivityState.DESTROYING) {
5715 final long origId = Binder.clearCallingIdentity();
5716 removeActivityFromHistoryLocked(r);
5717 Binder.restoreCallingIdentity(origId);
5718 }
5719 }
5720 }
5721 }
5722
5723 public String getCallingPackage(IBinder token) {
5724 synchronized (this) {
5725 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005726 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 }
5728 }
5729
5730 public ComponentName getCallingActivity(IBinder token) {
5731 synchronized (this) {
5732 HistoryRecord r = getCallingRecordLocked(token);
5733 return r != null ? r.intent.getComponent() : null;
5734 }
5735 }
5736
5737 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005738 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005739 if (index >= 0) {
5740 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5741 if (r != null) {
5742 return r.resultTo;
5743 }
5744 }
5745 return null;
5746 }
5747
5748 public ComponentName getActivityClassForToken(IBinder token) {
5749 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005750 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 if (index >= 0) {
5752 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5753 return r.intent.getComponent();
5754 }
5755 return null;
5756 }
5757 }
5758
5759 public String getPackageForToken(IBinder token) {
5760 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005761 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 if (index >= 0) {
5763 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5764 return r.packageName;
5765 }
5766 return null;
5767 }
5768 }
5769
5770 public IIntentSender getIntentSender(int type,
5771 String packageName, IBinder token, String resultWho,
5772 int requestCode, Intent intent, String resolvedType, int flags) {
5773 // Refuse possible leaked file descriptors
5774 if (intent != null && intent.hasFileDescriptors() == true) {
5775 throw new IllegalArgumentException("File descriptors passed in Intent");
5776 }
5777
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005778 if (type == INTENT_SENDER_BROADCAST) {
5779 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5780 throw new IllegalArgumentException(
5781 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5782 }
5783 }
5784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005785 synchronized(this) {
5786 int callingUid = Binder.getCallingUid();
5787 try {
5788 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5789 Process.supportsProcesses()) {
5790 int uid = ActivityThread.getPackageManager()
5791 .getPackageUid(packageName);
5792 if (uid != Binder.getCallingUid()) {
5793 String msg = "Permission Denial: getIntentSender() from pid="
5794 + Binder.getCallingPid()
5795 + ", uid=" + Binder.getCallingUid()
5796 + ", (need uid=" + uid + ")"
5797 + " is not allowed to send as package " + packageName;
5798 Log.w(TAG, msg);
5799 throw new SecurityException(msg);
5800 }
5801 }
5802 } catch (RemoteException e) {
5803 throw new SecurityException(e);
5804 }
5805 HistoryRecord activity = null;
5806 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005807 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 if (index < 0) {
5809 return null;
5810 }
5811 activity = (HistoryRecord)mHistory.get(index);
5812 if (activity.finishing) {
5813 return null;
5814 }
5815 }
5816
5817 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5818 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5819 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5820 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5821 |PendingIntent.FLAG_UPDATE_CURRENT);
5822
5823 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5824 type, packageName, activity, resultWho,
5825 requestCode, intent, resolvedType, flags);
5826 WeakReference<PendingIntentRecord> ref;
5827 ref = mIntentSenderRecords.get(key);
5828 PendingIntentRecord rec = ref != null ? ref.get() : null;
5829 if (rec != null) {
5830 if (!cancelCurrent) {
5831 if (updateCurrent) {
5832 rec.key.requestIntent.replaceExtras(intent);
5833 }
5834 return rec;
5835 }
5836 rec.canceled = true;
5837 mIntentSenderRecords.remove(key);
5838 }
5839 if (noCreate) {
5840 return rec;
5841 }
5842 rec = new PendingIntentRecord(this, key, callingUid);
5843 mIntentSenderRecords.put(key, rec.ref);
5844 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5845 if (activity.pendingResults == null) {
5846 activity.pendingResults
5847 = new HashSet<WeakReference<PendingIntentRecord>>();
5848 }
5849 activity.pendingResults.add(rec.ref);
5850 }
5851 return rec;
5852 }
5853 }
5854
5855 public void cancelIntentSender(IIntentSender sender) {
5856 if (!(sender instanceof PendingIntentRecord)) {
5857 return;
5858 }
5859 synchronized(this) {
5860 PendingIntentRecord rec = (PendingIntentRecord)sender;
5861 try {
5862 int uid = ActivityThread.getPackageManager()
5863 .getPackageUid(rec.key.packageName);
5864 if (uid != Binder.getCallingUid()) {
5865 String msg = "Permission Denial: cancelIntentSender() from pid="
5866 + Binder.getCallingPid()
5867 + ", uid=" + Binder.getCallingUid()
5868 + " is not allowed to cancel packges "
5869 + rec.key.packageName;
5870 Log.w(TAG, msg);
5871 throw new SecurityException(msg);
5872 }
5873 } catch (RemoteException e) {
5874 throw new SecurityException(e);
5875 }
5876 cancelIntentSenderLocked(rec, true);
5877 }
5878 }
5879
5880 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5881 rec.canceled = true;
5882 mIntentSenderRecords.remove(rec.key);
5883 if (cleanActivity && rec.key.activity != null) {
5884 rec.key.activity.pendingResults.remove(rec.ref);
5885 }
5886 }
5887
5888 public String getPackageForIntentSender(IIntentSender pendingResult) {
5889 if (!(pendingResult instanceof PendingIntentRecord)) {
5890 return null;
5891 }
5892 synchronized(this) {
5893 try {
5894 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5895 return res.key.packageName;
5896 } catch (ClassCastException e) {
5897 }
5898 }
5899 return null;
5900 }
5901
5902 public void setProcessLimit(int max) {
5903 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5904 "setProcessLimit()");
5905 mProcessLimit = max;
5906 }
5907
5908 public int getProcessLimit() {
5909 return mProcessLimit;
5910 }
5911
5912 void foregroundTokenDied(ForegroundToken token) {
5913 synchronized (ActivityManagerService.this) {
5914 synchronized (mPidsSelfLocked) {
5915 ForegroundToken cur
5916 = mForegroundProcesses.get(token.pid);
5917 if (cur != token) {
5918 return;
5919 }
5920 mForegroundProcesses.remove(token.pid);
5921 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5922 if (pr == null) {
5923 return;
5924 }
5925 pr.forcingToForeground = null;
5926 pr.foregroundServices = false;
5927 }
5928 updateOomAdjLocked();
5929 }
5930 }
5931
5932 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5933 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5934 "setProcessForeground()");
5935 synchronized(this) {
5936 boolean changed = false;
5937
5938 synchronized (mPidsSelfLocked) {
5939 ProcessRecord pr = mPidsSelfLocked.get(pid);
5940 if (pr == null) {
5941 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5942 return;
5943 }
5944 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5945 if (oldToken != null) {
5946 oldToken.token.unlinkToDeath(oldToken, 0);
5947 mForegroundProcesses.remove(pid);
5948 pr.forcingToForeground = null;
5949 changed = true;
5950 }
5951 if (isForeground && token != null) {
5952 ForegroundToken newToken = new ForegroundToken() {
5953 public void binderDied() {
5954 foregroundTokenDied(this);
5955 }
5956 };
5957 newToken.pid = pid;
5958 newToken.token = token;
5959 try {
5960 token.linkToDeath(newToken, 0);
5961 mForegroundProcesses.put(pid, newToken);
5962 pr.forcingToForeground = token;
5963 changed = true;
5964 } catch (RemoteException e) {
5965 // If the process died while doing this, we will later
5966 // do the cleanup with the process death link.
5967 }
5968 }
5969 }
5970
5971 if (changed) {
5972 updateOomAdjLocked();
5973 }
5974 }
5975 }
5976
5977 // =========================================================
5978 // PERMISSIONS
5979 // =========================================================
5980
5981 static class PermissionController extends IPermissionController.Stub {
5982 ActivityManagerService mActivityManagerService;
5983 PermissionController(ActivityManagerService activityManagerService) {
5984 mActivityManagerService = activityManagerService;
5985 }
5986
5987 public boolean checkPermission(String permission, int pid, int uid) {
5988 return mActivityManagerService.checkPermission(permission, pid,
5989 uid) == PackageManager.PERMISSION_GRANTED;
5990 }
5991 }
5992
5993 /**
5994 * This can be called with or without the global lock held.
5995 */
5996 int checkComponentPermission(String permission, int pid, int uid,
5997 int reqUid) {
5998 // We might be performing an operation on behalf of an indirect binder
5999 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6000 // client identity accordingly before proceeding.
6001 Identity tlsIdentity = sCallerIdentity.get();
6002 if (tlsIdentity != null) {
6003 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
6004 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6005 uid = tlsIdentity.uid;
6006 pid = tlsIdentity.pid;
6007 }
6008
6009 // Root, system server and our own process get to do everything.
6010 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6011 !Process.supportsProcesses()) {
6012 return PackageManager.PERMISSION_GRANTED;
6013 }
6014 // If the target requires a specific UID, always fail for others.
6015 if (reqUid >= 0 && uid != reqUid) {
root0369a7c2009-03-23 15:20:47 +01006016 Log.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 return PackageManager.PERMISSION_DENIED;
6018 }
6019 if (permission == null) {
6020 return PackageManager.PERMISSION_GRANTED;
6021 }
6022 try {
6023 return ActivityThread.getPackageManager()
6024 .checkUidPermission(permission, uid);
6025 } catch (RemoteException e) {
6026 // Should never happen, but if it does... deny!
6027 Log.e(TAG, "PackageManager is dead?!?", e);
6028 }
6029 return PackageManager.PERMISSION_DENIED;
6030 }
6031
6032 /**
6033 * As the only public entry point for permissions checking, this method
6034 * can enforce the semantic that requesting a check on a null global
6035 * permission is automatically denied. (Internally a null permission
6036 * string is used when calling {@link #checkComponentPermission} in cases
6037 * when only uid-based security is needed.)
6038 *
6039 * This can be called with or without the global lock held.
6040 */
6041 public int checkPermission(String permission, int pid, int uid) {
6042 if (permission == null) {
6043 return PackageManager.PERMISSION_DENIED;
6044 }
6045 return checkComponentPermission(permission, pid, uid, -1);
6046 }
6047
6048 /**
6049 * Binder IPC calls go through the public entry point.
6050 * This can be called with or without the global lock held.
6051 */
6052 int checkCallingPermission(String permission) {
6053 return checkPermission(permission,
6054 Binder.getCallingPid(),
6055 Binder.getCallingUid());
6056 }
6057
6058 /**
6059 * This can be called with or without the global lock held.
6060 */
6061 void enforceCallingPermission(String permission, String func) {
6062 if (checkCallingPermission(permission)
6063 == PackageManager.PERMISSION_GRANTED) {
6064 return;
6065 }
6066
6067 String msg = "Permission Denial: " + func + " from pid="
6068 + Binder.getCallingPid()
6069 + ", uid=" + Binder.getCallingUid()
6070 + " requires " + permission;
6071 Log.w(TAG, msg);
6072 throw new SecurityException(msg);
6073 }
6074
6075 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6076 ProviderInfo pi, int uid, int modeFlags) {
6077 try {
6078 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6079 if ((pi.readPermission != null) &&
6080 (pm.checkUidPermission(pi.readPermission, uid)
6081 != PackageManager.PERMISSION_GRANTED)) {
6082 return false;
6083 }
6084 }
6085 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6086 if ((pi.writePermission != null) &&
6087 (pm.checkUidPermission(pi.writePermission, uid)
6088 != PackageManager.PERMISSION_GRANTED)) {
6089 return false;
6090 }
6091 }
6092 return true;
6093 } catch (RemoteException e) {
6094 return false;
6095 }
6096 }
6097
6098 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6099 int modeFlags) {
6100 // Root gets to do everything.
6101 if (uid == 0 || !Process.supportsProcesses()) {
6102 return true;
6103 }
6104 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6105 if (perms == null) return false;
6106 UriPermission perm = perms.get(uri);
6107 if (perm == null) return false;
6108 return (modeFlags&perm.modeFlags) == modeFlags;
6109 }
6110
6111 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6112 // Another redirected-binder-call permissions check as in
6113 // {@link checkComponentPermission}.
6114 Identity tlsIdentity = sCallerIdentity.get();
6115 if (tlsIdentity != null) {
6116 uid = tlsIdentity.uid;
6117 pid = tlsIdentity.pid;
6118 }
6119
6120 // Our own process gets to do everything.
6121 if (pid == MY_PID) {
6122 return PackageManager.PERMISSION_GRANTED;
6123 }
6124 synchronized(this) {
6125 return checkUriPermissionLocked(uri, uid, modeFlags)
6126 ? PackageManager.PERMISSION_GRANTED
6127 : PackageManager.PERMISSION_DENIED;
6128 }
6129 }
6130
6131 private void grantUriPermissionLocked(int callingUid,
6132 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6133 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6134 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6135 if (modeFlags == 0) {
6136 return;
6137 }
6138
6139 final IPackageManager pm = ActivityThread.getPackageManager();
6140
6141 // If this is not a content: uri, we can't do anything with it.
6142 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
6143 return;
6144 }
6145
6146 String name = uri.getAuthority();
6147 ProviderInfo pi = null;
6148 ContentProviderRecord cpr
6149 = (ContentProviderRecord)mProvidersByName.get(name);
6150 if (cpr != null) {
6151 pi = cpr.info;
6152 } else {
6153 try {
6154 pi = pm.resolveContentProvider(name,
6155 PackageManager.GET_URI_PERMISSION_PATTERNS);
6156 } catch (RemoteException ex) {
6157 }
6158 }
6159 if (pi == null) {
6160 Log.w(TAG, "No content provider found for: " + name);
6161 return;
6162 }
6163
6164 int targetUid;
6165 try {
6166 targetUid = pm.getPackageUid(targetPkg);
6167 if (targetUid < 0) {
6168 return;
6169 }
6170 } catch (RemoteException ex) {
6171 return;
6172 }
6173
6174 // First... does the target actually need this permission?
6175 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6176 // No need to grant the target this permission.
6177 return;
6178 }
6179
6180 // Second... maybe someone else has already granted the
6181 // permission?
6182 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
6183 // No need to grant the target this permission.
6184 return;
6185 }
6186
6187 // Third... is the provider allowing granting of URI permissions?
6188 if (!pi.grantUriPermissions) {
6189 throw new SecurityException("Provider " + pi.packageName
6190 + "/" + pi.name
6191 + " does not allow granting of Uri permissions (uri "
6192 + uri + ")");
6193 }
6194 if (pi.uriPermissionPatterns != null) {
6195 final int N = pi.uriPermissionPatterns.length;
6196 boolean allowed = false;
6197 for (int i=0; i<N; i++) {
6198 if (pi.uriPermissionPatterns[i] != null
6199 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6200 allowed = true;
6201 break;
6202 }
6203 }
6204 if (!allowed) {
6205 throw new SecurityException("Provider " + pi.packageName
6206 + "/" + pi.name
6207 + " does not allow granting of permission to path of Uri "
6208 + uri);
6209 }
6210 }
6211
6212 // Fourth... does the caller itself have permission to access
6213 // this uri?
6214 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6215 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6216 throw new SecurityException("Uid " + callingUid
6217 + " does not have permission to uri " + uri);
6218 }
6219 }
6220
6221 // Okay! So here we are: the caller has the assumed permission
6222 // to the uri, and the target doesn't. Let's now give this to
6223 // the target.
6224
6225 HashMap<Uri, UriPermission> targetUris
6226 = mGrantedUriPermissions.get(targetUid);
6227 if (targetUris == null) {
6228 targetUris = new HashMap<Uri, UriPermission>();
6229 mGrantedUriPermissions.put(targetUid, targetUris);
6230 }
6231
6232 UriPermission perm = targetUris.get(uri);
6233 if (perm == null) {
6234 perm = new UriPermission(targetUid, uri);
6235 targetUris.put(uri, perm);
6236
6237 }
6238 perm.modeFlags |= modeFlags;
6239 if (activity == null) {
6240 perm.globalModeFlags |= modeFlags;
6241 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6242 perm.readActivities.add(activity);
6243 if (activity.readUriPermissions == null) {
6244 activity.readUriPermissions = new HashSet<UriPermission>();
6245 }
6246 activity.readUriPermissions.add(perm);
6247 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6248 perm.writeActivities.add(activity);
6249 if (activity.writeUriPermissions == null) {
6250 activity.writeUriPermissions = new HashSet<UriPermission>();
6251 }
6252 activity.writeUriPermissions.add(perm);
6253 }
6254 }
6255
6256 private void grantUriPermissionFromIntentLocked(int callingUid,
6257 String targetPkg, Intent intent, HistoryRecord activity) {
6258 if (intent == null) {
6259 return;
6260 }
6261 Uri data = intent.getData();
6262 if (data == null) {
6263 return;
6264 }
6265 grantUriPermissionLocked(callingUid, targetPkg, data,
6266 intent.getFlags(), activity);
6267 }
6268
6269 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6270 Uri uri, int modeFlags) {
6271 synchronized(this) {
6272 final ProcessRecord r = getRecordForAppLocked(caller);
6273 if (r == null) {
6274 throw new SecurityException("Unable to find app for caller "
6275 + caller
6276 + " when granting permission to uri " + uri);
6277 }
6278 if (targetPkg == null) {
6279 Log.w(TAG, "grantUriPermission: null target");
6280 return;
6281 }
6282 if (uri == null) {
6283 Log.w(TAG, "grantUriPermission: null uri");
6284 return;
6285 }
6286
6287 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6288 null);
6289 }
6290 }
6291
6292 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6293 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6294 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6295 HashMap<Uri, UriPermission> perms
6296 = mGrantedUriPermissions.get(perm.uid);
6297 if (perms != null) {
6298 perms.remove(perm.uri);
6299 if (perms.size() == 0) {
6300 mGrantedUriPermissions.remove(perm.uid);
6301 }
6302 }
6303 }
6304 }
6305
6306 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6307 if (activity.readUriPermissions != null) {
6308 for (UriPermission perm : activity.readUriPermissions) {
6309 perm.readActivities.remove(activity);
6310 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6311 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6312 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6313 removeUriPermissionIfNeededLocked(perm);
6314 }
6315 }
6316 }
6317 if (activity.writeUriPermissions != null) {
6318 for (UriPermission perm : activity.writeUriPermissions) {
6319 perm.writeActivities.remove(activity);
6320 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6321 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6322 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6323 removeUriPermissionIfNeededLocked(perm);
6324 }
6325 }
6326 }
6327 }
6328
6329 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6330 int modeFlags) {
6331 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6332 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6333 if (modeFlags == 0) {
6334 return;
6335 }
6336
6337 final IPackageManager pm = ActivityThread.getPackageManager();
6338
6339 final String authority = uri.getAuthority();
6340 ProviderInfo pi = null;
6341 ContentProviderRecord cpr
6342 = (ContentProviderRecord)mProvidersByName.get(authority);
6343 if (cpr != null) {
6344 pi = cpr.info;
6345 } else {
6346 try {
6347 pi = pm.resolveContentProvider(authority,
6348 PackageManager.GET_URI_PERMISSION_PATTERNS);
6349 } catch (RemoteException ex) {
6350 }
6351 }
6352 if (pi == null) {
6353 Log.w(TAG, "No content provider found for: " + authority);
6354 return;
6355 }
6356
6357 // Does the caller have this permission on the URI?
6358 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6359 // Right now, if you are not the original owner of the permission,
6360 // you are not allowed to revoke it.
6361 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6362 throw new SecurityException("Uid " + callingUid
6363 + " does not have permission to uri " + uri);
6364 //}
6365 }
6366
6367 // Go through all of the permissions and remove any that match.
6368 final List<String> SEGMENTS = uri.getPathSegments();
6369 if (SEGMENTS != null) {
6370 final int NS = SEGMENTS.size();
6371 int N = mGrantedUriPermissions.size();
6372 for (int i=0; i<N; i++) {
6373 HashMap<Uri, UriPermission> perms
6374 = mGrantedUriPermissions.valueAt(i);
6375 Iterator<UriPermission> it = perms.values().iterator();
6376 toploop:
6377 while (it.hasNext()) {
6378 UriPermission perm = it.next();
6379 Uri targetUri = perm.uri;
6380 if (!authority.equals(targetUri.getAuthority())) {
6381 continue;
6382 }
6383 List<String> targetSegments = targetUri.getPathSegments();
6384 if (targetSegments == null) {
6385 continue;
6386 }
6387 if (targetSegments.size() < NS) {
6388 continue;
6389 }
6390 for (int j=0; j<NS; j++) {
6391 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6392 continue toploop;
6393 }
6394 }
6395 perm.clearModes(modeFlags);
6396 if (perm.modeFlags == 0) {
6397 it.remove();
6398 }
6399 }
6400 if (perms.size() == 0) {
6401 mGrantedUriPermissions.remove(
6402 mGrantedUriPermissions.keyAt(i));
6403 N--;
6404 i--;
6405 }
6406 }
6407 }
6408 }
6409
6410 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6411 int modeFlags) {
6412 synchronized(this) {
6413 final ProcessRecord r = getRecordForAppLocked(caller);
6414 if (r == null) {
6415 throw new SecurityException("Unable to find app for caller "
6416 + caller
6417 + " when revoking permission to uri " + uri);
6418 }
6419 if (uri == null) {
6420 Log.w(TAG, "revokeUriPermission: null uri");
6421 return;
6422 }
6423
6424 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6425 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6426 if (modeFlags == 0) {
6427 return;
6428 }
6429
6430 final IPackageManager pm = ActivityThread.getPackageManager();
6431
6432 final String authority = uri.getAuthority();
6433 ProviderInfo pi = null;
6434 ContentProviderRecord cpr
6435 = (ContentProviderRecord)mProvidersByName.get(authority);
6436 if (cpr != null) {
6437 pi = cpr.info;
6438 } else {
6439 try {
6440 pi = pm.resolveContentProvider(authority,
6441 PackageManager.GET_URI_PERMISSION_PATTERNS);
6442 } catch (RemoteException ex) {
6443 }
6444 }
6445 if (pi == null) {
6446 Log.w(TAG, "No content provider found for: " + authority);
6447 return;
6448 }
6449
6450 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6451 }
6452 }
6453
6454 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6455 synchronized (this) {
6456 ProcessRecord app =
6457 who != null ? getRecordForAppLocked(who) : null;
6458 if (app == null) return;
6459
6460 Message msg = Message.obtain();
6461 msg.what = WAIT_FOR_DEBUGGER_MSG;
6462 msg.obj = app;
6463 msg.arg1 = waiting ? 1 : 0;
6464 mHandler.sendMessage(msg);
6465 }
6466 }
6467
6468 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6469 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006470 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006472 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006473 }
6474
6475 // =========================================================
6476 // TASK MANAGEMENT
6477 // =========================================================
6478
6479 public List getTasks(int maxNum, int flags,
6480 IThumbnailReceiver receiver) {
6481 ArrayList list = new ArrayList();
6482
6483 PendingThumbnailsRecord pending = null;
6484 IApplicationThread topThumbnail = null;
6485 HistoryRecord topRecord = null;
6486
6487 synchronized(this) {
6488 if (localLOGV) Log.v(
6489 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6490 + ", receiver=" + receiver);
6491
6492 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6493 != PackageManager.PERMISSION_GRANTED) {
6494 if (receiver != null) {
6495 // If the caller wants to wait for pending thumbnails,
6496 // it ain't gonna get them.
6497 try {
6498 receiver.finished();
6499 } catch (RemoteException ex) {
6500 }
6501 }
6502 String msg = "Permission Denial: getTasks() from pid="
6503 + Binder.getCallingPid()
6504 + ", uid=" + Binder.getCallingUid()
6505 + " requires " + android.Manifest.permission.GET_TASKS;
6506 Log.w(TAG, msg);
6507 throw new SecurityException(msg);
6508 }
6509
6510 int pos = mHistory.size()-1;
6511 HistoryRecord next =
6512 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6513 HistoryRecord top = null;
6514 CharSequence topDescription = null;
6515 TaskRecord curTask = null;
6516 int numActivities = 0;
6517 int numRunning = 0;
6518 while (pos >= 0 && maxNum > 0) {
6519 final HistoryRecord r = next;
6520 pos--;
6521 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6522
6523 // Initialize state for next task if needed.
6524 if (top == null ||
6525 (top.state == ActivityState.INITIALIZING
6526 && top.task == r.task)) {
6527 top = r;
6528 topDescription = r.description;
6529 curTask = r.task;
6530 numActivities = numRunning = 0;
6531 }
6532
6533 // Add 'r' into the current task.
6534 numActivities++;
6535 if (r.app != null && r.app.thread != null) {
6536 numRunning++;
6537 }
6538 if (topDescription == null) {
6539 topDescription = r.description;
6540 }
6541
6542 if (localLOGV) Log.v(
6543 TAG, r.intent.getComponent().flattenToShortString()
6544 + ": task=" + r.task);
6545
6546 // If the next one is a different task, generate a new
6547 // TaskInfo entry for what we have.
6548 if (next == null || next.task != curTask) {
6549 ActivityManager.RunningTaskInfo ci
6550 = new ActivityManager.RunningTaskInfo();
6551 ci.id = curTask.taskId;
6552 ci.baseActivity = r.intent.getComponent();
6553 ci.topActivity = top.intent.getComponent();
6554 ci.thumbnail = top.thumbnail;
6555 ci.description = topDescription;
6556 ci.numActivities = numActivities;
6557 ci.numRunning = numRunning;
6558 //System.out.println(
6559 // "#" + maxNum + ": " + " descr=" + ci.description);
6560 if (ci.thumbnail == null && receiver != null) {
6561 if (localLOGV) Log.v(
6562 TAG, "State=" + top.state + "Idle=" + top.idle
6563 + " app=" + top.app
6564 + " thr=" + (top.app != null ? top.app.thread : null));
6565 if (top.state == ActivityState.RESUMED
6566 || top.state == ActivityState.PAUSING) {
6567 if (top.idle && top.app != null
6568 && top.app.thread != null) {
6569 topRecord = top;
6570 topThumbnail = top.app.thread;
6571 } else {
6572 top.thumbnailNeeded = true;
6573 }
6574 }
6575 if (pending == null) {
6576 pending = new PendingThumbnailsRecord(receiver);
6577 }
6578 pending.pendingRecords.add(top);
6579 }
6580 list.add(ci);
6581 maxNum--;
6582 top = null;
6583 }
6584 }
6585
6586 if (pending != null) {
6587 mPendingThumbnails.add(pending);
6588 }
6589 }
6590
6591 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
6592
6593 if (topThumbnail != null) {
6594 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
6595 try {
6596 topThumbnail.requestThumbnail(topRecord);
6597 } catch (Exception e) {
6598 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
6599 sendPendingThumbnail(null, topRecord, null, null, true);
6600 }
6601 }
6602
6603 if (pending == null && receiver != null) {
6604 // In this case all thumbnails were available and the client
6605 // is being asked to be told when the remaining ones come in...
6606 // which is unusually, since the top-most currently running
6607 // activity should never have a canned thumbnail! Oh well.
6608 try {
6609 receiver.finished();
6610 } catch (RemoteException ex) {
6611 }
6612 }
6613
6614 return list;
6615 }
6616
6617 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6618 int flags) {
6619 synchronized (this) {
6620 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6621 "getRecentTasks()");
6622
6623 final int N = mRecentTasks.size();
6624 ArrayList<ActivityManager.RecentTaskInfo> res
6625 = new ArrayList<ActivityManager.RecentTaskInfo>(
6626 maxNum < N ? maxNum : N);
6627 for (int i=0; i<N && maxNum > 0; i++) {
6628 TaskRecord tr = mRecentTasks.get(i);
6629 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6630 || (tr.intent == null)
6631 || ((tr.intent.getFlags()
6632 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6633 ActivityManager.RecentTaskInfo rti
6634 = new ActivityManager.RecentTaskInfo();
6635 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6636 rti.baseIntent = new Intent(
6637 tr.intent != null ? tr.intent : tr.affinityIntent);
6638 rti.origActivity = tr.origActivity;
6639 res.add(rti);
6640 maxNum--;
6641 }
6642 }
6643 return res;
6644 }
6645 }
6646
6647 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6648 int j;
6649 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6650 TaskRecord jt = startTask;
6651
6652 // First look backwards
6653 for (j=startIndex-1; j>=0; j--) {
6654 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6655 if (r.task != jt) {
6656 jt = r.task;
6657 if (affinity.equals(jt.affinity)) {
6658 return j;
6659 }
6660 }
6661 }
6662
6663 // Now look forwards
6664 final int N = mHistory.size();
6665 jt = startTask;
6666 for (j=startIndex+1; j<N; j++) {
6667 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6668 if (r.task != jt) {
6669 if (affinity.equals(jt.affinity)) {
6670 return j;
6671 }
6672 jt = r.task;
6673 }
6674 }
6675
6676 // Might it be at the top?
6677 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6678 return N-1;
6679 }
6680
6681 return -1;
6682 }
6683
6684 /**
6685 * Perform a reset of the given task, if needed as part of launching it.
6686 * Returns the new HistoryRecord at the top of the task.
6687 */
6688 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6689 HistoryRecord newActivity) {
6690 boolean forceReset = (newActivity.info.flags
6691 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6692 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6693 if ((newActivity.info.flags
6694 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6695 forceReset = true;
6696 }
6697 }
6698
6699 final TaskRecord task = taskTop.task;
6700
6701 // We are going to move through the history list so that we can look
6702 // at each activity 'target' with 'below' either the interesting
6703 // activity immediately below it in the stack or null.
6704 HistoryRecord target = null;
6705 int targetI = 0;
6706 int taskTopI = -1;
6707 int replyChainEnd = -1;
6708 int lastReparentPos = -1;
6709 for (int i=mHistory.size()-1; i>=-1; i--) {
6710 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6711
6712 if (below != null && below.finishing) {
6713 continue;
6714 }
6715 if (target == null) {
6716 target = below;
6717 targetI = i;
6718 // If we were in the middle of a reply chain before this
6719 // task, it doesn't appear like the root of the chain wants
6720 // anything interesting, so drop it.
6721 replyChainEnd = -1;
6722 continue;
6723 }
6724
6725 final int flags = target.info.flags;
6726
6727 final boolean finishOnTaskLaunch =
6728 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6729 final boolean allowTaskReparenting =
6730 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6731
6732 if (target.task == task) {
6733 // We are inside of the task being reset... we'll either
6734 // finish this activity, push it out for another task,
6735 // or leave it as-is. We only do this
6736 // for activities that are not the root of the task (since
6737 // if we finish the root, we may no longer have the task!).
6738 if (taskTopI < 0) {
6739 taskTopI = targetI;
6740 }
6741 if (below != null && below.task == task) {
6742 final boolean clearWhenTaskReset =
6743 (target.intent.getFlags()
6744 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006745 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 // If this activity is sending a reply to a previous
6747 // activity, we can't do anything with it now until
6748 // we reach the start of the reply chain.
6749 // XXX note that we are assuming the result is always
6750 // to the previous activity, which is almost always
6751 // the case but we really shouldn't count on.
6752 if (replyChainEnd < 0) {
6753 replyChainEnd = targetI;
6754 }
Ed Heyl73798232009-03-24 21:32:21 -07006755 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 && target.taskAffinity != null
6757 && !target.taskAffinity.equals(task.affinity)) {
6758 // If this activity has an affinity for another
6759 // task, then we need to move it out of here. We will
6760 // move it as far out of the way as possible, to the
6761 // bottom of the activity stack. This also keeps it
6762 // correctly ordered with any activities we previously
6763 // moved.
6764 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6765 if (target.taskAffinity != null
6766 && target.taskAffinity.equals(p.task.affinity)) {
6767 // If the activity currently at the bottom has the
6768 // same task affinity as the one we are moving,
6769 // then merge it into the same task.
6770 target.task = p.task;
6771 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6772 + " out to bottom task " + p.task);
6773 } else {
6774 mCurTask++;
6775 if (mCurTask <= 0) {
6776 mCurTask = 1;
6777 }
6778 target.task = new TaskRecord(mCurTask, target.info, null,
6779 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6780 target.task.affinityIntent = target.intent;
6781 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6782 + " out to new task " + target.task);
6783 }
6784 mWindowManager.setAppGroupId(target, task.taskId);
6785 if (replyChainEnd < 0) {
6786 replyChainEnd = targetI;
6787 }
6788 int dstPos = 0;
6789 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6790 p = (HistoryRecord)mHistory.get(srcPos);
6791 if (p.finishing) {
6792 continue;
6793 }
6794 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6795 + " out to target's task " + target.task);
6796 task.numActivities--;
6797 p.task = target.task;
6798 target.task.numActivities++;
6799 mHistory.remove(srcPos);
6800 mHistory.add(dstPos, p);
6801 mWindowManager.moveAppToken(dstPos, p);
6802 mWindowManager.setAppGroupId(p, p.task.taskId);
6803 dstPos++;
6804 if (VALIDATE_TOKENS) {
6805 mWindowManager.validateAppTokens(mHistory);
6806 }
6807 i++;
6808 }
6809 if (taskTop == p) {
6810 taskTop = below;
6811 }
6812 if (taskTopI == replyChainEnd) {
6813 taskTopI = -1;
6814 }
6815 replyChainEnd = -1;
6816 addRecentTask(target.task);
6817 } else if (forceReset || finishOnTaskLaunch
6818 || clearWhenTaskReset) {
6819 // If the activity should just be removed -- either
6820 // because it asks for it, or the task should be
6821 // cleared -- then finish it and anything that is
6822 // part of its reply chain.
6823 if (clearWhenTaskReset) {
6824 // In this case, we want to finish this activity
6825 // and everything above it, so be sneaky and pretend
6826 // like these are all in the reply chain.
6827 replyChainEnd = targetI+1;
6828 while (replyChainEnd < mHistory.size() &&
6829 ((HistoryRecord)mHistory.get(
6830 replyChainEnd)).task == task) {
6831 replyChainEnd++;
6832 }
6833 replyChainEnd--;
6834 } else if (replyChainEnd < 0) {
6835 replyChainEnd = targetI;
6836 }
6837 HistoryRecord p = null;
6838 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6839 p = (HistoryRecord)mHistory.get(srcPos);
6840 if (p.finishing) {
6841 continue;
6842 }
6843 if (finishActivityLocked(p, srcPos,
6844 Activity.RESULT_CANCELED, null, "reset")) {
6845 replyChainEnd--;
6846 srcPos--;
6847 }
6848 }
6849 if (taskTop == p) {
6850 taskTop = below;
6851 }
6852 if (taskTopI == replyChainEnd) {
6853 taskTopI = -1;
6854 }
6855 replyChainEnd = -1;
6856 } else {
6857 // If we were in the middle of a chain, well the
6858 // activity that started it all doesn't want anything
6859 // special, so leave it all as-is.
6860 replyChainEnd = -1;
6861 }
6862 } else {
6863 // Reached the bottom of the task -- any reply chain
6864 // should be left as-is.
6865 replyChainEnd = -1;
6866 }
6867
6868 } else if (target.resultTo != null) {
6869 // If this activity is sending a reply to a previous
6870 // activity, we can't do anything with it now until
6871 // we reach the start of the reply chain.
6872 // XXX note that we are assuming the result is always
6873 // to the previous activity, which is almost always
6874 // the case but we really shouldn't count on.
6875 if (replyChainEnd < 0) {
6876 replyChainEnd = targetI;
6877 }
6878
6879 } else if (taskTopI >= 0 && allowTaskReparenting
6880 && task.affinity != null
6881 && task.affinity.equals(target.taskAffinity)) {
6882 // We are inside of another task... if this activity has
6883 // an affinity for our task, then either remove it if we are
6884 // clearing or move it over to our task. Note that
6885 // we currently punt on the case where we are resetting a
6886 // task that is not at the top but who has activities above
6887 // with an affinity to it... this is really not a normal
6888 // case, and we will need to later pull that task to the front
6889 // and usually at that point we will do the reset and pick
6890 // up those remaining activities. (This only happens if
6891 // someone starts an activity in a new task from an activity
6892 // in a task that is not currently on top.)
6893 if (forceReset || finishOnTaskLaunch) {
6894 if (replyChainEnd < 0) {
6895 replyChainEnd = targetI;
6896 }
6897 HistoryRecord p = null;
6898 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6899 p = (HistoryRecord)mHistory.get(srcPos);
6900 if (p.finishing) {
6901 continue;
6902 }
6903 if (finishActivityLocked(p, srcPos,
6904 Activity.RESULT_CANCELED, null, "reset")) {
6905 taskTopI--;
6906 lastReparentPos--;
6907 replyChainEnd--;
6908 srcPos--;
6909 }
6910 }
6911 replyChainEnd = -1;
6912 } else {
6913 if (replyChainEnd < 0) {
6914 replyChainEnd = targetI;
6915 }
6916 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6917 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6918 if (p.finishing) {
6919 continue;
6920 }
6921 if (lastReparentPos < 0) {
6922 lastReparentPos = taskTopI;
6923 taskTop = p;
6924 } else {
6925 lastReparentPos--;
6926 }
6927 mHistory.remove(srcPos);
6928 p.task.numActivities--;
6929 p.task = task;
6930 mHistory.add(lastReparentPos, p);
6931 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6932 + " in to resetting task " + task);
6933 task.numActivities++;
6934 mWindowManager.moveAppToken(lastReparentPos, p);
6935 mWindowManager.setAppGroupId(p, p.task.taskId);
6936 if (VALIDATE_TOKENS) {
6937 mWindowManager.validateAppTokens(mHistory);
6938 }
6939 }
6940 replyChainEnd = -1;
6941
6942 // Now we've moved it in to place... but what if this is
6943 // a singleTop activity and we have put it on top of another
6944 // instance of the same activity? Then we drop the instance
6945 // below so it remains singleTop.
6946 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6947 for (int j=lastReparentPos-1; j>=0; j--) {
6948 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6949 if (p.finishing) {
6950 continue;
6951 }
6952 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6953 if (finishActivityLocked(p, j,
6954 Activity.RESULT_CANCELED, null, "replace")) {
6955 taskTopI--;
6956 lastReparentPos--;
6957 }
6958 }
6959 }
6960 }
6961 }
6962 }
6963
6964 target = below;
6965 targetI = i;
6966 }
6967
6968 return taskTop;
6969 }
6970
6971 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006972 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006973 */
6974 public void moveTaskToFront(int task) {
6975 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6976 "moveTaskToFront()");
6977
6978 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006979 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6980 Binder.getCallingUid(), "Task to front")) {
6981 return;
6982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006983 final long origId = Binder.clearCallingIdentity();
6984 try {
6985 int N = mRecentTasks.size();
6986 for (int i=0; i<N; i++) {
6987 TaskRecord tr = mRecentTasks.get(i);
6988 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006989 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990 return;
6991 }
6992 }
6993 for (int i=mHistory.size()-1; i>=0; i--) {
6994 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
6995 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006996 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006997 return;
6998 }
6999 }
7000 } finally {
7001 Binder.restoreCallingIdentity(origId);
7002 }
7003 }
7004 }
7005
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007006 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007007 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
7008
7009 final int task = tr.taskId;
7010 int top = mHistory.size()-1;
7011
7012 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7013 // nothing to do!
7014 return;
7015 }
7016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007017 ArrayList moved = new ArrayList();
7018
7019 // Applying the affinities may have removed entries from the history,
7020 // so get the size again.
7021 top = mHistory.size()-1;
7022 int pos = top;
7023
7024 // Shift all activities with this task up to the top
7025 // of the stack, keeping them in the same internal order.
7026 while (pos >= 0) {
7027 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7028 if (localLOGV) Log.v(
7029 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7030 boolean first = true;
7031 if (r.task.taskId == task) {
7032 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
7033 mHistory.remove(pos);
7034 mHistory.add(top, r);
7035 moved.add(0, r);
7036 top--;
7037 if (first) {
7038 addRecentTask(r.task);
7039 first = false;
7040 }
7041 }
7042 pos--;
7043 }
7044
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007045 if (DEBUG_TRANSITION) Log.v(TAG,
7046 "Prepare to front transition: task=" + tr);
7047 if (reason != null &&
7048 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7049 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7050 HistoryRecord r = topRunningActivityLocked(null);
7051 if (r != null) {
7052 mNoAnimActivities.add(r);
7053 }
7054 } else {
7055 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7056 }
7057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 mWindowManager.moveAppTokensToTop(moved);
7059 if (VALIDATE_TOKENS) {
7060 mWindowManager.validateAppTokens(mHistory);
7061 }
7062
7063 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007064 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 }
7066
7067 private final void finishTaskMove(int task) {
7068 resumeTopActivityLocked(null);
7069 }
7070
7071 public void moveTaskToBack(int task) {
7072 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7073 "moveTaskToBack()");
7074
7075 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007076 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7077 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7078 Binder.getCallingUid(), "Task to back")) {
7079 return;
7080 }
7081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007083 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007084 Binder.restoreCallingIdentity(origId);
7085 }
7086 }
7087
7088 /**
7089 * Moves an activity, and all of the other activities within the same task, to the bottom
7090 * of the history stack. The activity's order within the task is unchanged.
7091 *
7092 * @param token A reference to the activity we wish to move
7093 * @param nonRoot If false then this only works if the activity is the root
7094 * of a task; if true it will work for any activity in a task.
7095 * @return Returns true if the move completed, false if not.
7096 */
7097 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7098 synchronized(this) {
7099 final long origId = Binder.clearCallingIdentity();
7100 int taskId = getTaskForActivityLocked(token, !nonRoot);
7101 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007102 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 }
7104 Binder.restoreCallingIdentity(origId);
7105 }
7106 return false;
7107 }
7108
7109 /**
7110 * Worker method for rearranging history stack. Implements the function of moving all
7111 * activities for a specific task (gathering them if disjoint) into a single group at the
7112 * bottom of the stack.
7113 *
7114 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7115 * to premeptively cancel the move.
7116 *
7117 * @param task The taskId to collect and move to the bottom.
7118 * @return Returns true if the move completed, false if not.
7119 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007120 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 Log.i(TAG, "moveTaskToBack: " + task);
7122
7123 // If we have a watcher, preflight the move before committing to it. First check
7124 // for *other* available tasks, but if none are available, then try again allowing the
7125 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007126 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 HistoryRecord next = topRunningActivityLocked(null, task);
7128 if (next == null) {
7129 next = topRunningActivityLocked(null, 0);
7130 }
7131 if (next != null) {
7132 // ask watcher if this is allowed
7133 boolean moveOK = true;
7134 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007135 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007136 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007137 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 }
7139 if (!moveOK) {
7140 return false;
7141 }
7142 }
7143 }
7144
7145 ArrayList moved = new ArrayList();
7146
7147 if (DEBUG_TRANSITION) Log.v(TAG,
7148 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149
7150 final int N = mHistory.size();
7151 int bottom = 0;
7152 int pos = 0;
7153
7154 // Shift all activities with this task down to the bottom
7155 // of the stack, keeping them in the same internal order.
7156 while (pos < N) {
7157 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7158 if (localLOGV) Log.v(
7159 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7160 if (r.task.taskId == task) {
7161 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
7162 mHistory.remove(pos);
7163 mHistory.add(bottom, r);
7164 moved.add(r);
7165 bottom++;
7166 }
7167 pos++;
7168 }
7169
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007170 if (reason != null &&
7171 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7172 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7173 HistoryRecord r = topRunningActivityLocked(null);
7174 if (r != null) {
7175 mNoAnimActivities.add(r);
7176 }
7177 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007178 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 mWindowManager.moveAppTokensToBottom(moved);
7181 if (VALIDATE_TOKENS) {
7182 mWindowManager.validateAppTokens(mHistory);
7183 }
7184
7185 finishTaskMove(task);
7186 return true;
7187 }
7188
7189 public void moveTaskBackwards(int task) {
7190 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7191 "moveTaskBackwards()");
7192
7193 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007194 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7195 Binder.getCallingUid(), "Task backwards")) {
7196 return;
7197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 final long origId = Binder.clearCallingIdentity();
7199 moveTaskBackwardsLocked(task);
7200 Binder.restoreCallingIdentity(origId);
7201 }
7202 }
7203
7204 private final void moveTaskBackwardsLocked(int task) {
7205 Log.e(TAG, "moveTaskBackwards not yet implemented!");
7206 }
7207
7208 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7209 synchronized(this) {
7210 return getTaskForActivityLocked(token, onlyRoot);
7211 }
7212 }
7213
7214 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7215 final int N = mHistory.size();
7216 TaskRecord lastTask = null;
7217 for (int i=0; i<N; i++) {
7218 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7219 if (r == token) {
7220 if (!onlyRoot || lastTask != r.task) {
7221 return r.task.taskId;
7222 }
7223 return -1;
7224 }
7225 lastTask = r.task;
7226 }
7227
7228 return -1;
7229 }
7230
7231 /**
7232 * Returns the top activity in any existing task matching the given
7233 * Intent. Returns null if no such task is found.
7234 */
7235 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7236 ComponentName cls = intent.getComponent();
7237 if (info.targetActivity != null) {
7238 cls = new ComponentName(info.packageName, info.targetActivity);
7239 }
7240
7241 TaskRecord cp = null;
7242
7243 final int N = mHistory.size();
7244 for (int i=(N-1); i>=0; i--) {
7245 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7246 if (!r.finishing && r.task != cp
7247 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7248 cp = r.task;
7249 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
7250 // + "/aff=" + r.task.affinity + " to new cls="
7251 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7252 if (r.task.affinity != null) {
7253 if (r.task.affinity.equals(info.taskAffinity)) {
7254 //Log.i(TAG, "Found matching affinity!");
7255 return r;
7256 }
7257 } else if (r.task.intent != null
7258 && r.task.intent.getComponent().equals(cls)) {
7259 //Log.i(TAG, "Found matching class!");
7260 //dump();
7261 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7262 return r;
7263 } else if (r.task.affinityIntent != null
7264 && r.task.affinityIntent.getComponent().equals(cls)) {
7265 //Log.i(TAG, "Found matching class!");
7266 //dump();
7267 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7268 return r;
7269 }
7270 }
7271 }
7272
7273 return null;
7274 }
7275
7276 /**
7277 * Returns the first activity (starting from the top of the stack) that
7278 * is the same as the given activity. Returns null if no such activity
7279 * is found.
7280 */
7281 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7282 ComponentName cls = intent.getComponent();
7283 if (info.targetActivity != null) {
7284 cls = new ComponentName(info.packageName, info.targetActivity);
7285 }
7286
7287 final int N = mHistory.size();
7288 for (int i=(N-1); i>=0; i--) {
7289 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7290 if (!r.finishing) {
7291 if (r.intent.getComponent().equals(cls)) {
7292 //Log.i(TAG, "Found matching class!");
7293 //dump();
7294 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7295 return r;
7296 }
7297 }
7298 }
7299
7300 return null;
7301 }
7302
7303 public void finishOtherInstances(IBinder token, ComponentName className) {
7304 synchronized(this) {
7305 final long origId = Binder.clearCallingIdentity();
7306
7307 int N = mHistory.size();
7308 TaskRecord lastTask = null;
7309 for (int i=0; i<N; i++) {
7310 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7311 if (r.realActivity.equals(className)
7312 && r != token && lastTask != r.task) {
7313 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7314 null, "others")) {
7315 i--;
7316 N--;
7317 }
7318 }
7319 lastTask = r.task;
7320 }
7321
7322 Binder.restoreCallingIdentity(origId);
7323 }
7324 }
7325
7326 // =========================================================
7327 // THUMBNAILS
7328 // =========================================================
7329
7330 public void reportThumbnail(IBinder token,
7331 Bitmap thumbnail, CharSequence description) {
7332 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7333 final long origId = Binder.clearCallingIdentity();
7334 sendPendingThumbnail(null, token, thumbnail, description, true);
7335 Binder.restoreCallingIdentity(origId);
7336 }
7337
7338 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7339 Bitmap thumbnail, CharSequence description, boolean always) {
7340 TaskRecord task = null;
7341 ArrayList receivers = null;
7342
7343 //System.out.println("Send pending thumbnail: " + r);
7344
7345 synchronized(this) {
7346 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007347 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007348 if (index < 0) {
7349 return;
7350 }
7351 r = (HistoryRecord)mHistory.get(index);
7352 }
7353 if (thumbnail == null) {
7354 thumbnail = r.thumbnail;
7355 description = r.description;
7356 }
7357 if (thumbnail == null && !always) {
7358 // If there is no thumbnail, and this entry is not actually
7359 // going away, then abort for now and pick up the next
7360 // thumbnail we get.
7361 return;
7362 }
7363 task = r.task;
7364
7365 int N = mPendingThumbnails.size();
7366 int i=0;
7367 while (i<N) {
7368 PendingThumbnailsRecord pr =
7369 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7370 //System.out.println("Looking in " + pr.pendingRecords);
7371 if (pr.pendingRecords.remove(r)) {
7372 if (receivers == null) {
7373 receivers = new ArrayList();
7374 }
7375 receivers.add(pr);
7376 if (pr.pendingRecords.size() == 0) {
7377 pr.finished = true;
7378 mPendingThumbnails.remove(i);
7379 N--;
7380 continue;
7381 }
7382 }
7383 i++;
7384 }
7385 }
7386
7387 if (receivers != null) {
7388 final int N = receivers.size();
7389 for (int i=0; i<N; i++) {
7390 try {
7391 PendingThumbnailsRecord pr =
7392 (PendingThumbnailsRecord)receivers.get(i);
7393 pr.receiver.newThumbnail(
7394 task != null ? task.taskId : -1, thumbnail, description);
7395 if (pr.finished) {
7396 pr.receiver.finished();
7397 }
7398 } catch (Exception e) {
7399 Log.w(TAG, "Exception thrown when sending thumbnail", e);
7400 }
7401 }
7402 }
7403 }
7404
7405 // =========================================================
7406 // CONTENT PROVIDERS
7407 // =========================================================
7408
7409 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7410 List providers = null;
7411 try {
7412 providers = ActivityThread.getPackageManager().
7413 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007414 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 } catch (RemoteException ex) {
7416 }
7417 if (providers != null) {
7418 final int N = providers.size();
7419 for (int i=0; i<N; i++) {
7420 ProviderInfo cpi =
7421 (ProviderInfo)providers.get(i);
7422 ContentProviderRecord cpr =
7423 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7424 if (cpr == null) {
7425 cpr = new ContentProviderRecord(cpi, app.info);
7426 mProvidersByClass.put(cpi.name, cpr);
7427 }
7428 app.pubProviders.put(cpi.name, cpr);
7429 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007430 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 }
7432 }
7433 return providers;
7434 }
7435
7436 private final String checkContentProviderPermissionLocked(
7437 ProviderInfo cpi, ProcessRecord r, int mode) {
7438 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7439 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7440 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7441 cpi.exported ? -1 : cpi.applicationInfo.uid)
7442 == PackageManager.PERMISSION_GRANTED
7443 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7444 return null;
7445 }
7446 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7447 cpi.exported ? -1 : cpi.applicationInfo.uid)
7448 == PackageManager.PERMISSION_GRANTED) {
7449 return null;
7450 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007451
7452 PathPermission[] pps = cpi.pathPermissions;
7453 if (pps != null) {
7454 int i = pps.length;
7455 while (i > 0) {
7456 i--;
7457 PathPermission pp = pps[i];
7458 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7459 cpi.exported ? -1 : cpi.applicationInfo.uid)
7460 == PackageManager.PERMISSION_GRANTED
7461 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7462 return null;
7463 }
7464 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7465 cpi.exported ? -1 : cpi.applicationInfo.uid)
7466 == PackageManager.PERMISSION_GRANTED) {
7467 return null;
7468 }
7469 }
7470 }
7471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 String msg = "Permission Denial: opening provider " + cpi.name
7473 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7474 + ", uid=" + callingUid + ") requires "
7475 + cpi.readPermission + " or " + cpi.writePermission;
7476 Log.w(TAG, msg);
7477 return msg;
7478 }
7479
7480 private final ContentProviderHolder getContentProviderImpl(
7481 IApplicationThread caller, String name) {
7482 ContentProviderRecord cpr;
7483 ProviderInfo cpi = null;
7484
7485 synchronized(this) {
7486 ProcessRecord r = null;
7487 if (caller != null) {
7488 r = getRecordForAppLocked(caller);
7489 if (r == null) {
7490 throw new SecurityException(
7491 "Unable to find app for caller " + caller
7492 + " (pid=" + Binder.getCallingPid()
7493 + ") when getting content provider " + name);
7494 }
7495 }
7496
7497 // First check if this content provider has been published...
7498 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7499 if (cpr != null) {
7500 cpi = cpr.info;
7501 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7502 return new ContentProviderHolder(cpi,
7503 cpi.readPermission != null
7504 ? cpi.readPermission : cpi.writePermission);
7505 }
7506
7507 if (r != null && cpr.canRunHere(r)) {
7508 // This provider has been published or is in the process
7509 // of being published... but it is also allowed to run
7510 // in the caller's process, so don't make a connection
7511 // and just let the caller instantiate its own instance.
7512 if (cpr.provider != null) {
7513 // don't give caller the provider object, it needs
7514 // to make its own.
7515 cpr = new ContentProviderRecord(cpr);
7516 }
7517 return cpr;
7518 }
7519
7520 final long origId = Binder.clearCallingIdentity();
7521
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007522 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 // return it right away.
7524 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007525 if (DEBUG_PROVIDER) Log.v(TAG,
7526 "Adding provider requested by "
7527 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007528 + cpr.info.processName);
7529 Integer cnt = r.conProviders.get(cpr);
7530 if (cnt == null) {
7531 r.conProviders.put(cpr, new Integer(1));
7532 } else {
7533 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 cpr.clients.add(r);
7536 } else {
7537 cpr.externals++;
7538 }
7539
7540 if (cpr.app != null) {
7541 updateOomAdjLocked(cpr.app);
7542 }
7543
7544 Binder.restoreCallingIdentity(origId);
7545
7546 } else {
7547 try {
7548 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007549 resolveContentProvider(name,
7550 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 } catch (RemoteException ex) {
7552 }
7553 if (cpi == null) {
7554 return null;
7555 }
7556
7557 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7558 return new ContentProviderHolder(cpi,
7559 cpi.readPermission != null
7560 ? cpi.readPermission : cpi.writePermission);
7561 }
7562
7563 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7564 final boolean firstClass = cpr == null;
7565 if (firstClass) {
7566 try {
7567 ApplicationInfo ai =
7568 ActivityThread.getPackageManager().
7569 getApplicationInfo(
7570 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007571 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 if (ai == null) {
7573 Log.w(TAG, "No package info for content provider "
7574 + cpi.name);
7575 return null;
7576 }
7577 cpr = new ContentProviderRecord(cpi, ai);
7578 } catch (RemoteException ex) {
7579 // pm is in same process, this will never happen.
7580 }
7581 }
7582
7583 if (r != null && cpr.canRunHere(r)) {
7584 // If this is a multiprocess provider, then just return its
7585 // info and allow the caller to instantiate it. Only do
7586 // this if the provider is the same user as the caller's
7587 // process, or can run as root (so can be in any process).
7588 return cpr;
7589 }
7590
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007591 if (DEBUG_PROVIDER) {
7592 RuntimeException e = new RuntimeException("here");
7593 Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
7594 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595 }
7596
7597 // This is single process, and our app is now connecting to it.
7598 // See if we are already in the process of launching this
7599 // provider.
7600 final int N = mLaunchingProviders.size();
7601 int i;
7602 for (i=0; i<N; i++) {
7603 if (mLaunchingProviders.get(i) == cpr) {
7604 break;
7605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 }
7607
7608 // If the provider is not already being launched, then get it
7609 // started.
7610 if (i >= N) {
7611 final long origId = Binder.clearCallingIdentity();
7612 ProcessRecord proc = startProcessLocked(cpi.processName,
7613 cpr.appInfo, false, 0, "content provider",
7614 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007615 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007616 if (proc == null) {
7617 Log.w(TAG, "Unable to launch app "
7618 + cpi.applicationInfo.packageName + "/"
7619 + cpi.applicationInfo.uid + " for provider "
7620 + name + ": process is bad");
7621 return null;
7622 }
7623 cpr.launchingApp = proc;
7624 mLaunchingProviders.add(cpr);
7625 Binder.restoreCallingIdentity(origId);
7626 }
7627
7628 // Make sure the provider is published (the same provider class
7629 // may be published under multiple names).
7630 if (firstClass) {
7631 mProvidersByClass.put(cpi.name, cpr);
7632 }
7633 mProvidersByName.put(name, cpr);
7634
7635 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007636 if (DEBUG_PROVIDER) Log.v(TAG,
7637 "Adding provider requested by "
7638 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007639 + cpr.info.processName);
7640 Integer cnt = r.conProviders.get(cpr);
7641 if (cnt == null) {
7642 r.conProviders.put(cpr, new Integer(1));
7643 } else {
7644 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 cpr.clients.add(r);
7647 } else {
7648 cpr.externals++;
7649 }
7650 }
7651 }
7652
7653 // Wait for the provider to be published...
7654 synchronized (cpr) {
7655 while (cpr.provider == null) {
7656 if (cpr.launchingApp == null) {
7657 Log.w(TAG, "Unable to launch app "
7658 + cpi.applicationInfo.packageName + "/"
7659 + cpi.applicationInfo.uid + " for provider "
7660 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007661 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 cpi.applicationInfo.packageName,
7663 cpi.applicationInfo.uid, name);
7664 return null;
7665 }
7666 try {
7667 cpr.wait();
7668 } catch (InterruptedException ex) {
7669 }
7670 }
7671 }
7672 return cpr;
7673 }
7674
7675 public final ContentProviderHolder getContentProvider(
7676 IApplicationThread caller, String name) {
7677 if (caller == null) {
7678 String msg = "null IApplicationThread when getting content provider "
7679 + name;
7680 Log.w(TAG, msg);
7681 throw new SecurityException(msg);
7682 }
7683
7684 return getContentProviderImpl(caller, name);
7685 }
7686
7687 private ContentProviderHolder getContentProviderExternal(String name) {
7688 return getContentProviderImpl(null, name);
7689 }
7690
7691 /**
7692 * Drop a content provider from a ProcessRecord's bookkeeping
7693 * @param cpr
7694 */
7695 public void removeContentProvider(IApplicationThread caller, String name) {
7696 synchronized (this) {
7697 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7698 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007699 // remove from mProvidersByClass
7700 if (DEBUG_PROVIDER) Log.v(TAG, name +
7701 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 return;
7703 }
7704 final ProcessRecord r = getRecordForAppLocked(caller);
7705 if (r == null) {
7706 throw new SecurityException(
7707 "Unable to find app for caller " + caller +
7708 " when removing content provider " + name);
7709 }
7710 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007711 ContentProviderRecord localCpr = (ContentProviderRecord)
7712 mProvidersByClass.get(cpr.info.name);
7713 if (DEBUG_PROVIDER) Log.v(TAG, "Removing provider requested by "
7714 + r.info.processName + " from process "
7715 + localCpr.appInfo.processName);
7716 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 //should not happen. taken care of as a local provider
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007718 Log.w(TAG, "removeContentProvider called on local provider: "
7719 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 return;
7721 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007722 Integer cnt = r.conProviders.get(localCpr);
7723 if (cnt == null || cnt.intValue() <= 1) {
7724 localCpr.clients.remove(r);
7725 r.conProviders.remove(localCpr);
7726 } else {
7727 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 }
7730 updateOomAdjLocked();
7731 }
7732 }
7733
7734 private void removeContentProviderExternal(String name) {
7735 synchronized (this) {
7736 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7737 if(cpr == null) {
7738 //remove from mProvidersByClass
7739 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
7740 return;
7741 }
7742
7743 //update content provider record entry info
7744 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7745 localCpr.externals--;
7746 if (localCpr.externals < 0) {
7747 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
7748 }
7749 updateOomAdjLocked();
7750 }
7751 }
7752
7753 public final void publishContentProviders(IApplicationThread caller,
7754 List<ContentProviderHolder> providers) {
7755 if (providers == null) {
7756 return;
7757 }
7758
7759 synchronized(this) {
7760 final ProcessRecord r = getRecordForAppLocked(caller);
7761 if (r == null) {
7762 throw new SecurityException(
7763 "Unable to find app for caller " + caller
7764 + " (pid=" + Binder.getCallingPid()
7765 + ") when publishing content providers");
7766 }
7767
7768 final long origId = Binder.clearCallingIdentity();
7769
7770 final int N = providers.size();
7771 for (int i=0; i<N; i++) {
7772 ContentProviderHolder src = providers.get(i);
7773 if (src == null || src.info == null || src.provider == null) {
7774 continue;
7775 }
7776 ContentProviderRecord dst =
7777 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7778 if (dst != null) {
7779 mProvidersByClass.put(dst.info.name, dst);
7780 String names[] = dst.info.authority.split(";");
7781 for (int j = 0; j < names.length; j++) {
7782 mProvidersByName.put(names[j], dst);
7783 }
7784
7785 int NL = mLaunchingProviders.size();
7786 int j;
7787 for (j=0; j<NL; j++) {
7788 if (mLaunchingProviders.get(j) == dst) {
7789 mLaunchingProviders.remove(j);
7790 j--;
7791 NL--;
7792 }
7793 }
7794 synchronized (dst) {
7795 dst.provider = src.provider;
7796 dst.app = r;
7797 dst.notifyAll();
7798 }
7799 updateOomAdjLocked(r);
7800 }
7801 }
7802
7803 Binder.restoreCallingIdentity(origId);
7804 }
7805 }
7806
7807 public static final void installSystemProviders() {
7808 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7809 List providers = mSelf.generateApplicationProvidersLocked(app);
7810 mSystemThread.installSystemProviders(providers);
7811 }
7812
7813 // =========================================================
7814 // GLOBAL MANAGEMENT
7815 // =========================================================
7816
7817 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7818 ApplicationInfo info, String customProcess) {
7819 String proc = customProcess != null ? customProcess : info.processName;
7820 BatteryStatsImpl.Uid.Proc ps = null;
7821 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7822 synchronized (stats) {
7823 ps = stats.getProcessStatsLocked(info.uid, proc);
7824 }
7825 return new ProcessRecord(ps, thread, info, proc);
7826 }
7827
7828 final ProcessRecord addAppLocked(ApplicationInfo info) {
7829 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7830
7831 if (app == null) {
7832 app = newProcessRecordLocked(null, info, null);
7833 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007834 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 }
7836
7837 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7838 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7839 app.persistent = true;
7840 app.maxAdj = CORE_SERVER_ADJ;
7841 }
7842 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7843 mPersistentStartingProcesses.add(app);
7844 startProcessLocked(app, "added application", app.processName);
7845 }
7846
7847 return app;
7848 }
7849
7850 public void unhandledBack() {
7851 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7852 "unhandledBack()");
7853
7854 synchronized(this) {
7855 int count = mHistory.size();
Dianne Hackborn03abb812010-01-04 18:43:19 -08007856 if (DEBUG_SWITCH) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 TAG, "Performing unhandledBack(): stack size = " + count);
7858 if (count > 1) {
7859 final long origId = Binder.clearCallingIdentity();
7860 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7861 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7862 Binder.restoreCallingIdentity(origId);
7863 }
7864 }
7865 }
7866
7867 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7868 String name = uri.getAuthority();
7869 ContentProviderHolder cph = getContentProviderExternal(name);
7870 ParcelFileDescriptor pfd = null;
7871 if (cph != null) {
7872 // We record the binder invoker's uid in thread-local storage before
7873 // going to the content provider to open the file. Later, in the code
7874 // that handles all permissions checks, we look for this uid and use
7875 // that rather than the Activity Manager's own uid. The effect is that
7876 // we do the check against the caller's permissions even though it looks
7877 // to the content provider like the Activity Manager itself is making
7878 // the request.
7879 sCallerIdentity.set(new Identity(
7880 Binder.getCallingPid(), Binder.getCallingUid()));
7881 try {
7882 pfd = cph.provider.openFile(uri, "r");
7883 } catch (FileNotFoundException e) {
7884 // do nothing; pfd will be returned null
7885 } finally {
7886 // Ensure that whatever happens, we clean up the identity state
7887 sCallerIdentity.remove();
7888 }
7889
7890 // We've got the fd now, so we're done with the provider.
7891 removeContentProviderExternal(name);
7892 } else {
7893 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7894 }
7895 return pfd;
7896 }
7897
7898 public void goingToSleep() {
7899 synchronized(this) {
7900 mSleeping = true;
7901 mWindowManager.setEventDispatching(false);
7902
7903 if (mResumedActivity != null) {
7904 pauseIfSleepingLocked();
7905 } else {
7906 Log.w(TAG, "goingToSleep with no resumed activity!");
7907 }
7908 }
7909 }
7910
Dianne Hackborn55280a92009-05-07 15:53:46 -07007911 public boolean shutdown(int timeout) {
7912 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7913 != PackageManager.PERMISSION_GRANTED) {
7914 throw new SecurityException("Requires permission "
7915 + android.Manifest.permission.SHUTDOWN);
7916 }
7917
7918 boolean timedout = false;
7919
7920 synchronized(this) {
7921 mShuttingDown = true;
7922 mWindowManager.setEventDispatching(false);
7923
7924 if (mResumedActivity != null) {
7925 pauseIfSleepingLocked();
7926 final long endTime = System.currentTimeMillis() + timeout;
7927 while (mResumedActivity != null || mPausingActivity != null) {
7928 long delay = endTime - System.currentTimeMillis();
7929 if (delay <= 0) {
7930 Log.w(TAG, "Activity manager shutdown timed out");
7931 timedout = true;
7932 break;
7933 }
7934 try {
7935 this.wait();
7936 } catch (InterruptedException e) {
7937 }
7938 }
7939 }
7940 }
7941
7942 mUsageStatsService.shutdown();
7943 mBatteryStatsService.shutdown();
7944
7945 return timedout;
7946 }
7947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007949 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950 if (!mGoingToSleep.isHeld()) {
7951 mGoingToSleep.acquire();
7952 if (mLaunchingActivity.isHeld()) {
7953 mLaunchingActivity.release();
7954 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7955 }
7956 }
7957
7958 // If we are not currently pausing an activity, get the current
7959 // one to pause. If we are pausing one, we will just let that stuff
7960 // run and release the wake lock when all done.
7961 if (mPausingActivity == null) {
7962 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7963 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7964 startPausingLocked(false, true);
7965 }
7966 }
7967 }
7968
7969 public void wakingUp() {
7970 synchronized(this) {
7971 if (mGoingToSleep.isHeld()) {
7972 mGoingToSleep.release();
7973 }
7974 mWindowManager.setEventDispatching(true);
7975 mSleeping = false;
7976 resumeTopActivityLocked(null);
7977 }
7978 }
7979
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007980 public void stopAppSwitches() {
7981 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7982 != PackageManager.PERMISSION_GRANTED) {
7983 throw new SecurityException("Requires permission "
7984 + android.Manifest.permission.STOP_APP_SWITCHES);
7985 }
7986
7987 synchronized(this) {
7988 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
7989 + APP_SWITCH_DELAY_TIME;
7990 mDidAppSwitch = false;
7991 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7992 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7993 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
7994 }
7995 }
7996
7997 public void resumeAppSwitches() {
7998 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7999 != PackageManager.PERMISSION_GRANTED) {
8000 throw new SecurityException("Requires permission "
8001 + android.Manifest.permission.STOP_APP_SWITCHES);
8002 }
8003
8004 synchronized(this) {
8005 // Note that we don't execute any pending app switches... we will
8006 // let those wait until either the timeout, or the next start
8007 // activity request.
8008 mAppSwitchesAllowedTime = 0;
8009 }
8010 }
8011
8012 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8013 String name) {
8014 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8015 return true;
8016 }
8017
8018 final int perm = checkComponentPermission(
8019 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8020 callingUid, -1);
8021 if (perm == PackageManager.PERMISSION_GRANTED) {
8022 return true;
8023 }
8024
8025 Log.w(TAG, name + " request from " + callingUid + " stopped");
8026 return false;
8027 }
8028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008029 public void setDebugApp(String packageName, boolean waitForDebugger,
8030 boolean persistent) {
8031 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8032 "setDebugApp()");
8033
8034 // Note that this is not really thread safe if there are multiple
8035 // callers into it at the same time, but that's not a situation we
8036 // care about.
8037 if (persistent) {
8038 final ContentResolver resolver = mContext.getContentResolver();
8039 Settings.System.putString(
8040 resolver, Settings.System.DEBUG_APP,
8041 packageName);
8042 Settings.System.putInt(
8043 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8044 waitForDebugger ? 1 : 0);
8045 }
8046
8047 synchronized (this) {
8048 if (!persistent) {
8049 mOrigDebugApp = mDebugApp;
8050 mOrigWaitForDebugger = mWaitForDebugger;
8051 }
8052 mDebugApp = packageName;
8053 mWaitForDebugger = waitForDebugger;
8054 mDebugTransient = !persistent;
8055 if (packageName != null) {
8056 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008057 forceStopPackageLocked(packageName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 Binder.restoreCallingIdentity(origId);
8059 }
8060 }
8061 }
8062
8063 public void setAlwaysFinish(boolean enabled) {
8064 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8065 "setAlwaysFinish()");
8066
8067 Settings.System.putInt(
8068 mContext.getContentResolver(),
8069 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8070
8071 synchronized (this) {
8072 mAlwaysFinishActivities = enabled;
8073 }
8074 }
8075
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008076 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008078 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008079 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008080 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 }
8082 }
8083
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008084 public boolean isUserAMonkey() {
8085 // For now the fact that there is a controller implies
8086 // we have a monkey.
8087 synchronized (this) {
8088 return mController != null;
8089 }
8090 }
8091
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008092 public void registerActivityWatcher(IActivityWatcher watcher) {
8093 mWatchers.register(watcher);
8094 }
8095
8096 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8097 mWatchers.unregister(watcher);
8098 }
8099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 public final void enterSafeMode() {
8101 synchronized(this) {
8102 // It only makes sense to do this before the system is ready
8103 // and started launching other packages.
8104 if (!mSystemReady) {
8105 try {
8106 ActivityThread.getPackageManager().enterSafeMode();
8107 } catch (RemoteException e) {
8108 }
8109
8110 View v = LayoutInflater.from(mContext).inflate(
8111 com.android.internal.R.layout.safe_mode, null);
8112 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8113 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8114 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8115 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8116 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8117 lp.format = v.getBackground().getOpacity();
8118 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8119 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8120 ((WindowManager)mContext.getSystemService(
8121 Context.WINDOW_SERVICE)).addView(v, lp);
8122 }
8123 }
8124 }
8125
8126 public void noteWakeupAlarm(IIntentSender sender) {
8127 if (!(sender instanceof PendingIntentRecord)) {
8128 return;
8129 }
8130 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8131 synchronized (stats) {
8132 if (mBatteryStatsService.isOnBattery()) {
8133 mBatteryStatsService.enforceCallingPermission();
8134 PendingIntentRecord rec = (PendingIntentRecord)sender;
8135 int MY_UID = Binder.getCallingUid();
8136 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8137 BatteryStatsImpl.Uid.Pkg pkg =
8138 stats.getPackageStatsLocked(uid, rec.key.packageName);
8139 pkg.incWakeupsLocked();
8140 }
8141 }
8142 }
8143
8144 public boolean killPidsForMemory(int[] pids) {
8145 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8146 throw new SecurityException("killPidsForMemory only available to the system");
8147 }
8148
8149 // XXX Note: don't acquire main activity lock here, because the window
8150 // manager calls in with its locks held.
8151
8152 boolean killed = false;
8153 synchronized (mPidsSelfLocked) {
8154 int[] types = new int[pids.length];
8155 int worstType = 0;
8156 for (int i=0; i<pids.length; i++) {
8157 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8158 if (proc != null) {
8159 int type = proc.setAdj;
8160 types[i] = type;
8161 if (type > worstType) {
8162 worstType = type;
8163 }
8164 }
8165 }
8166
8167 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8168 // then constrain it so we will kill all hidden procs.
8169 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8170 worstType = HIDDEN_APP_MIN_ADJ;
8171 }
8172 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
8173 for (int i=0; i<pids.length; i++) {
8174 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8175 if (proc == null) {
8176 continue;
8177 }
8178 int adj = proc.setAdj;
8179 if (adj >= worstType) {
8180 Log.w(TAG, "Killing for memory: " + proc + " (adj "
8181 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008182 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 proc.processName, adj);
8184 killed = true;
8185 Process.killProcess(pids[i]);
8186 }
8187 }
8188 }
8189 return killed;
8190 }
8191
8192 public void reportPss(IApplicationThread caller, int pss) {
8193 Watchdog.PssRequestor req;
8194 String name;
8195 ProcessRecord callerApp;
8196 synchronized (this) {
8197 if (caller == null) {
8198 return;
8199 }
8200 callerApp = getRecordForAppLocked(caller);
8201 if (callerApp == null) {
8202 return;
8203 }
8204 callerApp.lastPss = pss;
8205 req = callerApp;
8206 name = callerApp.processName;
8207 }
8208 Watchdog.getInstance().reportPss(req, name, pss);
8209 if (!callerApp.persistent) {
8210 removeRequestedPss(callerApp);
8211 }
8212 }
8213
8214 public void requestPss(Runnable completeCallback) {
8215 ArrayList<ProcessRecord> procs;
8216 synchronized (this) {
8217 mRequestPssCallback = completeCallback;
8218 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008219 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8220 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 if (!proc.persistent) {
8222 mRequestPssList.add(proc);
8223 }
8224 }
8225 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8226 }
8227
8228 int oldPri = Process.getThreadPriority(Process.myTid());
8229 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8230 for (int i=procs.size()-1; i>=0; i--) {
8231 ProcessRecord proc = procs.get(i);
8232 proc.lastPss = 0;
8233 proc.requestPss();
8234 }
8235 Process.setThreadPriority(oldPri);
8236 }
8237
8238 void removeRequestedPss(ProcessRecord proc) {
8239 Runnable callback = null;
8240 synchronized (this) {
8241 if (mRequestPssList.remove(proc)) {
8242 if (mRequestPssList.size() == 0) {
8243 callback = mRequestPssCallback;
8244 mRequestPssCallback = null;
8245 }
8246 }
8247 }
8248
8249 if (callback != null) {
8250 callback.run();
8251 }
8252 }
8253
8254 public void collectPss(Watchdog.PssStats stats) {
8255 stats.mEmptyPss = 0;
8256 stats.mEmptyCount = 0;
8257 stats.mBackgroundPss = 0;
8258 stats.mBackgroundCount = 0;
8259 stats.mServicePss = 0;
8260 stats.mServiceCount = 0;
8261 stats.mVisiblePss = 0;
8262 stats.mVisibleCount = 0;
8263 stats.mForegroundPss = 0;
8264 stats.mForegroundCount = 0;
8265 stats.mNoPssCount = 0;
8266 synchronized (this) {
8267 int i;
8268 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8269 ? mProcDeaths.length : stats.mProcDeaths.length;
8270 int aggr = 0;
8271 for (i=0; i<NPD; i++) {
8272 aggr += mProcDeaths[i];
8273 stats.mProcDeaths[i] = aggr;
8274 }
8275 while (i<stats.mProcDeaths.length) {
8276 stats.mProcDeaths[i] = 0;
8277 i++;
8278 }
8279
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008280 for (i=mLruProcesses.size()-1; i>=0; i--) {
8281 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 if (proc.persistent) {
8283 continue;
8284 }
8285 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
8286 if (proc.lastPss == 0) {
8287 stats.mNoPssCount++;
8288 continue;
8289 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008290 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8291 if (proc.empty) {
8292 stats.mEmptyPss += proc.lastPss;
8293 stats.mEmptyCount++;
8294 } else {
8295 stats.mBackgroundPss += proc.lastPss;
8296 stats.mBackgroundCount++;
8297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8299 stats.mVisiblePss += proc.lastPss;
8300 stats.mVisibleCount++;
8301 } else {
8302 stats.mForegroundPss += proc.lastPss;
8303 stats.mForegroundCount++;
8304 }
8305 }
8306 }
8307 }
8308
8309 public final void startRunning(String pkg, String cls, String action,
8310 String data) {
8311 synchronized(this) {
8312 if (mStartRunning) {
8313 return;
8314 }
8315 mStartRunning = true;
8316 mTopComponent = pkg != null && cls != null
8317 ? new ComponentName(pkg, cls) : null;
8318 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8319 mTopData = data;
8320 if (!mSystemReady) {
8321 return;
8322 }
8323 }
8324
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008325 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008326 }
8327
8328 private void retrieveSettings() {
8329 final ContentResolver resolver = mContext.getContentResolver();
8330 String debugApp = Settings.System.getString(
8331 resolver, Settings.System.DEBUG_APP);
8332 boolean waitForDebugger = Settings.System.getInt(
8333 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8334 boolean alwaysFinishActivities = Settings.System.getInt(
8335 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8336
8337 Configuration configuration = new Configuration();
8338 Settings.System.getConfiguration(resolver, configuration);
8339
8340 synchronized (this) {
8341 mDebugApp = mOrigDebugApp = debugApp;
8342 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8343 mAlwaysFinishActivities = alwaysFinishActivities;
8344 // This happens before any activities are started, so we can
8345 // change mConfiguration in-place.
8346 mConfiguration.updateFrom(configuration);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07008347 if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008348 }
8349 }
8350
8351 public boolean testIsSystemReady() {
8352 // no need to synchronize(this) just to read & return the value
8353 return mSystemReady;
8354 }
8355
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008356 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 // In the simulator, startRunning will never have been called, which
8358 // normally sets a few crucial variables. Do it here instead.
8359 if (!Process.supportsProcesses()) {
8360 mStartRunning = true;
8361 mTopAction = Intent.ACTION_MAIN;
8362 }
8363
8364 synchronized(this) {
8365 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008366 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008367 return;
8368 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008369
8370 // Check to see if there are any update receivers to run.
8371 if (!mDidUpdate) {
8372 if (mWaitingUpdate) {
8373 return;
8374 }
8375 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8376 List<ResolveInfo> ris = null;
8377 try {
8378 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8379 intent, null, 0);
8380 } catch (RemoteException e) {
8381 }
8382 if (ris != null) {
8383 for (int i=ris.size()-1; i>=0; i--) {
8384 if ((ris.get(i).activityInfo.applicationInfo.flags
8385 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8386 ris.remove(i);
8387 }
8388 }
8389 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8390 for (int i=0; i<ris.size(); i++) {
8391 ActivityInfo ai = ris.get(i).activityInfo;
8392 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8393 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008394 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008395 finisher = new IIntentReceiver.Stub() {
8396 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008397 String data, Bundle extras, boolean ordered,
8398 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008399 throws RemoteException {
8400 synchronized (ActivityManagerService.this) {
8401 mDidUpdate = true;
8402 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008403 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008404 }
8405 };
8406 }
8407 Log.i(TAG, "Sending system update to: " + intent.getComponent());
8408 broadcastIntentLocked(null, null, intent, null, finisher,
8409 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008410 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008411 mWaitingUpdate = true;
8412 }
8413 }
8414 }
8415 if (mWaitingUpdate) {
8416 return;
8417 }
8418 mDidUpdate = true;
8419 }
8420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008421 mSystemReady = true;
8422 if (!mStartRunning) {
8423 return;
8424 }
8425 }
8426
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008427 ArrayList<ProcessRecord> procsToKill = null;
8428 synchronized(mPidsSelfLocked) {
8429 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8430 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8431 if (!isAllowedWhileBooting(proc.info)){
8432 if (procsToKill == null) {
8433 procsToKill = new ArrayList<ProcessRecord>();
8434 }
8435 procsToKill.add(proc);
8436 }
8437 }
8438 }
8439
8440 if (procsToKill != null) {
8441 synchronized(this) {
8442 for (int i=procsToKill.size()-1; i>=0; i--) {
8443 ProcessRecord proc = procsToKill.get(i);
8444 Log.i(TAG, "Removing system update proc: " + proc);
8445 removeProcessLocked(proc, true);
8446 }
8447 }
8448 }
8449
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008450 Log.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008451 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 SystemClock.uptimeMillis());
8453
8454 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008455 // Make sure we have no pre-ready processes sitting around.
8456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8458 ResolveInfo ri = mContext.getPackageManager()
8459 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008460 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 CharSequence errorMsg = null;
8462 if (ri != null) {
8463 ActivityInfo ai = ri.activityInfo;
8464 ApplicationInfo app = ai.applicationInfo;
8465 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8466 mTopAction = Intent.ACTION_FACTORY_TEST;
8467 mTopData = null;
8468 mTopComponent = new ComponentName(app.packageName,
8469 ai.name);
8470 } else {
8471 errorMsg = mContext.getResources().getText(
8472 com.android.internal.R.string.factorytest_not_system);
8473 }
8474 } else {
8475 errorMsg = mContext.getResources().getText(
8476 com.android.internal.R.string.factorytest_no_action);
8477 }
8478 if (errorMsg != null) {
8479 mTopAction = null;
8480 mTopData = null;
8481 mTopComponent = null;
8482 Message msg = Message.obtain();
8483 msg.what = SHOW_FACTORY_ERROR_MSG;
8484 msg.getData().putCharSequence("msg", errorMsg);
8485 mHandler.sendMessage(msg);
8486 }
8487 }
8488 }
8489
8490 retrieveSettings();
8491
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008492 if (goingCallback != null) goingCallback.run();
8493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 synchronized (this) {
8495 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8496 try {
8497 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008498 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 if (apps != null) {
8500 int N = apps.size();
8501 int i;
8502 for (i=0; i<N; i++) {
8503 ApplicationInfo info
8504 = (ApplicationInfo)apps.get(i);
8505 if (info != null &&
8506 !info.packageName.equals("android")) {
8507 addAppLocked(info);
8508 }
8509 }
8510 }
8511 } catch (RemoteException ex) {
8512 // pm is in same process, this will never happen.
8513 }
8514 }
8515
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008516 // Start up initial activity.
8517 mBooting = true;
8518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519 try {
8520 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8521 Message msg = Message.obtain();
8522 msg.what = SHOW_UID_ERROR_MSG;
8523 mHandler.sendMessage(msg);
8524 }
8525 } catch (RemoteException e) {
8526 }
8527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 resumeTopActivityLocked(null);
8529 }
8530 }
8531
Dan Egnorb7f03672009-12-09 16:22:32 -08008532 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008533 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008535 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008536 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 startAppProblemLocked(app);
8538 app.stopFreezingAllLocked();
8539 return handleAppCrashLocked(app);
8540 }
8541
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008542 private ComponentName getErrorReportReceiver(ProcessRecord app) {
Doug Zongker43866e02010-01-07 12:09:54 -08008543 // check if error reporting is enabled in secure settings
8544 int enabled = Settings.Secure.getInt(mContext.getContentResolver(),
8545 Settings.Secure.SEND_ACTION_APP_ERROR, 0);
Jacek Surazskia2339432009-09-18 15:01:26 +02008546 if (enabled == 0) {
8547 return null;
8548 }
8549
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008550 IPackageManager pm = ActivityThread.getPackageManager();
Jacek Surazski82a73df2009-06-17 14:33:18 +02008551
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008552 try {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008553 // look for receiver in the installer package
8554 String candidate = pm.getInstallerPackageName(app.info.packageName);
8555 ComponentName result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8556 if (result != null) {
8557 return result;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008558 }
8559
Jacek Surazski82a73df2009-06-17 14:33:18 +02008560 // if the error app is on the system image, look for system apps
8561 // error receiver
8562 if ((app.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8563 candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
8564 result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8565 if (result != null) {
8566 return result;
8567 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008568 }
8569
Jacek Surazski82a73df2009-06-17 14:33:18 +02008570 // if there is a default receiver, try that
8571 candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
8572 return getErrorReportReceiver(pm, app.info.packageName, candidate);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008573 } catch (RemoteException e) {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008574 // should not happen
8575 Log.e(TAG, "error talking to PackageManager", e);
8576 return null;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008577 }
Jacek Surazski82a73df2009-06-17 14:33:18 +02008578 }
8579
8580 /**
8581 * Return activity in receiverPackage that handles ACTION_APP_ERROR.
8582 *
8583 * @param pm PackageManager isntance
8584 * @param errorPackage package which caused the error
8585 * @param receiverPackage candidate package to receive the error
8586 * @return activity component within receiverPackage which handles
8587 * ACTION_APP_ERROR, or null if not found
8588 */
8589 private ComponentName getErrorReportReceiver(IPackageManager pm, String errorPackage,
8590 String receiverPackage) throws RemoteException {
8591 if (receiverPackage == null || receiverPackage.length() == 0) {
8592 return null;
8593 }
8594
8595 // break the loop if it's the error report receiver package that crashed
8596 if (receiverPackage.equals(errorPackage)) {
8597 return null;
8598 }
8599
8600 Intent intent = new Intent(Intent.ACTION_APP_ERROR);
8601 intent.setPackage(receiverPackage);
8602 ResolveInfo info = pm.resolveIntent(intent, null, 0);
8603 if (info == null || info.activityInfo == null) {
8604 return null;
8605 }
8606 return new ComponentName(receiverPackage, info.activityInfo.name);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008607 }
8608
Dan Egnorb7f03672009-12-09 16:22:32 -08008609 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008610 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008612 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008613 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8614 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 startAppProblemLocked(app);
8616 app.stopFreezingAllLocked();
8617 }
8618
8619 /**
8620 * Generate a process error record, suitable for attachment to a ProcessRecord.
8621 *
8622 * @param app The ProcessRecord in which the error occurred.
8623 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8624 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008625 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 * @param shortMsg Short message describing the crash.
8627 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008628 * @param stackTrace Full crash stack trace, may be null.
8629 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 * @return Returns a fully-formed AppErrorStateInfo record.
8631 */
8632 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008633 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 report.condition = condition;
8637 report.processName = app.processName;
8638 report.pid = app.pid;
8639 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008640 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 report.shortMsg = shortMsg;
8642 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008643 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644
8645 return report;
8646 }
8647
Dan Egnor42471dd2010-01-07 17:25:22 -08008648 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 synchronized (this) {
8650 app.crashing = false;
8651 app.crashingReport = null;
8652 app.notResponding = false;
8653 app.notRespondingReport = null;
8654 if (app.anrDialog == fromDialog) {
8655 app.anrDialog = null;
8656 }
8657 if (app.waitDialog == fromDialog) {
8658 app.waitDialog = null;
8659 }
8660 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008661 handleAppCrashLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008662 Log.i(ActivityManagerService.TAG, "Killing process "
8663 + app.processName
8664 + " (pid=" + app.pid + ") at user's request");
8665 Process.killProcess(app.pid);
8666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008667 }
8668 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008669
Dan Egnorb7f03672009-12-09 16:22:32 -08008670 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 long now = SystemClock.uptimeMillis();
8672
8673 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8674 app.info.uid);
8675 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8676 // This process loses!
8677 Log.w(TAG, "Process " + app.info.processName
8678 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008679 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 app.info.processName, app.info.uid);
8681 killServicesLocked(app, false);
8682 for (int i=mHistory.size()-1; i>=0; i--) {
8683 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8684 if (r.app == app) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08008685 Log.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008686 + r.intent.getComponent().flattenToShortString());
8687 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8688 }
8689 }
8690 if (!app.persistent) {
8691 // We don't want to start this process again until the user
8692 // explicitly does so... but for persistent process, we really
8693 // need to keep it running. If a persistent process is actually
8694 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008695 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008696 app.info.processName);
8697 mBadProcesses.put(app.info.processName, app.info.uid, now);
8698 app.bad = true;
8699 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8700 app.removed = true;
8701 removeProcessLocked(app, false);
8702 return false;
8703 }
8704 }
8705
8706 // Bump up the crash count of any services currently running in the proc.
8707 if (app.services.size() != 0) {
8708 // Any services running in the application need to be placed
8709 // back in the pending list.
8710 Iterator it = app.services.iterator();
8711 while (it.hasNext()) {
8712 ServiceRecord sr = (ServiceRecord)it.next();
8713 sr.crashCount++;
8714 }
8715 }
8716
8717 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8718 return true;
8719 }
8720
8721 void startAppProblemLocked(ProcessRecord app) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008722 app.errorReportReceiver = getErrorReportReceiver(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 skipCurrentReceiverLocked(app);
8724 }
8725
8726 void skipCurrentReceiverLocked(ProcessRecord app) {
8727 boolean reschedule = false;
8728 BroadcastRecord r = app.curReceiver;
8729 if (r != null) {
8730 // The current broadcast is waiting for this app's receiver
8731 // to be finished. Looks like that's not going to happen, so
8732 // let the broadcast continue.
8733 logBroadcastReceiverDiscard(r);
8734 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8735 r.resultExtras, r.resultAbort, true);
8736 reschedule = true;
8737 }
8738 r = mPendingBroadcast;
8739 if (r != null && r.curApp == app) {
8740 if (DEBUG_BROADCAST) Log.v(TAG,
8741 "skip & discard pending app " + r);
8742 logBroadcastReceiverDiscard(r);
8743 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8744 r.resultExtras, r.resultAbort, true);
8745 reschedule = true;
8746 }
8747 if (reschedule) {
8748 scheduleBroadcastsLocked();
8749 }
8750 }
8751
Dan Egnor60d87622009-12-16 16:32:58 -08008752 /**
8753 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8754 * The application process will exit immediately after this call returns.
8755 * @param app object of the crashing app, null for the system server
8756 * @param crashInfo describing the exception
8757 */
8758 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8759 ProcessRecord r = findAppProcess(app);
8760
8761 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8762 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008763 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008764 crashInfo.exceptionClassName,
8765 crashInfo.exceptionMessage,
8766 crashInfo.throwFileName,
8767 crashInfo.throwLineNumber);
8768
Dan Egnor42471dd2010-01-07 17:25:22 -08008769 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008770
8771 crashApplication(r, crashInfo);
8772 }
8773
8774 /**
8775 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8776 * @param app object of the crashing app, null for the system server
8777 * @param tag reported by the caller
8778 * @param crashInfo describing the context of the error
8779 * @return true if the process should exit immediately (WTF is fatal)
8780 */
8781 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008782 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008783 ProcessRecord r = findAppProcess(app);
8784
8785 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8786 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008787 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008788 tag, crashInfo.exceptionMessage);
8789
Dan Egnor42471dd2010-01-07 17:25:22 -08008790 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008791
Doug Zongker43866e02010-01-07 12:09:54 -08008792 if (Settings.Secure.getInt(mContext.getContentResolver(),
8793 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008794 crashApplication(r, crashInfo);
8795 return true;
8796 } else {
8797 return false;
8798 }
8799 }
8800
8801 /**
8802 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8803 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8804 */
8805 private ProcessRecord findAppProcess(IBinder app) {
8806 if (app == null) {
8807 return null;
8808 }
8809
8810 synchronized (this) {
8811 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8812 final int NA = apps.size();
8813 for (int ia=0; ia<NA; ia++) {
8814 ProcessRecord p = apps.valueAt(ia);
8815 if (p.thread != null && p.thread.asBinder() == app) {
8816 return p;
8817 }
8818 }
8819 }
8820
8821 Log.w(TAG, "Can't find mystery application: " + app);
8822 return null;
8823 }
8824 }
8825
8826 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008827 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008828 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008829 * @param process which caused the error, null means the system server
8830 * @param activity which triggered the error, null if unknown
8831 * @param parent activity related to the error, null if unknown
8832 * @param subject line related to the error, null if absent
8833 * @param report in long form describing the error, null if absent
8834 * @param logFile to include in the report, null if none
8835 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008836 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008837 private void addErrorToDropBox(String eventType,
8838 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8839 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008840 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008841 String dropboxTag;
8842 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008843 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008844 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008845 dropboxTag = "system_app_" + eventType;
8846 } else {
8847 dropboxTag = "data_app_" + eventType;
8848 }
8849
8850 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8851 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8852 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008853 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008854 sb.append("Process: system_server\n");
8855 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008856 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008857 }
8858 if (process != null) {
8859 int flags = process.info.flags;
8860 IPackageManager pm = ActivityThread.getPackageManager();
8861 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8862 for (String pkg : process.pkgList) {
8863 sb.append("Package: ").append(pkg);
8864 try {
8865 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8866 if (pi != null) {
8867 sb.append(" v").append(pi.versionCode);
8868 if (pi.versionName != null) {
8869 sb.append(" (").append(pi.versionName).append(")");
8870 }
8871 }
8872 } catch (RemoteException e) {
8873 Log.e(TAG, "Error getting package info: " + pkg, e);
8874 }
8875 sb.append("\n");
8876 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008877 }
8878 if (activity != null) {
8879 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8880 }
8881 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8882 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8883 }
8884 if (parent != null && parent != activity) {
8885 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8886 }
8887 if (subject != null) {
8888 sb.append("Subject: ").append(subject).append("\n");
8889 }
8890 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8891 sb.append("\n");
8892 if (report != null) {
8893 sb.append(report);
8894 }
8895 if (logFile != null) {
8896 try {
8897 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8898 } catch (IOException e) {
8899 Log.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008900 }
8901 }
Dan Egnor60d87622009-12-16 16:32:58 -08008902 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008903 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08008904 }
8905 dbox.addText(dropboxTag, sb.toString());
8906 }
8907 }
8908
8909 /**
8910 * Bring up the "unexpected error" dialog box for a crashing app.
8911 * Deal with edge cases (intercepts from instrumented applications,
8912 * ActivityController, error intent receivers, that sort of thing).
8913 * @param r the application crashing
8914 * @param crashInfo describing the failure
8915 */
8916 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008917 long timeMillis = System.currentTimeMillis();
8918 String shortMsg = crashInfo.exceptionClassName;
8919 String longMsg = crashInfo.exceptionMessage;
8920 String stackTrace = crashInfo.stackTrace;
8921 if (shortMsg != null && longMsg != null) {
8922 longMsg = shortMsg + ": " + longMsg;
8923 } else if (shortMsg != null) {
8924 longMsg = shortMsg;
8925 }
8926
Dan Egnor60d87622009-12-16 16:32:58 -08008927 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008929 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 try {
8931 String name = r != null ? r.processName : null;
8932 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008933 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008934 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 Log.w(TAG, "Force-killing crashed app " + name
8936 + " at watcher's request");
8937 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008938 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 }
8940 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008941 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 }
8943 }
8944
8945 final long origId = Binder.clearCallingIdentity();
8946
8947 // If this process is running instrumentation, finish it.
8948 if (r != null && r.instrumentationClass != null) {
8949 Log.w(TAG, "Error in app " + r.processName
8950 + " running instrumentation " + r.instrumentationClass + ":");
8951 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
8952 if (longMsg != null) Log.w(TAG, " " + longMsg);
8953 Bundle info = new Bundle();
8954 info.putString("shortMsg", shortMsg);
8955 info.putString("longMsg", longMsg);
8956 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8957 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008958 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959 }
8960
Dan Egnor60d87622009-12-16 16:32:58 -08008961 // If we can't identify the process or it's already exceeded its crash quota,
8962 // quit right away without showing a crash dialog.
8963 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008965 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008966 }
8967
8968 Message msg = Message.obtain();
8969 msg.what = SHOW_ERROR_MSG;
8970 HashMap data = new HashMap();
8971 data.put("result", result);
8972 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 msg.obj = data;
8974 mHandler.sendMessage(msg);
8975
8976 Binder.restoreCallingIdentity(origId);
8977 }
8978
8979 int res = result.get();
8980
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008981 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 synchronized (this) {
8983 if (r != null) {
8984 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8985 SystemClock.uptimeMillis());
8986 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008987 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008988 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008989 }
8990 }
8991
8992 if (appErrorIntent != null) {
8993 try {
8994 mContext.startActivity(appErrorIntent);
8995 } catch (ActivityNotFoundException e) {
8996 Log.w(TAG, "bug report receiver dissappeared", e);
8997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008999 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009000
9001 Intent createAppErrorIntentLocked(ProcessRecord r,
9002 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9003 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009004 if (report == null) {
9005 return null;
9006 }
9007 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9008 result.setComponent(r.errorReportReceiver);
9009 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9010 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9011 return result;
9012 }
9013
Dan Egnorb7f03672009-12-09 16:22:32 -08009014 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9015 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009016 if (r.errorReportReceiver == null) {
9017 return null;
9018 }
9019
9020 if (!r.crashing && !r.notResponding) {
9021 return null;
9022 }
9023
Dan Egnorb7f03672009-12-09 16:22:32 -08009024 ApplicationErrorReport report = new ApplicationErrorReport();
9025 report.packageName = r.info.packageName;
9026 report.installerPackageName = r.errorReportReceiver.getPackageName();
9027 report.processName = r.processName;
9028 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009029 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009030
Dan Egnorb7f03672009-12-09 16:22:32 -08009031 if (r.crashing) {
9032 report.type = ApplicationErrorReport.TYPE_CRASH;
9033 report.crashInfo = crashInfo;
9034 } else if (r.notResponding) {
9035 report.type = ApplicationErrorReport.TYPE_ANR;
9036 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009037
Dan Egnorb7f03672009-12-09 16:22:32 -08009038 report.anrInfo.activity = r.notRespondingReport.tag;
9039 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9040 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009041 }
9042
Dan Egnorb7f03672009-12-09 16:22:32 -08009043 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009044 }
9045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9047 // assume our apps are happy - lazy create the list
9048 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9049
9050 synchronized (this) {
9051
9052 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009053 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9054 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9056 // This one's in trouble, so we'll generate a report for it
9057 // crashes are higher priority (in case there's a crash *and* an anr)
9058 ActivityManager.ProcessErrorStateInfo report = null;
9059 if (app.crashing) {
9060 report = app.crashingReport;
9061 } else if (app.notResponding) {
9062 report = app.notRespondingReport;
9063 }
9064
9065 if (report != null) {
9066 if (errList == null) {
9067 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9068 }
9069 errList.add(report);
9070 } else {
9071 Log.w(TAG, "Missing app error report, app = " + app.processName +
9072 " crashing = " + app.crashing +
9073 " notResponding = " + app.notResponding);
9074 }
9075 }
9076 }
9077 }
9078
9079 return errList;
9080 }
9081
9082 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9083 // Lazy instantiation of list
9084 List<ActivityManager.RunningAppProcessInfo> runList = null;
9085 synchronized (this) {
9086 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009087 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9088 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9090 // Generate process state info for running application
9091 ActivityManager.RunningAppProcessInfo currApp =
9092 new ActivityManager.RunningAppProcessInfo(app.processName,
9093 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009094 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009095 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009096 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9098 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9099 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009100 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9101 } else if (adj >= HOME_APP_ADJ) {
9102 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9103 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 } else if (adj >= SECONDARY_SERVER_ADJ) {
9105 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9106 } else if (adj >= VISIBLE_APP_ADJ) {
9107 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9108 } else {
9109 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9110 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009111 currApp.importanceReasonCode = app.adjTypeCode;
9112 if (app.adjSource instanceof ProcessRecord) {
9113 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9114 } else if (app.adjSource instanceof HistoryRecord) {
9115 HistoryRecord r = (HistoryRecord)app.adjSource;
9116 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9117 }
9118 if (app.adjTarget instanceof ComponentName) {
9119 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
9122 // + " lru=" + currApp.lru);
9123 if (runList == null) {
9124 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9125 }
9126 runList.add(currApp);
9127 }
9128 }
9129 }
9130 return runList;
9131 }
9132
9133 @Override
9134 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009135 if (checkCallingPermission(android.Manifest.permission.DUMP)
9136 != PackageManager.PERMISSION_GRANTED) {
9137 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9138 + Binder.getCallingPid()
9139 + ", uid=" + Binder.getCallingUid()
9140 + " without permission "
9141 + android.Manifest.permission.DUMP);
9142 return;
9143 }
9144
9145 boolean dumpAll = false;
9146
9147 int opti = 0;
9148 while (opti < args.length) {
9149 String opt = args[opti];
9150 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9151 break;
9152 }
9153 opti++;
9154 if ("-a".equals(opt)) {
9155 dumpAll = true;
9156 } else if ("-h".equals(opt)) {
9157 pw.println("Activity manager dump options:");
9158 pw.println(" [-a] [h- [cmd] ...");
9159 pw.println(" cmd may be one of:");
9160 pw.println(" activities: activity stack state");
9161 pw.println(" broadcasts: broadcast state");
9162 pw.println(" intents: pending intent state");
9163 pw.println(" processes: process state");
9164 pw.println(" providers: content provider state");
9165 pw.println(" services: service state");
9166 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009168 } else {
9169 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009171 }
9172
9173 // Is the caller requesting to dump a particular piece of data?
9174 if (opti < args.length) {
9175 String cmd = args[opti];
9176 opti++;
9177 if ("activities".equals(cmd) || "a".equals(cmd)) {
9178 synchronized (this) {
9179 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009181 return;
9182 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9183 synchronized (this) {
9184 dumpBroadcastsLocked(fd, pw, args, opti, true);
9185 }
9186 return;
9187 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9188 synchronized (this) {
9189 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9190 }
9191 return;
9192 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9193 synchronized (this) {
9194 dumpProcessesLocked(fd, pw, args, opti, true);
9195 }
9196 return;
9197 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9198 synchronized (this) {
9199 dumpProvidersLocked(fd, pw, args, opti, true);
9200 }
9201 return;
9202 } else if ("service".equals(cmd)) {
9203 dumpService(fd, pw, args, opti, true);
9204 return;
9205 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9206 synchronized (this) {
9207 dumpServicesLocked(fd, pw, args, opti, true);
9208 }
9209 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009210 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009211 }
9212
9213 // No piece of data specified, dump everything.
9214 synchronized (this) {
9215 boolean needSep;
9216 if (dumpAll) {
9217 pw.println("Providers in Current Activity Manager State:");
9218 }
9219 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9220 if (needSep) {
9221 pw.println(" ");
9222 }
9223 if (dumpAll) {
9224 pw.println("-------------------------------------------------------------------------------");
9225 pw.println("Broadcasts in Current Activity Manager State:");
9226 }
9227 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9228 if (needSep) {
9229 pw.println(" ");
9230 }
9231 if (dumpAll) {
9232 pw.println("-------------------------------------------------------------------------------");
9233 pw.println("Services in Current Activity Manager State:");
9234 }
9235 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9236 if (needSep) {
9237 pw.println(" ");
9238 }
9239 if (dumpAll) {
9240 pw.println("-------------------------------------------------------------------------------");
9241 pw.println("PendingIntents in Current Activity Manager State:");
9242 }
9243 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9244 if (needSep) {
9245 pw.println(" ");
9246 }
9247 if (dumpAll) {
9248 pw.println("-------------------------------------------------------------------------------");
9249 pw.println("Activities in Current Activity Manager State:");
9250 }
9251 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9252 if (needSep) {
9253 pw.println(" ");
9254 }
9255 if (dumpAll) {
9256 pw.println("-------------------------------------------------------------------------------");
9257 pw.println("Processes in Current Activity Manager State:");
9258 }
9259 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9260 }
9261 }
9262
9263 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9264 int opti, boolean dumpAll, boolean needHeader) {
9265 if (needHeader) {
9266 pw.println(" Activity stack:");
9267 }
9268 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9269 pw.println(" ");
9270 pw.println(" Running activities (most recent first):");
9271 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9272 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009274 pw.println(" Activities waiting for another to become visible:");
9275 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9276 }
9277 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009279 pw.println(" Activities waiting to stop:");
9280 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9281 }
9282 if (mFinishingActivities.size() > 0) {
9283 pw.println(" ");
9284 pw.println(" Activities waiting to finish:");
9285 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009288 pw.println(" ");
9289 pw.println(" mPausingActivity: " + mPausingActivity);
9290 pw.println(" mResumedActivity: " + mResumedActivity);
9291 pw.println(" mFocusedActivity: " + mFocusedActivity);
9292 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009294 if (dumpAll && mRecentTasks.size() > 0) {
9295 pw.println(" ");
9296 pw.println("Recent tasks in Current Activity Manager State:");
9297
9298 final int N = mRecentTasks.size();
9299 for (int i=0; i<N; i++) {
9300 TaskRecord tr = mRecentTasks.get(i);
9301 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9302 pw.println(tr);
9303 mRecentTasks.get(i).dump(pw, " ");
9304 }
9305 }
9306
9307 pw.println(" ");
9308 pw.println(" mCurTask: " + mCurTask);
9309
9310 return true;
9311 }
9312
9313 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9314 int opti, boolean dumpAll) {
9315 boolean needSep = false;
9316 int numPers = 0;
9317
9318 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9320 final int NA = procs.size();
9321 for (int ia=0; ia<NA; ia++) {
9322 if (!needSep) {
9323 pw.println(" All known processes:");
9324 needSep = true;
9325 }
9326 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009327 pw.print(r.persistent ? " *PERS*" : " *APP*");
9328 pw.print(" UID "); pw.print(procs.keyAt(ia));
9329 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 r.dump(pw, " ");
9331 if (r.persistent) {
9332 numPers++;
9333 }
9334 }
9335 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009336 }
9337
9338 if (mLruProcesses.size() > 0) {
9339 if (needSep) pw.println(" ");
9340 needSep = true;
9341 pw.println(" Running processes (most recent first):");
9342 dumpProcessList(pw, this, mLruProcesses, " ",
9343 "App ", "PERS", true);
9344 needSep = true;
9345 }
9346
9347 synchronized (mPidsSelfLocked) {
9348 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 if (needSep) pw.println(" ");
9350 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009351 pw.println(" PID mappings:");
9352 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9353 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9354 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009355 }
9356 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009357 }
9358
9359 if (mForegroundProcesses.size() > 0) {
9360 if (needSep) pw.println(" ");
9361 needSep = true;
9362 pw.println(" Foreground Processes:");
9363 for (int i=0; i<mForegroundProcesses.size(); i++) {
9364 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9365 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009367 }
9368
9369 if (mPersistentStartingProcesses.size() > 0) {
9370 if (needSep) pw.println(" ");
9371 needSep = true;
9372 pw.println(" Persisent processes that are starting:");
9373 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9374 "Starting Norm", "Restarting PERS", false);
9375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009376
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009377 if (mStartingProcesses.size() > 0) {
9378 if (needSep) pw.println(" ");
9379 needSep = true;
9380 pw.println(" Processes that are starting:");
9381 dumpProcessList(pw, this, mStartingProcesses, " ",
9382 "Starting Norm", "Starting PERS", false);
9383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009384
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009385 if (mRemovedProcesses.size() > 0) {
9386 if (needSep) pw.println(" ");
9387 needSep = true;
9388 pw.println(" Processes that are being removed:");
9389 dumpProcessList(pw, this, mRemovedProcesses, " ",
9390 "Removed Norm", "Removed PERS", false);
9391 }
9392
9393 if (mProcessesOnHold.size() > 0) {
9394 if (needSep) pw.println(" ");
9395 needSep = true;
9396 pw.println(" Processes that are on old until the system is ready:");
9397 dumpProcessList(pw, this, mProcessesOnHold, " ",
9398 "OnHold Norm", "OnHold PERS", false);
9399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009401 if (mProcessesToGc.size() > 0) {
9402 if (needSep) pw.println(" ");
9403 needSep = true;
9404 pw.println(" Processes that are waiting to GC:");
9405 long now = SystemClock.uptimeMillis();
9406 for (int i=0; i<mProcessesToGc.size(); i++) {
9407 ProcessRecord proc = mProcessesToGc.get(i);
9408 pw.print(" Process "); pw.println(proc);
9409 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9410 pw.print(", last gced=");
9411 pw.print(now-proc.lastRequestedGc);
9412 pw.print(" ms ago, last lowMem=");
9413 pw.print(now-proc.lastLowMemory);
9414 pw.println(" ms ago");
9415
9416 }
9417 }
9418
9419 if (mProcessCrashTimes.getMap().size() > 0) {
9420 if (needSep) pw.println(" ");
9421 needSep = true;
9422 pw.println(" Time since processes crashed:");
9423 long now = SystemClock.uptimeMillis();
9424 for (Map.Entry<String, SparseArray<Long>> procs
9425 : mProcessCrashTimes.getMap().entrySet()) {
9426 SparseArray<Long> uids = procs.getValue();
9427 final int N = uids.size();
9428 for (int i=0; i<N; i++) {
9429 pw.print(" Process "); pw.print(procs.getKey());
9430 pw.print(" uid "); pw.print(uids.keyAt(i));
9431 pw.print(": last crashed ");
9432 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009433 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009434 }
9435 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009437
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009438 if (mBadProcesses.getMap().size() > 0) {
9439 if (needSep) pw.println(" ");
9440 needSep = true;
9441 pw.println(" Bad processes:");
9442 for (Map.Entry<String, SparseArray<Long>> procs
9443 : mBadProcesses.getMap().entrySet()) {
9444 SparseArray<Long> uids = procs.getValue();
9445 final int N = uids.size();
9446 for (int i=0; i<N; i++) {
9447 pw.print(" Bad process "); pw.print(procs.getKey());
9448 pw.print(" uid "); pw.print(uids.keyAt(i));
9449 pw.print(": crashed at time ");
9450 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009451 }
9452 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009455 pw.println(" ");
9456 pw.println(" mHomeProcess: " + mHomeProcess);
9457 pw.println(" mConfiguration: " + mConfiguration);
9458 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9459 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9460 || mOrigWaitForDebugger) {
9461 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9462 + " mDebugTransient=" + mDebugTransient
9463 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9464 }
9465 if (mAlwaysFinishActivities || mController != null) {
9466 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9467 + " mController=" + mController);
9468 }
9469 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009470 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 pw.println(" mStartRunning=" + mStartRunning
9472 + " mSystemReady=" + mSystemReady
9473 + " mBooting=" + mBooting
9474 + " mBooted=" + mBooted
9475 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 pw.println(" mGoingToSleep=" + mGoingToSleep);
9477 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009478 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009479
9480 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 }
9482
9483 /**
9484 * There are three ways to call this:
9485 * - no service specified: dump all the services
9486 * - a flattened component name that matched an existing service was specified as the
9487 * first arg: dump that one service
9488 * - the first arg isn't the flattened component name of an existing service:
9489 * dump all services whose component contains the first arg as a substring
9490 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009491 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9492 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 String[] newArgs;
9494 String componentNameString;
9495 ServiceRecord r;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009496 if (opti <= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497 componentNameString = null;
9498 newArgs = EMPTY_STRING_ARRAY;
9499 r = null;
9500 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009501 componentNameString = args[opti];
9502 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9504 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009505 newArgs = new String[args.length - opti];
9506 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 }
9508
9509 if (r != null) {
9510 dumpService(fd, pw, r, newArgs);
9511 } else {
9512 for (ServiceRecord r1 : mServices.values()) {
9513 if (componentNameString == null
9514 || r1.name.flattenToString().contains(componentNameString)) {
9515 dumpService(fd, pw, r1, newArgs);
9516 }
9517 }
9518 }
9519 }
9520
9521 /**
9522 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9523 * there is a thread associated with the service.
9524 */
9525 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9526 pw.println(" Service " + r.name.flattenToString());
9527 if (r.app != null && r.app.thread != null) {
9528 try {
9529 // flush anything that is already in the PrintWriter since the thread is going
9530 // to write to the file descriptor directly
9531 pw.flush();
9532 r.app.thread.dumpService(fd, r, args);
9533 pw.print("\n");
9534 } catch (RemoteException e) {
9535 pw.println("got a RemoteException while dumping the service");
9536 }
9537 }
9538 }
9539
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009540 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9541 int opti, boolean dumpAll) {
9542 boolean needSep = false;
9543
9544 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 if (mRegisteredReceivers.size() > 0) {
9546 pw.println(" ");
9547 pw.println(" Registered Receivers:");
9548 Iterator it = mRegisteredReceivers.values().iterator();
9549 while (it.hasNext()) {
9550 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009551 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 r.dump(pw, " ");
9553 }
9554 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 pw.println(" ");
9557 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009558 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009559 needSep = true;
9560 }
9561
9562 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9563 || mPendingBroadcast != null) {
9564 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009566 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009567 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009568 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9569 pw.println(" Broadcast #" + i + ":");
9570 mParallelBroadcasts.get(i).dump(pw, " ");
9571 }
9572 if (mOrderedBroadcasts.size() > 0) {
9573 pw.println(" ");
9574 pw.println(" Active serialized broadcasts:");
9575 }
9576 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9577 pw.println(" Serialized Broadcast #" + i + ":");
9578 mOrderedBroadcasts.get(i).dump(pw, " ");
9579 }
9580 pw.println(" ");
9581 pw.println(" Pending broadcast:");
9582 if (mPendingBroadcast != null) {
9583 mPendingBroadcast.dump(pw, " ");
9584 } else {
9585 pw.println(" (null)");
9586 }
9587 needSep = true;
9588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009589
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009590 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009592 pw.println(" Historical broadcasts:");
9593 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9594 BroadcastRecord r = mBroadcastHistory[i];
9595 if (r == null) {
9596 break;
9597 }
9598 pw.println(" Historical Broadcast #" + i + ":");
9599 r.dump(pw, " ");
9600 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009601 needSep = true;
9602 }
9603
9604 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009605 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009606 pw.println(" Sticky broadcasts:");
9607 StringBuilder sb = new StringBuilder(128);
9608 for (Map.Entry<String, ArrayList<Intent>> ent
9609 : mStickyBroadcasts.entrySet()) {
9610 pw.print(" * Sticky action "); pw.print(ent.getKey());
9611 pw.println(":");
9612 ArrayList<Intent> intents = ent.getValue();
9613 final int N = intents.size();
9614 for (int i=0; i<N; i++) {
9615 sb.setLength(0);
9616 sb.append(" Intent: ");
9617 intents.get(i).toShortString(sb, true, false);
9618 pw.println(sb.toString());
9619 Bundle bundle = intents.get(i).getExtras();
9620 if (bundle != null) {
9621 pw.print(" ");
9622 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009623 }
9624 }
9625 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009626 needSep = true;
9627 }
9628
9629 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009631 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 pw.println(" mHandler:");
9633 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009634 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009636
9637 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 }
9639
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009640 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9641 int opti, boolean dumpAll) {
9642 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009644 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 if (mServices.size() > 0) {
9646 pw.println(" Active services:");
9647 Iterator<ServiceRecord> it = mServices.values().iterator();
9648 while (it.hasNext()) {
9649 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009650 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009651 r.dump(pw, " ");
9652 }
9653 needSep = true;
9654 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009657 if (mPendingServices.size() > 0) {
9658 if (needSep) pw.println(" ");
9659 pw.println(" Pending services:");
9660 for (int i=0; i<mPendingServices.size(); i++) {
9661 ServiceRecord r = mPendingServices.get(i);
9662 pw.print(" * Pending "); pw.println(r);
9663 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009665 needSep = true;
9666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009668 if (mRestartingServices.size() > 0) {
9669 if (needSep) pw.println(" ");
9670 pw.println(" Restarting services:");
9671 for (int i=0; i<mRestartingServices.size(); i++) {
9672 ServiceRecord r = mRestartingServices.get(i);
9673 pw.print(" * Restarting "); pw.println(r);
9674 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009676 needSep = true;
9677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009679 if (mStoppingServices.size() > 0) {
9680 if (needSep) pw.println(" ");
9681 pw.println(" Stopping services:");
9682 for (int i=0; i<mStoppingServices.size(); i++) {
9683 ServiceRecord r = mStoppingServices.get(i);
9684 pw.print(" * Stopping "); pw.println(r);
9685 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009687 needSep = true;
9688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009690 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 if (mServiceConnections.size() > 0) {
9692 if (needSep) pw.println(" ");
9693 pw.println(" Connection bindings to services:");
9694 Iterator<ConnectionRecord> it
9695 = mServiceConnections.values().iterator();
9696 while (it.hasNext()) {
9697 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009698 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699 r.dump(pw, " ");
9700 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009701 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 }
9703 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009704
9705 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706 }
9707
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009708 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9709 int opti, boolean dumpAll) {
9710 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009712 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009713 if (mProvidersByClass.size() > 0) {
9714 if (needSep) pw.println(" ");
9715 pw.println(" Published content providers (by class):");
9716 Iterator it = mProvidersByClass.entrySet().iterator();
9717 while (it.hasNext()) {
9718 Map.Entry e = (Map.Entry)it.next();
9719 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009720 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 r.dump(pw, " ");
9722 }
9723 needSep = true;
9724 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009725
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009726 if (mProvidersByName.size() > 0) {
9727 pw.println(" ");
9728 pw.println(" Authority to provider mappings:");
9729 Iterator it = mProvidersByName.entrySet().iterator();
9730 while (it.hasNext()) {
9731 Map.Entry e = (Map.Entry)it.next();
9732 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9733 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9734 pw.println(r);
9735 }
9736 needSep = true;
9737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009739
9740 if (mLaunchingProviders.size() > 0) {
9741 if (needSep) pw.println(" ");
9742 pw.println(" Launching content providers:");
9743 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9744 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9745 pw.println(mLaunchingProviders.get(i));
9746 }
9747 needSep = true;
9748 }
9749
9750 if (mGrantedUriPermissions.size() > 0) {
9751 pw.println();
9752 pw.println("Granted Uri Permissions:");
9753 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9754 int uid = mGrantedUriPermissions.keyAt(i);
9755 HashMap<Uri, UriPermission> perms
9756 = mGrantedUriPermissions.valueAt(i);
9757 pw.print(" * UID "); pw.print(uid);
9758 pw.println(" holds:");
9759 for (UriPermission perm : perms.values()) {
9760 pw.print(" "); pw.println(perm);
9761 perm.dump(pw, " ");
9762 }
9763 }
9764 needSep = true;
9765 }
9766
9767 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 }
9769
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009770 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9771 int opti, boolean dumpAll) {
9772 boolean needSep = false;
9773
9774 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 if (this.mIntentSenderRecords.size() > 0) {
9776 Iterator<WeakReference<PendingIntentRecord>> it
9777 = mIntentSenderRecords.values().iterator();
9778 while (it.hasNext()) {
9779 WeakReference<PendingIntentRecord> ref = it.next();
9780 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009781 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009783 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 rec.dump(pw, " ");
9785 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009786 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009787 }
9788 }
9789 }
9790 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009791
9792 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 }
9794
9795 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009796 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 TaskRecord lastTask = null;
9798 for (int i=list.size()-1; i>=0; i--) {
9799 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009800 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009801 if (lastTask != r.task) {
9802 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009803 pw.print(prefix);
9804 pw.print(full ? "* " : " ");
9805 pw.println(lastTask);
9806 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009807 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009810 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9811 pw.print(" #"); pw.print(i); pw.print(": ");
9812 pw.println(r);
9813 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009814 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816 }
9817 }
9818
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009819 private static String buildOomTag(String prefix, String space, int val, int base) {
9820 if (val == base) {
9821 if (space == null) return prefix;
9822 return prefix + " ";
9823 }
9824 return prefix + "+" + Integer.toString(val-base);
9825 }
9826
9827 private static final int dumpProcessList(PrintWriter pw,
9828 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 String prefix, String normalLabel, String persistentLabel,
9830 boolean inclOomAdj) {
9831 int numPers = 0;
9832 for (int i=list.size()-1; i>=0; i--) {
9833 ProcessRecord r = (ProcessRecord)list.get(i);
9834 if (false) {
9835 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9836 + " #" + i + ":");
9837 r.dump(pw, prefix + " ");
9838 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009839 String oomAdj;
9840 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009841 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009842 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009843 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9844 } else if (r.setAdj >= HOME_APP_ADJ) {
9845 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9846 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9847 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9848 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9849 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9850 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9851 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9852 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9853 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009854 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009855 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009856 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009857 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009858 } else {
9859 oomAdj = Integer.toString(r.setAdj);
9860 }
9861 String schedGroup;
9862 switch (r.setSchedGroup) {
9863 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9864 schedGroup = "B";
9865 break;
9866 case Process.THREAD_GROUP_DEFAULT:
9867 schedGroup = "F";
9868 break;
9869 default:
9870 schedGroup = Integer.toString(r.setSchedGroup);
9871 break;
9872 }
9873 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009875 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009876 if (r.adjSource != null || r.adjTarget != null) {
9877 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009878 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009880 } else {
9881 pw.println(String.format("%s%s #%2d: %s",
9882 prefix, (r.persistent ? persistentLabel : normalLabel),
9883 i, r.toString()));
9884 }
9885 if (r.persistent) {
9886 numPers++;
9887 }
9888 }
9889 return numPers;
9890 }
9891
9892 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
9893 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009894 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 long uptime = SystemClock.uptimeMillis();
9896 long realtime = SystemClock.elapsedRealtime();
9897
9898 if (isCheckinRequest) {
9899 // short checkin version
9900 pw.println(uptime + "," + realtime);
9901 pw.flush();
9902 } else {
9903 pw.println("Applications Memory Usage (kB):");
9904 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9905 }
9906 for (int i = list.size() - 1 ; i >= 0 ; i--) {
9907 ProcessRecord r = (ProcessRecord)list.get(i);
9908 if (r.thread != null) {
9909 if (!isCheckinRequest) {
9910 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9911 pw.flush();
9912 }
9913 try {
9914 r.thread.asBinder().dump(fd, args);
9915 } catch (RemoteException e) {
9916 if (!isCheckinRequest) {
9917 pw.println("Got RemoteException!");
9918 pw.flush();
9919 }
9920 }
9921 }
9922 }
9923 }
9924
9925 /**
9926 * Searches array of arguments for the specified string
9927 * @param args array of argument strings
9928 * @param value value to search for
9929 * @return true if the value is contained in the array
9930 */
9931 private static boolean scanArgs(String[] args, String value) {
9932 if (args != null) {
9933 for (String arg : args) {
9934 if (value.equals(arg)) {
9935 return true;
9936 }
9937 }
9938 }
9939 return false;
9940 }
9941
Dianne Hackborn75b03852009-06-12 15:43:26 -07009942 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 int count = mHistory.size();
9944
9945 // convert the token to an entry in the history.
9946 HistoryRecord r = null;
9947 int index = -1;
9948 for (int i=count-1; i>=0; i--) {
9949 Object o = mHistory.get(i);
9950 if (o == token) {
9951 r = (HistoryRecord)o;
9952 index = i;
9953 break;
9954 }
9955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956
9957 return index;
9958 }
9959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009960 private final void killServicesLocked(ProcessRecord app,
9961 boolean allowRestart) {
9962 // Report disconnected services.
9963 if (false) {
9964 // XXX we are letting the client link to the service for
9965 // death notifications.
9966 if (app.services.size() > 0) {
9967 Iterator it = app.services.iterator();
9968 while (it.hasNext()) {
9969 ServiceRecord r = (ServiceRecord)it.next();
9970 if (r.connections.size() > 0) {
9971 Iterator<ConnectionRecord> jt
9972 = r.connections.values().iterator();
9973 while (jt.hasNext()) {
9974 ConnectionRecord c = jt.next();
9975 if (c.binding.client != app) {
9976 try {
9977 //c.conn.connected(r.className, null);
9978 } catch (Exception e) {
9979 // todo: this should be asynchronous!
9980 Log.w(TAG, "Exception thrown disconnected servce "
9981 + r.shortName
9982 + " from app " + app.processName, e);
9983 }
9984 }
9985 }
9986 }
9987 }
9988 }
9989 }
9990
9991 // Clean up any connections this application has to other services.
9992 if (app.connections.size() > 0) {
9993 Iterator<ConnectionRecord> it = app.connections.iterator();
9994 while (it.hasNext()) {
9995 ConnectionRecord r = it.next();
9996 removeConnectionLocked(r, app, null);
9997 }
9998 }
9999 app.connections.clear();
10000
10001 if (app.services.size() != 0) {
10002 // Any services running in the application need to be placed
10003 // back in the pending list.
10004 Iterator it = app.services.iterator();
10005 while (it.hasNext()) {
10006 ServiceRecord sr = (ServiceRecord)it.next();
10007 synchronized (sr.stats.getBatteryStats()) {
10008 sr.stats.stopLaunchedLocked();
10009 }
10010 sr.app = null;
10011 sr.executeNesting = 0;
10012 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010013
10014 boolean hasClients = sr.bindings.size() > 0;
10015 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016 Iterator<IntentBindRecord> bindings
10017 = sr.bindings.values().iterator();
10018 while (bindings.hasNext()) {
10019 IntentBindRecord b = bindings.next();
10020 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
10021 + ": shouldUnbind=" + b.hasBound);
10022 b.binder = null;
10023 b.requested = b.received = b.hasBound = false;
10024 }
10025 }
10026
10027 if (sr.crashCount >= 2) {
10028 Log.w(TAG, "Service crashed " + sr.crashCount
10029 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010030 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 sr.crashCount, sr.shortName, app.pid);
10032 bringDownServiceLocked(sr, true);
10033 } else if (!allowRestart) {
10034 bringDownServiceLocked(sr, true);
10035 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010036 boolean canceled = scheduleServiceRestartLocked(sr, true);
10037
10038 // Should the service remain running? Note that in the
10039 // extreme case of so many attempts to deliver a command
10040 // that it failed, that we also will stop it here.
10041 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10042 if (sr.pendingStarts.size() == 0) {
10043 sr.startRequested = false;
10044 if (!hasClients) {
10045 // Whoops, no reason to restart!
10046 bringDownServiceLocked(sr, true);
10047 }
10048 }
10049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050 }
10051 }
10052
10053 if (!allowRestart) {
10054 app.services.clear();
10055 }
10056 }
10057
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010058 // Make sure we have no more records on the stopping list.
10059 int i = mStoppingServices.size();
10060 while (i > 0) {
10061 i--;
10062 ServiceRecord sr = mStoppingServices.get(i);
10063 if (sr.app == app) {
10064 mStoppingServices.remove(i);
10065 }
10066 }
10067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068 app.executingServices.clear();
10069 }
10070
10071 private final void removeDyingProviderLocked(ProcessRecord proc,
10072 ContentProviderRecord cpr) {
10073 synchronized (cpr) {
10074 cpr.launchingApp = null;
10075 cpr.notifyAll();
10076 }
10077
10078 mProvidersByClass.remove(cpr.info.name);
10079 String names[] = cpr.info.authority.split(";");
10080 for (int j = 0; j < names.length; j++) {
10081 mProvidersByName.remove(names[j]);
10082 }
10083
10084 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10085 while (cit.hasNext()) {
10086 ProcessRecord capp = cit.next();
10087 if (!capp.persistent && capp.thread != null
10088 && capp.pid != 0
10089 && capp.pid != MY_PID) {
10090 Log.i(TAG, "Killing app " + capp.processName
10091 + " (pid " + capp.pid
10092 + ") because provider " + cpr.info.name
10093 + " is in dying process " + proc.processName);
10094 Process.killProcess(capp.pid);
10095 }
10096 }
10097
10098 mLaunchingProviders.remove(cpr);
10099 }
10100
10101 /**
10102 * Main code for cleaning up a process when it has gone away. This is
10103 * called both as a result of the process dying, or directly when stopping
10104 * a process when running in single process mode.
10105 */
10106 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10107 boolean restarting, int index) {
10108 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010109 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110 }
10111
Dianne Hackborn36124872009-10-08 16:22:03 -070010112 mProcessesToGc.remove(app);
10113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 // Dismiss any open dialogs.
10115 if (app.crashDialog != null) {
10116 app.crashDialog.dismiss();
10117 app.crashDialog = null;
10118 }
10119 if (app.anrDialog != null) {
10120 app.anrDialog.dismiss();
10121 app.anrDialog = null;
10122 }
10123 if (app.waitDialog != null) {
10124 app.waitDialog.dismiss();
10125 app.waitDialog = null;
10126 }
10127
10128 app.crashing = false;
10129 app.notResponding = false;
10130
10131 app.resetPackageList();
10132 app.thread = null;
10133 app.forcingToForeground = null;
10134 app.foregroundServices = false;
10135
10136 killServicesLocked(app, true);
10137
10138 boolean restart = false;
10139
10140 int NL = mLaunchingProviders.size();
10141
10142 // Remove published content providers.
10143 if (!app.pubProviders.isEmpty()) {
10144 Iterator it = app.pubProviders.values().iterator();
10145 while (it.hasNext()) {
10146 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10147 cpr.provider = null;
10148 cpr.app = null;
10149
10150 // See if someone is waiting for this provider... in which
10151 // case we don't remove it, but just let it restart.
10152 int i = 0;
10153 if (!app.bad) {
10154 for (; i<NL; i++) {
10155 if (mLaunchingProviders.get(i) == cpr) {
10156 restart = true;
10157 break;
10158 }
10159 }
10160 } else {
10161 i = NL;
10162 }
10163
10164 if (i >= NL) {
10165 removeDyingProviderLocked(app, cpr);
10166 NL = mLaunchingProviders.size();
10167 }
10168 }
10169 app.pubProviders.clear();
10170 }
10171
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010172 // Take care of any launching providers waiting for this process.
10173 if (checkAppInLaunchingProvidersLocked(app, false)) {
10174 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010177 // Unregister from connected content providers.
10178 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010179 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010180 while (it.hasNext()) {
10181 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10182 cpr.clients.remove(app);
10183 }
10184 app.conProviders.clear();
10185 }
10186
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010187 // At this point there may be remaining entries in mLaunchingProviders
10188 // where we were the only one waiting, so they are no longer of use.
10189 // Look for these and clean up if found.
10190 // XXX Commented out for now. Trying to figure out a way to reproduce
10191 // the actual situation to identify what is actually going on.
10192 if (false) {
10193 for (int i=0; i<NL; i++) {
10194 ContentProviderRecord cpr = (ContentProviderRecord)
10195 mLaunchingProviders.get(i);
10196 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10197 synchronized (cpr) {
10198 cpr.launchingApp = null;
10199 cpr.notifyAll();
10200 }
10201 }
10202 }
10203 }
10204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 skipCurrentReceiverLocked(app);
10206
10207 // Unregister any receivers.
10208 if (app.receivers.size() > 0) {
10209 Iterator<ReceiverList> it = app.receivers.iterator();
10210 while (it.hasNext()) {
10211 removeReceiverLocked(it.next());
10212 }
10213 app.receivers.clear();
10214 }
10215
Christopher Tate181fafa2009-05-14 11:12:14 -070010216 // If the app is undergoing backup, tell the backup manager about it
10217 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
10218 if (DEBUG_BACKUP) Log.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
10219 try {
10220 IBackupManager bm = IBackupManager.Stub.asInterface(
10221 ServiceManager.getService(Context.BACKUP_SERVICE));
10222 bm.agentDisconnected(app.info.packageName);
10223 } catch (RemoteException e) {
10224 // can't happen; backup manager is local
10225 }
10226 }
10227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 // If the caller is restarting this app, then leave it in its
10229 // current lists and let the caller take care of it.
10230 if (restarting) {
10231 return;
10232 }
10233
10234 if (!app.persistent) {
10235 if (DEBUG_PROCESSES) Log.v(TAG,
10236 "Removing non-persistent process during cleanup: " + app);
10237 mProcessNames.remove(app.processName, app.info.uid);
10238 } else if (!app.removed) {
10239 // This app is persistent, so we need to keep its record around.
10240 // If it is not already on the pending app list, add it there
10241 // and start a new process for it.
10242 app.thread = null;
10243 app.forcingToForeground = null;
10244 app.foregroundServices = false;
10245 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10246 mPersistentStartingProcesses.add(app);
10247 restart = true;
10248 }
10249 }
10250 mProcessesOnHold.remove(app);
10251
The Android Open Source Project4df24232009-03-05 14:34:35 -080010252 if (app == mHomeProcess) {
10253 mHomeProcess = null;
10254 }
10255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 if (restart) {
10257 // We have components that still need to be running in the
10258 // process, so re-launch it.
10259 mProcessNames.put(app.processName, app.info.uid, app);
10260 startProcessLocked(app, "restart", app.processName);
10261 } else if (app.pid > 0 && app.pid != MY_PID) {
10262 // Goodbye!
10263 synchronized (mPidsSelfLocked) {
10264 mPidsSelfLocked.remove(app.pid);
10265 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10266 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010267 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 }
10269 }
10270
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010271 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10272 // Look through the content providers we are waiting to have launched,
10273 // and if any run in this process then either schedule a restart of
10274 // the process or kill the client waiting for it if this process has
10275 // gone bad.
10276 int NL = mLaunchingProviders.size();
10277 boolean restart = false;
10278 for (int i=0; i<NL; i++) {
10279 ContentProviderRecord cpr = (ContentProviderRecord)
10280 mLaunchingProviders.get(i);
10281 if (cpr.launchingApp == app) {
10282 if (!alwaysBad && !app.bad) {
10283 restart = true;
10284 } else {
10285 removeDyingProviderLocked(app, cpr);
10286 NL = mLaunchingProviders.size();
10287 }
10288 }
10289 }
10290 return restart;
10291 }
10292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 // =========================================================
10294 // SERVICES
10295 // =========================================================
10296
10297 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10298 ActivityManager.RunningServiceInfo info =
10299 new ActivityManager.RunningServiceInfo();
10300 info.service = r.name;
10301 if (r.app != null) {
10302 info.pid = r.app.pid;
10303 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010304 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010305 info.process = r.processName;
10306 info.foreground = r.isForeground;
10307 info.activeSince = r.createTime;
10308 info.started = r.startRequested;
10309 info.clientCount = r.connections.size();
10310 info.crashCount = r.crashCount;
10311 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010312 if (r.isForeground) {
10313 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10314 }
10315 if (r.startRequested) {
10316 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10317 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010318 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010319 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10320 }
10321 if (r.app != null && r.app.persistent) {
10322 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10323 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010324 for (ConnectionRecord conn : r.connections.values()) {
10325 if (conn.clientLabel != 0) {
10326 info.clientPackage = conn.binding.client.info.packageName;
10327 info.clientLabel = conn.clientLabel;
10328 break;
10329 }
10330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010331 return info;
10332 }
10333
10334 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10335 int flags) {
10336 synchronized (this) {
10337 ArrayList<ActivityManager.RunningServiceInfo> res
10338 = new ArrayList<ActivityManager.RunningServiceInfo>();
10339
10340 if (mServices.size() > 0) {
10341 Iterator<ServiceRecord> it = mServices.values().iterator();
10342 while (it.hasNext() && res.size() < maxNum) {
10343 res.add(makeRunningServiceInfoLocked(it.next()));
10344 }
10345 }
10346
10347 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10348 ServiceRecord r = mRestartingServices.get(i);
10349 ActivityManager.RunningServiceInfo info =
10350 makeRunningServiceInfoLocked(r);
10351 info.restarting = r.nextRestartTime;
10352 res.add(info);
10353 }
10354
10355 return res;
10356 }
10357 }
10358
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010359 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10360 synchronized (this) {
10361 ServiceRecord r = mServices.get(name);
10362 if (r != null) {
10363 for (ConnectionRecord conn : r.connections.values()) {
10364 if (conn.clientIntent != null) {
10365 return conn.clientIntent;
10366 }
10367 }
10368 }
10369 }
10370 return null;
10371 }
10372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 private final ServiceRecord findServiceLocked(ComponentName name,
10374 IBinder token) {
10375 ServiceRecord r = mServices.get(name);
10376 return r == token ? r : null;
10377 }
10378
10379 private final class ServiceLookupResult {
10380 final ServiceRecord record;
10381 final String permission;
10382
10383 ServiceLookupResult(ServiceRecord _record, String _permission) {
10384 record = _record;
10385 permission = _permission;
10386 }
10387 };
10388
10389 private ServiceLookupResult findServiceLocked(Intent service,
10390 String resolvedType) {
10391 ServiceRecord r = null;
10392 if (service.getComponent() != null) {
10393 r = mServices.get(service.getComponent());
10394 }
10395 if (r == null) {
10396 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10397 r = mServicesByIntent.get(filter);
10398 }
10399
10400 if (r == null) {
10401 try {
10402 ResolveInfo rInfo =
10403 ActivityThread.getPackageManager().resolveService(
10404 service, resolvedType, 0);
10405 ServiceInfo sInfo =
10406 rInfo != null ? rInfo.serviceInfo : null;
10407 if (sInfo == null) {
10408 return null;
10409 }
10410
10411 ComponentName name = new ComponentName(
10412 sInfo.applicationInfo.packageName, sInfo.name);
10413 r = mServices.get(name);
10414 } catch (RemoteException ex) {
10415 // pm is in same process, this will never happen.
10416 }
10417 }
10418 if (r != null) {
10419 int callingPid = Binder.getCallingPid();
10420 int callingUid = Binder.getCallingUid();
10421 if (checkComponentPermission(r.permission,
10422 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10423 != PackageManager.PERMISSION_GRANTED) {
10424 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10425 + " from pid=" + callingPid
10426 + ", uid=" + callingUid
10427 + " requires " + r.permission);
10428 return new ServiceLookupResult(null, r.permission);
10429 }
10430 return new ServiceLookupResult(r, null);
10431 }
10432 return null;
10433 }
10434
10435 private class ServiceRestarter implements Runnable {
10436 private ServiceRecord mService;
10437
10438 void setService(ServiceRecord service) {
10439 mService = service;
10440 }
10441
10442 public void run() {
10443 synchronized(ActivityManagerService.this) {
10444 performServiceRestartLocked(mService);
10445 }
10446 }
10447 }
10448
10449 private ServiceLookupResult retrieveServiceLocked(Intent service,
10450 String resolvedType, int callingPid, int callingUid) {
10451 ServiceRecord r = null;
10452 if (service.getComponent() != null) {
10453 r = mServices.get(service.getComponent());
10454 }
10455 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10456 r = mServicesByIntent.get(filter);
10457 if (r == null) {
10458 try {
10459 ResolveInfo rInfo =
10460 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010461 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 ServiceInfo sInfo =
10463 rInfo != null ? rInfo.serviceInfo : null;
10464 if (sInfo == null) {
10465 Log.w(TAG, "Unable to start service " + service +
10466 ": not found");
10467 return null;
10468 }
10469
10470 ComponentName name = new ComponentName(
10471 sInfo.applicationInfo.packageName, sInfo.name);
10472 r = mServices.get(name);
10473 if (r == null) {
10474 filter = new Intent.FilterComparison(service.cloneFilter());
10475 ServiceRestarter res = new ServiceRestarter();
10476 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10477 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10478 synchronized (stats) {
10479 ss = stats.getServiceStatsLocked(
10480 sInfo.applicationInfo.uid, sInfo.packageName,
10481 sInfo.name);
10482 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010483 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 res.setService(r);
10485 mServices.put(name, r);
10486 mServicesByIntent.put(filter, r);
10487
10488 // Make sure this component isn't in the pending list.
10489 int N = mPendingServices.size();
10490 for (int i=0; i<N; i++) {
10491 ServiceRecord pr = mPendingServices.get(i);
10492 if (pr.name.equals(name)) {
10493 mPendingServices.remove(i);
10494 i--;
10495 N--;
10496 }
10497 }
10498 }
10499 } catch (RemoteException ex) {
10500 // pm is in same process, this will never happen.
10501 }
10502 }
10503 if (r != null) {
10504 if (checkComponentPermission(r.permission,
10505 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10506 != PackageManager.PERMISSION_GRANTED) {
10507 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10508 + " from pid=" + Binder.getCallingPid()
10509 + ", uid=" + Binder.getCallingUid()
10510 + " requires " + r.permission);
10511 return new ServiceLookupResult(null, r.permission);
10512 }
10513 return new ServiceLookupResult(r, null);
10514 }
10515 return null;
10516 }
10517
10518 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10519 long now = SystemClock.uptimeMillis();
10520 if (r.executeNesting == 0 && r.app != null) {
10521 if (r.app.executingServices.size() == 0) {
10522 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10523 msg.obj = r.app;
10524 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10525 }
10526 r.app.executingServices.add(r);
10527 }
10528 r.executeNesting++;
10529 r.executingStart = now;
10530 }
10531
10532 private final void sendServiceArgsLocked(ServiceRecord r,
10533 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010534 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 if (N == 0) {
10536 return;
10537 }
10538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 int i = 0;
10540 while (i < N) {
10541 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010542 ServiceRecord.StartItem si = r.pendingStarts.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010544 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010545 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010546 // If somehow we got a dummy start at the front, then
10547 // just drop it here.
10548 i++;
10549 continue;
10550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 bumpServiceExecutingLocked(r);
10552 if (!oomAdjusted) {
10553 oomAdjusted = true;
10554 updateOomAdjLocked(r.app);
10555 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010556 int flags = 0;
10557 if (si.deliveryCount > 0) {
10558 flags |= Service.START_FLAG_RETRY;
10559 }
10560 if (si.doneExecutingCount > 0) {
10561 flags |= Service.START_FLAG_REDELIVERY;
10562 }
10563 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10564 si.deliveredTime = SystemClock.uptimeMillis();
10565 r.deliveredStarts.add(si);
10566 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010567 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010568 } catch (RemoteException e) {
10569 // Remote process gone... we'll let the normal cleanup take
10570 // care of this.
10571 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010572 } catch (Exception e) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010573 Log.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574 break;
10575 }
10576 }
10577 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010578 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 } else {
10580 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010582 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 }
10584 }
10585 }
10586
10587 private final boolean requestServiceBindingLocked(ServiceRecord r,
10588 IntentBindRecord i, boolean rebind) {
10589 if (r.app == null || r.app.thread == null) {
10590 // If service is not currently running, can't yet bind.
10591 return false;
10592 }
10593 if ((!i.requested || rebind) && i.apps.size() > 0) {
10594 try {
10595 bumpServiceExecutingLocked(r);
10596 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
10597 + ": shouldUnbind=" + i.hasBound);
10598 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10599 if (!rebind) {
10600 i.requested = true;
10601 }
10602 i.hasBound = true;
10603 i.doRebind = false;
10604 } catch (RemoteException e) {
10605 return false;
10606 }
10607 }
10608 return true;
10609 }
10610
10611 private final void requestServiceBindingsLocked(ServiceRecord r) {
10612 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10613 while (bindings.hasNext()) {
10614 IntentBindRecord i = bindings.next();
10615 if (!requestServiceBindingLocked(r, i, false)) {
10616 break;
10617 }
10618 }
10619 }
10620
10621 private final void realStartServiceLocked(ServiceRecord r,
10622 ProcessRecord app) throws RemoteException {
10623 if (app.thread == null) {
10624 throw new RemoteException();
10625 }
10626
10627 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010628 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629
10630 app.services.add(r);
10631 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010632 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010633
10634 boolean created = false;
10635 try {
10636 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
10637 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010638 mStringBuilder.setLength(0);
10639 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010640 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010642 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010643 synchronized (r.stats.getBatteryStats()) {
10644 r.stats.startLaunchedLocked();
10645 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010646 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010647 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010648 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 created = true;
10650 } finally {
10651 if (!created) {
10652 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010653 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 }
10655 }
10656
10657 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010658
10659 // If the service is in the started state, and there are no
10660 // pending arguments, then fake up one so its onStartCommand() will
10661 // be called.
10662 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10663 r.lastStartId++;
10664 if (r.lastStartId < 1) {
10665 r.lastStartId = 1;
10666 }
10667 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10668 }
10669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 sendServiceArgsLocked(r, true);
10671 }
10672
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010673 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10674 boolean allowCancel) {
10675 boolean canceled = false;
10676
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010677 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010678 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010679 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010680
10681 // Any delivered but not yet finished starts should be put back
10682 // on the pending list.
10683 final int N = r.deliveredStarts.size();
10684 if (N > 0) {
10685 for (int i=N-1; i>=0; i--) {
10686 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10687 if (si.intent == null) {
10688 // We'll generate this again if needed.
10689 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10690 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10691 r.pendingStarts.add(0, si);
10692 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10693 dur *= 2;
10694 if (minDuration < dur) minDuration = dur;
10695 if (resetTime < dur) resetTime = dur;
10696 } else {
10697 Log.w(TAG, "Canceling start item " + si.intent + " in service "
10698 + r.name);
10699 canceled = true;
10700 }
10701 }
10702 r.deliveredStarts.clear();
10703 }
10704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 r.totalRestartCount++;
10706 if (r.restartDelay == 0) {
10707 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010708 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 } else {
10710 // If it has been a "reasonably long time" since the service
10711 // was started, then reset our restart duration back to
10712 // the beginning, so we don't infinitely increase the duration
10713 // on a service that just occasionally gets killed (which is
10714 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010715 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010717 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010719 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010720 if (r.restartDelay < minDuration) {
10721 r.restartDelay = minDuration;
10722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010723 }
10724 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010725
10726 r.nextRestartTime = now + r.restartDelay;
10727
10728 // Make sure that we don't end up restarting a bunch of services
10729 // all at the same time.
10730 boolean repeat;
10731 do {
10732 repeat = false;
10733 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10734 ServiceRecord r2 = mRestartingServices.get(i);
10735 if (r2 != r && r.nextRestartTime
10736 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10737 && r.nextRestartTime
10738 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10739 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10740 r.restartDelay = r.nextRestartTime - now;
10741 repeat = true;
10742 break;
10743 }
10744 }
10745 } while (repeat);
10746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 if (!mRestartingServices.contains(r)) {
10748 mRestartingServices.add(r);
10749 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010750
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010751 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010754 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
10756 Log.w(TAG, "Scheduling restart of crashed service "
10757 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010758 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 r.shortName, r.restartDelay);
10760
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010761 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 }
10763
10764 final void performServiceRestartLocked(ServiceRecord r) {
10765 if (!mRestartingServices.contains(r)) {
10766 return;
10767 }
10768 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10769 }
10770
10771 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10772 if (r.restartDelay == 0) {
10773 return false;
10774 }
10775 r.resetRestartCounter();
10776 mRestartingServices.remove(r);
10777 mHandler.removeCallbacks(r.restarter);
10778 return true;
10779 }
10780
10781 private final boolean bringUpServiceLocked(ServiceRecord r,
10782 int intentFlags, boolean whileRestarting) {
10783 //Log.i(TAG, "Bring up service:");
10784 //r.dump(" ");
10785
Dianne Hackborn36124872009-10-08 16:22:03 -070010786 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 sendServiceArgsLocked(r, false);
10788 return true;
10789 }
10790
10791 if (!whileRestarting && r.restartDelay > 0) {
10792 // If waiting for a restart, then do nothing.
10793 return true;
10794 }
10795
10796 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
10797 + " " + r.intent);
10798
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010799 // We are now bringing the service up, so no longer in the
10800 // restarting state.
10801 mRestartingServices.remove(r);
10802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010803 final String appName = r.processName;
10804 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10805 if (app != null && app.thread != null) {
10806 try {
10807 realStartServiceLocked(r, app);
10808 return true;
10809 } catch (RemoteException e) {
10810 Log.w(TAG, "Exception when starting service " + r.shortName, e);
10811 }
10812
10813 // If a dead object exception was thrown -- fall through to
10814 // restart the application.
10815 }
10816
Dianne Hackborn36124872009-10-08 16:22:03 -070010817 // Not running -- get it started, and enqueue this service record
10818 // to be executed when the app comes up.
10819 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10820 "service", r.name, false) == null) {
10821 Log.w(TAG, "Unable to launch app "
10822 + r.appInfo.packageName + "/"
10823 + r.appInfo.uid + " for service "
10824 + r.intent.getIntent() + ": process is bad");
10825 bringDownServiceLocked(r, true);
10826 return false;
10827 }
10828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 mPendingServices.add(r);
10831 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 return true;
10834 }
10835
10836 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
10837 //Log.i(TAG, "Bring down service:");
10838 //r.dump(" ");
10839
10840 // Does it still need to run?
10841 if (!force && r.startRequested) {
10842 return;
10843 }
10844 if (r.connections.size() > 0) {
10845 if (!force) {
10846 // XXX should probably keep a count of the number of auto-create
10847 // connections directly in the service.
10848 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10849 while (it.hasNext()) {
10850 ConnectionRecord cr = it.next();
10851 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10852 return;
10853 }
10854 }
10855 }
10856
10857 // Report to all of the connections that the service is no longer
10858 // available.
10859 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10860 while (it.hasNext()) {
10861 ConnectionRecord c = it.next();
10862 try {
10863 // todo: shouldn't be a synchronous call!
10864 c.conn.connected(r.name, null);
10865 } catch (Exception e) {
10866 Log.w(TAG, "Failure disconnecting service " + r.name +
10867 " to connection " + c.conn.asBinder() +
10868 " (in " + c.binding.client.processName + ")", e);
10869 }
10870 }
10871 }
10872
10873 // Tell the service that it has been unbound.
10874 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10875 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10876 while (it.hasNext()) {
10877 IntentBindRecord ibr = it.next();
10878 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
10879 + ": hasBound=" + ibr.hasBound);
10880 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10881 try {
10882 bumpServiceExecutingLocked(r);
10883 updateOomAdjLocked(r.app);
10884 ibr.hasBound = false;
10885 r.app.thread.scheduleUnbindService(r,
10886 ibr.intent.getIntent());
10887 } catch (Exception e) {
10888 Log.w(TAG, "Exception when unbinding service "
10889 + r.shortName, e);
10890 serviceDoneExecutingLocked(r, true);
10891 }
10892 }
10893 }
10894 }
10895
10896 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
10897 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010898 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 System.identityHashCode(r), r.shortName,
10900 (r.app != null) ? r.app.pid : -1);
10901
10902 mServices.remove(r.name);
10903 mServicesByIntent.remove(r.intent);
10904 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
10905 r.totalRestartCount = 0;
10906 unscheduleServiceRestartLocked(r);
10907
10908 // Also make sure it is not on the pending list.
10909 int N = mPendingServices.size();
10910 for (int i=0; i<N; i++) {
10911 if (mPendingServices.get(i) == r) {
10912 mPendingServices.remove(i);
10913 if (DEBUG_SERVICE) Log.v(
10914 TAG, "Removed pending service: " + r.shortName);
10915 i--;
10916 N--;
10917 }
10918 }
10919
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010920 r.cancelNotification();
10921 r.isForeground = false;
10922 r.foregroundId = 0;
10923 r.foregroundNoti = null;
10924
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010925 // Clear start entries.
10926 r.deliveredStarts.clear();
10927 r.pendingStarts.clear();
10928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 if (r.app != null) {
10930 synchronized (r.stats.getBatteryStats()) {
10931 r.stats.stopLaunchedLocked();
10932 }
10933 r.app.services.remove(r);
10934 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010935 try {
Dianne Hackborna1e989b2009-09-01 19:54:29 -070010936 if (DEBUG_SERVICE) Log.v(TAG,
10937 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 bumpServiceExecutingLocked(r);
10939 mStoppingServices.add(r);
10940 updateOomAdjLocked(r.app);
10941 r.app.thread.scheduleStopService(r);
10942 } catch (Exception e) {
10943 Log.w(TAG, "Exception when stopping service "
10944 + r.shortName, e);
10945 serviceDoneExecutingLocked(r, true);
10946 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010947 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 } else {
10949 if (DEBUG_SERVICE) Log.v(
10950 TAG, "Removed service that has no process: " + r.shortName);
10951 }
10952 } else {
10953 if (DEBUG_SERVICE) Log.v(
10954 TAG, "Removed service that is not running: " + r.shortName);
10955 }
10956 }
10957
10958 ComponentName startServiceLocked(IApplicationThread caller,
10959 Intent service, String resolvedType,
10960 int callingPid, int callingUid) {
10961 synchronized(this) {
10962 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
10963 + " type=" + resolvedType + " args=" + service.getExtras());
10964
10965 if (caller != null) {
10966 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10967 if (callerApp == null) {
10968 throw new SecurityException(
10969 "Unable to find app for caller " + caller
10970 + " (pid=" + Binder.getCallingPid()
10971 + ") when starting service " + service);
10972 }
10973 }
10974
10975 ServiceLookupResult res =
10976 retrieveServiceLocked(service, resolvedType,
10977 callingPid, callingUid);
10978 if (res == null) {
10979 return null;
10980 }
10981 if (res.record == null) {
10982 return new ComponentName("!", res.permission != null
10983 ? res.permission : "private to package");
10984 }
10985 ServiceRecord r = res.record;
10986 if (unscheduleServiceRestartLocked(r)) {
10987 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
10988 + r.shortName);
10989 }
10990 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010991 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 r.lastStartId++;
10993 if (r.lastStartId < 1) {
10994 r.lastStartId = 1;
10995 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010996 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 r.lastActivity = SystemClock.uptimeMillis();
10998 synchronized (r.stats.getBatteryStats()) {
10999 r.stats.startRunningLocked();
11000 }
11001 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11002 return new ComponentName("!", "Service process is bad");
11003 }
11004 return r.name;
11005 }
11006 }
11007
11008 public ComponentName startService(IApplicationThread caller, Intent service,
11009 String resolvedType) {
11010 // Refuse possible leaked file descriptors
11011 if (service != null && service.hasFileDescriptors() == true) {
11012 throw new IllegalArgumentException("File descriptors passed in Intent");
11013 }
11014
11015 synchronized(this) {
11016 final int callingPid = Binder.getCallingPid();
11017 final int callingUid = Binder.getCallingUid();
11018 final long origId = Binder.clearCallingIdentity();
11019 ComponentName res = startServiceLocked(caller, service,
11020 resolvedType, callingPid, callingUid);
11021 Binder.restoreCallingIdentity(origId);
11022 return res;
11023 }
11024 }
11025
11026 ComponentName startServiceInPackage(int uid,
11027 Intent service, String resolvedType) {
11028 synchronized(this) {
11029 final long origId = Binder.clearCallingIdentity();
11030 ComponentName res = startServiceLocked(null, service,
11031 resolvedType, -1, uid);
11032 Binder.restoreCallingIdentity(origId);
11033 return res;
11034 }
11035 }
11036
11037 public int stopService(IApplicationThread caller, Intent service,
11038 String resolvedType) {
11039 // Refuse possible leaked file descriptors
11040 if (service != null && service.hasFileDescriptors() == true) {
11041 throw new IllegalArgumentException("File descriptors passed in Intent");
11042 }
11043
11044 synchronized(this) {
11045 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
11046 + " type=" + resolvedType);
11047
11048 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11049 if (caller != null && callerApp == null) {
11050 throw new SecurityException(
11051 "Unable to find app for caller " + caller
11052 + " (pid=" + Binder.getCallingPid()
11053 + ") when stopping service " + service);
11054 }
11055
11056 // If this service is active, make sure it is stopped.
11057 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11058 if (r != null) {
11059 if (r.record != null) {
11060 synchronized (r.record.stats.getBatteryStats()) {
11061 r.record.stats.stopRunningLocked();
11062 }
11063 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011064 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 final long origId = Binder.clearCallingIdentity();
11066 bringDownServiceLocked(r.record, false);
11067 Binder.restoreCallingIdentity(origId);
11068 return 1;
11069 }
11070 return -1;
11071 }
11072 }
11073
11074 return 0;
11075 }
11076
11077 public IBinder peekService(Intent service, String resolvedType) {
11078 // Refuse possible leaked file descriptors
11079 if (service != null && service.hasFileDescriptors() == true) {
11080 throw new IllegalArgumentException("File descriptors passed in Intent");
11081 }
11082
11083 IBinder ret = null;
11084
11085 synchronized(this) {
11086 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11087
11088 if (r != null) {
11089 // r.record is null if findServiceLocked() failed the caller permission check
11090 if (r.record == null) {
11091 throw new SecurityException(
11092 "Permission Denial: Accessing service " + r.record.name
11093 + " from pid=" + Binder.getCallingPid()
11094 + ", uid=" + Binder.getCallingUid()
11095 + " requires " + r.permission);
11096 }
11097 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11098 if (ib != null) {
11099 ret = ib.binder;
11100 }
11101 }
11102 }
11103
11104 return ret;
11105 }
11106
11107 public boolean stopServiceToken(ComponentName className, IBinder token,
11108 int startId) {
11109 synchronized(this) {
11110 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
11111 + " " + token + " startId=" + startId);
11112 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011113 if (r != null) {
11114 if (startId >= 0) {
11115 // Asked to only stop if done with all work. Note that
11116 // to avoid leaks, we will take this as dropping all
11117 // start items up to and including this one.
11118 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11119 if (si != null) {
11120 while (r.deliveredStarts.size() > 0) {
11121 if (r.deliveredStarts.remove(0) == si) {
11122 break;
11123 }
11124 }
11125 }
11126
11127 if (r.lastStartId != startId) {
11128 return false;
11129 }
11130
11131 if (r.deliveredStarts.size() > 0) {
11132 Log.w(TAG, "stopServiceToken startId " + startId
11133 + " is last, but have " + r.deliveredStarts.size()
11134 + " remaining args");
11135 }
11136 }
11137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 synchronized (r.stats.getBatteryStats()) {
11139 r.stats.stopRunningLocked();
11140 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011141 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 }
11143 final long origId = Binder.clearCallingIdentity();
11144 bringDownServiceLocked(r, false);
11145 Binder.restoreCallingIdentity(origId);
11146 return true;
11147 }
11148 }
11149 return false;
11150 }
11151
11152 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011153 int id, Notification notification, boolean removeNotification) {
11154 final long origId = Binder.clearCallingIdentity();
11155 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 synchronized(this) {
11157 ServiceRecord r = findServiceLocked(className, token);
11158 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011159 if (id != 0) {
11160 if (notification == null) {
11161 throw new IllegalArgumentException("null notification");
11162 }
11163 if (r.foregroundId != id) {
11164 r.cancelNotification();
11165 r.foregroundId = id;
11166 }
11167 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11168 r.foregroundNoti = notification;
11169 r.isForeground = true;
11170 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 if (r.app != null) {
11172 updateServiceForegroundLocked(r.app, true);
11173 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011174 } else {
11175 if (r.isForeground) {
11176 r.isForeground = false;
11177 if (r.app != null) {
11178 updateServiceForegroundLocked(r.app, true);
11179 }
11180 }
11181 if (removeNotification) {
11182 r.cancelNotification();
11183 r.foregroundId = 0;
11184 r.foregroundNoti = null;
11185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 }
11187 }
11188 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011189 } finally {
11190 Binder.restoreCallingIdentity(origId);
11191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 }
11193
11194 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11195 boolean anyForeground = false;
11196 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11197 if (sr.isForeground) {
11198 anyForeground = true;
11199 break;
11200 }
11201 }
11202 if (anyForeground != proc.foregroundServices) {
11203 proc.foregroundServices = anyForeground;
11204 if (oomAdj) {
11205 updateOomAdjLocked();
11206 }
11207 }
11208 }
11209
11210 public int bindService(IApplicationThread caller, IBinder token,
11211 Intent service, String resolvedType,
11212 IServiceConnection connection, int flags) {
11213 // Refuse possible leaked file descriptors
11214 if (service != null && service.hasFileDescriptors() == true) {
11215 throw new IllegalArgumentException("File descriptors passed in Intent");
11216 }
11217
11218 synchronized(this) {
11219 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
11220 + " type=" + resolvedType + " conn=" + connection.asBinder()
11221 + " flags=0x" + Integer.toHexString(flags));
11222 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11223 if (callerApp == null) {
11224 throw new SecurityException(
11225 "Unable to find app for caller " + caller
11226 + " (pid=" + Binder.getCallingPid()
11227 + ") when binding service " + service);
11228 }
11229
11230 HistoryRecord activity = null;
11231 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011232 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 if (aindex < 0) {
11234 Log.w(TAG, "Binding with unknown activity: " + token);
11235 return 0;
11236 }
11237 activity = (HistoryRecord)mHistory.get(aindex);
11238 }
11239
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011240 int clientLabel = 0;
11241 PendingIntent clientIntent = null;
11242
11243 if (callerApp.info.uid == Process.SYSTEM_UID) {
11244 // Hacky kind of thing -- allow system stuff to tell us
11245 // what they are, so we can report this elsewhere for
11246 // others to know why certain services are running.
11247 try {
11248 clientIntent = (PendingIntent)service.getParcelableExtra(
11249 Intent.EXTRA_CLIENT_INTENT);
11250 } catch (RuntimeException e) {
11251 }
11252 if (clientIntent != null) {
11253 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11254 if (clientLabel != 0) {
11255 // There are no useful extras in the intent, trash them.
11256 // System code calling with this stuff just needs to know
11257 // this will happen.
11258 service = service.cloneFilter();
11259 }
11260 }
11261 }
11262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 ServiceLookupResult res =
11264 retrieveServiceLocked(service, resolvedType,
11265 Binder.getCallingPid(), Binder.getCallingUid());
11266 if (res == null) {
11267 return 0;
11268 }
11269 if (res.record == null) {
11270 return -1;
11271 }
11272 ServiceRecord s = res.record;
11273
11274 final long origId = Binder.clearCallingIdentity();
11275
11276 if (unscheduleServiceRestartLocked(s)) {
11277 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
11278 + s.shortName);
11279 }
11280
11281 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11282 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011283 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284
11285 IBinder binder = connection.asBinder();
11286 s.connections.put(binder, c);
11287 b.connections.add(c);
11288 if (activity != null) {
11289 if (activity.connections == null) {
11290 activity.connections = new HashSet<ConnectionRecord>();
11291 }
11292 activity.connections.add(c);
11293 }
11294 b.client.connections.add(c);
11295 mServiceConnections.put(binder, c);
11296
11297 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11298 s.lastActivity = SystemClock.uptimeMillis();
11299 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11300 return 0;
11301 }
11302 }
11303
11304 if (s.app != null) {
11305 // This could have made the service more important.
11306 updateOomAdjLocked(s.app);
11307 }
11308
11309 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
11310 + ": received=" + b.intent.received
11311 + " apps=" + b.intent.apps.size()
11312 + " doRebind=" + b.intent.doRebind);
11313
11314 if (s.app != null && b.intent.received) {
11315 // Service is already running, so we can immediately
11316 // publish the connection.
11317 try {
11318 c.conn.connected(s.name, b.intent.binder);
11319 } catch (Exception e) {
11320 Log.w(TAG, "Failure sending service " + s.shortName
11321 + " to connection " + c.conn.asBinder()
11322 + " (in " + c.binding.client.processName + ")", e);
11323 }
11324
11325 // If this is the first app connected back to this binding,
11326 // and the service had previously asked to be told when
11327 // rebound, then do so.
11328 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11329 requestServiceBindingLocked(s, b.intent, true);
11330 }
11331 } else if (!b.intent.requested) {
11332 requestServiceBindingLocked(s, b.intent, false);
11333 }
11334
11335 Binder.restoreCallingIdentity(origId);
11336 }
11337
11338 return 1;
11339 }
11340
11341 private void removeConnectionLocked(
11342 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11343 IBinder binder = c.conn.asBinder();
11344 AppBindRecord b = c.binding;
11345 ServiceRecord s = b.service;
11346 s.connections.remove(binder);
11347 b.connections.remove(c);
11348 if (c.activity != null && c.activity != skipAct) {
11349 if (c.activity.connections != null) {
11350 c.activity.connections.remove(c);
11351 }
11352 }
11353 if (b.client != skipApp) {
11354 b.client.connections.remove(c);
11355 }
11356 mServiceConnections.remove(binder);
11357
11358 if (b.connections.size() == 0) {
11359 b.intent.apps.remove(b.client);
11360 }
11361
11362 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
11363 + ": shouldUnbind=" + b.intent.hasBound);
11364 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11365 && b.intent.hasBound) {
11366 try {
11367 bumpServiceExecutingLocked(s);
11368 updateOomAdjLocked(s.app);
11369 b.intent.hasBound = false;
11370 // Assume the client doesn't want to know about a rebind;
11371 // we will deal with that later if it asks for one.
11372 b.intent.doRebind = false;
11373 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11374 } catch (Exception e) {
11375 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
11376 serviceDoneExecutingLocked(s, true);
11377 }
11378 }
11379
11380 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11381 bringDownServiceLocked(s, false);
11382 }
11383 }
11384
11385 public boolean unbindService(IServiceConnection connection) {
11386 synchronized (this) {
11387 IBinder binder = connection.asBinder();
11388 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
11389 ConnectionRecord r = mServiceConnections.get(binder);
11390 if (r == null) {
11391 Log.w(TAG, "Unbind failed: could not find connection for "
11392 + connection.asBinder());
11393 return false;
11394 }
11395
11396 final long origId = Binder.clearCallingIdentity();
11397
11398 removeConnectionLocked(r, null, null);
11399
11400 if (r.binding.service.app != null) {
11401 // This could have made the service less important.
11402 updateOomAdjLocked(r.binding.service.app);
11403 }
11404
11405 Binder.restoreCallingIdentity(origId);
11406 }
11407
11408 return true;
11409 }
11410
11411 public void publishService(IBinder token, Intent intent, IBinder service) {
11412 // Refuse possible leaked file descriptors
11413 if (intent != null && intent.hasFileDescriptors() == true) {
11414 throw new IllegalArgumentException("File descriptors passed in Intent");
11415 }
11416
11417 synchronized(this) {
11418 if (!(token instanceof ServiceRecord)) {
11419 throw new IllegalArgumentException("Invalid service token");
11420 }
11421 ServiceRecord r = (ServiceRecord)token;
11422
11423 final long origId = Binder.clearCallingIdentity();
11424
11425 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
11426 + " " + intent + ": " + service);
11427 if (r != null) {
11428 Intent.FilterComparison filter
11429 = new Intent.FilterComparison(intent);
11430 IntentBindRecord b = r.bindings.get(filter);
11431 if (b != null && !b.received) {
11432 b.binder = service;
11433 b.requested = true;
11434 b.received = true;
11435 if (r.connections.size() > 0) {
11436 Iterator<ConnectionRecord> it
11437 = r.connections.values().iterator();
11438 while (it.hasNext()) {
11439 ConnectionRecord c = it.next();
11440 if (!filter.equals(c.binding.intent.intent)) {
11441 if (DEBUG_SERVICE) Log.v(
11442 TAG, "Not publishing to: " + c);
11443 if (DEBUG_SERVICE) Log.v(
11444 TAG, "Bound intent: " + c.binding.intent.intent);
11445 if (DEBUG_SERVICE) Log.v(
11446 TAG, "Published intent: " + intent);
11447 continue;
11448 }
11449 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
11450 try {
11451 c.conn.connected(r.name, service);
11452 } catch (Exception e) {
11453 Log.w(TAG, "Failure sending service " + r.name +
11454 " to connection " + c.conn.asBinder() +
11455 " (in " + c.binding.client.processName + ")", e);
11456 }
11457 }
11458 }
11459 }
11460
11461 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11462
11463 Binder.restoreCallingIdentity(origId);
11464 }
11465 }
11466 }
11467
11468 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11469 // Refuse possible leaked file descriptors
11470 if (intent != null && intent.hasFileDescriptors() == true) {
11471 throw new IllegalArgumentException("File descriptors passed in Intent");
11472 }
11473
11474 synchronized(this) {
11475 if (!(token instanceof ServiceRecord)) {
11476 throw new IllegalArgumentException("Invalid service token");
11477 }
11478 ServiceRecord r = (ServiceRecord)token;
11479
11480 final long origId = Binder.clearCallingIdentity();
11481
11482 if (r != null) {
11483 Intent.FilterComparison filter
11484 = new Intent.FilterComparison(intent);
11485 IntentBindRecord b = r.bindings.get(filter);
11486 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
11487 + " at " + b + ": apps="
11488 + (b != null ? b.apps.size() : 0));
11489 if (b != null) {
11490 if (b.apps.size() > 0) {
11491 // Applications have already bound since the last
11492 // unbind, so just rebind right here.
11493 requestServiceBindingLocked(r, b, true);
11494 } else {
11495 // Note to tell the service the next time there is
11496 // a new client.
11497 b.doRebind = true;
11498 }
11499 }
11500
11501 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11502
11503 Binder.restoreCallingIdentity(origId);
11504 }
11505 }
11506 }
11507
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011508 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 synchronized(this) {
11510 if (!(token instanceof ServiceRecord)) {
11511 throw new IllegalArgumentException("Invalid service token");
11512 }
11513 ServiceRecord r = (ServiceRecord)token;
11514 boolean inStopping = mStoppingServices.contains(token);
11515 if (r != null) {
11516 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
11517 + ": nesting=" + r.executeNesting
11518 + ", inStopping=" + inStopping);
11519 if (r != token) {
11520 Log.w(TAG, "Done executing service " + r.name
11521 + " with incorrect token: given " + token
11522 + ", expected " + r);
11523 return;
11524 }
11525
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011526 if (type == 1) {
11527 // This is a call from a service start... take care of
11528 // book-keeping.
11529 r.callStart = true;
11530 switch (res) {
11531 case Service.START_STICKY_COMPATIBILITY:
11532 case Service.START_STICKY: {
11533 // We are done with the associated start arguments.
11534 r.findDeliveredStart(startId, true);
11535 // Don't stop if killed.
11536 r.stopIfKilled = false;
11537 break;
11538 }
11539 case Service.START_NOT_STICKY: {
11540 // We are done with the associated start arguments.
11541 r.findDeliveredStart(startId, true);
11542 if (r.lastStartId == startId) {
11543 // There is no more work, and this service
11544 // doesn't want to hang around if killed.
11545 r.stopIfKilled = true;
11546 }
11547 break;
11548 }
11549 case Service.START_REDELIVER_INTENT: {
11550 // We'll keep this item until they explicitly
11551 // call stop for it, but keep track of the fact
11552 // that it was delivered.
11553 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11554 if (si != null) {
11555 si.deliveryCount = 0;
11556 si.doneExecutingCount++;
11557 // Don't stop if killed.
11558 r.stopIfKilled = true;
11559 }
11560 break;
11561 }
11562 default:
11563 throw new IllegalArgumentException(
11564 "Unknown service start result: " + res);
11565 }
11566 if (res == Service.START_STICKY_COMPATIBILITY) {
11567 r.callStart = false;
11568 }
11569 }
11570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 final long origId = Binder.clearCallingIdentity();
11572 serviceDoneExecutingLocked(r, inStopping);
11573 Binder.restoreCallingIdentity(origId);
11574 } else {
11575 Log.w(TAG, "Done executing unknown service " + r.name
11576 + " with token " + token);
11577 }
11578 }
11579 }
11580
11581 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11582 r.executeNesting--;
11583 if (r.executeNesting <= 0 && r.app != null) {
11584 r.app.executingServices.remove(r);
11585 if (r.app.executingServices.size() == 0) {
11586 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11587 }
11588 if (inStopping) {
11589 mStoppingServices.remove(r);
11590 }
11591 updateOomAdjLocked(r.app);
11592 }
11593 }
11594
11595 void serviceTimeout(ProcessRecord proc) {
11596 synchronized(this) {
11597 if (proc.executingServices.size() == 0 || proc.thread == null) {
11598 return;
11599 }
11600 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11601 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11602 ServiceRecord timeout = null;
11603 long nextTime = 0;
11604 while (it.hasNext()) {
11605 ServiceRecord sr = it.next();
11606 if (sr.executingStart < maxTime) {
11607 timeout = sr;
11608 break;
11609 }
11610 if (sr.executingStart > nextTime) {
11611 nextTime = sr.executingStart;
11612 }
11613 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011614 if (timeout != null && mLruProcesses.contains(proc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011615 Log.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011616 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 } else {
11618 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11619 msg.obj = proc;
11620 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11621 }
11622 }
11623 }
11624
11625 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011626 // BACKUP AND RESTORE
11627 // =========================================================
11628
11629 // Cause the target app to be launched if necessary and its backup agent
11630 // instantiated. The backup agent will invoke backupAgentCreated() on the
11631 // activity manager to announce its creation.
11632 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
11633 if (DEBUG_BACKUP) Log.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
11634 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11635
11636 synchronized(this) {
11637 // !!! TODO: currently no check here that we're already bound
11638 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11639 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11640 synchronized (stats) {
11641 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11642 }
11643
11644 BackupRecord r = new BackupRecord(ss, app, backupMode);
11645 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11646 // startProcessLocked() returns existing proc's record if it's already running
11647 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011648 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011649 if (proc == null) {
11650 Log.e(TAG, "Unable to start backup agent process " + r);
11651 return false;
11652 }
11653
11654 r.app = proc;
11655 mBackupTarget = r;
11656 mBackupAppName = app.packageName;
11657
Christopher Tate6fa95972009-06-05 18:43:55 -070011658 // Try not to kill the process during backup
11659 updateOomAdjLocked(proc);
11660
Christopher Tate181fafa2009-05-14 11:12:14 -070011661 // If the process is already attached, schedule the creation of the backup agent now.
11662 // If it is not yet live, this will be done when it attaches to the framework.
11663 if (proc.thread != null) {
11664 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc already running: " + proc);
11665 try {
11666 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11667 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011668 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011669 }
11670 } else {
11671 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc not running, waiting for attach");
11672 }
11673 // Invariants: at this point, the target app process exists and the application
11674 // is either already running or in the process of coming up. mBackupTarget and
11675 // mBackupAppName describe the app, so that when it binds back to the AM we
11676 // know that it's scheduled for a backup-agent operation.
11677 }
11678
11679 return true;
11680 }
11681
11682 // A backup agent has just come up
11683 public void backupAgentCreated(String agentPackageName, IBinder agent) {
11684 if (DEBUG_BACKUP) Log.v(TAG, "backupAgentCreated: " + agentPackageName
11685 + " = " + agent);
11686
11687 synchronized(this) {
11688 if (!agentPackageName.equals(mBackupAppName)) {
11689 Log.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
11690 return;
11691 }
11692
Christopher Tate043dadc2009-06-02 16:11:00 -070011693 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011694 try {
11695 IBackupManager bm = IBackupManager.Stub.asInterface(
11696 ServiceManager.getService(Context.BACKUP_SERVICE));
11697 bm.agentConnected(agentPackageName, agent);
11698 } catch (RemoteException e) {
11699 // can't happen; the backup manager service is local
11700 } catch (Exception e) {
11701 Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11702 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011703 } finally {
11704 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011705 }
11706 }
11707 }
11708
11709 // done with this agent
11710 public void unbindBackupAgent(ApplicationInfo appInfo) {
11711 if (DEBUG_BACKUP) Log.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011712 if (appInfo == null) {
11713 Log.w(TAG, "unbind backup agent for null app");
11714 return;
11715 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011716
11717 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011718 if (mBackupAppName == null) {
11719 Log.w(TAG, "Unbinding backup agent with no active backup");
11720 return;
11721 }
11722
Christopher Tate181fafa2009-05-14 11:12:14 -070011723 if (!mBackupAppName.equals(appInfo.packageName)) {
11724 Log.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
11725 return;
11726 }
11727
Christopher Tate6fa95972009-06-05 18:43:55 -070011728 ProcessRecord proc = mBackupTarget.app;
11729 mBackupTarget = null;
11730 mBackupAppName = null;
11731
11732 // Not backing this app up any more; reset its OOM adjustment
11733 updateOomAdjLocked(proc);
11734
Christopher Tatec7b31e32009-06-10 15:49:30 -070011735 // If the app crashed during backup, 'thread' will be null here
11736 if (proc.thread != null) {
11737 try {
11738 proc.thread.scheduleDestroyBackupAgent(appInfo);
11739 } catch (Exception e) {
11740 Log.e(TAG, "Exception when unbinding backup agent:");
11741 e.printStackTrace();
11742 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011743 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011744 }
11745 }
11746 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011747 // BROADCASTS
11748 // =========================================================
11749
11750 private final List getStickies(String action, IntentFilter filter,
11751 List cur) {
11752 final ContentResolver resolver = mContext.getContentResolver();
11753 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11754 if (list == null) {
11755 return cur;
11756 }
11757 int N = list.size();
11758 for (int i=0; i<N; i++) {
11759 Intent intent = list.get(i);
11760 if (filter.match(resolver, intent, true, TAG) >= 0) {
11761 if (cur == null) {
11762 cur = new ArrayList<Intent>();
11763 }
11764 cur.add(intent);
11765 }
11766 }
11767 return cur;
11768 }
11769
11770 private final void scheduleBroadcastsLocked() {
11771 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
11772 + mBroadcastsScheduled);
11773
11774 if (mBroadcastsScheduled) {
11775 return;
11776 }
11777 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11778 mBroadcastsScheduled = true;
11779 }
11780
11781 public Intent registerReceiver(IApplicationThread caller,
11782 IIntentReceiver receiver, IntentFilter filter, String permission) {
11783 synchronized(this) {
11784 ProcessRecord callerApp = null;
11785 if (caller != null) {
11786 callerApp = getRecordForAppLocked(caller);
11787 if (callerApp == null) {
11788 throw new SecurityException(
11789 "Unable to find app for caller " + caller
11790 + " (pid=" + Binder.getCallingPid()
11791 + ") when registering receiver " + receiver);
11792 }
11793 }
11794
11795 List allSticky = null;
11796
11797 // Look for any matching sticky broadcasts...
11798 Iterator actions = filter.actionsIterator();
11799 if (actions != null) {
11800 while (actions.hasNext()) {
11801 String action = (String)actions.next();
11802 allSticky = getStickies(action, filter, allSticky);
11803 }
11804 } else {
11805 allSticky = getStickies(null, filter, allSticky);
11806 }
11807
11808 // The first sticky in the list is returned directly back to
11809 // the client.
11810 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11811
11812 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
11813 + ": " + sticky);
11814
11815 if (receiver == null) {
11816 return sticky;
11817 }
11818
11819 ReceiverList rl
11820 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11821 if (rl == null) {
11822 rl = new ReceiverList(this, callerApp,
11823 Binder.getCallingPid(),
11824 Binder.getCallingUid(), receiver);
11825 if (rl.app != null) {
11826 rl.app.receivers.add(rl);
11827 } else {
11828 try {
11829 receiver.asBinder().linkToDeath(rl, 0);
11830 } catch (RemoteException e) {
11831 return sticky;
11832 }
11833 rl.linkedToDeath = true;
11834 }
11835 mRegisteredReceivers.put(receiver.asBinder(), rl);
11836 }
11837 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11838 rl.add(bf);
11839 if (!bf.debugCheck()) {
11840 Log.w(TAG, "==> For Dynamic broadast");
11841 }
11842 mReceiverResolver.addFilter(bf);
11843
11844 // Enqueue broadcasts for all existing stickies that match
11845 // this filter.
11846 if (allSticky != null) {
11847 ArrayList receivers = new ArrayList();
11848 receivers.add(bf);
11849
11850 int N = allSticky.size();
11851 for (int i=0; i<N; i++) {
11852 Intent intent = (Intent)allSticky.get(i);
11853 BroadcastRecord r = new BroadcastRecord(intent, null,
11854 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011855 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 if (mParallelBroadcasts.size() == 0) {
11857 scheduleBroadcastsLocked();
11858 }
11859 mParallelBroadcasts.add(r);
11860 }
11861 }
11862
11863 return sticky;
11864 }
11865 }
11866
11867 public void unregisterReceiver(IIntentReceiver receiver) {
11868 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
11869
11870 boolean doNext = false;
11871
11872 synchronized(this) {
11873 ReceiverList rl
11874 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11875 if (rl != null) {
11876 if (rl.curBroadcast != null) {
11877 BroadcastRecord r = rl.curBroadcast;
11878 doNext = finishReceiverLocked(
11879 receiver.asBinder(), r.resultCode, r.resultData,
11880 r.resultExtras, r.resultAbort, true);
11881 }
11882
11883 if (rl.app != null) {
11884 rl.app.receivers.remove(rl);
11885 }
11886 removeReceiverLocked(rl);
11887 if (rl.linkedToDeath) {
11888 rl.linkedToDeath = false;
11889 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11890 }
11891 }
11892 }
11893
11894 if (!doNext) {
11895 return;
11896 }
11897
11898 final long origId = Binder.clearCallingIdentity();
11899 processNextBroadcast(false);
11900 trimApplications();
11901 Binder.restoreCallingIdentity(origId);
11902 }
11903
11904 void removeReceiverLocked(ReceiverList rl) {
11905 mRegisteredReceivers.remove(rl.receiver.asBinder());
11906 int N = rl.size();
11907 for (int i=0; i<N; i++) {
11908 mReceiverResolver.removeFilter(rl.get(i));
11909 }
11910 }
11911
11912 private final int broadcastIntentLocked(ProcessRecord callerApp,
11913 String callerPackage, Intent intent, String resolvedType,
11914 IIntentReceiver resultTo, int resultCode, String resultData,
11915 Bundle map, String requiredPermission,
11916 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11917 intent = new Intent(intent);
11918
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011919 if (DEBUG_BROADCAST_LIGHT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011920 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11921 + " ordered=" + ordered);
11922 if ((resultTo != null) && !ordered) {
11923 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
11924 }
11925
11926 // Handle special intents: if this broadcast is from the package
11927 // manager about a package being removed, we need to remove all of
11928 // its activities from the history stack.
11929 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
11930 intent.getAction());
11931 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11932 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011933 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 || uidRemoved) {
11935 if (checkComponentPermission(
11936 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
11937 callingPid, callingUid, -1)
11938 == PackageManager.PERMISSION_GRANTED) {
11939 if (uidRemoved) {
11940 final Bundle intentExtras = intent.getExtras();
11941 final int uid = intentExtras != null
11942 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11943 if (uid >= 0) {
11944 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11945 synchronized (bs) {
11946 bs.removeUidStatsLocked(uid);
11947 }
11948 }
11949 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011950 // If resources are unvailble just force stop all
11951 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011952 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011953 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11954 if (list != null && (list.length > 0)) {
11955 for (String pkg : list) {
11956 forceStopPackageLocked(pkg, -1, false, true);
11957 }
11958 }
11959 } else {
11960 Uri data = intent.getData();
11961 String ssp;
11962 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11963 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11964 forceStopPackageLocked(ssp,
11965 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011967 }
11968 }
11969 }
11970 } else {
11971 String msg = "Permission Denial: " + intent.getAction()
11972 + " broadcast from " + callerPackage + " (pid=" + callingPid
11973 + ", uid=" + callingUid + ")"
11974 + " requires "
11975 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
11976 Log.w(TAG, msg);
11977 throw new SecurityException(msg);
11978 }
11979 }
11980
11981 /*
11982 * If this is the time zone changed action, queue up a message that will reset the timezone
11983 * of all currently running processes. This message will get queued up before the broadcast
11984 * happens.
11985 */
11986 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11987 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11988 }
11989
Dianne Hackborn854060af2009-07-09 18:14:31 -070011990 /*
11991 * Prevent non-system code (defined here to be non-persistent
11992 * processes) from sending protected broadcasts.
11993 */
11994 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11995 || callingUid == Process.SHELL_UID || callingUid == 0) {
11996 // Always okay.
11997 } else if (callerApp == null || !callerApp.persistent) {
11998 try {
11999 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12000 intent.getAction())) {
12001 String msg = "Permission Denial: not allowed to send broadcast "
12002 + intent.getAction() + " from pid="
12003 + callingPid + ", uid=" + callingUid;
12004 Log.w(TAG, msg);
12005 throw new SecurityException(msg);
12006 }
12007 } catch (RemoteException e) {
12008 Log.w(TAG, "Remote exception", e);
12009 return BROADCAST_SUCCESS;
12010 }
12011 }
12012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013 // Add to the sticky list if requested.
12014 if (sticky) {
12015 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12016 callingPid, callingUid)
12017 != PackageManager.PERMISSION_GRANTED) {
12018 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12019 + callingPid + ", uid=" + callingUid
12020 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12021 Log.w(TAG, msg);
12022 throw new SecurityException(msg);
12023 }
12024 if (requiredPermission != null) {
12025 Log.w(TAG, "Can't broadcast sticky intent " + intent
12026 + " and enforce permission " + requiredPermission);
12027 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12028 }
12029 if (intent.getComponent() != null) {
12030 throw new SecurityException(
12031 "Sticky broadcasts can't target a specific component");
12032 }
12033 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12034 if (list == null) {
12035 list = new ArrayList<Intent>();
12036 mStickyBroadcasts.put(intent.getAction(), list);
12037 }
12038 int N = list.size();
12039 int i;
12040 for (i=0; i<N; i++) {
12041 if (intent.filterEquals(list.get(i))) {
12042 // This sticky already exists, replace it.
12043 list.set(i, new Intent(intent));
12044 break;
12045 }
12046 }
12047 if (i >= N) {
12048 list.add(new Intent(intent));
12049 }
12050 }
12051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 // Figure out who all will receive this broadcast.
12053 List receivers = null;
12054 List<BroadcastFilter> registeredReceivers = null;
12055 try {
12056 if (intent.getComponent() != null) {
12057 // Broadcast is going to one specific receiver class...
12058 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012059 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012060 if (ai != null) {
12061 receivers = new ArrayList();
12062 ResolveInfo ri = new ResolveInfo();
12063 ri.activityInfo = ai;
12064 receivers.add(ri);
12065 }
12066 } else {
12067 // Need to resolve the intent to interested receivers...
12068 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12069 == 0) {
12070 receivers =
12071 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012072 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012073 }
Mihai Preda074edef2009-05-18 17:13:31 +020012074 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 }
12076 } catch (RemoteException ex) {
12077 // pm is in same process, this will never happen.
12078 }
12079
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012080 final boolean replacePending =
12081 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12082
12083 if (DEBUG_BROADCAST) Log.v(TAG, "Enqueing broadcast: " + intent.getAction()
12084 + " replacePending=" + replacePending);
12085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012086 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12087 if (!ordered && NR > 0) {
12088 // If we are not serializing this broadcast, then send the
12089 // registered receivers separately so they don't wait for the
12090 // components to be launched.
12091 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12092 callerPackage, callingPid, callingUid, requiredPermission,
12093 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012094 ordered, sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012095 if (DEBUG_BROADCAST) Log.v(
12096 TAG, "Enqueueing parallel broadcast " + r
12097 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012098 boolean replaced = false;
12099 if (replacePending) {
12100 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12101 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
12102 if (DEBUG_BROADCAST) Log.v(TAG,
12103 "***** DROPPING PARALLEL: " + intent);
12104 mParallelBroadcasts.set(i, r);
12105 replaced = true;
12106 break;
12107 }
12108 }
12109 }
12110 if (!replaced) {
12111 mParallelBroadcasts.add(r);
12112 scheduleBroadcastsLocked();
12113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114 registeredReceivers = null;
12115 NR = 0;
12116 }
12117
12118 // Merge into one list.
12119 int ir = 0;
12120 if (receivers != null) {
12121 // A special case for PACKAGE_ADDED: do not allow the package
12122 // being added to see this broadcast. This prevents them from
12123 // using this as a back door to get run as soon as they are
12124 // installed. Maybe in the future we want to have a special install
12125 // broadcast or such for apps, but we'd like to deliberately make
12126 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012127 String skipPackages[] = null;
12128 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12129 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12130 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12131 Uri data = intent.getData();
12132 if (data != null) {
12133 String pkgName = data.getSchemeSpecificPart();
12134 if (pkgName != null) {
12135 skipPackages = new String[] { pkgName };
12136 }
12137 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012138 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012139 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012140 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012141 if (skipPackages != null && (skipPackages.length > 0)) {
12142 for (String skipPackage : skipPackages) {
12143 if (skipPackage != null) {
12144 int NT = receivers.size();
12145 for (int it=0; it<NT; it++) {
12146 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12147 if (curt.activityInfo.packageName.equals(skipPackage)) {
12148 receivers.remove(it);
12149 it--;
12150 NT--;
12151 }
12152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 }
12154 }
12155 }
12156
12157 int NT = receivers != null ? receivers.size() : 0;
12158 int it = 0;
12159 ResolveInfo curt = null;
12160 BroadcastFilter curr = null;
12161 while (it < NT && ir < NR) {
12162 if (curt == null) {
12163 curt = (ResolveInfo)receivers.get(it);
12164 }
12165 if (curr == null) {
12166 curr = registeredReceivers.get(ir);
12167 }
12168 if (curr.getPriority() >= curt.priority) {
12169 // Insert this broadcast record into the final list.
12170 receivers.add(it, curr);
12171 ir++;
12172 curr = null;
12173 it++;
12174 NT++;
12175 } else {
12176 // Skip to the next ResolveInfo in the final list.
12177 it++;
12178 curt = null;
12179 }
12180 }
12181 }
12182 while (ir < NR) {
12183 if (receivers == null) {
12184 receivers = new ArrayList();
12185 }
12186 receivers.add(registeredReceivers.get(ir));
12187 ir++;
12188 }
12189
12190 if ((receivers != null && receivers.size() > 0)
12191 || resultTo != null) {
12192 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12193 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012194 receivers, resultTo, resultCode, resultData, map, ordered,
12195 sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012196 if (DEBUG_BROADCAST) Log.v(
12197 TAG, "Enqueueing ordered broadcast " + r
12198 + ": prev had " + mOrderedBroadcasts.size());
12199 if (DEBUG_BROADCAST) {
12200 int seq = r.intent.getIntExtra("seq", -1);
12201 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
12202 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012203 boolean replaced = false;
12204 if (replacePending) {
12205 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12206 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
12207 if (DEBUG_BROADCAST) Log.v(TAG,
12208 "***** DROPPING ORDERED: " + intent);
12209 mOrderedBroadcasts.set(i, r);
12210 replaced = true;
12211 break;
12212 }
12213 }
12214 }
12215 if (!replaced) {
12216 mOrderedBroadcasts.add(r);
12217 scheduleBroadcastsLocked();
12218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012219 }
12220
12221 return BROADCAST_SUCCESS;
12222 }
12223
12224 public final int broadcastIntent(IApplicationThread caller,
12225 Intent intent, String resolvedType, IIntentReceiver resultTo,
12226 int resultCode, String resultData, Bundle map,
12227 String requiredPermission, boolean serialized, boolean sticky) {
12228 // Refuse possible leaked file descriptors
12229 if (intent != null && intent.hasFileDescriptors() == true) {
12230 throw new IllegalArgumentException("File descriptors passed in Intent");
12231 }
12232
12233 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012234 int flags = intent.getFlags();
12235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012236 if (!mSystemReady) {
12237 // if the caller really truly claims to know what they're doing, go
12238 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12240 intent = new Intent(intent);
12241 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12242 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
12243 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12244 + " before boot completion");
12245 throw new IllegalStateException("Cannot broadcast before boot completed");
12246 }
12247 }
12248
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012249 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12250 throw new IllegalArgumentException(
12251 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12252 }
12253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12255 final int callingPid = Binder.getCallingPid();
12256 final int callingUid = Binder.getCallingUid();
12257 final long origId = Binder.clearCallingIdentity();
12258 int res = broadcastIntentLocked(callerApp,
12259 callerApp != null ? callerApp.info.packageName : null,
12260 intent, resolvedType, resultTo,
12261 resultCode, resultData, map, requiredPermission, serialized,
12262 sticky, callingPid, callingUid);
12263 Binder.restoreCallingIdentity(origId);
12264 return res;
12265 }
12266 }
12267
12268 int broadcastIntentInPackage(String packageName, int uid,
12269 Intent intent, String resolvedType, IIntentReceiver resultTo,
12270 int resultCode, String resultData, Bundle map,
12271 String requiredPermission, boolean serialized, boolean sticky) {
12272 synchronized(this) {
12273 final long origId = Binder.clearCallingIdentity();
12274 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12275 resultTo, resultCode, resultData, map, requiredPermission,
12276 serialized, sticky, -1, uid);
12277 Binder.restoreCallingIdentity(origId);
12278 return res;
12279 }
12280 }
12281
12282 public final void unbroadcastIntent(IApplicationThread caller,
12283 Intent intent) {
12284 // Refuse possible leaked file descriptors
12285 if (intent != null && intent.hasFileDescriptors() == true) {
12286 throw new IllegalArgumentException("File descriptors passed in Intent");
12287 }
12288
12289 synchronized(this) {
12290 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12291 != PackageManager.PERMISSION_GRANTED) {
12292 String msg = "Permission Denial: unbroadcastIntent() from pid="
12293 + Binder.getCallingPid()
12294 + ", uid=" + Binder.getCallingUid()
12295 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12296 Log.w(TAG, msg);
12297 throw new SecurityException(msg);
12298 }
12299 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12300 if (list != null) {
12301 int N = list.size();
12302 int i;
12303 for (i=0; i<N; i++) {
12304 if (intent.filterEquals(list.get(i))) {
12305 list.remove(i);
12306 break;
12307 }
12308 }
12309 }
12310 }
12311 }
12312
12313 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12314 String resultData, Bundle resultExtras, boolean resultAbort,
12315 boolean explicit) {
12316 if (mOrderedBroadcasts.size() == 0) {
12317 if (explicit) {
12318 Log.w(TAG, "finishReceiver called but no pending broadcasts");
12319 }
12320 return false;
12321 }
12322 BroadcastRecord r = mOrderedBroadcasts.get(0);
12323 if (r.receiver == null) {
12324 if (explicit) {
12325 Log.w(TAG, "finishReceiver called but none active");
12326 }
12327 return false;
12328 }
12329 if (r.receiver != receiver) {
12330 Log.w(TAG, "finishReceiver called but active receiver is different");
12331 return false;
12332 }
12333 int state = r.state;
12334 r.state = r.IDLE;
12335 if (state == r.IDLE) {
12336 if (explicit) {
12337 Log.w(TAG, "finishReceiver called but state is IDLE");
12338 }
12339 }
12340 r.receiver = null;
12341 r.intent.setComponent(null);
12342 if (r.curApp != null) {
12343 r.curApp.curReceiver = null;
12344 }
12345 if (r.curFilter != null) {
12346 r.curFilter.receiverList.curBroadcast = null;
12347 }
12348 r.curFilter = null;
12349 r.curApp = null;
12350 r.curComponent = null;
12351 r.curReceiver = null;
12352 mPendingBroadcast = null;
12353
12354 r.resultCode = resultCode;
12355 r.resultData = resultData;
12356 r.resultExtras = resultExtras;
12357 r.resultAbort = resultAbort;
12358
12359 // We will process the next receiver right now if this is finishing
12360 // an app receiver (which is always asynchronous) or after we have
12361 // come back from calling a receiver.
12362 return state == BroadcastRecord.APP_RECEIVE
12363 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12364 }
12365
12366 public void finishReceiver(IBinder who, int resultCode, String resultData,
12367 Bundle resultExtras, boolean resultAbort) {
12368 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
12369
12370 // Refuse possible leaked file descriptors
12371 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12372 throw new IllegalArgumentException("File descriptors passed in Bundle");
12373 }
12374
12375 boolean doNext;
12376
12377 final long origId = Binder.clearCallingIdentity();
12378
12379 synchronized(this) {
12380 doNext = finishReceiverLocked(
12381 who, resultCode, resultData, resultExtras, resultAbort, true);
12382 }
12383
12384 if (doNext) {
12385 processNextBroadcast(false);
12386 }
12387 trimApplications();
12388
12389 Binder.restoreCallingIdentity(origId);
12390 }
12391
12392 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12393 if (r.nextReceiver > 0) {
12394 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12395 if (curReceiver instanceof BroadcastFilter) {
12396 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012397 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012398 System.identityHashCode(r),
12399 r.intent.getAction(),
12400 r.nextReceiver - 1,
12401 System.identityHashCode(bf));
12402 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012403 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012404 System.identityHashCode(r),
12405 r.intent.getAction(),
12406 r.nextReceiver - 1,
12407 ((ResolveInfo)curReceiver).toString());
12408 }
12409 } else {
12410 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
12411 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012412 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 System.identityHashCode(r),
12414 r.intent.getAction(),
12415 r.nextReceiver,
12416 "NONE");
12417 }
12418 }
12419
12420 private final void broadcastTimeout() {
12421 synchronized (this) {
12422 if (mOrderedBroadcasts.size() == 0) {
12423 return;
12424 }
12425 long now = SystemClock.uptimeMillis();
12426 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012427 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012428 if (DEBUG_BROADCAST) Log.v(TAG,
12429 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012430 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012431 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012432 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433 return;
12434 }
12435
12436 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012437 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012438 r.anrCount++;
12439
12440 // Current receiver has passed its expiration date.
12441 if (r.nextReceiver <= 0) {
12442 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12443 return;
12444 }
12445
12446 ProcessRecord app = null;
12447
12448 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12449 Log.w(TAG, "Receiver during timeout: " + curReceiver);
12450 logBroadcastReceiverDiscard(r);
12451 if (curReceiver instanceof BroadcastFilter) {
12452 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12453 if (bf.receiverList.pid != 0
12454 && bf.receiverList.pid != MY_PID) {
12455 synchronized (this.mPidsSelfLocked) {
12456 app = this.mPidsSelfLocked.get(
12457 bf.receiverList.pid);
12458 }
12459 }
12460 } else {
12461 app = r.curApp;
12462 }
12463
12464 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012465 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012466 }
12467
12468 if (mPendingBroadcast == r) {
12469 mPendingBroadcast = null;
12470 }
12471
12472 // Move on to the next receiver.
12473 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12474 r.resultExtras, r.resultAbort, true);
12475 scheduleBroadcastsLocked();
12476 }
12477 }
12478
12479 private final void processCurBroadcastLocked(BroadcastRecord r,
12480 ProcessRecord app) throws RemoteException {
12481 if (app.thread == null) {
12482 throw new RemoteException();
12483 }
12484 r.receiver = app.thread.asBinder();
12485 r.curApp = app;
12486 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012487 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012488
12489 // Tell the application to launch this receiver.
12490 r.intent.setComponent(r.curComponent);
12491
12492 boolean started = false;
12493 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012494 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012495 "Delivering to component " + r.curComponent
12496 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012497 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12499 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12500 started = true;
12501 } finally {
12502 if (!started) {
12503 r.receiver = null;
12504 r.curApp = null;
12505 app.curReceiver = null;
12506 }
12507 }
12508
12509 }
12510
12511 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012512 Intent intent, int resultCode, String data, Bundle extras,
12513 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012514 if (app != null && app.thread != null) {
12515 // If we have an app thread, do the call through that so it is
12516 // correctly ordered with other one-way calls.
12517 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012518 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012520 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012521 }
12522 }
12523
12524 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12525 BroadcastFilter filter, boolean ordered) {
12526 boolean skip = false;
12527 if (filter.requiredPermission != null) {
12528 int perm = checkComponentPermission(filter.requiredPermission,
12529 r.callingPid, r.callingUid, -1);
12530 if (perm != PackageManager.PERMISSION_GRANTED) {
12531 Log.w(TAG, "Permission Denial: broadcasting "
12532 + r.intent.toString()
12533 + " from " + r.callerPackage + " (pid="
12534 + r.callingPid + ", uid=" + r.callingUid + ")"
12535 + " requires " + filter.requiredPermission
12536 + " due to registered receiver " + filter);
12537 skip = true;
12538 }
12539 }
12540 if (r.requiredPermission != null) {
12541 int perm = checkComponentPermission(r.requiredPermission,
12542 filter.receiverList.pid, filter.receiverList.uid, -1);
12543 if (perm != PackageManager.PERMISSION_GRANTED) {
12544 Log.w(TAG, "Permission Denial: receiving "
12545 + r.intent.toString()
12546 + " to " + filter.receiverList.app
12547 + " (pid=" + filter.receiverList.pid
12548 + ", uid=" + filter.receiverList.uid + ")"
12549 + " requires " + r.requiredPermission
12550 + " due to sender " + r.callerPackage
12551 + " (uid " + r.callingUid + ")");
12552 skip = true;
12553 }
12554 }
12555
12556 if (!skip) {
12557 // If this is not being sent as an ordered broadcast, then we
12558 // don't want to touch the fields that keep track of the current
12559 // state of ordered broadcasts.
12560 if (ordered) {
12561 r.receiver = filter.receiverList.receiver.asBinder();
12562 r.curFilter = filter;
12563 filter.receiverList.curBroadcast = r;
12564 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012565 if (filter.receiverList.app != null) {
12566 // Bump hosting application to no longer be in background
12567 // scheduling class. Note that we can't do that if there
12568 // isn't an app... but we can only be in that case for
12569 // things that directly call the IActivityManager API, which
12570 // are already core system stuff so don't matter for this.
12571 r.curApp = filter.receiverList.app;
12572 filter.receiverList.app.curReceiver = r;
12573 updateOomAdjLocked();
12574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012575 }
12576 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012577 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012579 Log.i(TAG, "Delivering to " + filter.receiverList.app
12580 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012581 }
12582 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12583 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012584 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012585 if (ordered) {
12586 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12587 }
12588 } catch (RemoteException e) {
12589 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
12590 if (ordered) {
12591 r.receiver = null;
12592 r.curFilter = null;
12593 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012594 if (filter.receiverList.app != null) {
12595 filter.receiverList.app.curReceiver = null;
12596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 }
12598 }
12599 }
12600 }
12601
Dianne Hackborn12527f92009-11-11 17:39:50 -080012602 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12603 if (r.callingUid < 0) {
12604 // This was from a registerReceiver() call; ignore it.
12605 return;
12606 }
12607 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12608 MAX_BROADCAST_HISTORY-1);
12609 r.finishTime = SystemClock.uptimeMillis();
12610 mBroadcastHistory[0] = r;
12611 }
12612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012613 private final void processNextBroadcast(boolean fromMsg) {
12614 synchronized(this) {
12615 BroadcastRecord r;
12616
12617 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
12618 + mParallelBroadcasts.size() + " broadcasts, "
12619 + mOrderedBroadcasts.size() + " serialized broadcasts");
12620
12621 updateCpuStats();
12622
12623 if (fromMsg) {
12624 mBroadcastsScheduled = false;
12625 }
12626
12627 // First, deliver any non-serialized broadcasts right away.
12628 while (mParallelBroadcasts.size() > 0) {
12629 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012630 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012631 final int N = r.receivers.size();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012632 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing parallel broadcast "
12633 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 for (int i=0; i<N; i++) {
12635 Object target = r.receivers.get(i);
12636 if (DEBUG_BROADCAST) Log.v(TAG,
12637 "Delivering non-serialized to registered "
12638 + target + ": " + r);
12639 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12640 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012641 addBroadcastToHistoryLocked(r);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012642 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Done with parallel broadcast "
12643 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012644 }
12645
12646 // Now take care of the next serialized one...
12647
12648 // If we are waiting for a process to come up to handle the next
12649 // broadcast, then do nothing at this point. Just in case, we
12650 // check that the process we're waiting for still exists.
12651 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012652 if (DEBUG_BROADCAST_LIGHT) {
12653 Log.v(TAG, "processNextBroadcast: waiting for "
12654 + mPendingBroadcast.curApp);
12655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656
12657 boolean isDead;
12658 synchronized (mPidsSelfLocked) {
12659 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12660 }
12661 if (!isDead) {
12662 // It's still alive, so keep waiting
12663 return;
12664 } else {
12665 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
12666 + " died before responding to broadcast");
12667 mPendingBroadcast = null;
12668 }
12669 }
12670
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012671 boolean looped = false;
12672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012673 do {
12674 if (mOrderedBroadcasts.size() == 0) {
12675 // No more broadcasts pending, so all done!
12676 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012677 if (looped) {
12678 // If we had finished the last ordered broadcast, then
12679 // make sure all processes have correct oom and sched
12680 // adjustments.
12681 updateOomAdjLocked();
12682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012683 return;
12684 }
12685 r = mOrderedBroadcasts.get(0);
12686 boolean forceReceive = false;
12687
12688 // Ensure that even if something goes awry with the timeout
12689 // detection, we catch "hung" broadcasts here, discard them,
12690 // and continue to make progress.
12691 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12692 long now = SystemClock.uptimeMillis();
12693 if (r.dispatchTime > 0) {
12694 if ((numReceivers > 0) &&
12695 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
12696 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
12697 + " now=" + now
12698 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012699 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012700 + " intent=" + r.intent
12701 + " numReceivers=" + numReceivers
12702 + " nextReceiver=" + r.nextReceiver
12703 + " state=" + r.state);
12704 broadcastTimeout(); // forcibly finish this broadcast
12705 forceReceive = true;
12706 r.state = BroadcastRecord.IDLE;
12707 }
12708 }
12709
12710 if (r.state != BroadcastRecord.IDLE) {
12711 if (DEBUG_BROADCAST) Log.d(TAG,
12712 "processNextBroadcast() called when not idle (state="
12713 + r.state + ")");
12714 return;
12715 }
12716
12717 if (r.receivers == null || r.nextReceiver >= numReceivers
12718 || r.resultAbort || forceReceive) {
12719 // No more receivers for this broadcast! Send the final
12720 // result if requested...
12721 if (r.resultTo != null) {
12722 try {
12723 if (DEBUG_BROADCAST) {
12724 int seq = r.intent.getIntExtra("seq", -1);
12725 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
12726 + " seq=" + seq + " app=" + r.callerApp);
12727 }
12728 performReceive(r.callerApp, r.resultTo,
12729 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012730 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012731 } catch (RemoteException e) {
12732 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
12733 }
12734 }
12735
12736 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
12737 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12738
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012739 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Finished with ordered broadcast "
12740 + r);
12741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012742 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012743 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012744 mOrderedBroadcasts.remove(0);
12745 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012746 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012747 continue;
12748 }
12749 } while (r == null);
12750
12751 // Get the next receiver...
12752 int recIdx = r.nextReceiver++;
12753
12754 // Keep track of when this receiver started, and make sure there
12755 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012756 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012758 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012759
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012760 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing ordered broadcast "
12761 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012762 if (DEBUG_BROADCAST) Log.v(TAG,
12763 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012764 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012766 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012767 }
12768
12769 Object nextReceiver = r.receivers.get(recIdx);
12770 if (nextReceiver instanceof BroadcastFilter) {
12771 // Simple case: this is a registered receiver who gets
12772 // a direct call.
12773 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
12774 if (DEBUG_BROADCAST) Log.v(TAG,
12775 "Delivering serialized to registered "
12776 + filter + ": " + r);
12777 deliverToRegisteredReceiver(r, filter, r.ordered);
12778 if (r.receiver == null || !r.ordered) {
12779 // The receiver has already finished, so schedule to
12780 // process the next one.
12781 r.state = BroadcastRecord.IDLE;
12782 scheduleBroadcastsLocked();
12783 }
12784 return;
12785 }
12786
12787 // Hard case: need to instantiate the receiver, possibly
12788 // starting its application process to host it.
12789
12790 ResolveInfo info =
12791 (ResolveInfo)nextReceiver;
12792
12793 boolean skip = false;
12794 int perm = checkComponentPermission(info.activityInfo.permission,
12795 r.callingPid, r.callingUid,
12796 info.activityInfo.exported
12797 ? -1 : info.activityInfo.applicationInfo.uid);
12798 if (perm != PackageManager.PERMISSION_GRANTED) {
12799 Log.w(TAG, "Permission Denial: broadcasting "
12800 + r.intent.toString()
12801 + " from " + r.callerPackage + " (pid=" + r.callingPid
12802 + ", uid=" + r.callingUid + ")"
12803 + " requires " + info.activityInfo.permission
12804 + " due to receiver " + info.activityInfo.packageName
12805 + "/" + info.activityInfo.name);
12806 skip = true;
12807 }
12808 if (r.callingUid != Process.SYSTEM_UID &&
12809 r.requiredPermission != null) {
12810 try {
12811 perm = ActivityThread.getPackageManager().
12812 checkPermission(r.requiredPermission,
12813 info.activityInfo.applicationInfo.packageName);
12814 } catch (RemoteException e) {
12815 perm = PackageManager.PERMISSION_DENIED;
12816 }
12817 if (perm != PackageManager.PERMISSION_GRANTED) {
12818 Log.w(TAG, "Permission Denial: receiving "
12819 + r.intent + " to "
12820 + info.activityInfo.applicationInfo.packageName
12821 + " requires " + r.requiredPermission
12822 + " due to sender " + r.callerPackage
12823 + " (uid " + r.callingUid + ")");
12824 skip = true;
12825 }
12826 }
12827 if (r.curApp != null && r.curApp.crashing) {
12828 // If the target process is crashing, just skip it.
12829 skip = true;
12830 }
12831
12832 if (skip) {
12833 r.receiver = null;
12834 r.curFilter = null;
12835 r.state = BroadcastRecord.IDLE;
12836 scheduleBroadcastsLocked();
12837 return;
12838 }
12839
12840 r.state = BroadcastRecord.APP_RECEIVE;
12841 String targetProcess = info.activityInfo.processName;
12842 r.curComponent = new ComponentName(
12843 info.activityInfo.applicationInfo.packageName,
12844 info.activityInfo.name);
12845 r.curReceiver = info.activityInfo;
12846
12847 // Is this receiver's application already running?
12848 ProcessRecord app = getProcessRecordLocked(targetProcess,
12849 info.activityInfo.applicationInfo.uid);
12850 if (app != null && app.thread != null) {
12851 try {
12852 processCurBroadcastLocked(r, app);
12853 return;
12854 } catch (RemoteException e) {
12855 Log.w(TAG, "Exception when sending broadcast to "
12856 + r.curComponent, e);
12857 }
12858
12859 // If a dead object exception was thrown -- fall through to
12860 // restart the application.
12861 }
12862
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012863 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 if ((r.curApp=startProcessLocked(targetProcess,
12865 info.activityInfo.applicationInfo, true,
12866 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012867 "broadcast", r.curComponent,
12868 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12869 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 // Ah, this recipient is unavailable. Finish it if necessary,
12871 // and mark the broadcast record as ready for the next.
12872 Log.w(TAG, "Unable to launch app "
12873 + info.activityInfo.applicationInfo.packageName + "/"
12874 + info.activityInfo.applicationInfo.uid + " for broadcast "
12875 + r.intent + ": process is bad");
12876 logBroadcastReceiverDiscard(r);
12877 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12878 r.resultExtras, r.resultAbort, true);
12879 scheduleBroadcastsLocked();
12880 r.state = BroadcastRecord.IDLE;
12881 return;
12882 }
12883
12884 mPendingBroadcast = r;
12885 }
12886 }
12887
12888 // =========================================================
12889 // INSTRUMENTATION
12890 // =========================================================
12891
12892 public boolean startInstrumentation(ComponentName className,
12893 String profileFile, int flags, Bundle arguments,
12894 IInstrumentationWatcher watcher) {
12895 // Refuse possible leaked file descriptors
12896 if (arguments != null && arguments.hasFileDescriptors()) {
12897 throw new IllegalArgumentException("File descriptors passed in Bundle");
12898 }
12899
12900 synchronized(this) {
12901 InstrumentationInfo ii = null;
12902 ApplicationInfo ai = null;
12903 try {
12904 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012905 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012907 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012908 } catch (PackageManager.NameNotFoundException e) {
12909 }
12910 if (ii == null) {
12911 reportStartInstrumentationFailure(watcher, className,
12912 "Unable to find instrumentation info for: " + className);
12913 return false;
12914 }
12915 if (ai == null) {
12916 reportStartInstrumentationFailure(watcher, className,
12917 "Unable to find instrumentation target package: " + ii.targetPackage);
12918 return false;
12919 }
12920
12921 int match = mContext.getPackageManager().checkSignatures(
12922 ii.targetPackage, ii.packageName);
12923 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12924 String msg = "Permission Denial: starting instrumentation "
12925 + className + " from pid="
12926 + Binder.getCallingPid()
12927 + ", uid=" + Binder.getCallingPid()
12928 + " not allowed because package " + ii.packageName
12929 + " does not have a signature matching the target "
12930 + ii.targetPackage;
12931 reportStartInstrumentationFailure(watcher, className, msg);
12932 throw new SecurityException(msg);
12933 }
12934
12935 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012936 forceStopPackageLocked(ii.targetPackage, -1, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012937 ProcessRecord app = addAppLocked(ai);
12938 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012939 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012940 app.instrumentationProfileFile = profileFile;
12941 app.instrumentationArguments = arguments;
12942 app.instrumentationWatcher = watcher;
12943 app.instrumentationResultClass = className;
12944 Binder.restoreCallingIdentity(origId);
12945 }
12946
12947 return true;
12948 }
12949
12950 /**
12951 * Report errors that occur while attempting to start Instrumentation. Always writes the
12952 * error to the logs, but if somebody is watching, send the report there too. This enables
12953 * the "am" command to report errors with more information.
12954 *
12955 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12956 * @param cn The component name of the instrumentation.
12957 * @param report The error report.
12958 */
12959 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12960 ComponentName cn, String report) {
12961 Log.w(TAG, report);
12962 try {
12963 if (watcher != null) {
12964 Bundle results = new Bundle();
12965 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12966 results.putString("Error", report);
12967 watcher.instrumentationStatus(cn, -1, results);
12968 }
12969 } catch (RemoteException e) {
12970 Log.w(TAG, e);
12971 }
12972 }
12973
12974 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12975 if (app.instrumentationWatcher != null) {
12976 try {
12977 // NOTE: IInstrumentationWatcher *must* be oneway here
12978 app.instrumentationWatcher.instrumentationFinished(
12979 app.instrumentationClass,
12980 resultCode,
12981 results);
12982 } catch (RemoteException e) {
12983 }
12984 }
12985 app.instrumentationWatcher = null;
12986 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012987 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012988 app.instrumentationProfileFile = null;
12989 app.instrumentationArguments = null;
12990
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012991 forceStopPackageLocked(app.processName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992 }
12993
12994 public void finishInstrumentation(IApplicationThread target,
12995 int resultCode, Bundle results) {
12996 // Refuse possible leaked file descriptors
12997 if (results != null && results.hasFileDescriptors()) {
12998 throw new IllegalArgumentException("File descriptors passed in Intent");
12999 }
13000
13001 synchronized(this) {
13002 ProcessRecord app = getRecordForAppLocked(target);
13003 if (app == null) {
13004 Log.w(TAG, "finishInstrumentation: no app for " + target);
13005 return;
13006 }
13007 final long origId = Binder.clearCallingIdentity();
13008 finishInstrumentationLocked(app, resultCode, results);
13009 Binder.restoreCallingIdentity(origId);
13010 }
13011 }
13012
13013 // =========================================================
13014 // CONFIGURATION
13015 // =========================================================
13016
13017 public ConfigurationInfo getDeviceConfigurationInfo() {
13018 ConfigurationInfo config = new ConfigurationInfo();
13019 synchronized (this) {
13020 config.reqTouchScreen = mConfiguration.touchscreen;
13021 config.reqKeyboardType = mConfiguration.keyboard;
13022 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013023 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13024 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013025 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13026 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013027 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13028 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013029 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13030 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013031 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013032 }
13033 return config;
13034 }
13035
13036 public Configuration getConfiguration() {
13037 Configuration ci;
13038 synchronized(this) {
13039 ci = new Configuration(mConfiguration);
13040 }
13041 return ci;
13042 }
13043
13044 public void updateConfiguration(Configuration values) {
13045 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13046 "updateConfiguration()");
13047
13048 synchronized(this) {
13049 if (values == null && mWindowManager != null) {
13050 // sentinel: fetch the current configuration from the window manager
13051 values = mWindowManager.computeNewConfiguration();
13052 }
13053
13054 final long origId = Binder.clearCallingIdentity();
13055 updateConfigurationLocked(values, null);
13056 Binder.restoreCallingIdentity(origId);
13057 }
13058 }
13059
13060 /**
13061 * Do either or both things: (1) change the current configuration, and (2)
13062 * make sure the given activity is running with the (now) current
13063 * configuration. Returns true if the activity has been left running, or
13064 * false if <var>starting</var> is being destroyed to match the new
13065 * configuration.
13066 */
13067 public boolean updateConfigurationLocked(Configuration values,
13068 HistoryRecord starting) {
13069 int changes = 0;
13070
13071 boolean kept = true;
13072
13073 if (values != null) {
13074 Configuration newConfig = new Configuration(mConfiguration);
13075 changes = newConfig.updateFrom(values);
13076 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013077 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013078 Log.i(TAG, "Updating configuration to: " + values);
13079 }
13080
Doug Zongker2bec3d42009-12-04 12:52:44 -080013081 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013082
13083 if (values.locale != null) {
13084 saveLocaleLocked(values.locale,
13085 !values.locale.equals(mConfiguration.locale),
13086 values.userSetLocale);
13087 }
13088
13089 mConfiguration = newConfig;
Dianne Hackborna8f60182009-09-01 19:01:50 -070013090 Log.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013091
13092 AttributeCache ac = AttributeCache.instance();
13093 if (ac != null) {
13094 ac.updateConfiguration(mConfiguration);
13095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013096
13097 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13098 msg.obj = new Configuration(mConfiguration);
13099 mHandler.sendMessage(msg);
13100
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013101 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13102 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013103 try {
13104 if (app.thread != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013105 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending to proc "
13106 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013107 app.thread.scheduleConfigurationChanged(mConfiguration);
13108 }
13109 } catch (Exception e) {
13110 }
13111 }
13112 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013113 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13114 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13116 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013117 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13118 broadcastIntentLocked(null, null,
13119 new Intent(Intent.ACTION_LOCALE_CHANGED),
13120 null, null, 0, null, null,
13121 null, false, false, MY_PID, Process.SYSTEM_UID);
13122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013123 }
13124 }
13125
13126 if (changes != 0 && starting == null) {
13127 // If the configuration changed, and the caller is not already
13128 // in the process of starting an activity, then find the top
13129 // activity to check if its configuration needs to change.
13130 starting = topRunningActivityLocked(null);
13131 }
13132
13133 if (starting != null) {
13134 kept = ensureActivityConfigurationLocked(starting, changes);
13135 if (kept) {
13136 // If this didn't result in the starting activity being
13137 // destroyed, then we need to make sure at this point that all
13138 // other activities are made visible.
13139 if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
13140 + ", ensuring others are correct.");
13141 ensureActivitiesVisibleLocked(starting, changes);
13142 }
13143 }
13144
13145 return kept;
13146 }
13147
13148 private final boolean relaunchActivityLocked(HistoryRecord r,
13149 int changes, boolean andResume) {
13150 List<ResultInfo> results = null;
13151 List<Intent> newIntents = null;
13152 if (andResume) {
13153 results = r.results;
13154 newIntents = r.newIntents;
13155 }
13156 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
13157 + " with results=" + results + " newIntents=" + newIntents
13158 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013159 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13160 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 r.task.taskId, r.shortComponentName);
13162
13163 r.startFreezingScreenLocked(r.app, 0);
13164
13165 try {
13166 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
13167 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013168 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013169 // Note: don't need to call pauseIfSleepingLocked() here, because
13170 // the caller will only pass in 'andResume' if this activity is
13171 // currently resumed, which implies we aren't sleeping.
13172 } catch (RemoteException e) {
13173 return false;
13174 }
13175
13176 if (andResume) {
13177 r.results = null;
13178 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013179 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013180 }
13181
13182 return true;
13183 }
13184
13185 /**
13186 * Make sure the given activity matches the current configuration. Returns
13187 * false if the activity had to be destroyed. Returns true if the
13188 * configuration is the same, or the activity will remain running as-is
13189 * for whatever reason. Ensures the HistoryRecord is updated with the
13190 * correct configuration and all other bookkeeping is handled.
13191 */
13192 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13193 int globalChanges) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013194 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13195 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013196
13197 // Short circuit: if the two configurations are the exact same
13198 // object (the common case), then there is nothing to do.
13199 Configuration newConfig = mConfiguration;
13200 if (r.configuration == newConfig) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013201 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13202 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 return true;
13204 }
13205
13206 // We don't worry about activities that are finishing.
13207 if (r.finishing) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013208 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013209 "Configuration doesn't matter in finishing " + r);
13210 r.stopFreezingScreenLocked(false);
13211 return true;
13212 }
13213
13214 // Okay we now are going to make this activity have the new config.
13215 // But then we need to figure out how it needs to deal with that.
13216 Configuration oldConfig = r.configuration;
13217 r.configuration = newConfig;
13218
13219 // If the activity isn't currently running, just leave the new
13220 // configuration and it will pick that up next time it starts.
13221 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013222 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013223 "Configuration doesn't matter not running " + r);
13224 r.stopFreezingScreenLocked(false);
13225 return true;
13226 }
13227
13228 // If the activity isn't persistent, there is a chance we will
13229 // need to restart it.
13230 if (!r.persistent) {
13231
13232 // Figure out what has changed between the two configurations.
13233 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013234 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
13235 Log.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013236 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013237 + Integer.toHexString(r.info.configChanges)
13238 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013239 }
13240 if ((changes&(~r.info.configChanges)) != 0) {
13241 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13242 r.configChangeFlags |= changes;
13243 r.startFreezingScreenLocked(r.app, globalChanges);
13244 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013245 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13246 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013247 destroyActivityLocked(r, true);
13248 } else if (r.state == ActivityState.PAUSING) {
13249 // A little annoying: we are waiting for this activity to
13250 // finish pausing. Let's not do anything now, but just
13251 // flag that it needs to be restarted when done pausing.
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013252 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13253 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013254 r.configDestroy = true;
13255 return true;
13256 } else if (r.state == ActivityState.RESUMED) {
13257 // Try to optimize this case: the configuration is changing
13258 // and we need to restart the top, resumed activity.
13259 // Instead of doing the normal handshaking, just say
13260 // "restart!".
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013261 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13262 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013263 relaunchActivityLocked(r, r.configChangeFlags, true);
13264 r.configChangeFlags = 0;
13265 } else {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013266 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13267 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 relaunchActivityLocked(r, r.configChangeFlags, false);
13269 r.configChangeFlags = 0;
13270 }
13271
13272 // All done... tell the caller we weren't able to keep this
13273 // activity around.
13274 return false;
13275 }
13276 }
13277
13278 // Default case: the activity can handle this new configuration, so
13279 // hand it over. Note that we don't need to give it the new
13280 // configuration, since we always send configuration changes to all
13281 // process when they happen so it can just use whatever configuration
13282 // it last got.
13283 if (r.app != null && r.app.thread != null) {
13284 try {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013285 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013286 r.app.thread.scheduleActivityConfigurationChanged(r);
13287 } catch (RemoteException e) {
13288 // If process died, whatever.
13289 }
13290 }
13291 r.stopFreezingScreenLocked(false);
13292
13293 return true;
13294 }
13295
13296 /**
13297 * Save the locale. You must be inside a synchronized (this) block.
13298 */
13299 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13300 if(isDiff) {
13301 SystemProperties.set("user.language", l.getLanguage());
13302 SystemProperties.set("user.region", l.getCountry());
13303 }
13304
13305 if(isPersist) {
13306 SystemProperties.set("persist.sys.language", l.getLanguage());
13307 SystemProperties.set("persist.sys.country", l.getCountry());
13308 SystemProperties.set("persist.sys.localevar", l.getVariant());
13309 }
13310 }
13311
13312 // =========================================================
13313 // LIFETIME MANAGEMENT
13314 // =========================================================
13315
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013316 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13317 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013318 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013319 // This adjustment has already been computed. If we are calling
13320 // from the top, we may have already computed our adjustment with
13321 // an earlier hidden adjustment that isn't really for us... if
13322 // so, use the new hidden adjustment.
13323 if (!recursed && app.hidden) {
13324 app.curAdj = hiddenAdj;
13325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013326 return app.curAdj;
13327 }
13328
13329 if (app.thread == null) {
13330 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013331 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013332 return (app.curAdj=EMPTY_APP_ADJ);
13333 }
13334
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013335 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13336 // The max adjustment doesn't allow this app to be anything
13337 // below foreground, so it is not worth doing work for it.
13338 app.adjType = "fixed";
13339 app.adjSeq = mAdjSeq;
13340 app.curRawAdj = app.maxAdj;
13341 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13342 return (app.curAdj=app.maxAdj);
13343 }
13344
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013345 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013346 app.adjSource = null;
13347 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013348 app.empty = false;
13349 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013350
The Android Open Source Project4df24232009-03-05 14:34:35 -080013351 // Determine the importance of the process, starting with most
13352 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013353 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013354 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013355 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013356 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013357 // The last app on the list is the foreground app.
13358 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013359 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013360 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013361 } else if (app.instrumentationClass != null) {
13362 // Don't want to kill running instrumentation.
13363 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013364 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013365 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013366 } else if (app.persistentActivities > 0) {
13367 // Special persistent activities... shouldn't be used these days.
13368 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013369 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013370 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 } else if (app.curReceiver != null ||
13372 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13373 // An app that is currently receiving a broadcast also
13374 // counts as being in the foreground.
13375 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013376 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013377 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 } else if (app.executingServices.size() > 0) {
13379 // An app that is currently executing a service callback also
13380 // counts as being in the foreground.
13381 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013382 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013383 app.adjType = "exec-service";
13384 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 // The user is aware of this app, so make it visible.
13386 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 = "foreground-service";
13389 } else if (app.forcingToForeground != null) {
13390 // The user is aware of this app, so make it visible.
13391 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013392 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013393 app.adjType = "force-foreground";
13394 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013395 } else if (app == mHomeProcess) {
13396 // This process is hosting what we currently consider to be the
13397 // home app, so we don't want to let it go into the background.
13398 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013399 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013400 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401 } else if ((N=app.activities.size()) != 0) {
13402 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013403 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013405 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013406 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013407 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408 for (int j=0; j<N; j++) {
13409 if (((HistoryRecord)app.activities.get(j)).visible) {
13410 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013411 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013412 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013413 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013414 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 break;
13416 }
13417 }
13418 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013419 // A very not-needed process. If this is lower in the lru list,
13420 // we will push it in to the empty bucket.
13421 app.hidden = true;
13422 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013423 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013424 adj = hiddenAdj;
13425 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013426 }
13427
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013428 //Log.i(TAG, "OOM " + app + ": initial adj=" + adj);
13429
The Android Open Source Project4df24232009-03-05 14:34:35 -080013430 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013431 // there are applications dependent on our services or providers, but
13432 // this gives us a baseline and makes sure we don't get into an
13433 // infinite recursion.
13434 app.adjSeq = mAdjSeq;
13435 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436
Christopher Tate6fa95972009-06-05 18:43:55 -070013437 if (mBackupTarget != null && app == mBackupTarget.app) {
13438 // If possible we want to avoid killing apps while they're being backed up
13439 if (adj > BACKUP_APP_ADJ) {
13440 if (DEBUG_BACKUP) Log.v(TAG, "oom BACKUP_APP_ADJ for " + app);
13441 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013442 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013443 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013444 }
13445 }
13446
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013447 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13448 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449 final long now = SystemClock.uptimeMillis();
13450 // This process is more important if the top activity is
13451 // bound to the service.
13452 Iterator jt = app.services.iterator();
13453 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13454 ServiceRecord s = (ServiceRecord)jt.next();
13455 if (s.startRequested) {
13456 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13457 // This service has seen some activity within
13458 // recent memory, so we will keep its process ahead
13459 // of the background processes.
13460 if (adj > SECONDARY_SERVER_ADJ) {
13461 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013462 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013463 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013464 }
13465 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013466 // If we have let the service slide into the background
13467 // state, still have some text describing what it is doing
13468 // even though the service no longer has an impact.
13469 if (adj > SECONDARY_SERVER_ADJ) {
13470 app.adjType = "started-bg-services";
13471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013472 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013473 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13474 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013475 Iterator<ConnectionRecord> kt
13476 = s.connections.values().iterator();
13477 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13478 // XXX should compute this based on the max of
13479 // all connected clients.
13480 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013481 if (cr.binding.client == app) {
13482 // Binding to ourself is not interesting.
13483 continue;
13484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013485 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13486 ProcessRecord client = cr.binding.client;
13487 int myHiddenAdj = hiddenAdj;
13488 if (myHiddenAdj > client.hiddenAdj) {
13489 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13490 myHiddenAdj = client.hiddenAdj;
13491 } else {
13492 myHiddenAdj = VISIBLE_APP_ADJ;
13493 }
13494 }
13495 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013496 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013497 if (adj > clientAdj) {
13498 adj = clientAdj > VISIBLE_APP_ADJ
13499 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013500 if (!client.hidden) {
13501 app.hidden = false;
13502 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013503 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013504 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13505 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013506 app.adjSource = cr.binding.client;
13507 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013508 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013509 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13510 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13511 schedGroup = Process.THREAD_GROUP_DEFAULT;
13512 }
13513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013514 }
13515 HistoryRecord a = cr.activity;
13516 //if (a != null) {
13517 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
13518 //}
13519 if (a != null && adj > FOREGROUND_APP_ADJ &&
13520 (a.state == ActivityState.RESUMED
13521 || a.state == ActivityState.PAUSING)) {
13522 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013523 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013524 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013525 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013526 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13527 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013528 app.adjSource = a;
13529 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013530 }
13531 }
13532 }
13533 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013534
13535 // Finally, f this process has active services running in it, we
13536 // would like to avoid killing it unless it would prevent the current
13537 // application from running. By default we put the process in
13538 // with the rest of the background processes; as we scan through
13539 // its services we may bump it up from there.
13540 if (adj > hiddenAdj) {
13541 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013542 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013543 app.adjType = "bg-services";
13544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 }
13546
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013547 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13548 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013549 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013550 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13551 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013552 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13553 if (cpr.clients.size() != 0) {
13554 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13555 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13556 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013557 if (client == app) {
13558 // Being our own client is not interesting.
13559 continue;
13560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013561 int myHiddenAdj = hiddenAdj;
13562 if (myHiddenAdj > client.hiddenAdj) {
13563 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13564 myHiddenAdj = client.hiddenAdj;
13565 } else {
13566 myHiddenAdj = FOREGROUND_APP_ADJ;
13567 }
13568 }
13569 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013570 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013571 if (adj > clientAdj) {
13572 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013573 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013574 if (!client.hidden) {
13575 app.hidden = false;
13576 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013577 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013578 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13579 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013580 app.adjSource = client;
13581 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013582 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013583 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13584 schedGroup = Process.THREAD_GROUP_DEFAULT;
13585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013586 }
13587 }
13588 // If the provider has external (non-framework) process
13589 // dependencies, ensure that its adjustment is at least
13590 // FOREGROUND_APP_ADJ.
13591 if (cpr.externals != 0) {
13592 if (adj > FOREGROUND_APP_ADJ) {
13593 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013594 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013595 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013596 app.adjType = "provider";
13597 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013598 }
13599 }
13600 }
13601 }
13602
13603 app.curRawAdj = adj;
13604
13605 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
13606 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13607 if (adj > app.maxAdj) {
13608 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013609 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13610 schedGroup = Process.THREAD_GROUP_DEFAULT;
13611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013612 }
13613
13614 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013615 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013617 return adj;
13618 }
13619
13620 /**
13621 * Ask a given process to GC right now.
13622 */
13623 final void performAppGcLocked(ProcessRecord app) {
13624 try {
13625 app.lastRequestedGc = SystemClock.uptimeMillis();
13626 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013627 if (app.reportLowMemory) {
13628 app.reportLowMemory = false;
13629 app.thread.scheduleLowMemory();
13630 } else {
13631 app.thread.processInBackground();
13632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013633 }
13634 } catch (Exception e) {
13635 // whatever.
13636 }
13637 }
13638
13639 /**
13640 * Returns true if things are idle enough to perform GCs.
13641 */
13642 private final boolean canGcNow() {
13643 return mParallelBroadcasts.size() == 0
13644 && mOrderedBroadcasts.size() == 0
13645 && (mSleeping || (mResumedActivity != null &&
13646 mResumedActivity.idle));
13647 }
13648
13649 /**
13650 * Perform GCs on all processes that are waiting for it, but only
13651 * if things are idle.
13652 */
13653 final void performAppGcsLocked() {
13654 final int N = mProcessesToGc.size();
13655 if (N <= 0) {
13656 return;
13657 }
13658 if (canGcNow()) {
13659 while (mProcessesToGc.size() > 0) {
13660 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013661 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13662 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13663 <= SystemClock.uptimeMillis()) {
13664 // To avoid spamming the system, we will GC processes one
13665 // at a time, waiting a few seconds between each.
13666 performAppGcLocked(proc);
13667 scheduleAppGcsLocked();
13668 return;
13669 } else {
13670 // It hasn't been long enough since we last GCed this
13671 // process... put it in the list to wait for its time.
13672 addProcessToGcListLocked(proc);
13673 break;
13674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013675 }
13676 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013677
13678 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013679 }
13680 }
13681
13682 /**
13683 * If all looks good, perform GCs on all processes waiting for them.
13684 */
13685 final void performAppGcsIfAppropriateLocked() {
13686 if (canGcNow()) {
13687 performAppGcsLocked();
13688 return;
13689 }
13690 // Still not idle, wait some more.
13691 scheduleAppGcsLocked();
13692 }
13693
13694 /**
13695 * Schedule the execution of all pending app GCs.
13696 */
13697 final void scheduleAppGcsLocked() {
13698 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013699
13700 if (mProcessesToGc.size() > 0) {
13701 // Schedule a GC for the time to the next process.
13702 ProcessRecord proc = mProcessesToGc.get(0);
13703 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13704
13705 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13706 long now = SystemClock.uptimeMillis();
13707 if (when < (now+GC_TIMEOUT)) {
13708 when = now + GC_TIMEOUT;
13709 }
13710 mHandler.sendMessageAtTime(msg, when);
13711 }
13712 }
13713
13714 /**
13715 * Add a process to the array of processes waiting to be GCed. Keeps the
13716 * list in sorted order by the last GC time. The process can't already be
13717 * on the list.
13718 */
13719 final void addProcessToGcListLocked(ProcessRecord proc) {
13720 boolean added = false;
13721 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13722 if (mProcessesToGc.get(i).lastRequestedGc <
13723 proc.lastRequestedGc) {
13724 added = true;
13725 mProcessesToGc.add(i+1, proc);
13726 break;
13727 }
13728 }
13729 if (!added) {
13730 mProcessesToGc.add(0, proc);
13731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013732 }
13733
13734 /**
13735 * Set up to ask a process to GC itself. This will either do it
13736 * immediately, or put it on the list of processes to gc the next
13737 * time things are idle.
13738 */
13739 final void scheduleAppGcLocked(ProcessRecord app) {
13740 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013741 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013742 return;
13743 }
13744 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013745 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013746 scheduleAppGcsLocked();
13747 }
13748 }
13749
13750 private final boolean updateOomAdjLocked(
13751 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13752 app.hiddenAdj = hiddenAdj;
13753
13754 if (app.thread == null) {
13755 return true;
13756 }
13757
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013758 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013759
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013760 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013761 if (app.curRawAdj != app.setRawAdj) {
13762 if (app.curRawAdj > FOREGROUND_APP_ADJ
13763 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13764 // If this app is transitioning from foreground to
13765 // non-foreground, have it do a gc.
13766 scheduleAppGcLocked(app);
13767 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13768 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13769 // Likewise do a gc when an app is moving in to the
13770 // background (such as a service stopping).
13771 scheduleAppGcLocked(app);
13772 }
13773 app.setRawAdj = app.curRawAdj;
13774 }
13775 if (adj != app.setAdj) {
13776 if (Process.setOomAdj(app.pid, adj)) {
13777 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
13778 TAG, "Set app " + app.processName +
13779 " oom adj to " + adj);
13780 app.setAdj = adj;
13781 } else {
13782 return false;
13783 }
13784 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013785 if (app.setSchedGroup != app.curSchedGroup) {
13786 app.setSchedGroup = app.curSchedGroup;
13787 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG,
13788 "Setting process group of " + app.processName
13789 + " to " + app.curSchedGroup);
13790 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013791 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013792 try {
13793 Process.setProcessGroup(app.pid, app.curSchedGroup);
13794 } catch (Exception e) {
13795 Log.w(TAG, "Failed setting process group of " + app.pid
13796 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013797 e.printStackTrace();
13798 } finally {
13799 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013800 }
13801 }
13802 if (false) {
13803 if (app.thread != null) {
13804 try {
13805 app.thread.setSchedulingGroup(app.curSchedGroup);
13806 } catch (RemoteException e) {
13807 }
13808 }
13809 }
13810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013811 }
13812
13813 return true;
13814 }
13815
13816 private final HistoryRecord resumedAppLocked() {
13817 HistoryRecord resumedActivity = mResumedActivity;
13818 if (resumedActivity == null || resumedActivity.app == null) {
13819 resumedActivity = mPausingActivity;
13820 if (resumedActivity == null || resumedActivity.app == null) {
13821 resumedActivity = topRunningActivityLocked(null);
13822 }
13823 }
13824 return resumedActivity;
13825 }
13826
13827 private final boolean updateOomAdjLocked(ProcessRecord app) {
13828 final HistoryRecord TOP_ACT = resumedAppLocked();
13829 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13830 int curAdj = app.curAdj;
13831 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13832 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13833
13834 mAdjSeq++;
13835
13836 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13837 if (res) {
13838 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13839 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13840 if (nowHidden != wasHidden) {
13841 // Changed to/from hidden state, so apps after it in the LRU
13842 // list may also be changed.
13843 updateOomAdjLocked();
13844 }
13845 }
13846 return res;
13847 }
13848
13849 private final boolean updateOomAdjLocked() {
13850 boolean didOomAdj = true;
13851 final HistoryRecord TOP_ACT = resumedAppLocked();
13852 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13853
13854 if (false) {
13855 RuntimeException e = new RuntimeException();
13856 e.fillInStackTrace();
13857 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
13858 }
13859
13860 mAdjSeq++;
13861
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013862 // Let's determine how many processes we have running vs.
13863 // how many slots we have for background processes; we may want
13864 // to put multiple processes in a slot of there are enough of
13865 // them.
13866 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13867 int factor = (mLruProcesses.size()-4)/numSlots;
13868 if (factor < 1) factor = 1;
13869 int step = 0;
13870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013871 // First try updating the OOM adjustment for each of the
13872 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013873 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13875 while (i > 0) {
13876 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013877 ProcessRecord app = mLruProcesses.get(i);
13878 //Log.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013879 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013880 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013881 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013882 step++;
13883 if (step >= factor) {
13884 step = 0;
13885 curHiddenAdj++;
13886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013887 }
13888 } else {
13889 didOomAdj = false;
13890 }
13891 }
13892
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013893 // If we return false, we will fall back on killing processes to
13894 // have a fixed limit. Do this if a limit has been requested; else
13895 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013896 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13897 }
13898
13899 private final void trimApplications() {
13900 synchronized (this) {
13901 int i;
13902
13903 // First remove any unused application processes whose package
13904 // has been removed.
13905 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13906 final ProcessRecord app = mRemovedProcesses.get(i);
13907 if (app.activities.size() == 0
13908 && app.curReceiver == null && app.services.size() == 0) {
13909 Log.i(
13910 TAG, "Exiting empty application process "
13911 + app.processName + " ("
13912 + (app.thread != null ? app.thread.asBinder() : null)
13913 + ")\n");
13914 if (app.pid > 0 && app.pid != MY_PID) {
13915 Process.killProcess(app.pid);
13916 } else {
13917 try {
13918 app.thread.scheduleExit();
13919 } catch (Exception e) {
13920 // Ignore exceptions.
13921 }
13922 }
13923 cleanUpApplicationRecordLocked(app, false, -1);
13924 mRemovedProcesses.remove(i);
13925
13926 if (app.persistent) {
13927 if (app.persistent) {
13928 addAppLocked(app.info);
13929 }
13930 }
13931 }
13932 }
13933
13934 // Now try updating the OOM adjustment for each of the
13935 // application processes based on their current state.
13936 // If the setOomAdj() API is not supported, then go with our
13937 // back-up plan...
13938 if (!updateOomAdjLocked()) {
13939
13940 // Count how many processes are running services.
13941 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013942 for (i=mLruProcesses.size()-1; i>=0; i--) {
13943 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013944
13945 if (app.persistent || app.services.size() != 0
13946 || app.curReceiver != null
13947 || app.persistentActivities > 0) {
13948 // Don't count processes holding services against our
13949 // maximum process count.
13950 if (localLOGV) Log.v(
13951 TAG, "Not trimming app " + app + " with services: "
13952 + app.services);
13953 numServiceProcs++;
13954 }
13955 }
13956
13957 int curMaxProcs = mProcessLimit;
13958 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13959 if (mAlwaysFinishActivities) {
13960 curMaxProcs = 1;
13961 }
13962 curMaxProcs += numServiceProcs;
13963
13964 // Quit as many processes as we can to get down to the desired
13965 // process count. First remove any processes that no longer
13966 // have activites running in them.
13967 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013968 i<mLruProcesses.size()
13969 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013970 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013971 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013972 // Quit an application only if it is not currently
13973 // running any activities.
13974 if (!app.persistent && app.activities.size() == 0
13975 && app.curReceiver == null && app.services.size() == 0) {
13976 Log.i(
13977 TAG, "Exiting empty application process "
13978 + app.processName + " ("
13979 + (app.thread != null ? app.thread.asBinder() : null)
13980 + ")\n");
13981 if (app.pid > 0 && app.pid != MY_PID) {
13982 Process.killProcess(app.pid);
13983 } else {
13984 try {
13985 app.thread.scheduleExit();
13986 } catch (Exception e) {
13987 // Ignore exceptions.
13988 }
13989 }
13990 // todo: For now we assume the application is not buggy
13991 // or evil, and will quit as a result of our request.
13992 // Eventually we need to drive this off of the death
13993 // notification, and kill the process if it takes too long.
13994 cleanUpApplicationRecordLocked(app, false, i);
13995 i--;
13996 }
13997 }
13998
13999 // If we still have too many processes, now from the least
14000 // recently used process we start finishing activities.
14001 if (Config.LOGV) Log.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014002 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014003 " of " + curMaxProcs + " processes");
14004 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014005 i<mLruProcesses.size()
14006 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014007 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014008 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014009 // Quit the application only if we have a state saved for
14010 // all of its activities.
14011 boolean canQuit = !app.persistent && app.curReceiver == null
14012 && app.services.size() == 0
14013 && app.persistentActivities == 0;
14014 int NUMA = app.activities.size();
14015 int j;
14016 if (Config.LOGV) Log.v(
14017 TAG, "Looking to quit " + app.processName);
14018 for (j=0; j<NUMA && canQuit; j++) {
14019 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14020 if (Config.LOGV) Log.v(
14021 TAG, " " + r.intent.getComponent().flattenToShortString()
14022 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14023 canQuit = (r.haveState || !r.stateNotNeeded)
14024 && !r.visible && r.stopped;
14025 }
14026 if (canQuit) {
14027 // Finish all of the activities, and then the app itself.
14028 for (j=0; j<NUMA; j++) {
14029 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14030 if (!r.finishing) {
14031 destroyActivityLocked(r, false);
14032 }
14033 r.resultTo = null;
14034 }
14035 Log.i(TAG, "Exiting application process "
14036 + app.processName + " ("
14037 + (app.thread != null ? app.thread.asBinder() : null)
14038 + ")\n");
14039 if (app.pid > 0 && app.pid != MY_PID) {
14040 Process.killProcess(app.pid);
14041 } else {
14042 try {
14043 app.thread.scheduleExit();
14044 } catch (Exception e) {
14045 // Ignore exceptions.
14046 }
14047 }
14048 // todo: For now we assume the application is not buggy
14049 // or evil, and will quit as a result of our request.
14050 // Eventually we need to drive this off of the death
14051 // notification, and kill the process if it takes too long.
14052 cleanUpApplicationRecordLocked(app, false, i);
14053 i--;
14054 //dump();
14055 }
14056 }
14057
14058 }
14059
14060 int curMaxActivities = MAX_ACTIVITIES;
14061 if (mAlwaysFinishActivities) {
14062 curMaxActivities = 1;
14063 }
14064
14065 // Finally, if there are too many activities now running, try to
14066 // finish as many as we can to get back down to the limit.
14067 for ( i=0;
14068 i<mLRUActivities.size()
14069 && mLRUActivities.size() > curMaxActivities;
14070 i++) {
14071 final HistoryRecord r
14072 = (HistoryRecord)mLRUActivities.get(i);
14073
14074 // We can finish this one if we have its icicle saved and
14075 // it is not persistent.
14076 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14077 && r.stopped && !r.persistent && !r.finishing) {
14078 final int origSize = mLRUActivities.size();
14079 destroyActivityLocked(r, true);
14080
14081 // This will remove it from the LRU list, so keep
14082 // our index at the same value. Note that this check to
14083 // see if the size changes is just paranoia -- if
14084 // something unexpected happens, we don't want to end up
14085 // in an infinite loop.
14086 if (origSize > mLRUActivities.size()) {
14087 i--;
14088 }
14089 }
14090 }
14091 }
14092 }
14093
14094 /** This method sends the specified signal to each of the persistent apps */
14095 public void signalPersistentProcesses(int sig) throws RemoteException {
14096 if (sig != Process.SIGNAL_USR1) {
14097 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14098 }
14099
14100 synchronized (this) {
14101 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14102 != PackageManager.PERMISSION_GRANTED) {
14103 throw new SecurityException("Requires permission "
14104 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14105 }
14106
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014107 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14108 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014109 if (r.thread != null && r.persistent) {
14110 Process.sendSignal(r.pid, sig);
14111 }
14112 }
14113 }
14114 }
14115
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014116 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014117 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014118
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014119 try {
14120 synchronized (this) {
14121 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14122 // its own permission.
14123 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14124 != PackageManager.PERMISSION_GRANTED) {
14125 throw new SecurityException("Requires permission "
14126 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014127 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014128
14129 if (start && fd == null) {
14130 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014131 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014132
14133 ProcessRecord proc = null;
14134 try {
14135 int pid = Integer.parseInt(process);
14136 synchronized (mPidsSelfLocked) {
14137 proc = mPidsSelfLocked.get(pid);
14138 }
14139 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014140 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014141
14142 if (proc == null) {
14143 HashMap<String, SparseArray<ProcessRecord>> all
14144 = mProcessNames.getMap();
14145 SparseArray<ProcessRecord> procs = all.get(process);
14146 if (procs != null && procs.size() > 0) {
14147 proc = procs.valueAt(0);
14148 }
14149 }
14150
14151 if (proc == null || proc.thread == null) {
14152 throw new IllegalArgumentException("Unknown process: " + process);
14153 }
14154
14155 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14156 if (isSecure) {
14157 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14158 throw new SecurityException("Process not debuggable: " + proc);
14159 }
14160 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014161
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014162 proc.thread.profilerControl(start, path, fd);
14163 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014164 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014165 }
14166 } catch (RemoteException e) {
14167 throw new IllegalStateException("Process disappeared");
14168 } finally {
14169 if (fd != null) {
14170 try {
14171 fd.close();
14172 } catch (IOException e) {
14173 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014174 }
14175 }
14176 }
14177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014178 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14179 public void monitor() {
14180 synchronized (this) { }
14181 }
14182}