blob: 45c3f0057d31e5387fb18f0e49d64633a8759265 [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 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800769 * Current sequencing integer of the configuration, for skipping old
770 * configurations.
771 */
772 int mConfigurationSeq = 0;
773
774 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700775 * Hardware-reported OpenGLES version.
776 */
777 final int GL_ES_VERSION;
778
779 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 * List of initialization arguments to pass to all processes when binding applications to them.
781 * For example, references to the commonly used services.
782 */
783 HashMap<String, IBinder> mAppBindArgs;
784
785 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700786 * Temporary to avoid allocations. Protected by main lock.
787 */
788 final StringBuilder mStringBuilder = new StringBuilder(256);
789
790 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 * Used to control how we initialize the service.
792 */
793 boolean mStartRunning = false;
794 ComponentName mTopComponent;
795 String mTopAction;
796 String mTopData;
797 boolean mSystemReady = false;
798 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700799 boolean mWaitingUpdate = false;
800 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801
802 Context mContext;
803
804 int mFactoryTest;
805
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700806 boolean mCheckedForSetup;
807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700809 * The time at which we will allow normal application switches again,
810 * after a call to {@link #stopAppSwitches()}.
811 */
812 long mAppSwitchesAllowedTime;
813
814 /**
815 * This is set to true after the first switch after mAppSwitchesAllowedTime
816 * is set; any switches after that will clear the time.
817 */
818 boolean mDidAppSwitch;
819
820 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 * Set while we are wanting to sleep, to prevent any
822 * activities from being started/resumed.
823 */
824 boolean mSleeping = false;
825
826 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700827 * Set if we are shutting down the system, similar to sleeping.
828 */
829 boolean mShuttingDown = false;
830
831 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 * Set when the system is going to sleep, until we have
833 * successfully paused the current activity and released our wake lock.
834 * At that point the system is allowed to actually sleep.
835 */
836 PowerManager.WakeLock mGoingToSleep;
837
838 /**
839 * We don't want to allow the device to go to sleep while in the process
840 * of launching an activity. This is primarily to allow alarm intent
841 * receivers to launch an activity and get that to run before the device
842 * goes back to sleep.
843 */
844 PowerManager.WakeLock mLaunchingActivity;
845
846 /**
847 * Task identifier that activities are currently being started
848 * in. Incremented each time a new task is created.
849 * todo: Replace this with a TokenSpace class that generates non-repeating
850 * integers that won't wrap.
851 */
852 int mCurTask = 1;
853
854 /**
855 * Current sequence id for oom_adj computation traversal.
856 */
857 int mAdjSeq = 0;
858
859 /**
860 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
861 * is set, indicating the user wants processes started in such a way
862 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
863 * running in each process (thus no pre-initialized process, etc).
864 */
865 boolean mSimpleProcessManagement = false;
866
867 /**
868 * System monitoring: number of processes that died since the last
869 * N procs were started.
870 */
871 int[] mProcDeaths = new int[20];
872
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700873 /**
874 * This is set if we had to do a delayed dexopt of an app before launching
875 * it, to increasing the ANR timeouts in that case.
876 */
877 boolean mDidDexOpt;
878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 String mDebugApp = null;
880 boolean mWaitForDebugger = false;
881 boolean mDebugTransient = false;
882 String mOrigDebugApp = null;
883 boolean mOrigWaitForDebugger = false;
884 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700885 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700887 final RemoteCallbackList<IActivityWatcher> mWatchers
888 = new RemoteCallbackList<IActivityWatcher>();
889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 /**
891 * Callback of last caller to {@link #requestPss}.
892 */
893 Runnable mRequestPssCallback;
894
895 /**
896 * Remaining processes for which we are waiting results from the last
897 * call to {@link #requestPss}.
898 */
899 final ArrayList<ProcessRecord> mRequestPssList
900 = new ArrayList<ProcessRecord>();
901
902 /**
903 * Runtime statistics collection thread. This object's lock is used to
904 * protect all related state.
905 */
906 final Thread mProcessStatsThread;
907
908 /**
909 * Used to collect process stats when showing not responding dialog.
910 * Protected by mProcessStatsThread.
911 */
912 final ProcessStats mProcessStats = new ProcessStats(
913 MONITOR_THREAD_CPU_USAGE);
914 long mLastCpuTime = 0;
915 long mLastWriteTime = 0;
916
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700917 long mInitialStartTime = 0;
918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 /**
920 * Set to true after the system has finished booting.
921 */
922 boolean mBooted = false;
923
924 int mProcessLimit = 0;
925
926 WindowManagerService mWindowManager;
927
928 static ActivityManagerService mSelf;
929 static ActivityThread mSystemThread;
930
931 private final class AppDeathRecipient implements IBinder.DeathRecipient {
932 final ProcessRecord mApp;
933 final int mPid;
934 final IApplicationThread mAppThread;
935
936 AppDeathRecipient(ProcessRecord app, int pid,
937 IApplicationThread thread) {
938 if (localLOGV) Log.v(
939 TAG, "New death recipient " + this
940 + " for thread " + thread.asBinder());
941 mApp = app;
942 mPid = pid;
943 mAppThread = thread;
944 }
945
946 public void binderDied() {
947 if (localLOGV) Log.v(
948 TAG, "Death received in " + this
949 + " for thread " + mAppThread.asBinder());
950 removeRequestedPss(mApp);
951 synchronized(ActivityManagerService.this) {
952 appDiedLocked(mApp, mPid, mAppThread);
953 }
954 }
955 }
956
957 static final int SHOW_ERROR_MSG = 1;
958 static final int SHOW_NOT_RESPONDING_MSG = 2;
959 static final int SHOW_FACTORY_ERROR_MSG = 3;
960 static final int UPDATE_CONFIGURATION_MSG = 4;
961 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
962 static final int WAIT_FOR_DEBUGGER_MSG = 6;
963 static final int BROADCAST_INTENT_MSG = 7;
964 static final int BROADCAST_TIMEOUT_MSG = 8;
965 static final int PAUSE_TIMEOUT_MSG = 9;
966 static final int IDLE_TIMEOUT_MSG = 10;
967 static final int IDLE_NOW_MSG = 11;
968 static final int SERVICE_TIMEOUT_MSG = 12;
969 static final int UPDATE_TIME_ZONE = 13;
970 static final int SHOW_UID_ERROR_MSG = 14;
971 static final int IM_FEELING_LUCKY_MSG = 15;
972 static final int LAUNCH_TIMEOUT_MSG = 16;
973 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 static final int RESUME_TOP_ACTIVITY_MSG = 19;
975 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700976 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700977 static final int KILL_APPLICATION_MSG = 22;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978
979 AlertDialog mUidAlert;
980
981 final Handler mHandler = new Handler() {
982 //public Handler() {
983 // if (localLOGV) Log.v(TAG, "Handler started!");
984 //}
985
986 public void handleMessage(Message msg) {
987 switch (msg.what) {
988 case SHOW_ERROR_MSG: {
989 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 synchronized (ActivityManagerService.this) {
991 ProcessRecord proc = (ProcessRecord)data.get("app");
992 if (proc != null && proc.crashDialog != null) {
993 Log.e(TAG, "App already has crash dialog: " + proc);
994 return;
995 }
996 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700997 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800998 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 d.show();
1000 proc.crashDialog = d;
1001 } else {
1002 // The device is asleep, so just pretend that the user
1003 // saw a crash dialog and hit "force quit".
1004 res.set(0);
1005 }
1006 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001007
1008 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 } break;
1010 case SHOW_NOT_RESPONDING_MSG: {
1011 synchronized (ActivityManagerService.this) {
1012 HashMap data = (HashMap) msg.obj;
1013 ProcessRecord proc = (ProcessRecord)data.get("app");
1014 if (proc != null && proc.anrDialog != null) {
1015 Log.e(TAG, "App already has anr dialog: " + proc);
1016 return;
1017 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001018
1019 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1020 null, null, 0, null, null, null,
1021 false, false, MY_PID, Process.SYSTEM_UID);
1022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1024 mContext, proc, (HistoryRecord)data.get("activity"));
1025 d.show();
1026 proc.anrDialog = d;
1027 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001028
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001029 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 } break;
1031 case SHOW_FACTORY_ERROR_MSG: {
1032 Dialog d = new FactoryErrorDialog(
1033 mContext, msg.getData().getCharSequence("msg"));
1034 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001035 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 } break;
1037 case UPDATE_CONFIGURATION_MSG: {
1038 final ContentResolver resolver = mContext.getContentResolver();
1039 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1040 } break;
1041 case GC_BACKGROUND_PROCESSES_MSG: {
1042 synchronized (ActivityManagerService.this) {
1043 performAppGcsIfAppropriateLocked();
1044 }
1045 } break;
1046 case WAIT_FOR_DEBUGGER_MSG: {
1047 synchronized (ActivityManagerService.this) {
1048 ProcessRecord app = (ProcessRecord)msg.obj;
1049 if (msg.arg1 != 0) {
1050 if (!app.waitedForDebugger) {
1051 Dialog d = new AppWaitingForDebuggerDialog(
1052 ActivityManagerService.this,
1053 mContext, app);
1054 app.waitDialog = d;
1055 app.waitedForDebugger = true;
1056 d.show();
1057 }
1058 } else {
1059 if (app.waitDialog != null) {
1060 app.waitDialog.dismiss();
1061 app.waitDialog = null;
1062 }
1063 }
1064 }
1065 } break;
1066 case BROADCAST_INTENT_MSG: {
1067 if (DEBUG_BROADCAST) Log.v(
1068 TAG, "Received BROADCAST_INTENT_MSG");
1069 processNextBroadcast(true);
1070 } break;
1071 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001072 if (mDidDexOpt) {
1073 mDidDexOpt = false;
1074 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1075 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1076 return;
1077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 broadcastTimeout();
1079 } break;
1080 case PAUSE_TIMEOUT_MSG: {
1081 IBinder token = (IBinder)msg.obj;
1082 // We don't at this point know if the activity is fullscreen,
1083 // so we need to be conservative and assume it isn't.
1084 Log.w(TAG, "Activity pause timeout for " + token);
1085 activityPaused(token, null, true);
1086 } break;
1087 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001088 if (mDidDexOpt) {
1089 mDidDexOpt = false;
1090 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1091 nmsg.obj = msg.obj;
1092 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1093 return;
1094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 // We don't at this point know if the activity is fullscreen,
1096 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001097 IBinder token = (IBinder)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 Log.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001099 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 } break;
1101 case DESTROY_TIMEOUT_MSG: {
1102 IBinder token = (IBinder)msg.obj;
1103 // We don't at this point know if the activity is fullscreen,
1104 // so we need to be conservative and assume it isn't.
1105 Log.w(TAG, "Activity destroy timeout for " + token);
1106 activityDestroyed(token);
1107 } break;
1108 case IDLE_NOW_MSG: {
1109 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001110 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 } break;
1112 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001113 if (mDidDexOpt) {
1114 mDidDexOpt = false;
1115 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1116 nmsg.obj = msg.obj;
1117 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1118 return;
1119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 serviceTimeout((ProcessRecord)msg.obj);
1121 } break;
1122 case UPDATE_TIME_ZONE: {
1123 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001124 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1125 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 if (r.thread != null) {
1127 try {
1128 r.thread.updateTimeZone();
1129 } catch (RemoteException ex) {
1130 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
1131 }
1132 }
1133 }
1134 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001135 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 case SHOW_UID_ERROR_MSG: {
1137 // XXX This is a temporary dialog, no need to localize.
1138 AlertDialog d = new BaseErrorDialog(mContext);
1139 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1140 d.setCancelable(false);
1141 d.setTitle("System UIDs Inconsistent");
1142 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1143 d.setButton("I'm Feeling Lucky",
1144 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1145 mUidAlert = d;
1146 d.show();
1147 } break;
1148 case IM_FEELING_LUCKY_MSG: {
1149 if (mUidAlert != null) {
1150 mUidAlert.dismiss();
1151 mUidAlert = null;
1152 }
1153 } break;
1154 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001155 if (mDidDexOpt) {
1156 mDidDexOpt = false;
1157 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1158 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1159 return;
1160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 synchronized (ActivityManagerService.this) {
1162 if (mLaunchingActivity.isHeld()) {
1163 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1164 mLaunchingActivity.release();
1165 }
1166 }
1167 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 case RESUME_TOP_ACTIVITY_MSG: {
1169 synchronized (ActivityManagerService.this) {
1170 resumeTopActivityLocked(null);
1171 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001172 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001174 if (mDidDexOpt) {
1175 mDidDexOpt = false;
1176 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1177 nmsg.obj = msg.obj;
1178 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1179 return;
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 ProcessRecord app = (ProcessRecord)msg.obj;
1182 synchronized (ActivityManagerService.this) {
1183 processStartTimedOutLocked(app);
1184 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001185 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001186 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1187 synchronized (ActivityManagerService.this) {
1188 doPendingActivityLaunchesLocked(true);
1189 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001190 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001191 case KILL_APPLICATION_MSG: {
1192 synchronized (ActivityManagerService.this) {
1193 int uid = msg.arg1;
1194 boolean restart = (msg.arg2 == 1);
1195 String pkg = (String) msg.obj;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08001196 forceStopPackageLocked(pkg, uid, restart, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001197 }
1198 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 }
1200 }
1201 };
1202
1203 public static void setSystemProcess() {
1204 try {
1205 ActivityManagerService m = mSelf;
1206
1207 ServiceManager.addService("activity", m);
1208 ServiceManager.addService("meminfo", new MemBinder(m));
1209 if (MONITOR_CPU_USAGE) {
1210 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 ServiceManager.addService("permission", new PermissionController(m));
1213
1214 ApplicationInfo info =
1215 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001216 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001217 mSystemThread.installSystemApplicationInfo(info);
1218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 synchronized (mSelf) {
1220 ProcessRecord app = mSelf.newProcessRecordLocked(
1221 mSystemThread.getApplicationThread(), info,
1222 info.processName);
1223 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001224 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 app.maxAdj = SYSTEM_ADJ;
1226 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1227 synchronized (mSelf.mPidsSelfLocked) {
1228 mSelf.mPidsSelfLocked.put(app.pid, app);
1229 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001230 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 }
1232 } catch (PackageManager.NameNotFoundException e) {
1233 throw new RuntimeException(
1234 "Unable to find android system package", e);
1235 }
1236 }
1237
1238 public void setWindowManager(WindowManagerService wm) {
1239 mWindowManager = wm;
1240 }
1241
1242 public static final Context main(int factoryTest) {
1243 AThread thr = new AThread();
1244 thr.start();
1245
1246 synchronized (thr) {
1247 while (thr.mService == null) {
1248 try {
1249 thr.wait();
1250 } catch (InterruptedException e) {
1251 }
1252 }
1253 }
1254
1255 ActivityManagerService m = thr.mService;
1256 mSelf = m;
1257 ActivityThread at = ActivityThread.systemMain();
1258 mSystemThread = at;
1259 Context context = at.getSystemContext();
1260 m.mContext = context;
1261 m.mFactoryTest = factoryTest;
1262 PowerManager pm =
1263 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1264 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1265 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1266 m.mLaunchingActivity.setReferenceCounted(false);
1267
1268 m.mBatteryStatsService.publish(context);
1269 m.mUsageStatsService.publish(context);
1270
1271 synchronized (thr) {
1272 thr.mReady = true;
1273 thr.notifyAll();
1274 }
1275
1276 m.startRunning(null, null, null, null);
1277
1278 return context;
1279 }
1280
1281 public static ActivityManagerService self() {
1282 return mSelf;
1283 }
1284
1285 static class AThread extends Thread {
1286 ActivityManagerService mService;
1287 boolean mReady = false;
1288
1289 public AThread() {
1290 super("ActivityManager");
1291 }
1292
1293 public void run() {
1294 Looper.prepare();
1295
1296 android.os.Process.setThreadPriority(
1297 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1298
1299 ActivityManagerService m = new ActivityManagerService();
1300
1301 synchronized (this) {
1302 mService = m;
1303 notifyAll();
1304 }
1305
1306 synchronized (this) {
1307 while (!mReady) {
1308 try {
1309 wait();
1310 } catch (InterruptedException e) {
1311 }
1312 }
1313 }
1314
1315 Looper.loop();
1316 }
1317 }
1318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 static class MemBinder extends Binder {
1320 ActivityManagerService mActivityManagerService;
1321 MemBinder(ActivityManagerService activityManagerService) {
1322 mActivityManagerService = activityManagerService;
1323 }
1324
1325 @Override
1326 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1327 ActivityManagerService service = mActivityManagerService;
1328 ArrayList<ProcessRecord> procs;
1329 synchronized (mActivityManagerService) {
1330 if (args != null && args.length > 0
1331 && args[0].charAt(0) != '-') {
1332 procs = new ArrayList<ProcessRecord>();
1333 int pid = -1;
1334 try {
1335 pid = Integer.parseInt(args[0]);
1336 } catch (NumberFormatException e) {
1337
1338 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001339 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1340 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 if (proc.pid == pid) {
1342 procs.add(proc);
1343 } else if (proc.processName.equals(args[0])) {
1344 procs.add(proc);
1345 }
1346 }
1347 if (procs.size() <= 0) {
1348 pw.println("No process found for: " + args[0]);
1349 return;
1350 }
1351 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001352 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 }
1354 }
1355 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1356 }
1357 }
1358
1359 static class CpuBinder extends Binder {
1360 ActivityManagerService mActivityManagerService;
1361 CpuBinder(ActivityManagerService activityManagerService) {
1362 mActivityManagerService = activityManagerService;
1363 }
1364
1365 @Override
1366 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1367 synchronized (mActivityManagerService.mProcessStatsThread) {
1368 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1369 }
1370 }
1371 }
1372
1373 private ActivityManagerService() {
1374 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1375 if (v != null && Integer.getInteger(v) != 0) {
1376 mSimpleProcessManagement = true;
1377 }
1378 v = System.getenv("ANDROID_DEBUG_APP");
1379 if (v != null) {
1380 mSimpleProcessManagement = true;
1381 }
1382
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001383 Log.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
1384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 File dataDir = Environment.getDataDirectory();
1386 File systemDir = new File(dataDir, "system");
1387 systemDir.mkdirs();
1388 mBatteryStatsService = new BatteryStatsService(new File(
1389 systemDir, "batterystats.bin").toString());
1390 mBatteryStatsService.getActiveStatistics().readLocked();
1391 mBatteryStatsService.getActiveStatistics().writeLocked();
1392
1393 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001394 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395
Jack Palevichb90d28c2009-07-22 15:35:24 -07001396 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1397 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 mConfiguration.makeDefault();
1400 mProcessStats.init();
1401
1402 // Add ourself to the Watchdog monitors.
1403 Watchdog.getInstance().addMonitor(this);
1404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 mProcessStatsThread = new Thread("ProcessStats") {
1406 public void run() {
1407 while (true) {
1408 try {
1409 try {
1410 synchronized(this) {
1411 final long now = SystemClock.uptimeMillis();
1412 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1413 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
1414 //Log.i(TAG, "Cpu delay=" + nextCpuDelay
1415 // + ", write delay=" + nextWriteDelay);
1416 if (nextWriteDelay < nextCpuDelay) {
1417 nextCpuDelay = nextWriteDelay;
1418 }
1419 if (nextCpuDelay > 0) {
1420 this.wait(nextCpuDelay);
1421 }
1422 }
1423 } catch (InterruptedException e) {
1424 }
1425
1426 updateCpuStatsNow();
1427 } catch (Exception e) {
1428 Log.e(TAG, "Unexpected exception collecting process stats", e);
1429 }
1430 }
1431 }
1432 };
1433 mProcessStatsThread.start();
1434 }
1435
1436 @Override
1437 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1438 throws RemoteException {
1439 try {
1440 return super.onTransact(code, data, reply, flags);
1441 } catch (RuntimeException e) {
1442 // The activity manager only throws security exceptions, so let's
1443 // log all others.
1444 if (!(e instanceof SecurityException)) {
1445 Log.e(TAG, "Activity Manager Crash", e);
1446 }
1447 throw e;
1448 }
1449 }
1450
1451 void updateCpuStats() {
1452 synchronized (mProcessStatsThread) {
1453 final long now = SystemClock.uptimeMillis();
1454 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1455 mProcessStatsThread.notify();
1456 }
1457 }
1458 }
1459
1460 void updateCpuStatsNow() {
1461 synchronized (mProcessStatsThread) {
1462 final long now = SystemClock.uptimeMillis();
1463 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 if (MONITOR_CPU_USAGE &&
1466 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1467 mLastCpuTime = now;
1468 haveNewCpuStats = true;
1469 mProcessStats.update();
1470 //Log.i(TAG, mProcessStats.printCurrentState());
1471 //Log.i(TAG, "Total CPU usage: "
1472 // + mProcessStats.getTotalCpuPercent() + "%");
1473
1474 // Log the cpu usage if the property is set.
1475 if ("true".equals(SystemProperties.get("events.cpu"))) {
1476 int user = mProcessStats.getLastUserTime();
1477 int system = mProcessStats.getLastSystemTime();
1478 int iowait = mProcessStats.getLastIoWaitTime();
1479 int irq = mProcessStats.getLastIrqTime();
1480 int softIrq = mProcessStats.getLastSoftIrqTime();
1481 int idle = mProcessStats.getLastIdleTime();
1482
1483 int total = user + system + iowait + irq + softIrq + idle;
1484 if (total == 0) total = 1;
1485
Doug Zongker2bec3d42009-12-04 12:52:44 -08001486 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 ((user+system+iowait+irq+softIrq) * 100) / total,
1488 (user * 100) / total,
1489 (system * 100) / total,
1490 (iowait * 100) / total,
1491 (irq * 100) / total,
1492 (softIrq * 100) / total);
1493 }
1494 }
1495
Amith Yamasanie43530a2009-08-21 13:11:37 -07001496 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001497 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001498 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 synchronized(mPidsSelfLocked) {
1500 if (haveNewCpuStats) {
1501 if (mBatteryStatsService.isOnBattery()) {
1502 final int N = mProcessStats.countWorkingStats();
1503 for (int i=0; i<N; i++) {
1504 ProcessStats.Stats st
1505 = mProcessStats.getWorkingStats(i);
1506 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1507 if (pr != null) {
1508 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
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 } else {
1512 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001513 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001514 if (ps != null) {
1515 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001516 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 }
1519 }
1520 }
1521 }
1522 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1525 mLastWriteTime = now;
1526 mBatteryStatsService.getActiveStatistics().writeLocked();
1527 }
1528 }
1529 }
1530 }
1531
1532 /**
1533 * Initialize the application bind args. These are passed to each
1534 * process when the bindApplication() IPC is sent to the process. They're
1535 * lazily setup to make sure the services are running when they're asked for.
1536 */
1537 private HashMap<String, IBinder> getCommonServicesLocked() {
1538 if (mAppBindArgs == null) {
1539 mAppBindArgs = new HashMap<String, IBinder>();
1540
1541 // Setup the application init args
1542 mAppBindArgs.put("package", ServiceManager.getService("package"));
1543 mAppBindArgs.put("window", ServiceManager.getService("window"));
1544 mAppBindArgs.put(Context.ALARM_SERVICE,
1545 ServiceManager.getService(Context.ALARM_SERVICE));
1546 }
1547 return mAppBindArgs;
1548 }
1549
1550 private final void setFocusedActivityLocked(HistoryRecord r) {
1551 if (mFocusedActivity != r) {
1552 mFocusedActivity = r;
1553 mWindowManager.setFocusedApp(r, true);
1554 }
1555 }
1556
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001557 private final void updateLruProcessLocked(ProcessRecord app,
1558 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001560 int lrui = mLruProcesses.indexOf(app);
1561 if (lrui >= 0) mLruProcesses.remove(lrui);
1562
1563 int i = mLruProcesses.size()-1;
1564 int skipTop = 0;
1565
1566 // compute the new weight for this process.
1567 if (updateActivityTime) {
1568 app.lastActivityTime = SystemClock.uptimeMillis();
1569 }
1570 if (app.activities.size() > 0) {
1571 // If this process has activities, we more strongly want to keep
1572 // it around.
1573 app.lruWeight = app.lastActivityTime;
1574 } else if (app.pubProviders.size() > 0) {
1575 // If this process contains content providers, we want to keep
1576 // it a little more strongly.
1577 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1578 // Also don't let it kick out the first few "real" hidden processes.
1579 skipTop = MIN_HIDDEN_APPS;
1580 } else {
1581 // If this process doesn't have activities, we less strongly
1582 // want to keep it around, and generally want to avoid getting
1583 // in front of any very recently used activities.
1584 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1585 // Also don't let it kick out the first few "real" hidden processes.
1586 skipTop = MIN_HIDDEN_APPS;
1587 }
1588 while (i >= 0) {
1589 ProcessRecord p = mLruProcesses.get(i);
1590 // If this app shouldn't be in front of the first N background
1591 // apps, then skip over that many that are currently hidden.
1592 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1593 skipTop--;
1594 }
1595 if (p.lruWeight <= app.lruWeight){
1596 mLruProcesses.add(i+1, app);
1597 break;
1598 }
1599 i--;
1600 }
1601 if (i < 0) {
1602 mLruProcesses.add(0, app);
1603 }
1604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 //Log.i(TAG, "Putting proc to front: " + app.processName);
1606 if (oomAdj) {
1607 updateOomAdjLocked();
1608 }
1609 }
1610
1611 private final boolean updateLRUListLocked(HistoryRecord r) {
1612 final boolean hadit = mLRUActivities.remove(r);
1613 mLRUActivities.add(r);
1614 return hadit;
1615 }
1616
1617 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1618 int i = mHistory.size()-1;
1619 while (i >= 0) {
1620 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1621 if (!r.finishing && r != notTop) {
1622 return r;
1623 }
1624 i--;
1625 }
1626 return null;
1627 }
1628
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001629 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1630 int i = mHistory.size()-1;
1631 while (i >= 0) {
1632 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1633 if (!r.finishing && !r.delayedResume && r != notTop) {
1634 return r;
1635 }
1636 i--;
1637 }
1638 return null;
1639 }
1640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 /**
1642 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001643 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 *
1645 * @param token If non-null, any history records matching this token will be skipped.
1646 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1647 *
1648 * @return Returns the HistoryRecord of the next activity on the stack.
1649 */
1650 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1651 int i = mHistory.size()-1;
1652 while (i >= 0) {
1653 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1654 // Note: the taskId check depends on real taskId fields being non-zero
1655 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1656 return r;
1657 }
1658 i--;
1659 }
1660 return null;
1661 }
1662
1663 private final ProcessRecord getProcessRecordLocked(
1664 String processName, int uid) {
1665 if (uid == Process.SYSTEM_UID) {
1666 // The system gets to run in any process. If there are multiple
1667 // processes with the same uid, just pick the first (this
1668 // should never happen).
1669 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1670 processName);
1671 return procs != null ? procs.valueAt(0) : null;
1672 }
1673 ProcessRecord proc = mProcessNames.get(processName, uid);
1674 return proc;
1675 }
1676
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001677 private void ensurePackageDexOpt(String packageName) {
1678 IPackageManager pm = ActivityThread.getPackageManager();
1679 try {
1680 if (pm.performDexOpt(packageName)) {
1681 mDidDexOpt = true;
1682 }
1683 } catch (RemoteException e) {
1684 }
1685 }
1686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 private boolean isNextTransitionForward() {
1688 int transit = mWindowManager.getPendingAppTransition();
1689 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1690 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1691 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1692 }
1693
1694 private final boolean realStartActivityLocked(HistoryRecord r,
1695 ProcessRecord app, boolean andResume, boolean checkConfig)
1696 throws RemoteException {
1697
1698 r.startFreezingScreenLocked(app, 0);
1699 mWindowManager.setAppVisibility(r, true);
1700
1701 // Have the window manager re-evaluate the orientation of
1702 // the screen based on the new activity order. Note that
1703 // as a result of this, it can call back into the activity
1704 // manager with a new orientation. We don't care about that,
1705 // because the activity is not currently running so we are
1706 // just restarting it anyway.
1707 if (checkConfig) {
1708 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001709 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 r.mayFreezeScreenLocked(app) ? r : null);
1711 updateConfigurationLocked(config, r);
1712 }
1713
1714 r.app = app;
1715
1716 if (localLOGV) Log.v(TAG, "Launching: " + r);
1717
1718 int idx = app.activities.indexOf(r);
1719 if (idx < 0) {
1720 app.activities.add(r);
1721 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001722 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723
1724 try {
1725 if (app.thread == null) {
1726 throw new RemoteException();
1727 }
1728 List<ResultInfo> results = null;
1729 List<Intent> newIntents = null;
1730 if (andResume) {
1731 results = r.results;
1732 newIntents = r.newIntents;
1733 }
1734 if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
1735 + " icicle=" + r.icicle
1736 + " with results=" + results + " newIntents=" + newIntents
1737 + " andResume=" + andResume);
1738 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001739 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 System.identityHashCode(r),
1741 r.task.taskId, r.shortComponentName);
1742 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001743 if (r.isHomeActivity) {
1744 mHomeProcess = app;
1745 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001746 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001748 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 r.info, r.icicle, results, newIntents, !andResume,
1750 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 } catch (RemoteException e) {
1752 if (r.launchFailed) {
1753 // This is the second time we failed -- finish activity
1754 // and give up.
1755 Log.e(TAG, "Second failure launching "
1756 + r.intent.getComponent().flattenToShortString()
1757 + ", giving up", e);
1758 appDiedLocked(app, app.pid, app.thread);
1759 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1760 "2nd-crash");
1761 return false;
1762 }
1763
1764 // This is the first time we failed -- restart process and
1765 // retry.
1766 app.activities.remove(r);
1767 throw e;
1768 }
1769
1770 r.launchFailed = false;
1771 if (updateLRUListLocked(r)) {
1772 Log.w(TAG, "Activity " + r
1773 + " being launched, but already in LRU list");
1774 }
1775
1776 if (andResume) {
1777 // As part of the process of launching, ActivityThread also performs
1778 // a resume.
1779 r.state = ActivityState.RESUMED;
1780 r.icicle = null;
1781 r.haveState = false;
1782 r.stopped = false;
1783 mResumedActivity = r;
1784 r.task.touchActiveTime();
1785 completeResumeLocked(r);
1786 pauseIfSleepingLocked();
1787 } else {
1788 // This activity is not starting in the resumed state... which
1789 // should look like we asked it to pause+stop (but remain visible),
1790 // and it has done so and reported back the current icicle and
1791 // other state.
1792 r.state = ActivityState.STOPPED;
1793 r.stopped = true;
1794 }
1795
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001796 // Launch the new version setup screen if needed. We do this -after-
1797 // launching the initial activity (that is, home), so that it can have
1798 // a chance to initialize itself while in the background, making the
1799 // switch back to it faster and look better.
1800 startSetupActivityLocked();
1801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 return true;
1803 }
1804
1805 private final void startSpecificActivityLocked(HistoryRecord r,
1806 boolean andResume, boolean checkConfig) {
1807 // Is this activity's application already running?
1808 ProcessRecord app = getProcessRecordLocked(r.processName,
1809 r.info.applicationInfo.uid);
1810
1811 if (r.startTime == 0) {
1812 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001813 if (mInitialStartTime == 0) {
1814 mInitialStartTime = r.startTime;
1815 }
1816 } else if (mInitialStartTime == 0) {
1817 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 }
1819
1820 if (app != null && app.thread != null) {
1821 try {
1822 realStartActivityLocked(r, app, andResume, checkConfig);
1823 return;
1824 } catch (RemoteException e) {
1825 Log.w(TAG, "Exception when starting activity "
1826 + r.intent.getComponent().flattenToShortString(), e);
1827 }
1828
1829 // If a dead object exception was thrown -- fall through to
1830 // restart the application.
1831 }
1832
1833 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001834 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 }
1836
1837 private final ProcessRecord startProcessLocked(String processName,
1838 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001839 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1841 // We don't have to do anything more if:
1842 // (1) There is an existing application record; and
1843 // (2) The caller doesn't think it is dead, OR there is no thread
1844 // object attached to it so we know it couldn't have crashed; and
1845 // (3) There is a pid assigned to it, so it is either starting or
1846 // already running.
1847 if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
1848 + " app=" + app + " knownToBeDead=" + knownToBeDead
1849 + " thread=" + (app != null ? app.thread : null)
1850 + " pid=" + (app != null ? app.pid : -1));
1851 if (app != null &&
1852 (!knownToBeDead || app.thread == null) && app.pid > 0) {
1853 return app;
1854 }
1855
1856 String hostingNameStr = hostingName != null
1857 ? hostingName.flattenToShortString() : null;
1858
1859 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1860 // If we are in the background, then check to see if this process
1861 // is bad. If so, we will just silently fail.
1862 if (mBadProcesses.get(info.processName, info.uid) != null) {
1863 return null;
1864 }
1865 } else {
1866 // When the user is explicitly starting a process, then clear its
1867 // crash count so that we won't make it bad until they see at
1868 // least one crash dialog again, and make the process good again
1869 // if it had been bad.
1870 mProcessCrashTimes.remove(info.processName, info.uid);
1871 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001872 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 info.processName);
1874 mBadProcesses.remove(info.processName, info.uid);
1875 if (app != null) {
1876 app.bad = false;
1877 }
1878 }
1879 }
1880
1881 if (app == null) {
1882 app = newProcessRecordLocked(null, info, processName);
1883 mProcessNames.put(processName, info.uid, app);
1884 } else {
1885 // If this is a new package in the process, add the package to the list
1886 app.addPackage(info.packageName);
1887 }
1888
1889 // If the system is not ready yet, then hold off on starting this
1890 // process until it is.
1891 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001892 && !isAllowedWhileBooting(info)
1893 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 if (!mProcessesOnHold.contains(app)) {
1895 mProcessesOnHold.add(app);
1896 }
1897 return app;
1898 }
1899
1900 startProcessLocked(app, hostingType, hostingNameStr);
1901 return (app.pid != 0) ? app : null;
1902 }
1903
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001904 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1905 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1906 }
1907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 private final void startProcessLocked(ProcessRecord app,
1909 String hostingType, String hostingNameStr) {
1910 if (app.pid > 0 && app.pid != MY_PID) {
1911 synchronized (mPidsSelfLocked) {
1912 mPidsSelfLocked.remove(app.pid);
1913 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1914 }
1915 app.pid = 0;
1916 }
1917
1918 mProcessesOnHold.remove(app);
1919
1920 updateCpuStats();
1921
1922 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1923 mProcDeaths[0] = 0;
1924
1925 try {
1926 int uid = app.info.uid;
1927 int[] gids = null;
1928 try {
1929 gids = mContext.getPackageManager().getPackageGids(
1930 app.info.packageName);
1931 } catch (PackageManager.NameNotFoundException e) {
1932 Log.w(TAG, "Unable to retrieve gids", e);
1933 }
1934 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1935 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1936 && mTopComponent != null
1937 && app.processName.equals(mTopComponent.getPackageName())) {
1938 uid = 0;
1939 }
1940 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1941 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1942 uid = 0;
1943 }
1944 }
1945 int debugFlags = 0;
1946 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1947 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1948 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001949 // Run the app in safe mode if its manifest requests so or the
1950 // system is booted in safe mode.
1951 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1952 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001953 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1956 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1957 }
1958 if ("1".equals(SystemProperties.get("debug.assert"))) {
1959 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1960 }
1961 int pid = Process.start("android.app.ActivityThread",
1962 mSimpleProcessManagement ? app.processName : null, uid, uid,
1963 gids, debugFlags, null);
1964 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1965 synchronized (bs) {
1966 if (bs.isOnBattery()) {
1967 app.batteryStats.incStartsLocked();
1968 }
1969 }
1970
Doug Zongker2bec3d42009-12-04 12:52:44 -08001971 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 app.processName, hostingType,
1973 hostingNameStr != null ? hostingNameStr : "");
1974
1975 if (app.persistent) {
1976 Watchdog.getInstance().processStarted(app, app.processName, pid);
1977 }
1978
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001979 StringBuilder buf = mStringBuilder;
1980 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 buf.append("Start proc ");
1982 buf.append(app.processName);
1983 buf.append(" for ");
1984 buf.append(hostingType);
1985 if (hostingNameStr != null) {
1986 buf.append(" ");
1987 buf.append(hostingNameStr);
1988 }
1989 buf.append(": pid=");
1990 buf.append(pid);
1991 buf.append(" uid=");
1992 buf.append(uid);
1993 buf.append(" gids={");
1994 if (gids != null) {
1995 for (int gi=0; gi<gids.length; gi++) {
1996 if (gi != 0) buf.append(", ");
1997 buf.append(gids[gi]);
1998
1999 }
2000 }
2001 buf.append("}");
2002 Log.i(TAG, buf.toString());
2003 if (pid == 0 || pid == MY_PID) {
2004 // Processes are being emulated with threads.
2005 app.pid = MY_PID;
2006 app.removed = false;
2007 mStartingProcesses.add(app);
2008 } else if (pid > 0) {
2009 app.pid = pid;
2010 app.removed = false;
2011 synchronized (mPidsSelfLocked) {
2012 this.mPidsSelfLocked.put(pid, app);
2013 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2014 msg.obj = app;
2015 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2016 }
2017 } else {
2018 app.pid = 0;
2019 RuntimeException e = new RuntimeException(
2020 "Failure starting process " + app.processName
2021 + ": returned pid=" + pid);
2022 Log.e(TAG, e.getMessage(), e);
2023 }
2024 } catch (RuntimeException e) {
2025 // XXX do better error recovery.
2026 app.pid = 0;
2027 Log.e(TAG, "Failure starting process " + app.processName, e);
2028 }
2029 }
2030
2031 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2032 if (mPausingActivity != null) {
2033 RuntimeException e = new RuntimeException();
2034 Log.e(TAG, "Trying to pause when pause is already pending for "
2035 + mPausingActivity, e);
2036 }
2037 HistoryRecord prev = mResumedActivity;
2038 if (prev == null) {
2039 RuntimeException e = new RuntimeException();
2040 Log.e(TAG, "Trying to pause when nothing is resumed", e);
2041 resumeTopActivityLocked(null);
2042 return;
2043 }
2044 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
2045 mResumedActivity = null;
2046 mPausingActivity = prev;
2047 mLastPausedActivity = prev;
2048 prev.state = ActivityState.PAUSING;
2049 prev.task.touchActiveTime();
2050
2051 updateCpuStats();
2052
2053 if (prev.app != null && prev.app.thread != null) {
2054 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
2055 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002056 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 System.identityHashCode(prev),
2058 prev.shortComponentName);
2059 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2060 prev.configChangeFlags);
2061 updateUsageStats(prev, false);
2062 } catch (Exception e) {
2063 // Ignore exception, if process died other code will cleanup.
2064 Log.w(TAG, "Exception thrown during pause", e);
2065 mPausingActivity = null;
2066 mLastPausedActivity = null;
2067 }
2068 } else {
2069 mPausingActivity = null;
2070 mLastPausedActivity = null;
2071 }
2072
2073 // If we are not going to sleep, we want to ensure the device is
2074 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002075 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 mLaunchingActivity.acquire();
2077 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2078 // To be safe, don't allow the wake lock to be held for too long.
2079 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2080 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2081 }
2082 }
2083
2084
2085 if (mPausingActivity != null) {
2086 // Have the window manager pause its key dispatching until the new
2087 // activity has started. If we're pausing the activity just because
2088 // the screen is being turned off and the UI is sleeping, don't interrupt
2089 // key dispatch; the same activity will pick it up again on wakeup.
2090 if (!uiSleeping) {
2091 prev.pauseKeyDispatchingLocked();
2092 } else {
2093 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
2094 }
2095
2096 // Schedule a pause timeout in case the app doesn't respond.
2097 // We don't give it much time because this directly impacts the
2098 // responsiveness seen by the user.
2099 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2100 msg.obj = prev;
2101 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
2102 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
2103 } else {
2104 // This activity failed to schedule the
2105 // pause, so just treat it as being paused now.
2106 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
2107 resumeTopActivityLocked(null);
2108 }
2109 }
2110
2111 private final void completePauseLocked() {
2112 HistoryRecord prev = mPausingActivity;
2113 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
2114
2115 if (prev != null) {
2116 if (prev.finishing) {
2117 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
2118 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2119 } else if (prev.app != null) {
2120 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
2121 if (prev.waitingVisible) {
2122 prev.waitingVisible = false;
2123 mWaitingVisibleActivities.remove(prev);
2124 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
2125 TAG, "Complete pause, no longer waiting: " + prev);
2126 }
2127 if (prev.configDestroy) {
2128 // The previous is being paused because the configuration
2129 // is changing, which means it is actually stopping...
2130 // To juggle the fact that we are also starting a new
2131 // instance right now, we need to first completely stop
2132 // the current instance before starting the new one.
2133 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
2134 destroyActivityLocked(prev, true);
2135 } else {
2136 mStoppingActivities.add(prev);
2137 if (mStoppingActivities.size() > 3) {
2138 // If we already have a few activities waiting to stop,
2139 // then give up on things going idle and start clearing
2140 // them out.
2141 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
2142 Message msg = Message.obtain();
2143 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2144 mHandler.sendMessage(msg);
2145 }
2146 }
2147 } else {
2148 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
2149 prev = null;
2150 }
2151 mPausingActivity = null;
2152 }
2153
Dianne Hackborn55280a92009-05-07 15:53:46 -07002154 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 resumeTopActivityLocked(prev);
2156 } else {
2157 if (mGoingToSleep.isHeld()) {
2158 mGoingToSleep.release();
2159 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002160 if (mShuttingDown) {
2161 notifyAll();
2162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 }
2164
2165 if (prev != null) {
2166 prev.resumeKeyDispatchingLocked();
2167 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002168
2169 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2170 long diff = 0;
2171 synchronized (mProcessStatsThread) {
2172 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2173 }
2174 if (diff > 0) {
2175 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2176 synchronized (bsi) {
2177 BatteryStatsImpl.Uid.Proc ps =
2178 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2179 prev.info.packageName);
2180 if (ps != null) {
2181 ps.addForegroundTimeLocked(diff);
2182 }
2183 }
2184 }
2185 }
2186 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 }
2188
2189 /**
2190 * Once we know that we have asked an application to put an activity in
2191 * the resumed state (either by launching it or explicitly telling it),
2192 * this function updates the rest of our state to match that fact.
2193 */
2194 private final void completeResumeLocked(HistoryRecord next) {
2195 next.idle = false;
2196 next.results = null;
2197 next.newIntents = null;
2198
2199 // schedule an idle timeout in case the app doesn't do it for us.
2200 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2201 msg.obj = next;
2202 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2203
2204 if (false) {
2205 // The activity was never told to pause, so just keep
2206 // things going as-is. To maintain our own state,
2207 // we need to emulate it coming back and saying it is
2208 // idle.
2209 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2210 msg.obj = next;
2211 mHandler.sendMessage(msg);
2212 }
2213
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002214 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 next.thumbnail = null;
2217 setFocusedActivityLocked(next);
2218 next.resumeKeyDispatchingLocked();
2219 ensureActivitiesVisibleLocked(null, 0);
2220 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002221 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002222
2223 // Mark the point when the activity is resuming
2224 // TODO: To be more accurate, the mark should be before the onCreate,
2225 // not after the onResume. But for subsequent starts, onResume is fine.
2226 if (next.app != null) {
2227 synchronized (mProcessStatsThread) {
2228 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2229 }
2230 } else {
2231 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 }
2234
2235 /**
2236 * Make sure that all activities that need to be visible (that is, they
2237 * currently can be seen by the user) actually are.
2238 */
2239 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2240 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2241 if (DEBUG_VISBILITY) Log.v(
2242 TAG, "ensureActivitiesVisible behind " + top
2243 + " configChanges=0x" + Integer.toHexString(configChanges));
2244
2245 // If the top activity is not fullscreen, then we need to
2246 // make sure any activities under it are now visible.
2247 final int count = mHistory.size();
2248 int i = count-1;
2249 while (mHistory.get(i) != top) {
2250 i--;
2251 }
2252 HistoryRecord r;
2253 boolean behindFullscreen = false;
2254 for (; i>=0; i--) {
2255 r = (HistoryRecord)mHistory.get(i);
2256 if (DEBUG_VISBILITY) Log.v(
2257 TAG, "Make visible? " + r + " finishing=" + r.finishing
2258 + " state=" + r.state);
2259 if (r.finishing) {
2260 continue;
2261 }
2262
2263 final boolean doThisProcess = onlyThisProcess == null
2264 || onlyThisProcess.equals(r.processName);
2265
2266 // First: if this is not the current activity being started, make
2267 // sure it matches the current configuration.
2268 if (r != starting && doThisProcess) {
2269 ensureActivityConfigurationLocked(r, 0);
2270 }
2271
2272 if (r.app == null || r.app.thread == null) {
2273 if (onlyThisProcess == null
2274 || onlyThisProcess.equals(r.processName)) {
2275 // This activity needs to be visible, but isn't even
2276 // running... get it started, but don't resume it
2277 // at this point.
2278 if (DEBUG_VISBILITY) Log.v(
2279 TAG, "Start and freeze screen for " + r);
2280 if (r != starting) {
2281 r.startFreezingScreenLocked(r.app, configChanges);
2282 }
2283 if (!r.visible) {
2284 if (DEBUG_VISBILITY) Log.v(
2285 TAG, "Starting and making visible: " + r);
2286 mWindowManager.setAppVisibility(r, true);
2287 }
2288 if (r != starting) {
2289 startSpecificActivityLocked(r, false, false);
2290 }
2291 }
2292
2293 } else if (r.visible) {
2294 // If this activity is already visible, then there is nothing
2295 // else to do here.
2296 if (DEBUG_VISBILITY) Log.v(
2297 TAG, "Skipping: already visible at " + r);
2298 r.stopFreezingScreenLocked(false);
2299
2300 } else if (onlyThisProcess == null) {
2301 // This activity is not currently visible, but is running.
2302 // Tell it to become visible.
2303 r.visible = true;
2304 if (r.state != ActivityState.RESUMED && r != starting) {
2305 // If this activity is paused, tell it
2306 // to now show its window.
2307 if (DEBUG_VISBILITY) Log.v(
2308 TAG, "Making visible and scheduling visibility: " + r);
2309 try {
2310 mWindowManager.setAppVisibility(r, true);
2311 r.app.thread.scheduleWindowVisibility(r, true);
2312 r.stopFreezingScreenLocked(false);
2313 } catch (Exception e) {
2314 // Just skip on any failure; we'll make it
2315 // visible when it next restarts.
2316 Log.w(TAG, "Exception thrown making visibile: "
2317 + r.intent.getComponent(), e);
2318 }
2319 }
2320 }
2321
2322 // Aggregate current change flags.
2323 configChanges |= r.configChangeFlags;
2324
2325 if (r.fullscreen) {
2326 // At this point, nothing else needs to be shown
2327 if (DEBUG_VISBILITY) Log.v(
2328 TAG, "Stopping: fullscreen at " + r);
2329 behindFullscreen = true;
2330 i--;
2331 break;
2332 }
2333 }
2334
2335 // Now for any activities that aren't visible to the user, make
2336 // sure they no longer are keeping the screen frozen.
2337 while (i >= 0) {
2338 r = (HistoryRecord)mHistory.get(i);
2339 if (DEBUG_VISBILITY) Log.v(
2340 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2341 + " state=" + r.state
2342 + " behindFullscreen=" + behindFullscreen);
2343 if (!r.finishing) {
2344 if (behindFullscreen) {
2345 if (r.visible) {
2346 if (DEBUG_VISBILITY) Log.v(
2347 TAG, "Making invisible: " + r);
2348 r.visible = false;
2349 try {
2350 mWindowManager.setAppVisibility(r, false);
2351 if ((r.state == ActivityState.STOPPING
2352 || r.state == ActivityState.STOPPED)
2353 && r.app != null && r.app.thread != null) {
2354 if (DEBUG_VISBILITY) Log.v(
2355 TAG, "Scheduling invisibility: " + r);
2356 r.app.thread.scheduleWindowVisibility(r, false);
2357 }
2358 } catch (Exception e) {
2359 // Just skip on any failure; we'll make it
2360 // visible when it next restarts.
2361 Log.w(TAG, "Exception thrown making hidden: "
2362 + r.intent.getComponent(), e);
2363 }
2364 } else {
2365 if (DEBUG_VISBILITY) Log.v(
2366 TAG, "Already invisible: " + r);
2367 }
2368 } else if (r.fullscreen) {
2369 if (DEBUG_VISBILITY) Log.v(
2370 TAG, "Now behindFullscreen: " + r);
2371 behindFullscreen = true;
2372 }
2373 }
2374 i--;
2375 }
2376 }
2377
2378 /**
2379 * Version of ensureActivitiesVisible that can easily be called anywhere.
2380 */
2381 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2382 int configChanges) {
2383 HistoryRecord r = topRunningActivityLocked(null);
2384 if (r != null) {
2385 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2386 }
2387 }
2388
2389 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2390 if (resumed) {
2391 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2392 } else {
2393 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2394 }
2395 }
2396
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002397 private boolean startHomeActivityLocked() {
2398 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2399 && mTopAction == null) {
2400 // We are running in factory test mode, but unable to find
2401 // the factory test app, so just sit around displaying the
2402 // error message and don't try to start anything.
2403 return false;
2404 }
2405 Intent intent = new Intent(
2406 mTopAction,
2407 mTopData != null ? Uri.parse(mTopData) : null);
2408 intent.setComponent(mTopComponent);
2409 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2410 intent.addCategory(Intent.CATEGORY_HOME);
2411 }
2412 ActivityInfo aInfo =
2413 intent.resolveActivityInfo(mContext.getPackageManager(),
2414 STOCK_PM_FLAGS);
2415 if (aInfo != null) {
2416 intent.setComponent(new ComponentName(
2417 aInfo.applicationInfo.packageName, aInfo.name));
2418 // Don't do this if the home app is currently being
2419 // instrumented.
2420 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2421 aInfo.applicationInfo.uid);
2422 if (app == null || app.instrumentationClass == null) {
2423 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2424 startActivityLocked(null, intent, null, null, 0, aInfo,
2425 null, null, 0, 0, 0, false, false);
2426 }
2427 }
2428
2429
2430 return true;
2431 }
2432
2433 /**
2434 * Starts the "new version setup screen" if appropriate.
2435 */
2436 private void startSetupActivityLocked() {
2437 // Only do this once per boot.
2438 if (mCheckedForSetup) {
2439 return;
2440 }
2441
2442 // We will show this screen if the current one is a different
2443 // version than the last one shown, and we are not running in
2444 // low-level factory test mode.
2445 final ContentResolver resolver = mContext.getContentResolver();
2446 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2447 Settings.Secure.getInt(resolver,
2448 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2449 mCheckedForSetup = true;
2450
2451 // See if we should be showing the platform update setup UI.
2452 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2453 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2454 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2455
2456 // We don't allow third party apps to replace this.
2457 ResolveInfo ri = null;
2458 for (int i=0; ris != null && i<ris.size(); i++) {
2459 if ((ris.get(i).activityInfo.applicationInfo.flags
2460 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2461 ri = ris.get(i);
2462 break;
2463 }
2464 }
2465
2466 if (ri != null) {
2467 String vers = ri.activityInfo.metaData != null
2468 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2469 : null;
2470 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2471 vers = ri.activityInfo.applicationInfo.metaData.getString(
2472 Intent.METADATA_SETUP_VERSION);
2473 }
2474 String lastVers = Settings.Secure.getString(
2475 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2476 if (vers != null && !vers.equals(lastVers)) {
2477 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2478 intent.setComponent(new ComponentName(
2479 ri.activityInfo.packageName, ri.activityInfo.name));
2480 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2481 null, null, 0, 0, 0, false, false);
2482 }
2483 }
2484 }
2485 }
2486
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002487 private void reportResumedActivityLocked(HistoryRecord r) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002488 //Log.i(TAG, "**** REPORT RESUME: " + r);
2489
2490 final int identHash = System.identityHashCode(r);
2491 updateUsageStats(r, true);
2492
2493 int i = mWatchers.beginBroadcast();
2494 while (i > 0) {
2495 i--;
2496 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2497 if (w != null) {
2498 try {
2499 w.activityResuming(identHash);
2500 } catch (RemoteException e) {
2501 }
2502 }
2503 }
2504 mWatchers.finishBroadcast();
2505 }
2506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 /**
2508 * Ensure that the top activity in the stack is resumed.
2509 *
2510 * @param prev The previously resumed activity, for when in the process
2511 * of pausing; can be null to call from elsewhere.
2512 *
2513 * @return Returns true if something is being resumed, or false if
2514 * nothing happened.
2515 */
2516 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2517 // Find the first activity that is not finishing.
2518 HistoryRecord next = topRunningActivityLocked(null);
2519
2520 // Remember how we'll process this pause/resume situation, and ensure
2521 // that the state is reset however we wind up proceeding.
2522 final boolean userLeaving = mUserLeaving;
2523 mUserLeaving = false;
2524
2525 if (next == null) {
2526 // There are no more activities! Let's just start up the
2527 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002528 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 }
2530
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002531 next.delayedResume = false;
2532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 // If the top activity is the resumed one, nothing to do.
2534 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2535 // Make sure we have executed any pending transitions, since there
2536 // should be nothing left to do at this point.
2537 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002538 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 return false;
2540 }
2541
2542 // If we are sleeping, and there is no resumed activity, and the top
2543 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002544 if ((mSleeping || mShuttingDown)
2545 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 // Make sure we have executed any pending transitions, since there
2547 // should be nothing left to do at this point.
2548 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002549 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 return false;
2551 }
2552
2553 // The activity may be waiting for stop, but that is no longer
2554 // appropriate for it.
2555 mStoppingActivities.remove(next);
2556 mWaitingVisibleActivities.remove(next);
2557
2558 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2559
2560 // If we are currently pausing an activity, then don't do anything
2561 // until that is done.
2562 if (mPausingActivity != null) {
2563 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2564 return false;
2565 }
2566
2567 // We need to start pausing the current activity so the top one
2568 // can be resumed...
2569 if (mResumedActivity != null) {
2570 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2571 startPausingLocked(userLeaving, false);
2572 return true;
2573 }
2574
2575 if (prev != null && prev != next) {
2576 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2577 prev.waitingVisible = true;
2578 mWaitingVisibleActivities.add(prev);
2579 if (DEBUG_SWITCH) Log.v(
2580 TAG, "Resuming top, waiting visible to hide: " + prev);
2581 } else {
2582 // The next activity is already visible, so hide the previous
2583 // activity's windows right now so we can show the new one ASAP.
2584 // We only do this if the previous is finishing, which should mean
2585 // it is on top of the one being resumed so hiding it quickly
2586 // is good. Otherwise, we want to do the normal route of allowing
2587 // the resumed activity to be shown so we can decide if the
2588 // previous should actually be hidden depending on whether the
2589 // new one is found to be full-screen or not.
2590 if (prev.finishing) {
2591 mWindowManager.setAppVisibility(prev, false);
2592 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2593 + prev + ", waitingVisible="
2594 + (prev != null ? prev.waitingVisible : null)
2595 + ", nowVisible=" + next.nowVisible);
2596 } else {
2597 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2598 + prev + ", waitingVisible="
2599 + (prev != null ? prev.waitingVisible : null)
2600 + ", nowVisible=" + next.nowVisible);
2601 }
2602 }
2603 }
2604
2605 // We are starting up the next activity, so tell the window manager
2606 // that the previous one will be hidden soon. This way it can know
2607 // to ignore it when computing the desired screen orientation.
2608 if (prev != null) {
2609 if (prev.finishing) {
2610 if (DEBUG_TRANSITION) Log.v(TAG,
2611 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002612 if (mNoAnimActivities.contains(prev)) {
2613 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2614 } else {
2615 mWindowManager.prepareAppTransition(prev.task == next.task
2616 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2617 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 mWindowManager.setAppWillBeHidden(prev);
2620 mWindowManager.setAppVisibility(prev, false);
2621 } else {
2622 if (DEBUG_TRANSITION) Log.v(TAG,
2623 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002624 if (mNoAnimActivities.contains(next)) {
2625 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2626 } else {
2627 mWindowManager.prepareAppTransition(prev.task == next.task
2628 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2629 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 }
2632 if (false) {
2633 mWindowManager.setAppWillBeHidden(prev);
2634 mWindowManager.setAppVisibility(prev, false);
2635 }
2636 } else if (mHistory.size() > 1) {
2637 if (DEBUG_TRANSITION) Log.v(TAG,
2638 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002639 if (mNoAnimActivities.contains(next)) {
2640 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2641 } else {
2642 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 }
2645
2646 if (next.app != null && next.app.thread != null) {
2647 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2648
2649 // This activity is now becoming visible.
2650 mWindowManager.setAppVisibility(next, true);
2651
2652 HistoryRecord lastResumedActivity = mResumedActivity;
2653 ActivityState lastState = next.state;
2654
2655 updateCpuStats();
2656
2657 next.state = ActivityState.RESUMED;
2658 mResumedActivity = next;
2659 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002660 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 updateLRUListLocked(next);
2662
2663 // Have the window manager re-evaluate the orientation of
2664 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002665 boolean updated;
2666 synchronized (this) {
2667 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2668 mConfiguration,
2669 next.mayFreezeScreenLocked(next.app) ? next : null);
2670 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002671 next.frozenBeforeDestroy = true;
2672 }
2673 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002675 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 // The configuration update wasn't able to keep the existing
2677 // instance of the activity, and instead started a new one.
2678 // We should be all done, but let's just make sure our activity
2679 // is still at the top and schedule another run if something
2680 // weird happened.
2681 HistoryRecord nextNext = topRunningActivityLocked(null);
2682 if (DEBUG_SWITCH) Log.i(TAG,
2683 "Activity config changed during resume: " + next
2684 + ", new next: " + nextNext);
2685 if (nextNext != next) {
2686 // Do over!
2687 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2688 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002689 setFocusedActivityLocked(next);
2690 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002692 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 return true;
2694 }
2695
2696 try {
2697 // Deliver all pending results.
2698 ArrayList a = next.results;
2699 if (a != null) {
2700 final int N = a.size();
2701 if (!next.finishing && N > 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002702 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 TAG, "Delivering results to " + next
2704 + ": " + a);
2705 next.app.thread.scheduleSendResult(next, a);
2706 }
2707 }
2708
2709 if (next.newIntents != null) {
2710 next.app.thread.scheduleNewIntent(next.newIntents, next);
2711 }
2712
Doug Zongker2bec3d42009-12-04 12:52:44 -08002713 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 System.identityHashCode(next),
2715 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716
2717 next.app.thread.scheduleResumeActivity(next,
2718 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 pauseIfSleepingLocked();
2721
2722 } catch (Exception e) {
2723 // Whoops, need to restart this activity!
2724 next.state = lastState;
2725 mResumedActivity = lastResumedActivity;
Dianne Hackborn03abb812010-01-04 18:43:19 -08002726 Log.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 if (!next.hasBeenLaunched) {
2728 next.hasBeenLaunched = true;
2729 } else {
2730 if (SHOW_APP_STARTING_ICON) {
2731 mWindowManager.setAppStartingWindow(
2732 next, next.packageName, next.theme,
2733 next.nonLocalizedLabel,
2734 next.labelRes, next.icon, null, true);
2735 }
2736 }
2737 startSpecificActivityLocked(next, true, false);
2738 return true;
2739 }
2740
2741 // From this point on, if something goes wrong there is no way
2742 // to recover the activity.
2743 try {
2744 next.visible = true;
2745 completeResumeLocked(next);
2746 } catch (Exception e) {
2747 // If any exception gets thrown, toss away this
2748 // activity and try the next one.
2749 Log.w(TAG, "Exception thrown during resume of " + next, e);
2750 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2751 "resume-exception");
2752 return true;
2753 }
2754
2755 // Didn't need to use the icicle, and it is now out of date.
2756 next.icicle = null;
2757 next.haveState = false;
2758 next.stopped = false;
2759
2760 } else {
2761 // Whoops, need to restart this activity!
2762 if (!next.hasBeenLaunched) {
2763 next.hasBeenLaunched = true;
2764 } else {
2765 if (SHOW_APP_STARTING_ICON) {
2766 mWindowManager.setAppStartingWindow(
2767 next, next.packageName, next.theme,
2768 next.nonLocalizedLabel,
2769 next.labelRes, next.icon, null, true);
2770 }
2771 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2772 }
2773 startSpecificActivityLocked(next, true, true);
2774 }
2775
2776 return true;
2777 }
2778
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002779 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2780 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 final int NH = mHistory.size();
2782
2783 int addPos = -1;
2784
2785 if (!newTask) {
2786 // If starting in an existing task, find where that is...
2787 HistoryRecord next = null;
2788 boolean startIt = true;
2789 for (int i = NH-1; i >= 0; i--) {
2790 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2791 if (p.finishing) {
2792 continue;
2793 }
2794 if (p.task == r.task) {
2795 // Here it is! Now, if this is not yet visible to the
2796 // user, then just add it without starting; it will
2797 // get started when the user navigates back to it.
2798 addPos = i+1;
2799 if (!startIt) {
2800 mHistory.add(addPos, r);
2801 r.inHistory = true;
2802 r.task.numActivities++;
2803 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2804 r.info.screenOrientation, r.fullscreen);
2805 if (VALIDATE_TOKENS) {
2806 mWindowManager.validateAppTokens(mHistory);
2807 }
2808 return;
2809 }
2810 break;
2811 }
2812 if (p.fullscreen) {
2813 startIt = false;
2814 }
2815 next = p;
2816 }
2817 }
2818
2819 // Place a new activity at top of stack, so it is next to interact
2820 // with the user.
2821 if (addPos < 0) {
2822 addPos = mHistory.size();
2823 }
2824
2825 // If we are not placing the new activity frontmost, we do not want
2826 // to deliver the onUserLeaving callback to the actual frontmost
2827 // activity
2828 if (addPos < NH) {
2829 mUserLeaving = false;
2830 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2831 }
2832
2833 // Slot the activity into the history stack and proceed
2834 mHistory.add(addPos, r);
2835 r.inHistory = true;
2836 r.frontOfTask = newTask;
2837 r.task.numActivities++;
2838 if (NH > 0) {
2839 // We want to show the starting preview window if we are
2840 // switching to a new task, or the next activity's process is
2841 // not currently running.
2842 boolean showStartingIcon = newTask;
2843 ProcessRecord proc = r.app;
2844 if (proc == null) {
2845 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2846 }
2847 if (proc == null || proc.thread == null) {
2848 showStartingIcon = true;
2849 }
2850 if (DEBUG_TRANSITION) Log.v(TAG,
2851 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002852 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2853 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2854 mNoAnimActivities.add(r);
2855 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2856 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2857 mNoAnimActivities.remove(r);
2858 } else {
2859 mWindowManager.prepareAppTransition(newTask
2860 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2861 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2862 mNoAnimActivities.remove(r);
2863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 mWindowManager.addAppToken(
2865 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2866 boolean doShow = true;
2867 if (newTask) {
2868 // Even though this activity is starting fresh, we still need
2869 // to reset it to make sure we apply affinities to move any
2870 // existing activities from other tasks in to it.
2871 // If the caller has requested that the target task be
2872 // reset, then do so.
2873 if ((r.intent.getFlags()
2874 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2875 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002876 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 }
2878 }
2879 if (SHOW_APP_STARTING_ICON && doShow) {
2880 // Figure out if we are transitioning from another activity that is
2881 // "has the same starting icon" as the next one. This allows the
2882 // window manager to keep the previous window it had previously
2883 // created, if it still had one.
2884 HistoryRecord prev = mResumedActivity;
2885 if (prev != null) {
2886 // We don't want to reuse the previous starting preview if:
2887 // (1) The current activity is in a different task.
2888 if (prev.task != r.task) prev = null;
2889 // (2) The current activity is already displayed.
2890 else if (prev.nowVisible) prev = null;
2891 }
2892 mWindowManager.setAppStartingWindow(
2893 r, r.packageName, r.theme, r.nonLocalizedLabel,
2894 r.labelRes, r.icon, prev, showStartingIcon);
2895 }
2896 } else {
2897 // If this is the first activity, don't do any fancy animations,
2898 // because there is nothing for it to animate on top of.
2899 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2900 r.info.screenOrientation, r.fullscreen);
2901 }
2902 if (VALIDATE_TOKENS) {
2903 mWindowManager.validateAppTokens(mHistory);
2904 }
2905
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002906 if (doResume) {
2907 resumeTopActivityLocked(null);
2908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909 }
2910
2911 /**
2912 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002913 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2914 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 * an instance of that activity in the stack and, if found, finish all
2916 * activities on top of it and return the instance.
2917 *
2918 * @param newR Description of the new activity being started.
2919 * @return Returns the old activity that should be continue to be used,
2920 * or null if none was found.
2921 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002922 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002923 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002925
2926 // First find the requested task.
2927 while (i > 0) {
2928 i--;
2929 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2930 if (r.task.taskId == taskId) {
2931 i++;
2932 break;
2933 }
2934 }
2935
2936 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 while (i > 0) {
2938 i--;
2939 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2940 if (r.finishing) {
2941 continue;
2942 }
2943 if (r.task.taskId != taskId) {
2944 return null;
2945 }
2946 if (r.realActivity.equals(newR.realActivity)) {
2947 // Here it is! Now finish everything in front...
2948 HistoryRecord ret = r;
2949 if (doClear) {
2950 while (i < (mHistory.size()-1)) {
2951 i++;
2952 r = (HistoryRecord)mHistory.get(i);
2953 if (r.finishing) {
2954 continue;
2955 }
2956 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2957 null, "clear")) {
2958 i--;
2959 }
2960 }
2961 }
2962
2963 // Finally, if this is a normal launch mode (that is, not
2964 // expecting onNewIntent()), then we will finish the current
2965 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002966 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2967 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002969 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 if (index >= 0) {
2971 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2972 null, "clear");
2973 }
2974 return null;
2975 }
2976 }
2977
2978 return ret;
2979 }
2980 }
2981
2982 return null;
2983 }
2984
2985 /**
2986 * Find the activity in the history stack within the given task. Returns
2987 * the index within the history at which it's found, or < 0 if not found.
2988 */
2989 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
2990 int i = mHistory.size();
2991 while (i > 0) {
2992 i--;
2993 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
2994 if (candidate.task.taskId != task) {
2995 break;
2996 }
2997 if (candidate.realActivity.equals(r.realActivity)) {
2998 return i;
2999 }
3000 }
3001
3002 return -1;
3003 }
3004
3005 /**
3006 * Reorder the history stack so that the activity at the given index is
3007 * brought to the front.
3008 */
3009 private final HistoryRecord moveActivityToFrontLocked(int where) {
3010 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3011 int top = mHistory.size();
3012 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3013 mHistory.add(top, newTop);
3014 oldTop.frontOfTask = false;
3015 newTop.frontOfTask = true;
3016 return newTop;
3017 }
3018
3019 /**
3020 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3021 * method will be called at the proper time.
3022 */
3023 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3024 boolean sent = false;
3025 if (r.state == ActivityState.RESUMED
3026 && r.app != null && r.app.thread != null) {
3027 try {
3028 ArrayList<Intent> ar = new ArrayList<Intent>();
3029 ar.add(new Intent(intent));
3030 r.app.thread.scheduleNewIntent(ar, r);
3031 sent = true;
3032 } catch (Exception e) {
3033 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
3034 }
3035 }
3036 if (!sent) {
3037 r.addNewIntentLocked(new Intent(intent));
3038 }
3039 }
3040
3041 private final void logStartActivity(int tag, HistoryRecord r,
3042 TaskRecord task) {
3043 EventLog.writeEvent(tag,
3044 System.identityHashCode(r), task.taskId,
3045 r.shortComponentName, r.intent.getAction(),
3046 r.intent.getType(), r.intent.getDataString(),
3047 r.intent.getFlags());
3048 }
3049
3050 private final int startActivityLocked(IApplicationThread caller,
3051 Intent intent, String resolvedType,
3052 Uri[] grantedUriPermissions,
3053 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3054 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003055 int callingPid, int callingUid, boolean onlyIfNeeded,
3056 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 Log.i(TAG, "Starting activity: " + intent);
3058
3059 HistoryRecord sourceRecord = null;
3060 HistoryRecord resultRecord = null;
3061 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003062 int index = indexOfTokenLocked(resultTo);
The Android Open Source Project10592532009-03-18 17:39:46 -07003063 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3065 if (index >= 0) {
3066 sourceRecord = (HistoryRecord)mHistory.get(index);
3067 if (requestCode >= 0 && !sourceRecord.finishing) {
3068 resultRecord = sourceRecord;
3069 }
3070 }
3071 }
3072
3073 int launchFlags = intent.getFlags();
3074
3075 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3076 && sourceRecord != null) {
3077 // Transfer the result target from the source activity to the new
3078 // one being started, including any failures.
3079 if (requestCode >= 0) {
3080 return START_FORWARD_AND_REQUEST_CONFLICT;
3081 }
3082 resultRecord = sourceRecord.resultTo;
3083 resultWho = sourceRecord.resultWho;
3084 requestCode = sourceRecord.requestCode;
3085 sourceRecord.resultTo = null;
3086 if (resultRecord != null) {
3087 resultRecord.removeResultsLocked(
3088 sourceRecord, resultWho, requestCode);
3089 }
3090 }
3091
3092 int err = START_SUCCESS;
3093
3094 if (intent.getComponent() == null) {
3095 // We couldn't find a class that can handle the given Intent.
3096 // That's the end of that!
3097 err = START_INTENT_NOT_RESOLVED;
3098 }
3099
3100 if (err == START_SUCCESS && aInfo == null) {
3101 // We couldn't find the specific class specified in the Intent.
3102 // Also the end of the line.
3103 err = START_CLASS_NOT_FOUND;
3104 }
3105
3106 ProcessRecord callerApp = null;
3107 if (err == START_SUCCESS && caller != null) {
3108 callerApp = getRecordForAppLocked(caller);
3109 if (callerApp != null) {
3110 callingPid = callerApp.pid;
3111 callingUid = callerApp.info.uid;
3112 } else {
3113 Log.w(TAG, "Unable to find app for caller " + caller
3114 + " (pid=" + callingPid + ") when starting: "
3115 + intent.toString());
3116 err = START_PERMISSION_DENIED;
3117 }
3118 }
3119
3120 if (err != START_SUCCESS) {
3121 if (resultRecord != null) {
3122 sendActivityResultLocked(-1,
3123 resultRecord, resultWho, requestCode,
3124 Activity.RESULT_CANCELED, null);
3125 }
3126 return err;
3127 }
3128
3129 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3130 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3131 if (perm != PackageManager.PERMISSION_GRANTED) {
3132 if (resultRecord != null) {
3133 sendActivityResultLocked(-1,
3134 resultRecord, resultWho, requestCode,
3135 Activity.RESULT_CANCELED, null);
3136 }
3137 String msg = "Permission Denial: starting " + intent.toString()
3138 + " from " + callerApp + " (pid=" + callingPid
3139 + ", uid=" + callingUid + ")"
3140 + " requires " + aInfo.permission;
3141 Log.w(TAG, msg);
3142 throw new SecurityException(msg);
3143 }
3144
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003145 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 boolean abort = false;
3147 try {
3148 // The Intent we give to the watcher has the extra data
3149 // stripped off, since it can contain private information.
3150 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003151 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003152 aInfo.applicationInfo.packageName);
3153 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003154 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 }
3156
3157 if (abort) {
3158 if (resultRecord != null) {
3159 sendActivityResultLocked(-1,
3160 resultRecord, resultWho, requestCode,
3161 Activity.RESULT_CANCELED, null);
3162 }
3163 // We pretend to the caller that it was really started, but
3164 // they will just get a cancel result.
3165 return START_SUCCESS;
3166 }
3167 }
3168
3169 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3170 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003171 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003173 if (mResumedActivity == null
3174 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3175 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3176 PendingActivityLaunch pal = new PendingActivityLaunch();
3177 pal.r = r;
3178 pal.sourceRecord = sourceRecord;
3179 pal.grantedUriPermissions = grantedUriPermissions;
3180 pal.grantedMode = grantedMode;
3181 pal.onlyIfNeeded = onlyIfNeeded;
3182 mPendingActivityLaunches.add(pal);
3183 return START_SWITCHES_CANCELED;
3184 }
3185 }
3186
3187 if (mDidAppSwitch) {
3188 // This is the second allowed switch since we stopped switches,
3189 // so now just generally allow switches. Use case: user presses
3190 // home (switches disabled, switch to home, mDidAppSwitch now true);
3191 // user taps a home icon (coming from home so allowed, we hit here
3192 // and now allow anyone to switch again).
3193 mAppSwitchesAllowedTime = 0;
3194 } else {
3195 mDidAppSwitch = true;
3196 }
3197
3198 doPendingActivityLaunchesLocked(false);
3199
3200 return startActivityUncheckedLocked(r, sourceRecord,
3201 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3202 }
3203
3204 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3205 final int N = mPendingActivityLaunches.size();
3206 if (N <= 0) {
3207 return;
3208 }
3209 for (int i=0; i<N; i++) {
3210 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3211 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3212 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3213 doResume && i == (N-1));
3214 }
3215 mPendingActivityLaunches.clear();
3216 }
3217
3218 private final int startActivityUncheckedLocked(HistoryRecord r,
3219 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3220 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3221 final Intent intent = r.intent;
3222 final int callingUid = r.launchedFromUid;
3223
3224 int launchFlags = intent.getFlags();
3225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 // We'll invoke onUserLeaving before onPause only if the launching
3227 // activity did not explicitly state that this is an automated launch.
3228 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
3229 if (DEBUG_USER_LEAVING) Log.v(TAG,
3230 "startActivity() => mUserLeaving=" + mUserLeaving);
3231
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003232 // If the caller has asked not to resume at this point, we make note
3233 // of this in the record so that we can skip it when trying to find
3234 // the top running activity.
3235 if (!doResume) {
3236 r.delayedResume = true;
3237 }
3238
3239 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3240 != 0 ? r : null;
3241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 // If the onlyIfNeeded flag is set, then we can do this if the activity
3243 // being launched is the same as the one making the call... or, as
3244 // a special case, if we do not know the caller then we count the
3245 // current top activity as the caller.
3246 if (onlyIfNeeded) {
3247 HistoryRecord checkedCaller = sourceRecord;
3248 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003249 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 }
3251 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3252 // Caller is not the same as launcher, so always needed.
3253 onlyIfNeeded = false;
3254 }
3255 }
3256
3257 if (grantedUriPermissions != null && callingUid > 0) {
3258 for (int i=0; i<grantedUriPermissions.length; i++) {
3259 grantUriPermissionLocked(callingUid, r.packageName,
3260 grantedUriPermissions[i], grantedMode, r);
3261 }
3262 }
3263
3264 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3265 intent, r);
3266
3267 if (sourceRecord == null) {
3268 // This activity is not being started from another... in this
3269 // case we -always- start a new task.
3270 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
3271 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
3272 + intent);
3273 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3274 }
3275 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3276 // The original activity who is starting us is running as a single
3277 // instance... this new activity it is starting must go on its
3278 // own task.
3279 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3280 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3281 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3282 // The activity being started is a single instance... it always
3283 // gets launched into its own task.
3284 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3285 }
3286
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003287 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 // For whatever reason this activity is being launched into a new
3289 // task... yet the caller has requested a result back. Well, that
3290 // is pretty messed up, so instead immediately send back a cancel
3291 // and let the new task continue launched as normal without a
3292 // dependency on its originator.
3293 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3294 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003295 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 Activity.RESULT_CANCELED, null);
3297 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 }
3299
3300 boolean addingToTask = false;
3301 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3302 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3303 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3304 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3305 // If bring to front is requested, and no result is requested, and
3306 // we can find a task that was started with this same
3307 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003308 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 // See if there is a task to bring to the front. If this is
3310 // a SINGLE_INSTANCE activity, there can be one and only one
3311 // instance of it in the history, and it is always in its own
3312 // unique task, so we do a special search.
3313 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3314 ? findTaskLocked(intent, r.info)
3315 : findActivityLocked(intent, r.info);
3316 if (taskTop != null) {
3317 if (taskTop.task.intent == null) {
3318 // This task was started because of movement of
3319 // the activity based on affinity... now that we
3320 // are actually launching it, we can assign the
3321 // base intent.
3322 taskTop.task.setIntent(intent, r.info);
3323 }
3324 // If the target task is not in the front, then we need
3325 // to bring it to the front... except... well, with
3326 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3327 // to have the same behavior as if a new instance was
3328 // being started, which means not bringing it to the front
3329 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003330 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 if (curTop.task != taskTop.task) {
3332 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3333 boolean callerAtFront = sourceRecord == null
3334 || curTop.task == sourceRecord.task;
3335 if (callerAtFront) {
3336 // We really do want to push this one into the
3337 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003338 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 }
3340 }
3341 // If the caller has requested that the target task be
3342 // reset, then do so.
3343 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3344 taskTop = resetTaskIfNeededLocked(taskTop, r);
3345 }
3346 if (onlyIfNeeded) {
3347 // We don't need to start a new activity, and
3348 // the client said not to do anything if that
3349 // is the case, so this is it! And for paranoia, make
3350 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003351 if (doResume) {
3352 resumeTopActivityLocked(null);
3353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 return START_RETURN_INTENT_TO_CALLER;
3355 }
3356 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3357 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3358 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3359 // In this situation we want to remove all activities
3360 // from the task up to the one being started. In most
3361 // cases this means we are resetting the task to its
3362 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003363 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003364 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 if (top != null) {
3366 if (top.frontOfTask) {
3367 // Activity aliases may mean we use different
3368 // intents for the top activity, so make sure
3369 // the task now has the identity of the new
3370 // intent.
3371 top.task.setIntent(r.intent, r.info);
3372 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003373 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 deliverNewIntentLocked(top, r.intent);
3375 } else {
3376 // A special case: we need to
3377 // start the activity because it is not currently
3378 // running, and the caller has asked to clear the
3379 // current task to have this activity at the top.
3380 addingToTask = true;
3381 // Now pretend like this activity is being started
3382 // by the top of its task, so it is put in the
3383 // right place.
3384 sourceRecord = taskTop;
3385 }
3386 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3387 // In this case the top activity on the task is the
3388 // same as the one being launched, so we take that
3389 // as a request to bring the task to the foreground.
3390 // If the top activity in the task is the root
3391 // activity, deliver this new intent to it if it
3392 // desires.
3393 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3394 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003395 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 if (taskTop.frontOfTask) {
3397 taskTop.task.setIntent(r.intent, r.info);
3398 }
3399 deliverNewIntentLocked(taskTop, r.intent);
3400 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3401 // In this case we are launching the root activity
3402 // of the task, but with a different intent. We
3403 // should start a new instance on top.
3404 addingToTask = true;
3405 sourceRecord = taskTop;
3406 }
3407 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3408 // In this case an activity is being launched in to an
3409 // existing task, without resetting that task. This
3410 // is typically the situation of launching an activity
3411 // from a notification or shortcut. We want to place
3412 // the new activity on top of the current task.
3413 addingToTask = true;
3414 sourceRecord = taskTop;
3415 } else if (!taskTop.task.rootWasReset) {
3416 // In this case we are launching in to an existing task
3417 // that has not yet been started from its front door.
3418 // The current task has been brought to the front.
3419 // Ideally, we'd probably like to place this new task
3420 // at the bottom of its stack, but that's a little hard
3421 // to do with the current organization of the code so
3422 // for now we'll just drop it.
3423 taskTop.task.setIntent(r.intent, r.info);
3424 }
3425 if (!addingToTask) {
3426 // We didn't do anything... but it was needed (a.k.a., client
3427 // don't use that intent!) And for paranoia, make
3428 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003429 if (doResume) {
3430 resumeTopActivityLocked(null);
3431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 return START_TASK_TO_FRONT;
3433 }
3434 }
3435 }
3436 }
3437
3438 //String uri = r.intent.toURI();
3439 //Intent intent2 = new Intent(uri);
3440 //Log.i(TAG, "Given intent: " + r.intent);
3441 //Log.i(TAG, "URI is: " + uri);
3442 //Log.i(TAG, "To intent: " + intent2);
3443
3444 if (r.packageName != null) {
3445 // If the activity being launched is the same as the one currently
3446 // at the top, then we need to check if it should only be launched
3447 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003448 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3449 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 if (top.realActivity.equals(r.realActivity)) {
3451 if (top.app != null && top.app.thread != null) {
3452 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3453 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3454 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003455 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 // For paranoia, make sure we have correctly
3457 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003458 if (doResume) {
3459 resumeTopActivityLocked(null);
3460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 if (onlyIfNeeded) {
3462 // We don't need to start a new activity, and
3463 // the client said not to do anything if that
3464 // is the case, so this is it!
3465 return START_RETURN_INTENT_TO_CALLER;
3466 }
3467 deliverNewIntentLocked(top, r.intent);
3468 return START_DELIVERED_TO_TOP;
3469 }
3470 }
3471 }
3472 }
3473
3474 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003475 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003477 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 Activity.RESULT_CANCELED, null);
3479 }
3480 return START_CLASS_NOT_FOUND;
3481 }
3482
3483 boolean newTask = false;
3484
3485 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003486 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3488 // todo: should do better management of integers.
3489 mCurTask++;
3490 if (mCurTask <= 0) {
3491 mCurTask = 1;
3492 }
3493 r.task = new TaskRecord(mCurTask, r.info, intent,
3494 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3495 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3496 + " in new task " + r.task);
3497 newTask = true;
3498 addRecentTask(r.task);
3499
3500 } else if (sourceRecord != null) {
3501 if (!addingToTask &&
3502 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3503 // In this case, we are adding the activity to an existing
3504 // task, but the caller has asked to clear that task if the
3505 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003506 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003507 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003509 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 deliverNewIntentLocked(top, r.intent);
3511 // For paranoia, make sure we have correctly
3512 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003513 if (doResume) {
3514 resumeTopActivityLocked(null);
3515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 return START_DELIVERED_TO_TOP;
3517 }
3518 } else if (!addingToTask &&
3519 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3520 // In this case, we are launching an activity in our own task
3521 // that may already be running somewhere in the history, and
3522 // we want to shuffle it to the front of the stack if so.
3523 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3524 if (where >= 0) {
3525 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003526 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003528 if (doResume) {
3529 resumeTopActivityLocked(null);
3530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 return START_DELIVERED_TO_TOP;
3532 }
3533 }
3534 // An existing activity is starting this new activity, so we want
3535 // to keep the new one in the same task as the one that is starting
3536 // it.
3537 r.task = sourceRecord.task;
3538 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3539 + " in existing task " + r.task);
3540
3541 } else {
3542 // This not being started from an existing activity, and not part
3543 // of a new task... just put it in the top task, though these days
3544 // this case should never happen.
3545 final int N = mHistory.size();
3546 HistoryRecord prev =
3547 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3548 r.task = prev != null
3549 ? prev.task
3550 : new TaskRecord(mCurTask, r.info, intent,
3551 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3552 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3553 + " in new guessed " + r.task);
3554 }
3555 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003556 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003558 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003559 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560 return START_SUCCESS;
3561 }
3562
3563 public final int startActivity(IApplicationThread caller,
3564 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3565 int grantedMode, IBinder resultTo,
3566 String resultWho, int requestCode, boolean onlyIfNeeded,
3567 boolean debug) {
3568 // Refuse possible leaked file descriptors
3569 if (intent != null && intent.hasFileDescriptors()) {
3570 throw new IllegalArgumentException("File descriptors passed in Intent");
3571 }
3572
The Android Open Source Project4df24232009-03-05 14:34:35 -08003573 final boolean componentSpecified = intent.getComponent() != null;
3574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 // Don't modify the client's object!
3576 intent = new Intent(intent);
3577
3578 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 ActivityInfo aInfo;
3580 try {
3581 ResolveInfo rInfo =
3582 ActivityThread.getPackageManager().resolveIntent(
3583 intent, resolvedType,
3584 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003585 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 aInfo = rInfo != null ? rInfo.activityInfo : null;
3587 } catch (RemoteException e) {
3588 aInfo = null;
3589 }
3590
3591 if (aInfo != null) {
3592 // Store the found target back into the intent, because now that
3593 // we have it we never want to do this again. For example, if the
3594 // user navigates back to this point in the history, we should
3595 // always restart the exact same activity.
3596 intent.setComponent(new ComponentName(
3597 aInfo.applicationInfo.packageName, aInfo.name));
3598
3599 // Don't debug things in the system process
3600 if (debug) {
3601 if (!aInfo.processName.equals("system")) {
3602 setDebugApp(aInfo.processName, true, false);
3603 }
3604 }
3605 }
3606
3607 synchronized(this) {
3608 final long origId = Binder.clearCallingIdentity();
3609 int res = startActivityLocked(caller, intent, resolvedType,
3610 grantedUriPermissions, grantedMode, aInfo,
3611 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003612 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 Binder.restoreCallingIdentity(origId);
3614 return res;
3615 }
3616 }
3617
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003618 public int startActivityIntentSender(IApplicationThread caller,
3619 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003620 IBinder resultTo, String resultWho, int requestCode,
3621 int flagsMask, int flagsValues) {
3622 // Refuse possible leaked file descriptors
3623 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3624 throw new IllegalArgumentException("File descriptors passed in Intent");
3625 }
3626
3627 IIntentSender sender = intent.getTarget();
3628 if (!(sender instanceof PendingIntentRecord)) {
3629 throw new IllegalArgumentException("Bad PendingIntent object");
3630 }
3631
3632 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003633
3634 synchronized (this) {
3635 // If this is coming from the currently resumed activity, it is
3636 // effectively saying that app switches are allowed at this point.
3637 if (mResumedActivity != null
3638 && mResumedActivity.info.applicationInfo.uid ==
3639 Binder.getCallingUid()) {
3640 mAppSwitchesAllowedTime = 0;
3641 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003642 }
3643
3644 return pir.sendInner(0, fillInIntent, resolvedType,
3645 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3646 }
3647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 public boolean startNextMatchingActivity(IBinder callingActivity,
3649 Intent intent) {
3650 // Refuse possible leaked file descriptors
3651 if (intent != null && intent.hasFileDescriptors() == true) {
3652 throw new IllegalArgumentException("File descriptors passed in Intent");
3653 }
3654
3655 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003656 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 if (index < 0) {
3658 return false;
3659 }
3660 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3661 if (r.app == null || r.app.thread == null) {
3662 // The caller is not running... d'oh!
3663 return false;
3664 }
3665 intent = new Intent(intent);
3666 // The caller is not allowed to change the data.
3667 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3668 // And we are resetting to find the next component...
3669 intent.setComponent(null);
3670
3671 ActivityInfo aInfo = null;
3672 try {
3673 List<ResolveInfo> resolves =
3674 ActivityThread.getPackageManager().queryIntentActivities(
3675 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003676 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677
3678 // Look for the original activity in the list...
3679 final int N = resolves != null ? resolves.size() : 0;
3680 for (int i=0; i<N; i++) {
3681 ResolveInfo rInfo = resolves.get(i);
3682 if (rInfo.activityInfo.packageName.equals(r.packageName)
3683 && rInfo.activityInfo.name.equals(r.info.name)) {
3684 // We found the current one... the next matching is
3685 // after it.
3686 i++;
3687 if (i<N) {
3688 aInfo = resolves.get(i).activityInfo;
3689 }
3690 break;
3691 }
3692 }
3693 } catch (RemoteException e) {
3694 }
3695
3696 if (aInfo == null) {
3697 // Nobody who is next!
3698 return false;
3699 }
3700
3701 intent.setComponent(new ComponentName(
3702 aInfo.applicationInfo.packageName, aInfo.name));
3703 intent.setFlags(intent.getFlags()&~(
3704 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3705 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3706 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3707 Intent.FLAG_ACTIVITY_NEW_TASK));
3708
3709 // Okay now we need to start the new activity, replacing the
3710 // currently running activity. This is a little tricky because
3711 // we want to start the new one as if the current one is finished,
3712 // but not finish the current one first so that there is no flicker.
3713 // And thus...
3714 final boolean wasFinishing = r.finishing;
3715 r.finishing = true;
3716
3717 // Propagate reply information over to the new activity.
3718 final HistoryRecord resultTo = r.resultTo;
3719 final String resultWho = r.resultWho;
3720 final int requestCode = r.requestCode;
3721 r.resultTo = null;
3722 if (resultTo != null) {
3723 resultTo.removeResultsLocked(r, resultWho, requestCode);
3724 }
3725
3726 final long origId = Binder.clearCallingIdentity();
3727 // XXX we are not dealing with propagating grantedUriPermissions...
3728 // those are not yet exposed to user code, so there is no need.
3729 int res = startActivityLocked(r.app.thread, intent,
3730 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003731 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 Binder.restoreCallingIdentity(origId);
3733
3734 r.finishing = wasFinishing;
3735 if (res != START_SUCCESS) {
3736 return false;
3737 }
3738 return true;
3739 }
3740 }
3741
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003742 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 Intent intent, String resolvedType, IBinder resultTo,
3744 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003745
3746 // This is so super not safe, that only the system (or okay root)
3747 // can do it.
3748 final int callingUid = Binder.getCallingUid();
3749 if (callingUid != 0 && callingUid != Process.myUid()) {
3750 throw new SecurityException(
3751 "startActivityInPackage only available to the system");
3752 }
3753
The Android Open Source Project4df24232009-03-05 14:34:35 -08003754 final boolean componentSpecified = intent.getComponent() != null;
3755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 // Don't modify the client's object!
3757 intent = new Intent(intent);
3758
3759 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 ActivityInfo aInfo;
3761 try {
3762 ResolveInfo rInfo =
3763 ActivityThread.getPackageManager().resolveIntent(
3764 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003765 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 aInfo = rInfo != null ? rInfo.activityInfo : null;
3767 } catch (RemoteException e) {
3768 aInfo = null;
3769 }
3770
3771 if (aInfo != null) {
3772 // Store the found target back into the intent, because now that
3773 // we have it we never want to do this again. For example, if the
3774 // user navigates back to this point in the history, we should
3775 // always restart the exact same activity.
3776 intent.setComponent(new ComponentName(
3777 aInfo.applicationInfo.packageName, aInfo.name));
3778 }
3779
3780 synchronized(this) {
3781 return startActivityLocked(null, intent, resolvedType,
3782 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003783 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 }
3785 }
3786
3787 private final void addRecentTask(TaskRecord task) {
3788 // Remove any existing entries that are the same kind of task.
3789 int N = mRecentTasks.size();
3790 for (int i=0; i<N; i++) {
3791 TaskRecord tr = mRecentTasks.get(i);
3792 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3793 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3794 mRecentTasks.remove(i);
3795 i--;
3796 N--;
3797 if (task.intent == null) {
3798 // If the new recent task we are adding is not fully
3799 // specified, then replace it with the existing recent task.
3800 task = tr;
3801 }
3802 }
3803 }
3804 if (N >= MAX_RECENT_TASKS) {
3805 mRecentTasks.remove(N-1);
3806 }
3807 mRecentTasks.add(0, task);
3808 }
3809
3810 public void setRequestedOrientation(IBinder token,
3811 int requestedOrientation) {
3812 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003813 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (index < 0) {
3815 return;
3816 }
3817 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3818 final long origId = Binder.clearCallingIdentity();
3819 mWindowManager.setAppOrientation(r, requestedOrientation);
3820 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003821 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 r.mayFreezeScreenLocked(r.app) ? r : null);
3823 if (config != null) {
3824 r.frozenBeforeDestroy = true;
3825 if (!updateConfigurationLocked(config, r)) {
3826 resumeTopActivityLocked(null);
3827 }
3828 }
3829 Binder.restoreCallingIdentity(origId);
3830 }
3831 }
3832
3833 public int getRequestedOrientation(IBinder token) {
3834 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003835 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 if (index < 0) {
3837 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3838 }
3839 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3840 return mWindowManager.getAppOrientation(r);
3841 }
3842 }
3843
3844 private final void stopActivityLocked(HistoryRecord r) {
3845 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3846 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3847 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3848 if (!r.finishing) {
3849 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3850 "no-history");
3851 }
3852 } else if (r.app != null && r.app.thread != null) {
3853 if (mFocusedActivity == r) {
3854 setFocusedActivityLocked(topRunningActivityLocked(null));
3855 }
3856 r.resumeKeyDispatchingLocked();
3857 try {
3858 r.stopped = false;
3859 r.state = ActivityState.STOPPING;
3860 if (DEBUG_VISBILITY) Log.v(
3861 TAG, "Stopping visible=" + r.visible + " for " + r);
3862 if (!r.visible) {
3863 mWindowManager.setAppVisibility(r, false);
3864 }
3865 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3866 } catch (Exception e) {
3867 // Maybe just ignore exceptions here... if the process
3868 // has crashed, our death notification will clean things
3869 // up.
3870 Log.w(TAG, "Exception thrown during pause", e);
3871 // Just in case, assume it to be stopped.
3872 r.stopped = true;
3873 r.state = ActivityState.STOPPED;
3874 if (r.configDestroy) {
3875 destroyActivityLocked(r, true);
3876 }
3877 }
3878 }
3879 }
3880
3881 /**
3882 * @return Returns true if the activity is being finished, false if for
3883 * some reason it is being left as-is.
3884 */
3885 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3886 Intent resultData, String reason) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003887 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 TAG, "Finishing activity: token=" + token
3889 + ", result=" + resultCode + ", data=" + resultData);
3890
Dianne Hackborn75b03852009-06-12 15:43:26 -07003891 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 if (index < 0) {
3893 return false;
3894 }
3895 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3896
3897 // Is this the last activity left?
3898 boolean lastActivity = true;
3899 for (int i=mHistory.size()-1; i>=0; i--) {
3900 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3901 if (!p.finishing && p != r) {
3902 lastActivity = false;
3903 break;
3904 }
3905 }
3906
3907 // If this is the last activity, but it is the home activity, then
3908 // just don't finish it.
3909 if (lastActivity) {
3910 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3911 return false;
3912 }
3913 }
3914
3915 finishActivityLocked(r, index, resultCode, resultData, reason);
3916 return true;
3917 }
3918
3919 /**
3920 * @return Returns true if this activity has been removed from the history
3921 * list, or false if it is still in the list and will be removed later.
3922 */
3923 private final boolean finishActivityLocked(HistoryRecord r, int index,
3924 int resultCode, Intent resultData, String reason) {
3925 if (r.finishing) {
3926 Log.w(TAG, "Duplicate finish request for " + r);
3927 return false;
3928 }
3929
3930 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08003931 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 System.identityHashCode(r),
3933 r.task.taskId, r.shortComponentName, reason);
3934 r.task.numActivities--;
3935 if (r.frontOfTask && index < (mHistory.size()-1)) {
3936 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3937 if (next.task == r.task) {
3938 next.frontOfTask = true;
3939 }
3940 }
3941
3942 r.pauseKeyDispatchingLocked();
3943 if (mFocusedActivity == r) {
3944 setFocusedActivityLocked(topRunningActivityLocked(null));
3945 }
3946
3947 // send the result
3948 HistoryRecord resultTo = r.resultTo;
3949 if (resultTo != null) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003950 if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
3951 + " who=" + r.resultWho + " req=" + r.requestCode
3952 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 if (r.info.applicationInfo.uid > 0) {
3954 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3955 r.packageName, resultData, r);
3956 }
3957 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3958 resultData);
3959 r.resultTo = null;
3960 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003961 else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962
3963 // Make sure this HistoryRecord is not holding on to other resources,
3964 // because clients have remote IPC references to this object so we
3965 // can't assume that will go away and want to avoid circular IPC refs.
3966 r.results = null;
3967 r.pendingResults = null;
3968 r.newIntents = null;
3969 r.icicle = null;
3970
3971 if (mPendingThumbnails.size() > 0) {
3972 // There are clients waiting to receive thumbnails so, in case
3973 // this is an activity that someone is waiting for, add it
3974 // to the pending list so we can correctly update the clients.
3975 mCancelledThumbnails.add(r);
3976 }
3977
3978 if (mResumedActivity == r) {
3979 boolean endTask = index <= 0
3980 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3981 if (DEBUG_TRANSITION) Log.v(TAG,
3982 "Prepare close transition: finishing " + r);
3983 mWindowManager.prepareAppTransition(endTask
3984 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3985 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
3986
3987 // Tell window manager to prepare for this one to be removed.
3988 mWindowManager.setAppVisibility(r, false);
3989
3990 if (mPausingActivity == null) {
3991 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
3992 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
3993 startPausingLocked(false, false);
3994 }
3995
3996 } else if (r.state != ActivityState.PAUSING) {
3997 // If the activity is PAUSING, we will complete the finish once
3998 // it is done pausing; else we can just directly finish it here.
3999 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
4000 return finishCurrentActivityLocked(r, index,
4001 FINISH_AFTER_PAUSE) == null;
4002 } else {
4003 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
4004 }
4005
4006 return false;
4007 }
4008
4009 private static final int FINISH_IMMEDIATELY = 0;
4010 private static final int FINISH_AFTER_PAUSE = 1;
4011 private static final int FINISH_AFTER_VISIBLE = 2;
4012
4013 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4014 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004015 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 if (index < 0) {
4017 return null;
4018 }
4019
4020 return finishCurrentActivityLocked(r, index, mode);
4021 }
4022
4023 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4024 int index, int mode) {
4025 // First things first: if this activity is currently visible,
4026 // and the resumed activity is not yet visible, then hold off on
4027 // finishing until the resumed one becomes visible.
4028 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4029 if (!mStoppingActivities.contains(r)) {
4030 mStoppingActivities.add(r);
4031 if (mStoppingActivities.size() > 3) {
4032 // If we already have a few activities waiting to stop,
4033 // then give up on things going idle and start clearing
4034 // them out.
4035 Message msg = Message.obtain();
4036 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4037 mHandler.sendMessage(msg);
4038 }
4039 }
4040 r.state = ActivityState.STOPPING;
4041 updateOomAdjLocked();
4042 return r;
4043 }
4044
4045 // make sure the record is cleaned out of other places.
4046 mStoppingActivities.remove(r);
4047 mWaitingVisibleActivities.remove(r);
4048 if (mResumedActivity == r) {
4049 mResumedActivity = null;
4050 }
4051 final ActivityState prevState = r.state;
4052 r.state = ActivityState.FINISHING;
4053
4054 if (mode == FINISH_IMMEDIATELY
4055 || prevState == ActivityState.STOPPED
4056 || prevState == ActivityState.INITIALIZING) {
4057 // If this activity is already stopped, we can just finish
4058 // it right now.
4059 return destroyActivityLocked(r, true) ? null : r;
4060 } else {
4061 // Need to go through the full pause cycle to get this
4062 // activity into the stopped state and then finish it.
4063 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
4064 mFinishingActivities.add(r);
4065 resumeTopActivityLocked(null);
4066 }
4067 return r;
4068 }
4069
4070 /**
4071 * This is the internal entry point for handling Activity.finish().
4072 *
4073 * @param token The Binder token referencing the Activity we want to finish.
4074 * @param resultCode Result code, if any, from this Activity.
4075 * @param resultData Result data (Intent), if any, from this Activity.
4076 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004077 * @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 -08004078 */
4079 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4080 // Refuse possible leaked file descriptors
4081 if (resultData != null && resultData.hasFileDescriptors() == true) {
4082 throw new IllegalArgumentException("File descriptors passed in Intent");
4083 }
4084
4085 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004086 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 // Find the first activity that is not finishing.
4088 HistoryRecord next = topRunningActivityLocked(token, 0);
4089 if (next != null) {
4090 // ask watcher if this is allowed
4091 boolean resumeOK = true;
4092 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004093 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004095 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096 }
4097
4098 if (!resumeOK) {
4099 return false;
4100 }
4101 }
4102 }
4103 final long origId = Binder.clearCallingIdentity();
4104 boolean res = requestFinishActivityLocked(token, resultCode,
4105 resultData, "app-request");
4106 Binder.restoreCallingIdentity(origId);
4107 return res;
4108 }
4109 }
4110
4111 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4112 String resultWho, int requestCode, int resultCode, Intent data) {
4113
4114 if (callingUid > 0) {
4115 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4116 data, r);
4117 }
4118
The Android Open Source Project10592532009-03-18 17:39:46 -07004119 if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
4120 + " : who=" + resultWho + " req=" + requestCode
4121 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4123 try {
4124 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4125 list.add(new ResultInfo(resultWho, requestCode,
4126 resultCode, data));
4127 r.app.thread.scheduleSendResult(r, list);
4128 return;
4129 } catch (Exception e) {
4130 Log.w(TAG, "Exception thrown sending result to " + r, e);
4131 }
4132 }
4133
4134 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4135 }
4136
4137 public final void finishSubActivity(IBinder token, String resultWho,
4138 int requestCode) {
4139 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004140 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 if (index < 0) {
4142 return;
4143 }
4144 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4145
4146 final long origId = Binder.clearCallingIdentity();
4147
4148 int i;
4149 for (i=mHistory.size()-1; i>=0; i--) {
4150 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4151 if (r.resultTo == self && r.requestCode == requestCode) {
4152 if ((r.resultWho == null && resultWho == null) ||
4153 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4154 finishActivityLocked(r, i,
4155 Activity.RESULT_CANCELED, null, "request-sub");
4156 }
4157 }
4158 }
4159
4160 Binder.restoreCallingIdentity(origId);
4161 }
4162 }
4163
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004164 public void overridePendingTransition(IBinder token, String packageName,
4165 int enterAnim, int exitAnim) {
4166 synchronized(this) {
4167 int index = indexOfTokenLocked(token);
4168 if (index < 0) {
4169 return;
4170 }
4171 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4172
4173 final long origId = Binder.clearCallingIdentity();
4174
4175 if (self.state == ActivityState.RESUMED
4176 || self.state == ActivityState.PAUSING) {
4177 mWindowManager.overridePendingAppTransition(packageName,
4178 enterAnim, exitAnim);
4179 }
4180
4181 Binder.restoreCallingIdentity(origId);
4182 }
4183 }
4184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 /**
4186 * Perform clean-up of service connections in an activity record.
4187 */
4188 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4189 // Throw away any services that have been bound by this activity.
4190 if (r.connections != null) {
4191 Iterator<ConnectionRecord> it = r.connections.iterator();
4192 while (it.hasNext()) {
4193 ConnectionRecord c = it.next();
4194 removeConnectionLocked(c, null, r);
4195 }
4196 r.connections = null;
4197 }
4198 }
4199
4200 /**
4201 * Perform the common clean-up of an activity record. This is called both
4202 * as part of destroyActivityLocked() (when destroying the client-side
4203 * representation) and cleaning things up as a result of its hosting
4204 * processing going away, in which case there is no remaining client-side
4205 * state to destroy so only the cleanup here is needed.
4206 */
4207 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4208 if (mResumedActivity == r) {
4209 mResumedActivity = null;
4210 }
4211 if (mFocusedActivity == r) {
4212 mFocusedActivity = null;
4213 }
4214
4215 r.configDestroy = false;
4216 r.frozenBeforeDestroy = false;
4217
4218 // Make sure this record is no longer in the pending finishes list.
4219 // This could happen, for example, if we are trimming activities
4220 // down to the max limit while they are still waiting to finish.
4221 mFinishingActivities.remove(r);
4222 mWaitingVisibleActivities.remove(r);
4223
4224 // Remove any pending results.
4225 if (r.finishing && r.pendingResults != null) {
4226 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4227 PendingIntentRecord rec = apr.get();
4228 if (rec != null) {
4229 cancelIntentSenderLocked(rec, false);
4230 }
4231 }
4232 r.pendingResults = null;
4233 }
4234
4235 if (cleanServices) {
4236 cleanUpActivityServicesLocked(r);
4237 }
4238
4239 if (mPendingThumbnails.size() > 0) {
4240 // There are clients waiting to receive thumbnails so, in case
4241 // this is an activity that someone is waiting for, add it
4242 // to the pending list so we can correctly update the clients.
4243 mCancelledThumbnails.add(r);
4244 }
4245
4246 // Get rid of any pending idle timeouts.
4247 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4248 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4249 }
4250
4251 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4252 if (r.state != ActivityState.DESTROYED) {
4253 mHistory.remove(r);
4254 r.inHistory = false;
4255 r.state = ActivityState.DESTROYED;
4256 mWindowManager.removeAppToken(r);
4257 if (VALIDATE_TOKENS) {
4258 mWindowManager.validateAppTokens(mHistory);
4259 }
4260 cleanUpActivityServicesLocked(r);
4261 removeActivityUriPermissionsLocked(r);
4262 }
4263 }
4264
4265 /**
4266 * Destroy the current CLIENT SIDE instance of an activity. This may be
4267 * called both when actually finishing an activity, or when performing
4268 * a configuration switch where we destroy the current client-side object
4269 * but then create a new client-side object for this same HistoryRecord.
4270 */
4271 private final boolean destroyActivityLocked(HistoryRecord r,
4272 boolean removeFromApp) {
4273 if (DEBUG_SWITCH) Log.v(
4274 TAG, "Removing activity: token=" + r
4275 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004276 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 System.identityHashCode(r),
4278 r.task.taskId, r.shortComponentName);
4279
4280 boolean removedFromHistory = false;
4281
4282 cleanUpActivityLocked(r, false);
4283
Dianne Hackborn03abb812010-01-04 18:43:19 -08004284 final boolean hadApp = r.app != null;
4285
4286 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 if (removeFromApp) {
4288 int idx = r.app.activities.indexOf(r);
4289 if (idx >= 0) {
4290 r.app.activities.remove(idx);
4291 }
4292 if (r.persistent) {
4293 decPersistentCountLocked(r.app);
4294 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004295 if (r.app.activities.size() == 0) {
4296 // No longer have activities, so update location in
4297 // LRU list.
4298 updateLruProcessLocked(r.app, true, false);
4299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300 }
4301
4302 boolean skipDestroy = false;
4303
4304 try {
4305 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
4306 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4307 r.configChangeFlags);
4308 } catch (Exception e) {
4309 // We can just ignore exceptions here... if the process
4310 // has crashed, our death notification will clean things
4311 // up.
4312 //Log.w(TAG, "Exception thrown during finish", e);
4313 if (r.finishing) {
4314 removeActivityFromHistoryLocked(r);
4315 removedFromHistory = true;
4316 skipDestroy = true;
4317 }
4318 }
4319
4320 r.app = null;
4321 r.nowVisible = false;
4322
4323 if (r.finishing && !skipDestroy) {
4324 r.state = ActivityState.DESTROYING;
4325 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4326 msg.obj = r;
4327 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4328 } else {
4329 r.state = ActivityState.DESTROYED;
4330 }
4331 } else {
4332 // remove this record from the history.
4333 if (r.finishing) {
4334 removeActivityFromHistoryLocked(r);
4335 removedFromHistory = true;
4336 } else {
4337 r.state = ActivityState.DESTROYED;
4338 }
4339 }
4340
4341 r.configChangeFlags = 0;
4342
Dianne Hackborn03abb812010-01-04 18:43:19 -08004343 if (!mLRUActivities.remove(r) && hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4345 }
4346
4347 return removedFromHistory;
4348 }
4349
Dianne Hackborn03abb812010-01-04 18:43:19 -08004350 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 int i = list.size();
4352 if (localLOGV) Log.v(
4353 TAG, "Removing app " + app + " from list " + list
4354 + " with " + i + " entries");
4355 while (i > 0) {
4356 i--;
4357 HistoryRecord r = (HistoryRecord)list.get(i);
4358 if (localLOGV) Log.v(
4359 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4360 if (r.app == app) {
4361 if (localLOGV) Log.v(TAG, "Removing this entry!");
4362 list.remove(i);
4363 }
4364 }
4365 }
4366
4367 /**
4368 * Main function for removing an existing process from the activity manager
4369 * as a result of that process going away. Clears out all connections
4370 * to the process.
4371 */
4372 private final void handleAppDiedLocked(ProcessRecord app,
4373 boolean restarting) {
4374 cleanUpApplicationRecordLocked(app, restarting, -1);
4375 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004376 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 }
4378
4379 // Just in case...
4380 if (mPausingActivity != null && mPausingActivity.app == app) {
4381 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
4382 mPausingActivity = null;
4383 }
4384 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4385 mLastPausedActivity = null;
4386 }
4387
4388 // Remove this application's activities from active lists.
4389 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4390 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4391 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4392 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4393
4394 boolean atTop = true;
4395 boolean hasVisibleActivities = false;
4396
4397 // Clean out the history list.
4398 int i = mHistory.size();
4399 if (localLOGV) Log.v(
4400 TAG, "Removing app " + app + " from history with " + i + " entries");
4401 while (i > 0) {
4402 i--;
4403 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4404 if (localLOGV) Log.v(
4405 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4406 if (r.app == app) {
4407 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4408 if (localLOGV) Log.v(
4409 TAG, "Removing this entry! frozen=" + r.haveState
4410 + " finishing=" + r.finishing);
4411 mHistory.remove(i);
4412
4413 r.inHistory = false;
4414 mWindowManager.removeAppToken(r);
4415 if (VALIDATE_TOKENS) {
4416 mWindowManager.validateAppTokens(mHistory);
4417 }
4418 removeActivityUriPermissionsLocked(r);
4419
4420 } else {
4421 // We have the current state for this activity, so
4422 // it can be restarted later when needed.
4423 if (localLOGV) Log.v(
4424 TAG, "Keeping entry, setting app to null");
4425 if (r.visible) {
4426 hasVisibleActivities = true;
4427 }
4428 r.app = null;
4429 r.nowVisible = false;
4430 if (!r.haveState) {
4431 r.icicle = null;
4432 }
4433 }
4434
4435 cleanUpActivityLocked(r, true);
4436 r.state = ActivityState.STOPPED;
4437 }
4438 atTop = false;
4439 }
4440
4441 app.activities.clear();
4442
4443 if (app.instrumentationClass != null) {
4444 Log.w(TAG, "Crash of app " + app.processName
4445 + " running instrumentation " + app.instrumentationClass);
4446 Bundle info = new Bundle();
4447 info.putString("shortMsg", "Process crashed.");
4448 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4449 }
4450
4451 if (!restarting) {
4452 if (!resumeTopActivityLocked(null)) {
4453 // If there was nothing to resume, and we are not already
4454 // restarting this process, but there is a visible activity that
4455 // is hosted by the process... then make sure all visible
4456 // activities are running, taking care of restarting this
4457 // process.
4458 if (hasVisibleActivities) {
4459 ensureActivitiesVisibleLocked(null, 0);
4460 }
4461 }
4462 }
4463 }
4464
4465 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4466 IBinder threadBinder = thread.asBinder();
4467
4468 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004469 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4470 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4472 return i;
4473 }
4474 }
4475 return -1;
4476 }
4477
4478 private final ProcessRecord getRecordForAppLocked(
4479 IApplicationThread thread) {
4480 if (thread == null) {
4481 return null;
4482 }
4483
4484 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004485 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 }
4487
4488 private final void appDiedLocked(ProcessRecord app, int pid,
4489 IApplicationThread thread) {
4490
4491 mProcDeaths[0]++;
4492
4493 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4494 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4495 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004496 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 if (localLOGV) Log.v(
4498 TAG, "Dying app: " + app + ", pid: " + pid
4499 + ", thread: " + thread.asBinder());
4500 boolean doLowMem = app.instrumentationClass == null;
4501 handleAppDiedLocked(app, false);
4502
4503 if (doLowMem) {
4504 // If there are no longer any background processes running,
4505 // and the app that died was not running instrumentation,
4506 // then tell everyone we are now low on memory.
4507 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004508 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4509 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4511 haveBg = true;
4512 break;
4513 }
4514 }
4515
4516 if (!haveBg) {
4517 Log.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004518 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004519 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004520 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4521 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004522 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004523 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4524 // The low memory report is overriding any current
4525 // state for a GC request. Make sure to do
4526 // visible/foreground processes first.
4527 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4528 rec.lastRequestedGc = 0;
4529 } else {
4530 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004532 rec.reportLowMemory = true;
4533 rec.lastLowMemory = now;
4534 mProcessesToGc.remove(rec);
4535 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
4537 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004538 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 }
4540 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004541 } else if (DEBUG_PROCESSES) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004542 Log.d(TAG, "Received spurious death notification for thread "
4543 + thread.asBinder());
4544 }
4545 }
4546
Dan Egnor42471dd2010-01-07 17:25:22 -08004547 /**
4548 * If a stack trace dump file is configured, dump process stack traces.
4549 * @param pids of dalvik VM processes to dump stack traces for
4550 * @return file containing stack traces, or null if no dump file is configured
4551 */
4552 private static File dumpStackTraces(ArrayList<Integer> pids) {
4553 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4554 if (tracesPath == null || tracesPath.length() == 0) {
4555 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004557
4558 File tracesFile = new File(tracesPath);
4559 try {
4560 File tracesDir = tracesFile.getParentFile();
4561 if (!tracesDir.exists()) tracesFile.mkdirs();
4562 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4563
4564 if (tracesFile.exists()) tracesFile.delete();
4565 tracesFile.createNewFile();
4566 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4567 } catch (IOException e) {
4568 Log.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
4569 return null;
4570 }
4571
4572 // Use a FileObserver to detect when traces finish writing.
4573 // The order of traces is considered important to maintain for legibility.
4574 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4575 public synchronized void onEvent(int event, String path) { notify(); }
4576 };
4577
4578 try {
4579 observer.startWatching();
4580 int num = pids.size();
4581 for (int i = 0; i < num; i++) {
4582 synchronized (observer) {
4583 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4584 observer.wait(200); // Wait for write-close, give up after 200msec
4585 }
4586 }
4587 } catch (InterruptedException e) {
4588 Log.wtf(TAG, e);
4589 } finally {
4590 observer.stopWatching();
4591 }
4592
4593 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 }
4595
Dan Egnor42471dd2010-01-07 17:25:22 -08004596 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4597 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 if (app.notResponding || app.crashing) {
4599 return;
4600 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004603 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4604 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605
Dan Egnor42471dd2010-01-07 17:25:22 -08004606 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4607 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4608 pids.add(app.pid);
4609
4610 int parentPid = app.pid;
4611 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4612 if (parentPid != app.pid) pids.add(parentPid);
4613
4614 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4615
4616 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4617 ProcessRecord r = mLruProcesses.get(i);
4618 if (r != null && r.thread != null) {
4619 int pid = r.pid;
4620 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 }
4622 }
4623
Dan Egnor42471dd2010-01-07 17:25:22 -08004624 File tracesFile = dumpStackTraces(pids);
4625
4626 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004627 StringBuilder info = mStringBuilder;
4628 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004629 info.append("ANR in ").append(app.processName);
4630 if (activity != null && activity.shortComponentName != null) {
4631 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004632 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004633 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004635 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004637 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004638 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640
Dan Egnor42471dd2010-01-07 17:25:22 -08004641 String cpuInfo = null;
4642 if (MONITOR_CPU_USAGE) {
4643 updateCpuStatsNow();
4644 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4645 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 }
4647
Dan Egnor42471dd2010-01-07 17:25:22 -08004648 Log.e(TAG, info.toString());
4649 if (tracesFile == null) {
4650 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4651 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4652 }
4653
4654 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4655
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004656 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004658 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4659 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004660 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004661 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4662 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 }
4664 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004665 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 }
4667 }
4668
Dan Egnor42471dd2010-01-07 17:25:22 -08004669 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4670 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4671 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4672 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4673 Process.killProcess(app.pid);
4674 return;
4675 }
4676
4677 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 makeAppNotRespondingLocked(app,
4679 activity != null ? activity.shortComponentName : null,
4680 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004681 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004682
4683 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 Message msg = Message.obtain();
4685 HashMap map = new HashMap();
4686 msg.what = SHOW_NOT_RESPONDING_MSG;
4687 msg.obj = map;
4688 map.put("app", app);
4689 if (activity != null) {
4690 map.put("activity", activity);
4691 }
4692
4693 mHandler.sendMessage(msg);
4694 return;
4695 }
4696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 private final void decPersistentCountLocked(ProcessRecord app)
4698 {
4699 app.persistentActivities--;
4700 if (app.persistentActivities > 0) {
4701 // Still more of 'em...
4702 return;
4703 }
4704 if (app.persistent) {
4705 // Ah, but the application itself is persistent. Whatever!
4706 return;
4707 }
4708
4709 // App is no longer persistent... make sure it and the ones
4710 // following it in the LRU list have the correc oom_adj.
4711 updateOomAdjLocked();
4712 }
4713
4714 public void setPersistent(IBinder token, boolean isPersistent) {
4715 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4716 != PackageManager.PERMISSION_GRANTED) {
4717 String msg = "Permission Denial: setPersistent() from pid="
4718 + Binder.getCallingPid()
4719 + ", uid=" + Binder.getCallingUid()
4720 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4721 Log.w(TAG, msg);
4722 throw new SecurityException(msg);
4723 }
4724
4725 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004726 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 if (index < 0) {
4728 return;
4729 }
4730 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4731 ProcessRecord app = r.app;
4732
4733 if (localLOGV) Log.v(
4734 TAG, "Setting persistence " + isPersistent + ": " + r);
4735
4736 if (isPersistent) {
4737 if (r.persistent) {
4738 // Okay okay, I heard you already!
4739 if (localLOGV) Log.v(TAG, "Already persistent!");
4740 return;
4741 }
4742 r.persistent = true;
4743 app.persistentActivities++;
4744 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4745 if (app.persistentActivities > 1) {
4746 // We aren't the first...
4747 if (localLOGV) Log.v(TAG, "Not the first!");
4748 return;
4749 }
4750 if (app.persistent) {
4751 // This would be redundant.
4752 if (localLOGV) Log.v(TAG, "App is persistent!");
4753 return;
4754 }
4755
4756 // App is now persistent... make sure it and the ones
4757 // following it now have the correct oom_adj.
4758 final long origId = Binder.clearCallingIdentity();
4759 updateOomAdjLocked();
4760 Binder.restoreCallingIdentity(origId);
4761
4762 } else {
4763 if (!r.persistent) {
4764 // Okay okay, I heard you already!
4765 return;
4766 }
4767 r.persistent = false;
4768 final long origId = Binder.clearCallingIdentity();
4769 decPersistentCountLocked(app);
4770 Binder.restoreCallingIdentity(origId);
4771
4772 }
4773 }
4774 }
4775
4776 public boolean clearApplicationUserData(final String packageName,
4777 final IPackageDataObserver observer) {
4778 int uid = Binder.getCallingUid();
4779 int pid = Binder.getCallingPid();
4780 long callingId = Binder.clearCallingIdentity();
4781 try {
4782 IPackageManager pm = ActivityThread.getPackageManager();
4783 int pkgUid = -1;
4784 synchronized(this) {
4785 try {
4786 pkgUid = pm.getPackageUid(packageName);
4787 } catch (RemoteException e) {
4788 }
4789 if (pkgUid == -1) {
4790 Log.w(TAG, "Invalid packageName:" + packageName);
4791 return false;
4792 }
4793 if (uid == pkgUid || checkComponentPermission(
4794 android.Manifest.permission.CLEAR_APP_USER_DATA,
4795 pid, uid, -1)
4796 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004797 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 } else {
4799 throw new SecurityException(pid+" does not have permission:"+
4800 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4801 "for process:"+packageName);
4802 }
4803 }
4804
4805 try {
4806 //clear application user data
4807 pm.clearApplicationUserData(packageName, observer);
4808 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4809 Uri.fromParts("package", packageName, null));
4810 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4811 broadcastIntentLocked(null, null, intent,
4812 null, null, 0, null, null, null,
4813 false, false, MY_PID, Process.SYSTEM_UID);
4814 } catch (RemoteException e) {
4815 }
4816 } finally {
4817 Binder.restoreCallingIdentity(callingId);
4818 }
4819 return true;
4820 }
4821
Dianne Hackborn03abb812010-01-04 18:43:19 -08004822 public void killBackgroundProcesses(final String packageName) {
4823 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4824 != PackageManager.PERMISSION_GRANTED &&
4825 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4826 != PackageManager.PERMISSION_GRANTED) {
4827 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 + Binder.getCallingPid()
4829 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004830 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 Log.w(TAG, msg);
4832 throw new SecurityException(msg);
4833 }
4834
4835 long callingId = Binder.clearCallingIdentity();
4836 try {
4837 IPackageManager pm = ActivityThread.getPackageManager();
4838 int pkgUid = -1;
4839 synchronized(this) {
4840 try {
4841 pkgUid = pm.getPackageUid(packageName);
4842 } catch (RemoteException e) {
4843 }
4844 if (pkgUid == -1) {
4845 Log.w(TAG, "Invalid packageName: " + packageName);
4846 return;
4847 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004848 killPackageProcessesLocked(packageName, pkgUid,
4849 SECONDARY_SERVER_ADJ, false);
4850 }
4851 } finally {
4852 Binder.restoreCallingIdentity(callingId);
4853 }
4854 }
4855
4856 public void forceStopPackage(final String packageName) {
4857 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4858 != PackageManager.PERMISSION_GRANTED) {
4859 String msg = "Permission Denial: forceStopPackage() from pid="
4860 + Binder.getCallingPid()
4861 + ", uid=" + Binder.getCallingUid()
4862 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4863 Log.w(TAG, msg);
4864 throw new SecurityException(msg);
4865 }
4866
4867 long callingId = Binder.clearCallingIdentity();
4868 try {
4869 IPackageManager pm = ActivityThread.getPackageManager();
4870 int pkgUid = -1;
4871 synchronized(this) {
4872 try {
4873 pkgUid = pm.getPackageUid(packageName);
4874 } catch (RemoteException e) {
4875 }
4876 if (pkgUid == -1) {
4877 Log.w(TAG, "Invalid packageName: " + packageName);
4878 return;
4879 }
4880 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 }
4882 } finally {
4883 Binder.restoreCallingIdentity(callingId);
4884 }
4885 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004886
4887 /*
4888 * The pkg name and uid have to be specified.
4889 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4890 */
4891 public void killApplicationWithUid(String pkg, int uid) {
4892 if (pkg == null) {
4893 return;
4894 }
4895 // Make sure the uid is valid.
4896 if (uid < 0) {
4897 Log.w(TAG, "Invalid uid specified for pkg : " + pkg);
4898 return;
4899 }
4900 int callerUid = Binder.getCallingUid();
4901 // Only the system server can kill an application
4902 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004903 // Post an aysnc message to kill the application
4904 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4905 msg.arg1 = uid;
4906 msg.arg2 = 0;
4907 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004908 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004909 } else {
4910 throw new SecurityException(callerUid + " cannot kill pkg: " +
4911 pkg);
4912 }
4913 }
4914
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004915 public void closeSystemDialogs(String reason) {
4916 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
4917 if (reason != null) {
4918 intent.putExtra("reason", reason);
4919 }
4920
4921 final int uid = Binder.getCallingUid();
4922 final long origId = Binder.clearCallingIdentity();
4923 synchronized (this) {
4924 int i = mWatchers.beginBroadcast();
4925 while (i > 0) {
4926 i--;
4927 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4928 if (w != null) {
4929 try {
4930 w.closingSystemDialogs(reason);
4931 } catch (RemoteException e) {
4932 }
4933 }
4934 }
4935 mWatchers.finishBroadcast();
4936
Dianne Hackbornffa42482009-09-23 22:20:11 -07004937 mWindowManager.closeSystemDialogs(reason);
4938
4939 for (i=mHistory.size()-1; i>=0; i--) {
4940 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4941 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4942 finishActivityLocked(r, i,
4943 Activity.RESULT_CANCELED, null, "close-sys");
4944 }
4945 }
4946
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004947 broadcastIntentLocked(null, null, intent, null,
4948 null, 0, null, null, null, false, false, -1, uid);
4949 }
4950 Binder.restoreCallingIdentity(origId);
4951 }
4952
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004953 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004954 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004955 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4956 for (int i=pids.length-1; i>=0; i--) {
4957 infos[i] = new Debug.MemoryInfo();
4958 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004959 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004960 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004961 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004962
4963 public void killApplicationProcess(String processName, int uid) {
4964 if (processName == null) {
4965 return;
4966 }
4967
4968 int callerUid = Binder.getCallingUid();
4969 // Only the system server can kill an application
4970 if (callerUid == Process.SYSTEM_UID) {
4971 synchronized (this) {
4972 ProcessRecord app = getProcessRecordLocked(processName, uid);
4973 if (app != null) {
4974 try {
4975 app.thread.scheduleSuicide();
4976 } catch (RemoteException e) {
4977 // If the other end already died, then our work here is done.
4978 }
4979 } else {
4980 Log.w(TAG, "Process/uid not found attempting kill of "
4981 + processName + " / " + uid);
4982 }
4983 }
4984 } else {
4985 throw new SecurityException(callerUid + " cannot kill app process: " +
4986 processName);
4987 }
4988 }
4989
Dianne Hackborn03abb812010-01-04 18:43:19 -08004990 private void forceStopPackageLocked(final String packageName, int uid) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004991 forceStopPackageLocked(packageName, uid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4993 Uri.fromParts("package", packageName, null));
4994 intent.putExtra(Intent.EXTRA_UID, uid);
4995 broadcastIntentLocked(null, null, intent,
4996 null, null, 0, null, null, null,
4997 false, false, MY_PID, Process.SYSTEM_UID);
4998 }
4999
Dianne Hackborn03abb812010-01-04 18:43:19 -08005000 private final void killPackageProcessesLocked(String packageName, int uid,
5001 int minOomAdj, boolean callerWillRestart) {
5002 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003
Dianne Hackborn03abb812010-01-04 18:43:19 -08005004 // Remove all processes this package may have touched: all with the
5005 // same UID (except for the system or root user), and all whose name
5006 // matches the package name.
5007 final String procNamePrefix = packageName + ":";
5008 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5009 final int NA = apps.size();
5010 for (int ia=0; ia<NA; ia++) {
5011 ProcessRecord app = apps.valueAt(ia);
5012 if (app.removed) {
5013 procs.add(app);
5014 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5015 || app.processName.equals(packageName)
5016 || app.processName.startsWith(procNamePrefix)) {
5017 if (app.setAdj >= minOomAdj) {
5018 app.removed = true;
5019 procs.add(app);
5020 }
5021 }
5022 }
5023 }
5024
5025 int N = procs.size();
5026 for (int i=0; i<N; i++) {
5027 removeProcessLocked(procs.get(i), callerWillRestart);
5028 }
5029 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005030
Dianne Hackborn03abb812010-01-04 18:43:19 -08005031 private final void forceStopPackageLocked(String name, int uid,
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005032 boolean callerWillRestart, boolean purgeCache) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 int i, N;
5034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 if (uid < 0) {
5036 try {
5037 uid = ActivityThread.getPackageManager().getPackageUid(name);
5038 } catch (RemoteException e) {
5039 }
5040 }
5041
Dianne Hackborn03abb812010-01-04 18:43:19 -08005042 Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
5043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5045 while (badApps.hasNext()) {
5046 SparseArray<Long> ba = badApps.next();
5047 if (ba.get(uid) != null) {
5048 badApps.remove();
5049 }
5050 }
5051
Dianne Hackborn03abb812010-01-04 18:43:19 -08005052 killPackageProcessesLocked(name, uid, -100, callerWillRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053
5054 for (i=mHistory.size()-1; i>=0; i--) {
5055 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5056 if (r.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005057 Log.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 if (r.app != null) {
5059 r.app.removed = true;
5060 }
5061 r.app = null;
5062 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5063 }
5064 }
5065
5066 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5067 for (ServiceRecord service : mServices.values()) {
5068 if (service.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005069 Log.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 if (service.app != null) {
5071 service.app.removed = true;
5072 }
5073 service.app = null;
5074 services.add(service);
5075 }
5076 }
5077
5078 N = services.size();
5079 for (i=0; i<N; i++) {
5080 bringDownServiceLocked(services.get(i), true);
5081 }
5082
5083 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005084 if (purgeCache) {
5085 AttributeCache ac = AttributeCache.instance();
5086 if (ac != null) {
5087 ac.removePackage(name);
5088 }
5089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 }
5091
5092 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5093 final String name = app.processName;
5094 final int uid = app.info.uid;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005095 if (DEBUG_PROCESSES) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 TAG, "Force removing process " + app + " (" + name
5097 + "/" + uid + ")");
5098
5099 mProcessNames.remove(name, uid);
5100 boolean needRestart = false;
5101 if (app.pid > 0 && app.pid != MY_PID) {
5102 int pid = app.pid;
5103 synchronized (mPidsSelfLocked) {
5104 mPidsSelfLocked.remove(pid);
5105 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5106 }
5107 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005108 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 Process.killProcess(pid);
5110
5111 if (app.persistent) {
5112 if (!callerWillRestart) {
5113 addAppLocked(app.info);
5114 } else {
5115 needRestart = true;
5116 }
5117 }
5118 } else {
5119 mRemovedProcesses.add(app);
5120 }
5121
5122 return needRestart;
5123 }
5124
5125 private final void processStartTimedOutLocked(ProcessRecord app) {
5126 final int pid = app.pid;
5127 boolean gone = false;
5128 synchronized (mPidsSelfLocked) {
5129 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5130 if (knownApp != null && knownApp.thread == null) {
5131 mPidsSelfLocked.remove(pid);
5132 gone = true;
5133 }
5134 }
5135
5136 if (gone) {
5137 Log.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005138 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005139 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005141 // Take care of any launching providers waiting for this process.
5142 checkAppInLaunchingProvidersLocked(app, true);
5143 // Take care of any services that are waiting for the process.
5144 for (int i=0; i<mPendingServices.size(); i++) {
5145 ServiceRecord sr = mPendingServices.get(i);
5146 if (app.info.uid == sr.appInfo.uid
5147 && app.processName.equals(sr.processName)) {
5148 Log.w(TAG, "Forcing bringing down service: " + sr);
5149 mPendingServices.remove(i);
5150 i--;
5151 bringDownServiceLocked(sr, true);
5152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005154 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005155 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
5156 Log.w(TAG, "Unattached app died before backup, skipping");
5157 try {
5158 IBackupManager bm = IBackupManager.Stub.asInterface(
5159 ServiceManager.getService(Context.BACKUP_SERVICE));
5160 bm.agentDisconnected(app.info.packageName);
5161 } catch (RemoteException e) {
5162 // Can't happen; the backup manager is local
5163 }
5164 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005165 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
5166 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
5167 mPendingBroadcast = null;
5168 scheduleBroadcastsLocked();
5169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 } else {
5171 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
5172 }
5173 }
5174
5175 private final boolean attachApplicationLocked(IApplicationThread thread,
5176 int pid) {
5177
5178 // Find the application record that is being attached... either via
5179 // the pid if we are running in multiple processes, or just pull the
5180 // next app record if we are emulating process with anonymous threads.
5181 ProcessRecord app;
5182 if (pid != MY_PID && pid >= 0) {
5183 synchronized (mPidsSelfLocked) {
5184 app = mPidsSelfLocked.get(pid);
5185 }
5186 } else if (mStartingProcesses.size() > 0) {
5187 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005188 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 } else {
5190 app = null;
5191 }
5192
5193 if (app == null) {
5194 Log.w(TAG, "No pending application record for pid " + pid
5195 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005196 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 if (pid > 0 && pid != MY_PID) {
5198 Process.killProcess(pid);
5199 } else {
5200 try {
5201 thread.scheduleExit();
5202 } catch (Exception e) {
5203 // Ignore exceptions.
5204 }
5205 }
5206 return false;
5207 }
5208
5209 // If this application record is still attached to a previous
5210 // process, clean it up now.
5211 if (app.thread != null) {
5212 handleAppDiedLocked(app, true);
5213 }
5214
5215 // Tell the process all about itself.
5216
5217 if (localLOGV) Log.v(
5218 TAG, "Binding process pid " + pid + " to record " + app);
5219
5220 String processName = app.processName;
5221 try {
5222 thread.asBinder().linkToDeath(new AppDeathRecipient(
5223 app, pid, thread), 0);
5224 } catch (RemoteException e) {
5225 app.resetPackageList();
5226 startProcessLocked(app, "link fail", processName);
5227 return false;
5228 }
5229
Doug Zongker2bec3d42009-12-04 12:52:44 -08005230 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231
5232 app.thread = thread;
5233 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005234 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5235 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 app.forcingToForeground = null;
5237 app.foregroundServices = false;
5238 app.debugging = false;
5239
5240 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5241
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005242 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5243 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005245 if (!normalMode) {
5246 Log.i(TAG, "Launching preboot mode app: " + app);
5247 }
5248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 if (localLOGV) Log.v(
5250 TAG, "New app record " + app
5251 + " thread=" + thread.asBinder() + " pid=" + pid);
5252 try {
5253 int testMode = IApplicationThread.DEBUG_OFF;
5254 if (mDebugApp != null && mDebugApp.equals(processName)) {
5255 testMode = mWaitForDebugger
5256 ? IApplicationThread.DEBUG_WAIT
5257 : IApplicationThread.DEBUG_ON;
5258 app.debugging = true;
5259 if (mDebugTransient) {
5260 mDebugApp = mOrigDebugApp;
5261 mWaitForDebugger = mOrigWaitForDebugger;
5262 }
5263 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005264
Christopher Tate181fafa2009-05-14 11:12:14 -07005265 // If the app is being launched for restore or full backup, set it up specially
5266 boolean isRestrictedBackupMode = false;
5267 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5268 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5269 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5270 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005271
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005272 ensurePackageDexOpt(app.instrumentationInfo != null
5273 ? app.instrumentationInfo.packageName
5274 : app.info.packageName);
5275 if (app.instrumentationClass != null) {
5276 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005277 }
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005278 if (DEBUG_CONFIGURATION) Log.v(TAG, "Binding proc "
5279 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005280 thread.bindApplication(processName, app.instrumentationInfo != null
5281 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 app.instrumentationClass, app.instrumentationProfileFile,
5283 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005284 isRestrictedBackupMode || !normalMode,
5285 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005286 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005287 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 } catch (Exception e) {
5289 // todo: Yikes! What should we do? For now we will try to
5290 // start another process, but that could easily get us in
5291 // an infinite loop of restarting processes...
5292 Log.w(TAG, "Exception thrown during bind!", e);
5293
5294 app.resetPackageList();
5295 startProcessLocked(app, "bind fail", processName);
5296 return false;
5297 }
5298
5299 // Remove this record from the list of starting applications.
5300 mPersistentStartingProcesses.remove(app);
5301 mProcessesOnHold.remove(app);
5302
5303 boolean badApp = false;
5304 boolean didSomething = false;
5305
5306 // See if the top visible activity is waiting to run in this process...
5307 HistoryRecord hr = topRunningActivityLocked(null);
5308 if (hr != null) {
5309 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5310 && processName.equals(hr.processName)) {
5311 try {
5312 if (realStartActivityLocked(hr, app, true, true)) {
5313 didSomething = true;
5314 }
5315 } catch (Exception e) {
5316 Log.w(TAG, "Exception in new application when starting activity "
5317 + hr.intent.getComponent().flattenToShortString(), e);
5318 badApp = true;
5319 }
5320 } else {
5321 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5322 }
5323 }
5324
5325 // Find any services that should be running in this process...
5326 if (!badApp && mPendingServices.size() > 0) {
5327 ServiceRecord sr = null;
5328 try {
5329 for (int i=0; i<mPendingServices.size(); i++) {
5330 sr = mPendingServices.get(i);
5331 if (app.info.uid != sr.appInfo.uid
5332 || !processName.equals(sr.processName)) {
5333 continue;
5334 }
5335
5336 mPendingServices.remove(i);
5337 i--;
5338 realStartServiceLocked(sr, app);
5339 didSomething = true;
5340 }
5341 } catch (Exception e) {
5342 Log.w(TAG, "Exception in new application when starting service "
5343 + sr.shortName, e);
5344 badApp = true;
5345 }
5346 }
5347
5348 // Check if the next broadcast receiver is in this process...
5349 BroadcastRecord br = mPendingBroadcast;
5350 if (!badApp && br != null && br.curApp == app) {
5351 try {
5352 mPendingBroadcast = null;
5353 processCurBroadcastLocked(br, app);
5354 didSomething = true;
5355 } catch (Exception e) {
5356 Log.w(TAG, "Exception in new application when starting receiver "
5357 + br.curComponent.flattenToShortString(), e);
5358 badApp = true;
5359 logBroadcastReceiverDiscard(br);
5360 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5361 br.resultExtras, br.resultAbort, true);
5362 scheduleBroadcastsLocked();
5363 }
5364 }
5365
Christopher Tate181fafa2009-05-14 11:12:14 -07005366 // Check whether the next backup agent is in this process...
5367 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
5368 if (DEBUG_BACKUP) Log.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005369 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005370 try {
5371 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5372 } catch (Exception e) {
5373 Log.w(TAG, "Exception scheduling backup agent creation: ");
5374 e.printStackTrace();
5375 }
5376 }
5377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 if (badApp) {
5379 // todo: Also need to kill application to deal with all
5380 // kinds of exceptions.
5381 handleAppDiedLocked(app, false);
5382 return false;
5383 }
5384
5385 if (!didSomething) {
5386 updateOomAdjLocked();
5387 }
5388
5389 return true;
5390 }
5391
5392 public final void attachApplication(IApplicationThread thread) {
5393 synchronized (this) {
5394 int callingPid = Binder.getCallingPid();
5395 final long origId = Binder.clearCallingIdentity();
5396 attachApplicationLocked(thread, callingPid);
5397 Binder.restoreCallingIdentity(origId);
5398 }
5399 }
5400
Dianne Hackborne88846e2009-09-30 21:34:25 -07005401 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005403 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 Binder.restoreCallingIdentity(origId);
5405 }
5406
5407 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5408 boolean remove) {
5409 int N = mStoppingActivities.size();
5410 if (N <= 0) return null;
5411
5412 ArrayList<HistoryRecord> stops = null;
5413
5414 final boolean nowVisible = mResumedActivity != null
5415 && mResumedActivity.nowVisible
5416 && !mResumedActivity.waitingVisible;
5417 for (int i=0; i<N; i++) {
5418 HistoryRecord s = mStoppingActivities.get(i);
5419 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
5420 + nowVisible + " waitingVisible=" + s.waitingVisible
5421 + " finishing=" + s.finishing);
5422 if (s.waitingVisible && nowVisible) {
5423 mWaitingVisibleActivities.remove(s);
5424 s.waitingVisible = false;
5425 if (s.finishing) {
5426 // If this activity is finishing, it is sitting on top of
5427 // everyone else but we now know it is no longer needed...
5428 // so get rid of it. Otherwise, we need to go through the
5429 // normal flow and hide it once we determine that it is
5430 // hidden by the activities in front of it.
5431 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
5432 mWindowManager.setAppVisibility(s, false);
5433 }
5434 }
5435 if (!s.waitingVisible && remove) {
5436 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
5437 if (stops == null) {
5438 stops = new ArrayList<HistoryRecord>();
5439 }
5440 stops.add(s);
5441 mStoppingActivities.remove(i);
5442 N--;
5443 i--;
5444 }
5445 }
5446
5447 return stops;
5448 }
5449
5450 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005451 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005452 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 mWindowManager.enableScreenAfterBoot();
5454 }
5455
Dianne Hackborne88846e2009-09-30 21:34:25 -07005456 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5457 Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
5459
5460 ArrayList<HistoryRecord> stops = null;
5461 ArrayList<HistoryRecord> finishes = null;
5462 ArrayList<HistoryRecord> thumbnails = null;
5463 int NS = 0;
5464 int NF = 0;
5465 int NT = 0;
5466 IApplicationThread sendThumbnail = null;
5467 boolean booting = false;
5468 boolean enableScreen = false;
5469
5470 synchronized (this) {
5471 if (token != null) {
5472 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5473 }
5474
5475 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005476 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 if (index >= 0) {
5478 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5479
Dianne Hackborne88846e2009-09-30 21:34:25 -07005480 // This is a hack to semi-deal with a race condition
5481 // in the client where it can be constructed with a
5482 // newer configuration from when we asked it to launch.
5483 // We'll update with whatever configuration it now says
5484 // it used to launch.
5485 if (config != null) {
5486 r.configuration = config;
5487 }
5488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 // No longer need to keep the device awake.
5490 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5491 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5492 mLaunchingActivity.release();
5493 }
5494
5495 // We are now idle. If someone is waiting for a thumbnail from
5496 // us, we can now deliver.
5497 r.idle = true;
5498 scheduleAppGcsLocked();
5499 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5500 sendThumbnail = r.app.thread;
5501 r.thumbnailNeeded = false;
5502 }
5503
5504 // If this activity is fullscreen, set up to hide those under it.
5505
5506 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
5507 ensureActivitiesVisibleLocked(null, 0);
5508
5509 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
5510 if (!mBooted && !fromTimeout) {
5511 mBooted = true;
5512 enableScreen = true;
5513 }
5514 }
5515
5516 // Atomically retrieve all of the other things to do.
5517 stops = processStoppingActivitiesLocked(true);
5518 NS = stops != null ? stops.size() : 0;
5519 if ((NF=mFinishingActivities.size()) > 0) {
5520 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5521 mFinishingActivities.clear();
5522 }
5523 if ((NT=mCancelledThumbnails.size()) > 0) {
5524 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5525 mCancelledThumbnails.clear();
5526 }
5527
5528 booting = mBooting;
5529 mBooting = false;
5530 }
5531
5532 int i;
5533
5534 // Send thumbnail if requested.
5535 if (sendThumbnail != null) {
5536 try {
5537 sendThumbnail.requestThumbnail(token);
5538 } catch (Exception e) {
5539 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5540 sendPendingThumbnail(null, token, null, null, true);
5541 }
5542 }
5543
5544 // Stop any activities that are scheduled to do so but have been
5545 // waiting for the next one to start.
5546 for (i=0; i<NS; i++) {
5547 HistoryRecord r = (HistoryRecord)stops.get(i);
5548 synchronized (this) {
5549 if (r.finishing) {
5550 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5551 } else {
5552 stopActivityLocked(r);
5553 }
5554 }
5555 }
5556
5557 // Finish any activities that are scheduled to do so but have been
5558 // waiting for the next one to start.
5559 for (i=0; i<NF; i++) {
5560 HistoryRecord r = (HistoryRecord)finishes.get(i);
5561 synchronized (this) {
5562 destroyActivityLocked(r, true);
5563 }
5564 }
5565
5566 // Report back to any thumbnail receivers.
5567 for (i=0; i<NT; i++) {
5568 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5569 sendPendingThumbnail(r, null, null, null, true);
5570 }
5571
5572 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005573 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 }
5575
5576 trimApplications();
5577 //dump();
5578 //mWindowManager.dump();
5579
5580 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 enableScreenAfterBoot();
5582 }
5583 }
5584
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005585 final void finishBooting() {
5586 // Ensure that any processes we had put on hold are now started
5587 // up.
5588 final int NP = mProcessesOnHold.size();
5589 if (NP > 0) {
5590 ArrayList<ProcessRecord> procs =
5591 new ArrayList<ProcessRecord>(mProcessesOnHold);
5592 for (int ip=0; ip<NP; ip++) {
5593 this.startProcessLocked(procs.get(ip), "on-hold", null);
5594 }
5595 }
5596 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5597 // Tell anyone interested that we are done booting!
5598 synchronized (this) {
5599 broadcastIntentLocked(null, null,
5600 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5601 null, null, 0, null, null,
5602 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5603 false, false, MY_PID, Process.SYSTEM_UID);
5604 }
5605 }
5606 }
5607
5608 final void ensureBootCompleted() {
5609 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005610 boolean enableScreen;
5611 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005612 booting = mBooting;
5613 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005614 enableScreen = !mBooted;
5615 mBooted = true;
5616 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005617
5618 if (booting) {
5619 finishBooting();
5620 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005621
5622 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005623 enableScreenAfterBoot();
5624 }
5625 }
5626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 public final void activityPaused(IBinder token, Bundle icicle) {
5628 // Refuse possible leaked file descriptors
5629 if (icicle != null && icicle.hasFileDescriptors()) {
5630 throw new IllegalArgumentException("File descriptors passed in Bundle");
5631 }
5632
5633 final long origId = Binder.clearCallingIdentity();
5634 activityPaused(token, icicle, false);
5635 Binder.restoreCallingIdentity(origId);
5636 }
5637
5638 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
5639 if (DEBUG_PAUSE) Log.v(
5640 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5641 + ", timeout=" + timeout);
5642
5643 HistoryRecord r = null;
5644
5645 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005646 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 if (index >= 0) {
5648 r = (HistoryRecord)mHistory.get(index);
5649 if (!timeout) {
5650 r.icicle = icicle;
5651 r.haveState = true;
5652 }
5653 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5654 if (mPausingActivity == r) {
5655 r.state = ActivityState.PAUSED;
5656 completePauseLocked();
5657 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005658 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 System.identityHashCode(r), r.shortComponentName,
5660 mPausingActivity != null
5661 ? mPausingActivity.shortComponentName : "(none)");
5662 }
5663 }
5664 }
5665 }
5666
5667 public final void activityStopped(IBinder token, Bitmap thumbnail,
5668 CharSequence description) {
5669 if (localLOGV) Log.v(
5670 TAG, "Activity stopped: token=" + token);
5671
5672 HistoryRecord r = null;
5673
5674 final long origId = Binder.clearCallingIdentity();
5675
5676 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005677 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 if (index >= 0) {
5679 r = (HistoryRecord)mHistory.get(index);
5680 r.thumbnail = thumbnail;
5681 r.description = description;
5682 r.stopped = true;
5683 r.state = ActivityState.STOPPED;
5684 if (!r.finishing) {
5685 if (r.configDestroy) {
5686 destroyActivityLocked(r, true);
5687 resumeTopActivityLocked(null);
5688 }
5689 }
5690 }
5691 }
5692
5693 if (r != null) {
5694 sendPendingThumbnail(r, null, null, null, false);
5695 }
5696
5697 trimApplications();
5698
5699 Binder.restoreCallingIdentity(origId);
5700 }
5701
5702 public final void activityDestroyed(IBinder token) {
5703 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
5704 synchronized (this) {
5705 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5706
Dianne Hackborn75b03852009-06-12 15:43:26 -07005707 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005708 if (index >= 0) {
5709 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5710 if (r.state == ActivityState.DESTROYING) {
5711 final long origId = Binder.clearCallingIdentity();
5712 removeActivityFromHistoryLocked(r);
5713 Binder.restoreCallingIdentity(origId);
5714 }
5715 }
5716 }
5717 }
5718
5719 public String getCallingPackage(IBinder token) {
5720 synchronized (this) {
5721 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005722 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 }
5724 }
5725
5726 public ComponentName getCallingActivity(IBinder token) {
5727 synchronized (this) {
5728 HistoryRecord r = getCallingRecordLocked(token);
5729 return r != null ? r.intent.getComponent() : null;
5730 }
5731 }
5732
5733 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005734 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 if (index >= 0) {
5736 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5737 if (r != null) {
5738 return r.resultTo;
5739 }
5740 }
5741 return null;
5742 }
5743
5744 public ComponentName getActivityClassForToken(IBinder token) {
5745 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005746 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747 if (index >= 0) {
5748 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5749 return r.intent.getComponent();
5750 }
5751 return null;
5752 }
5753 }
5754
5755 public String getPackageForToken(IBinder token) {
5756 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005757 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 if (index >= 0) {
5759 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5760 return r.packageName;
5761 }
5762 return null;
5763 }
5764 }
5765
5766 public IIntentSender getIntentSender(int type,
5767 String packageName, IBinder token, String resultWho,
5768 int requestCode, Intent intent, String resolvedType, int flags) {
5769 // Refuse possible leaked file descriptors
5770 if (intent != null && intent.hasFileDescriptors() == true) {
5771 throw new IllegalArgumentException("File descriptors passed in Intent");
5772 }
5773
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005774 if (type == INTENT_SENDER_BROADCAST) {
5775 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5776 throw new IllegalArgumentException(
5777 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5778 }
5779 }
5780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 synchronized(this) {
5782 int callingUid = Binder.getCallingUid();
5783 try {
5784 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5785 Process.supportsProcesses()) {
5786 int uid = ActivityThread.getPackageManager()
5787 .getPackageUid(packageName);
5788 if (uid != Binder.getCallingUid()) {
5789 String msg = "Permission Denial: getIntentSender() from pid="
5790 + Binder.getCallingPid()
5791 + ", uid=" + Binder.getCallingUid()
5792 + ", (need uid=" + uid + ")"
5793 + " is not allowed to send as package " + packageName;
5794 Log.w(TAG, msg);
5795 throw new SecurityException(msg);
5796 }
5797 }
5798 } catch (RemoteException e) {
5799 throw new SecurityException(e);
5800 }
5801 HistoryRecord activity = null;
5802 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005803 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005804 if (index < 0) {
5805 return null;
5806 }
5807 activity = (HistoryRecord)mHistory.get(index);
5808 if (activity.finishing) {
5809 return null;
5810 }
5811 }
5812
5813 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5814 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5815 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5816 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5817 |PendingIntent.FLAG_UPDATE_CURRENT);
5818
5819 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5820 type, packageName, activity, resultWho,
5821 requestCode, intent, resolvedType, flags);
5822 WeakReference<PendingIntentRecord> ref;
5823 ref = mIntentSenderRecords.get(key);
5824 PendingIntentRecord rec = ref != null ? ref.get() : null;
5825 if (rec != null) {
5826 if (!cancelCurrent) {
5827 if (updateCurrent) {
5828 rec.key.requestIntent.replaceExtras(intent);
5829 }
5830 return rec;
5831 }
5832 rec.canceled = true;
5833 mIntentSenderRecords.remove(key);
5834 }
5835 if (noCreate) {
5836 return rec;
5837 }
5838 rec = new PendingIntentRecord(this, key, callingUid);
5839 mIntentSenderRecords.put(key, rec.ref);
5840 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5841 if (activity.pendingResults == null) {
5842 activity.pendingResults
5843 = new HashSet<WeakReference<PendingIntentRecord>>();
5844 }
5845 activity.pendingResults.add(rec.ref);
5846 }
5847 return rec;
5848 }
5849 }
5850
5851 public void cancelIntentSender(IIntentSender sender) {
5852 if (!(sender instanceof PendingIntentRecord)) {
5853 return;
5854 }
5855 synchronized(this) {
5856 PendingIntentRecord rec = (PendingIntentRecord)sender;
5857 try {
5858 int uid = ActivityThread.getPackageManager()
5859 .getPackageUid(rec.key.packageName);
5860 if (uid != Binder.getCallingUid()) {
5861 String msg = "Permission Denial: cancelIntentSender() from pid="
5862 + Binder.getCallingPid()
5863 + ", uid=" + Binder.getCallingUid()
5864 + " is not allowed to cancel packges "
5865 + rec.key.packageName;
5866 Log.w(TAG, msg);
5867 throw new SecurityException(msg);
5868 }
5869 } catch (RemoteException e) {
5870 throw new SecurityException(e);
5871 }
5872 cancelIntentSenderLocked(rec, true);
5873 }
5874 }
5875
5876 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5877 rec.canceled = true;
5878 mIntentSenderRecords.remove(rec.key);
5879 if (cleanActivity && rec.key.activity != null) {
5880 rec.key.activity.pendingResults.remove(rec.ref);
5881 }
5882 }
5883
5884 public String getPackageForIntentSender(IIntentSender pendingResult) {
5885 if (!(pendingResult instanceof PendingIntentRecord)) {
5886 return null;
5887 }
5888 synchronized(this) {
5889 try {
5890 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5891 return res.key.packageName;
5892 } catch (ClassCastException e) {
5893 }
5894 }
5895 return null;
5896 }
5897
5898 public void setProcessLimit(int max) {
5899 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5900 "setProcessLimit()");
5901 mProcessLimit = max;
5902 }
5903
5904 public int getProcessLimit() {
5905 return mProcessLimit;
5906 }
5907
5908 void foregroundTokenDied(ForegroundToken token) {
5909 synchronized (ActivityManagerService.this) {
5910 synchronized (mPidsSelfLocked) {
5911 ForegroundToken cur
5912 = mForegroundProcesses.get(token.pid);
5913 if (cur != token) {
5914 return;
5915 }
5916 mForegroundProcesses.remove(token.pid);
5917 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5918 if (pr == null) {
5919 return;
5920 }
5921 pr.forcingToForeground = null;
5922 pr.foregroundServices = false;
5923 }
5924 updateOomAdjLocked();
5925 }
5926 }
5927
5928 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5929 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5930 "setProcessForeground()");
5931 synchronized(this) {
5932 boolean changed = false;
5933
5934 synchronized (mPidsSelfLocked) {
5935 ProcessRecord pr = mPidsSelfLocked.get(pid);
5936 if (pr == null) {
5937 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5938 return;
5939 }
5940 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5941 if (oldToken != null) {
5942 oldToken.token.unlinkToDeath(oldToken, 0);
5943 mForegroundProcesses.remove(pid);
5944 pr.forcingToForeground = null;
5945 changed = true;
5946 }
5947 if (isForeground && token != null) {
5948 ForegroundToken newToken = new ForegroundToken() {
5949 public void binderDied() {
5950 foregroundTokenDied(this);
5951 }
5952 };
5953 newToken.pid = pid;
5954 newToken.token = token;
5955 try {
5956 token.linkToDeath(newToken, 0);
5957 mForegroundProcesses.put(pid, newToken);
5958 pr.forcingToForeground = token;
5959 changed = true;
5960 } catch (RemoteException e) {
5961 // If the process died while doing this, we will later
5962 // do the cleanup with the process death link.
5963 }
5964 }
5965 }
5966
5967 if (changed) {
5968 updateOomAdjLocked();
5969 }
5970 }
5971 }
5972
5973 // =========================================================
5974 // PERMISSIONS
5975 // =========================================================
5976
5977 static class PermissionController extends IPermissionController.Stub {
5978 ActivityManagerService mActivityManagerService;
5979 PermissionController(ActivityManagerService activityManagerService) {
5980 mActivityManagerService = activityManagerService;
5981 }
5982
5983 public boolean checkPermission(String permission, int pid, int uid) {
5984 return mActivityManagerService.checkPermission(permission, pid,
5985 uid) == PackageManager.PERMISSION_GRANTED;
5986 }
5987 }
5988
5989 /**
5990 * This can be called with or without the global lock held.
5991 */
5992 int checkComponentPermission(String permission, int pid, int uid,
5993 int reqUid) {
5994 // We might be performing an operation on behalf of an indirect binder
5995 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
5996 // client identity accordingly before proceeding.
5997 Identity tlsIdentity = sCallerIdentity.get();
5998 if (tlsIdentity != null) {
5999 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
6000 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6001 uid = tlsIdentity.uid;
6002 pid = tlsIdentity.pid;
6003 }
6004
6005 // Root, system server and our own process get to do everything.
6006 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6007 !Process.supportsProcesses()) {
6008 return PackageManager.PERMISSION_GRANTED;
6009 }
6010 // If the target requires a specific UID, always fail for others.
6011 if (reqUid >= 0 && uid != reqUid) {
root0369a7c2009-03-23 15:20:47 +01006012 Log.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 return PackageManager.PERMISSION_DENIED;
6014 }
6015 if (permission == null) {
6016 return PackageManager.PERMISSION_GRANTED;
6017 }
6018 try {
6019 return ActivityThread.getPackageManager()
6020 .checkUidPermission(permission, uid);
6021 } catch (RemoteException e) {
6022 // Should never happen, but if it does... deny!
6023 Log.e(TAG, "PackageManager is dead?!?", e);
6024 }
6025 return PackageManager.PERMISSION_DENIED;
6026 }
6027
6028 /**
6029 * As the only public entry point for permissions checking, this method
6030 * can enforce the semantic that requesting a check on a null global
6031 * permission is automatically denied. (Internally a null permission
6032 * string is used when calling {@link #checkComponentPermission} in cases
6033 * when only uid-based security is needed.)
6034 *
6035 * This can be called with or without the global lock held.
6036 */
6037 public int checkPermission(String permission, int pid, int uid) {
6038 if (permission == null) {
6039 return PackageManager.PERMISSION_DENIED;
6040 }
6041 return checkComponentPermission(permission, pid, uid, -1);
6042 }
6043
6044 /**
6045 * Binder IPC calls go through the public entry point.
6046 * This can be called with or without the global lock held.
6047 */
6048 int checkCallingPermission(String permission) {
6049 return checkPermission(permission,
6050 Binder.getCallingPid(),
6051 Binder.getCallingUid());
6052 }
6053
6054 /**
6055 * This can be called with or without the global lock held.
6056 */
6057 void enforceCallingPermission(String permission, String func) {
6058 if (checkCallingPermission(permission)
6059 == PackageManager.PERMISSION_GRANTED) {
6060 return;
6061 }
6062
6063 String msg = "Permission Denial: " + func + " from pid="
6064 + Binder.getCallingPid()
6065 + ", uid=" + Binder.getCallingUid()
6066 + " requires " + permission;
6067 Log.w(TAG, msg);
6068 throw new SecurityException(msg);
6069 }
6070
6071 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6072 ProviderInfo pi, int uid, int modeFlags) {
6073 try {
6074 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6075 if ((pi.readPermission != null) &&
6076 (pm.checkUidPermission(pi.readPermission, uid)
6077 != PackageManager.PERMISSION_GRANTED)) {
6078 return false;
6079 }
6080 }
6081 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6082 if ((pi.writePermission != null) &&
6083 (pm.checkUidPermission(pi.writePermission, uid)
6084 != PackageManager.PERMISSION_GRANTED)) {
6085 return false;
6086 }
6087 }
6088 return true;
6089 } catch (RemoteException e) {
6090 return false;
6091 }
6092 }
6093
6094 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6095 int modeFlags) {
6096 // Root gets to do everything.
6097 if (uid == 0 || !Process.supportsProcesses()) {
6098 return true;
6099 }
6100 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6101 if (perms == null) return false;
6102 UriPermission perm = perms.get(uri);
6103 if (perm == null) return false;
6104 return (modeFlags&perm.modeFlags) == modeFlags;
6105 }
6106
6107 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6108 // Another redirected-binder-call permissions check as in
6109 // {@link checkComponentPermission}.
6110 Identity tlsIdentity = sCallerIdentity.get();
6111 if (tlsIdentity != null) {
6112 uid = tlsIdentity.uid;
6113 pid = tlsIdentity.pid;
6114 }
6115
6116 // Our own process gets to do everything.
6117 if (pid == MY_PID) {
6118 return PackageManager.PERMISSION_GRANTED;
6119 }
6120 synchronized(this) {
6121 return checkUriPermissionLocked(uri, uid, modeFlags)
6122 ? PackageManager.PERMISSION_GRANTED
6123 : PackageManager.PERMISSION_DENIED;
6124 }
6125 }
6126
6127 private void grantUriPermissionLocked(int callingUid,
6128 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6129 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6130 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6131 if (modeFlags == 0) {
6132 return;
6133 }
6134
6135 final IPackageManager pm = ActivityThread.getPackageManager();
6136
6137 // If this is not a content: uri, we can't do anything with it.
6138 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
6139 return;
6140 }
6141
6142 String name = uri.getAuthority();
6143 ProviderInfo pi = null;
6144 ContentProviderRecord cpr
6145 = (ContentProviderRecord)mProvidersByName.get(name);
6146 if (cpr != null) {
6147 pi = cpr.info;
6148 } else {
6149 try {
6150 pi = pm.resolveContentProvider(name,
6151 PackageManager.GET_URI_PERMISSION_PATTERNS);
6152 } catch (RemoteException ex) {
6153 }
6154 }
6155 if (pi == null) {
6156 Log.w(TAG, "No content provider found for: " + name);
6157 return;
6158 }
6159
6160 int targetUid;
6161 try {
6162 targetUid = pm.getPackageUid(targetPkg);
6163 if (targetUid < 0) {
6164 return;
6165 }
6166 } catch (RemoteException ex) {
6167 return;
6168 }
6169
6170 // First... does the target actually need this permission?
6171 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6172 // No need to grant the target this permission.
6173 return;
6174 }
6175
6176 // Second... maybe someone else has already granted the
6177 // permission?
6178 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
6179 // No need to grant the target this permission.
6180 return;
6181 }
6182
6183 // Third... is the provider allowing granting of URI permissions?
6184 if (!pi.grantUriPermissions) {
6185 throw new SecurityException("Provider " + pi.packageName
6186 + "/" + pi.name
6187 + " does not allow granting of Uri permissions (uri "
6188 + uri + ")");
6189 }
6190 if (pi.uriPermissionPatterns != null) {
6191 final int N = pi.uriPermissionPatterns.length;
6192 boolean allowed = false;
6193 for (int i=0; i<N; i++) {
6194 if (pi.uriPermissionPatterns[i] != null
6195 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6196 allowed = true;
6197 break;
6198 }
6199 }
6200 if (!allowed) {
6201 throw new SecurityException("Provider " + pi.packageName
6202 + "/" + pi.name
6203 + " does not allow granting of permission to path of Uri "
6204 + uri);
6205 }
6206 }
6207
6208 // Fourth... does the caller itself have permission to access
6209 // this uri?
6210 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6211 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6212 throw new SecurityException("Uid " + callingUid
6213 + " does not have permission to uri " + uri);
6214 }
6215 }
6216
6217 // Okay! So here we are: the caller has the assumed permission
6218 // to the uri, and the target doesn't. Let's now give this to
6219 // the target.
6220
6221 HashMap<Uri, UriPermission> targetUris
6222 = mGrantedUriPermissions.get(targetUid);
6223 if (targetUris == null) {
6224 targetUris = new HashMap<Uri, UriPermission>();
6225 mGrantedUriPermissions.put(targetUid, targetUris);
6226 }
6227
6228 UriPermission perm = targetUris.get(uri);
6229 if (perm == null) {
6230 perm = new UriPermission(targetUid, uri);
6231 targetUris.put(uri, perm);
6232
6233 }
6234 perm.modeFlags |= modeFlags;
6235 if (activity == null) {
6236 perm.globalModeFlags |= modeFlags;
6237 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6238 perm.readActivities.add(activity);
6239 if (activity.readUriPermissions == null) {
6240 activity.readUriPermissions = new HashSet<UriPermission>();
6241 }
6242 activity.readUriPermissions.add(perm);
6243 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6244 perm.writeActivities.add(activity);
6245 if (activity.writeUriPermissions == null) {
6246 activity.writeUriPermissions = new HashSet<UriPermission>();
6247 }
6248 activity.writeUriPermissions.add(perm);
6249 }
6250 }
6251
6252 private void grantUriPermissionFromIntentLocked(int callingUid,
6253 String targetPkg, Intent intent, HistoryRecord activity) {
6254 if (intent == null) {
6255 return;
6256 }
6257 Uri data = intent.getData();
6258 if (data == null) {
6259 return;
6260 }
6261 grantUriPermissionLocked(callingUid, targetPkg, data,
6262 intent.getFlags(), activity);
6263 }
6264
6265 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6266 Uri uri, int modeFlags) {
6267 synchronized(this) {
6268 final ProcessRecord r = getRecordForAppLocked(caller);
6269 if (r == null) {
6270 throw new SecurityException("Unable to find app for caller "
6271 + caller
6272 + " when granting permission to uri " + uri);
6273 }
6274 if (targetPkg == null) {
6275 Log.w(TAG, "grantUriPermission: null target");
6276 return;
6277 }
6278 if (uri == null) {
6279 Log.w(TAG, "grantUriPermission: null uri");
6280 return;
6281 }
6282
6283 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6284 null);
6285 }
6286 }
6287
6288 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6289 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6290 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6291 HashMap<Uri, UriPermission> perms
6292 = mGrantedUriPermissions.get(perm.uid);
6293 if (perms != null) {
6294 perms.remove(perm.uri);
6295 if (perms.size() == 0) {
6296 mGrantedUriPermissions.remove(perm.uid);
6297 }
6298 }
6299 }
6300 }
6301
6302 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6303 if (activity.readUriPermissions != null) {
6304 for (UriPermission perm : activity.readUriPermissions) {
6305 perm.readActivities.remove(activity);
6306 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6307 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6308 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6309 removeUriPermissionIfNeededLocked(perm);
6310 }
6311 }
6312 }
6313 if (activity.writeUriPermissions != null) {
6314 for (UriPermission perm : activity.writeUriPermissions) {
6315 perm.writeActivities.remove(activity);
6316 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6317 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6318 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6319 removeUriPermissionIfNeededLocked(perm);
6320 }
6321 }
6322 }
6323 }
6324
6325 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6326 int modeFlags) {
6327 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6328 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6329 if (modeFlags == 0) {
6330 return;
6331 }
6332
6333 final IPackageManager pm = ActivityThread.getPackageManager();
6334
6335 final String authority = uri.getAuthority();
6336 ProviderInfo pi = null;
6337 ContentProviderRecord cpr
6338 = (ContentProviderRecord)mProvidersByName.get(authority);
6339 if (cpr != null) {
6340 pi = cpr.info;
6341 } else {
6342 try {
6343 pi = pm.resolveContentProvider(authority,
6344 PackageManager.GET_URI_PERMISSION_PATTERNS);
6345 } catch (RemoteException ex) {
6346 }
6347 }
6348 if (pi == null) {
6349 Log.w(TAG, "No content provider found for: " + authority);
6350 return;
6351 }
6352
6353 // Does the caller have this permission on the URI?
6354 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6355 // Right now, if you are not the original owner of the permission,
6356 // you are not allowed to revoke it.
6357 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6358 throw new SecurityException("Uid " + callingUid
6359 + " does not have permission to uri " + uri);
6360 //}
6361 }
6362
6363 // Go through all of the permissions and remove any that match.
6364 final List<String> SEGMENTS = uri.getPathSegments();
6365 if (SEGMENTS != null) {
6366 final int NS = SEGMENTS.size();
6367 int N = mGrantedUriPermissions.size();
6368 for (int i=0; i<N; i++) {
6369 HashMap<Uri, UriPermission> perms
6370 = mGrantedUriPermissions.valueAt(i);
6371 Iterator<UriPermission> it = perms.values().iterator();
6372 toploop:
6373 while (it.hasNext()) {
6374 UriPermission perm = it.next();
6375 Uri targetUri = perm.uri;
6376 if (!authority.equals(targetUri.getAuthority())) {
6377 continue;
6378 }
6379 List<String> targetSegments = targetUri.getPathSegments();
6380 if (targetSegments == null) {
6381 continue;
6382 }
6383 if (targetSegments.size() < NS) {
6384 continue;
6385 }
6386 for (int j=0; j<NS; j++) {
6387 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6388 continue toploop;
6389 }
6390 }
6391 perm.clearModes(modeFlags);
6392 if (perm.modeFlags == 0) {
6393 it.remove();
6394 }
6395 }
6396 if (perms.size() == 0) {
6397 mGrantedUriPermissions.remove(
6398 mGrantedUriPermissions.keyAt(i));
6399 N--;
6400 i--;
6401 }
6402 }
6403 }
6404 }
6405
6406 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6407 int modeFlags) {
6408 synchronized(this) {
6409 final ProcessRecord r = getRecordForAppLocked(caller);
6410 if (r == null) {
6411 throw new SecurityException("Unable to find app for caller "
6412 + caller
6413 + " when revoking permission to uri " + uri);
6414 }
6415 if (uri == null) {
6416 Log.w(TAG, "revokeUriPermission: null uri");
6417 return;
6418 }
6419
6420 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6421 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6422 if (modeFlags == 0) {
6423 return;
6424 }
6425
6426 final IPackageManager pm = ActivityThread.getPackageManager();
6427
6428 final String authority = uri.getAuthority();
6429 ProviderInfo pi = null;
6430 ContentProviderRecord cpr
6431 = (ContentProviderRecord)mProvidersByName.get(authority);
6432 if (cpr != null) {
6433 pi = cpr.info;
6434 } else {
6435 try {
6436 pi = pm.resolveContentProvider(authority,
6437 PackageManager.GET_URI_PERMISSION_PATTERNS);
6438 } catch (RemoteException ex) {
6439 }
6440 }
6441 if (pi == null) {
6442 Log.w(TAG, "No content provider found for: " + authority);
6443 return;
6444 }
6445
6446 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6447 }
6448 }
6449
6450 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6451 synchronized (this) {
6452 ProcessRecord app =
6453 who != null ? getRecordForAppLocked(who) : null;
6454 if (app == null) return;
6455
6456 Message msg = Message.obtain();
6457 msg.what = WAIT_FOR_DEBUGGER_MSG;
6458 msg.obj = app;
6459 msg.arg1 = waiting ? 1 : 0;
6460 mHandler.sendMessage(msg);
6461 }
6462 }
6463
6464 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6465 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006466 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006468 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 }
6470
6471 // =========================================================
6472 // TASK MANAGEMENT
6473 // =========================================================
6474
6475 public List getTasks(int maxNum, int flags,
6476 IThumbnailReceiver receiver) {
6477 ArrayList list = new ArrayList();
6478
6479 PendingThumbnailsRecord pending = null;
6480 IApplicationThread topThumbnail = null;
6481 HistoryRecord topRecord = null;
6482
6483 synchronized(this) {
6484 if (localLOGV) Log.v(
6485 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6486 + ", receiver=" + receiver);
6487
6488 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6489 != PackageManager.PERMISSION_GRANTED) {
6490 if (receiver != null) {
6491 // If the caller wants to wait for pending thumbnails,
6492 // it ain't gonna get them.
6493 try {
6494 receiver.finished();
6495 } catch (RemoteException ex) {
6496 }
6497 }
6498 String msg = "Permission Denial: getTasks() from pid="
6499 + Binder.getCallingPid()
6500 + ", uid=" + Binder.getCallingUid()
6501 + " requires " + android.Manifest.permission.GET_TASKS;
6502 Log.w(TAG, msg);
6503 throw new SecurityException(msg);
6504 }
6505
6506 int pos = mHistory.size()-1;
6507 HistoryRecord next =
6508 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6509 HistoryRecord top = null;
6510 CharSequence topDescription = null;
6511 TaskRecord curTask = null;
6512 int numActivities = 0;
6513 int numRunning = 0;
6514 while (pos >= 0 && maxNum > 0) {
6515 final HistoryRecord r = next;
6516 pos--;
6517 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6518
6519 // Initialize state for next task if needed.
6520 if (top == null ||
6521 (top.state == ActivityState.INITIALIZING
6522 && top.task == r.task)) {
6523 top = r;
6524 topDescription = r.description;
6525 curTask = r.task;
6526 numActivities = numRunning = 0;
6527 }
6528
6529 // Add 'r' into the current task.
6530 numActivities++;
6531 if (r.app != null && r.app.thread != null) {
6532 numRunning++;
6533 }
6534 if (topDescription == null) {
6535 topDescription = r.description;
6536 }
6537
6538 if (localLOGV) Log.v(
6539 TAG, r.intent.getComponent().flattenToShortString()
6540 + ": task=" + r.task);
6541
6542 // If the next one is a different task, generate a new
6543 // TaskInfo entry for what we have.
6544 if (next == null || next.task != curTask) {
6545 ActivityManager.RunningTaskInfo ci
6546 = new ActivityManager.RunningTaskInfo();
6547 ci.id = curTask.taskId;
6548 ci.baseActivity = r.intent.getComponent();
6549 ci.topActivity = top.intent.getComponent();
6550 ci.thumbnail = top.thumbnail;
6551 ci.description = topDescription;
6552 ci.numActivities = numActivities;
6553 ci.numRunning = numRunning;
6554 //System.out.println(
6555 // "#" + maxNum + ": " + " descr=" + ci.description);
6556 if (ci.thumbnail == null && receiver != null) {
6557 if (localLOGV) Log.v(
6558 TAG, "State=" + top.state + "Idle=" + top.idle
6559 + " app=" + top.app
6560 + " thr=" + (top.app != null ? top.app.thread : null));
6561 if (top.state == ActivityState.RESUMED
6562 || top.state == ActivityState.PAUSING) {
6563 if (top.idle && top.app != null
6564 && top.app.thread != null) {
6565 topRecord = top;
6566 topThumbnail = top.app.thread;
6567 } else {
6568 top.thumbnailNeeded = true;
6569 }
6570 }
6571 if (pending == null) {
6572 pending = new PendingThumbnailsRecord(receiver);
6573 }
6574 pending.pendingRecords.add(top);
6575 }
6576 list.add(ci);
6577 maxNum--;
6578 top = null;
6579 }
6580 }
6581
6582 if (pending != null) {
6583 mPendingThumbnails.add(pending);
6584 }
6585 }
6586
6587 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
6588
6589 if (topThumbnail != null) {
6590 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
6591 try {
6592 topThumbnail.requestThumbnail(topRecord);
6593 } catch (Exception e) {
6594 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
6595 sendPendingThumbnail(null, topRecord, null, null, true);
6596 }
6597 }
6598
6599 if (pending == null && receiver != null) {
6600 // In this case all thumbnails were available and the client
6601 // is being asked to be told when the remaining ones come in...
6602 // which is unusually, since the top-most currently running
6603 // activity should never have a canned thumbnail! Oh well.
6604 try {
6605 receiver.finished();
6606 } catch (RemoteException ex) {
6607 }
6608 }
6609
6610 return list;
6611 }
6612
6613 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6614 int flags) {
6615 synchronized (this) {
6616 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6617 "getRecentTasks()");
6618
6619 final int N = mRecentTasks.size();
6620 ArrayList<ActivityManager.RecentTaskInfo> res
6621 = new ArrayList<ActivityManager.RecentTaskInfo>(
6622 maxNum < N ? maxNum : N);
6623 for (int i=0; i<N && maxNum > 0; i++) {
6624 TaskRecord tr = mRecentTasks.get(i);
6625 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6626 || (tr.intent == null)
6627 || ((tr.intent.getFlags()
6628 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6629 ActivityManager.RecentTaskInfo rti
6630 = new ActivityManager.RecentTaskInfo();
6631 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6632 rti.baseIntent = new Intent(
6633 tr.intent != null ? tr.intent : tr.affinityIntent);
6634 rti.origActivity = tr.origActivity;
6635 res.add(rti);
6636 maxNum--;
6637 }
6638 }
6639 return res;
6640 }
6641 }
6642
6643 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6644 int j;
6645 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6646 TaskRecord jt = startTask;
6647
6648 // First look backwards
6649 for (j=startIndex-1; j>=0; j--) {
6650 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6651 if (r.task != jt) {
6652 jt = r.task;
6653 if (affinity.equals(jt.affinity)) {
6654 return j;
6655 }
6656 }
6657 }
6658
6659 // Now look forwards
6660 final int N = mHistory.size();
6661 jt = startTask;
6662 for (j=startIndex+1; j<N; j++) {
6663 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6664 if (r.task != jt) {
6665 if (affinity.equals(jt.affinity)) {
6666 return j;
6667 }
6668 jt = r.task;
6669 }
6670 }
6671
6672 // Might it be at the top?
6673 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6674 return N-1;
6675 }
6676
6677 return -1;
6678 }
6679
6680 /**
6681 * Perform a reset of the given task, if needed as part of launching it.
6682 * Returns the new HistoryRecord at the top of the task.
6683 */
6684 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6685 HistoryRecord newActivity) {
6686 boolean forceReset = (newActivity.info.flags
6687 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6688 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6689 if ((newActivity.info.flags
6690 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6691 forceReset = true;
6692 }
6693 }
6694
6695 final TaskRecord task = taskTop.task;
6696
6697 // We are going to move through the history list so that we can look
6698 // at each activity 'target' with 'below' either the interesting
6699 // activity immediately below it in the stack or null.
6700 HistoryRecord target = null;
6701 int targetI = 0;
6702 int taskTopI = -1;
6703 int replyChainEnd = -1;
6704 int lastReparentPos = -1;
6705 for (int i=mHistory.size()-1; i>=-1; i--) {
6706 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6707
6708 if (below != null && below.finishing) {
6709 continue;
6710 }
6711 if (target == null) {
6712 target = below;
6713 targetI = i;
6714 // If we were in the middle of a reply chain before this
6715 // task, it doesn't appear like the root of the chain wants
6716 // anything interesting, so drop it.
6717 replyChainEnd = -1;
6718 continue;
6719 }
6720
6721 final int flags = target.info.flags;
6722
6723 final boolean finishOnTaskLaunch =
6724 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6725 final boolean allowTaskReparenting =
6726 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6727
6728 if (target.task == task) {
6729 // We are inside of the task being reset... we'll either
6730 // finish this activity, push it out for another task,
6731 // or leave it as-is. We only do this
6732 // for activities that are not the root of the task (since
6733 // if we finish the root, we may no longer have the task!).
6734 if (taskTopI < 0) {
6735 taskTopI = targetI;
6736 }
6737 if (below != null && below.task == task) {
6738 final boolean clearWhenTaskReset =
6739 (target.intent.getFlags()
6740 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006741 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 // If this activity is sending a reply to a previous
6743 // activity, we can't do anything with it now until
6744 // we reach the start of the reply chain.
6745 // XXX note that we are assuming the result is always
6746 // to the previous activity, which is almost always
6747 // the case but we really shouldn't count on.
6748 if (replyChainEnd < 0) {
6749 replyChainEnd = targetI;
6750 }
Ed Heyl73798232009-03-24 21:32:21 -07006751 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 && target.taskAffinity != null
6753 && !target.taskAffinity.equals(task.affinity)) {
6754 // If this activity has an affinity for another
6755 // task, then we need to move it out of here. We will
6756 // move it as far out of the way as possible, to the
6757 // bottom of the activity stack. This also keeps it
6758 // correctly ordered with any activities we previously
6759 // moved.
6760 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6761 if (target.taskAffinity != null
6762 && target.taskAffinity.equals(p.task.affinity)) {
6763 // If the activity currently at the bottom has the
6764 // same task affinity as the one we are moving,
6765 // then merge it into the same task.
6766 target.task = p.task;
6767 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6768 + " out to bottom task " + p.task);
6769 } else {
6770 mCurTask++;
6771 if (mCurTask <= 0) {
6772 mCurTask = 1;
6773 }
6774 target.task = new TaskRecord(mCurTask, target.info, null,
6775 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6776 target.task.affinityIntent = target.intent;
6777 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6778 + " out to new task " + target.task);
6779 }
6780 mWindowManager.setAppGroupId(target, task.taskId);
6781 if (replyChainEnd < 0) {
6782 replyChainEnd = targetI;
6783 }
6784 int dstPos = 0;
6785 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6786 p = (HistoryRecord)mHistory.get(srcPos);
6787 if (p.finishing) {
6788 continue;
6789 }
6790 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6791 + " out to target's task " + target.task);
6792 task.numActivities--;
6793 p.task = target.task;
6794 target.task.numActivities++;
6795 mHistory.remove(srcPos);
6796 mHistory.add(dstPos, p);
6797 mWindowManager.moveAppToken(dstPos, p);
6798 mWindowManager.setAppGroupId(p, p.task.taskId);
6799 dstPos++;
6800 if (VALIDATE_TOKENS) {
6801 mWindowManager.validateAppTokens(mHistory);
6802 }
6803 i++;
6804 }
6805 if (taskTop == p) {
6806 taskTop = below;
6807 }
6808 if (taskTopI == replyChainEnd) {
6809 taskTopI = -1;
6810 }
6811 replyChainEnd = -1;
6812 addRecentTask(target.task);
6813 } else if (forceReset || finishOnTaskLaunch
6814 || clearWhenTaskReset) {
6815 // If the activity should just be removed -- either
6816 // because it asks for it, or the task should be
6817 // cleared -- then finish it and anything that is
6818 // part of its reply chain.
6819 if (clearWhenTaskReset) {
6820 // In this case, we want to finish this activity
6821 // and everything above it, so be sneaky and pretend
6822 // like these are all in the reply chain.
6823 replyChainEnd = targetI+1;
6824 while (replyChainEnd < mHistory.size() &&
6825 ((HistoryRecord)mHistory.get(
6826 replyChainEnd)).task == task) {
6827 replyChainEnd++;
6828 }
6829 replyChainEnd--;
6830 } else if (replyChainEnd < 0) {
6831 replyChainEnd = targetI;
6832 }
6833 HistoryRecord p = null;
6834 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6835 p = (HistoryRecord)mHistory.get(srcPos);
6836 if (p.finishing) {
6837 continue;
6838 }
6839 if (finishActivityLocked(p, srcPos,
6840 Activity.RESULT_CANCELED, null, "reset")) {
6841 replyChainEnd--;
6842 srcPos--;
6843 }
6844 }
6845 if (taskTop == p) {
6846 taskTop = below;
6847 }
6848 if (taskTopI == replyChainEnd) {
6849 taskTopI = -1;
6850 }
6851 replyChainEnd = -1;
6852 } else {
6853 // If we were in the middle of a chain, well the
6854 // activity that started it all doesn't want anything
6855 // special, so leave it all as-is.
6856 replyChainEnd = -1;
6857 }
6858 } else {
6859 // Reached the bottom of the task -- any reply chain
6860 // should be left as-is.
6861 replyChainEnd = -1;
6862 }
6863
6864 } else if (target.resultTo != null) {
6865 // If this activity is sending a reply to a previous
6866 // activity, we can't do anything with it now until
6867 // we reach the start of the reply chain.
6868 // XXX note that we are assuming the result is always
6869 // to the previous activity, which is almost always
6870 // the case but we really shouldn't count on.
6871 if (replyChainEnd < 0) {
6872 replyChainEnd = targetI;
6873 }
6874
6875 } else if (taskTopI >= 0 && allowTaskReparenting
6876 && task.affinity != null
6877 && task.affinity.equals(target.taskAffinity)) {
6878 // We are inside of another task... if this activity has
6879 // an affinity for our task, then either remove it if we are
6880 // clearing or move it over to our task. Note that
6881 // we currently punt on the case where we are resetting a
6882 // task that is not at the top but who has activities above
6883 // with an affinity to it... this is really not a normal
6884 // case, and we will need to later pull that task to the front
6885 // and usually at that point we will do the reset and pick
6886 // up those remaining activities. (This only happens if
6887 // someone starts an activity in a new task from an activity
6888 // in a task that is not currently on top.)
6889 if (forceReset || finishOnTaskLaunch) {
6890 if (replyChainEnd < 0) {
6891 replyChainEnd = targetI;
6892 }
6893 HistoryRecord p = null;
6894 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6895 p = (HistoryRecord)mHistory.get(srcPos);
6896 if (p.finishing) {
6897 continue;
6898 }
6899 if (finishActivityLocked(p, srcPos,
6900 Activity.RESULT_CANCELED, null, "reset")) {
6901 taskTopI--;
6902 lastReparentPos--;
6903 replyChainEnd--;
6904 srcPos--;
6905 }
6906 }
6907 replyChainEnd = -1;
6908 } else {
6909 if (replyChainEnd < 0) {
6910 replyChainEnd = targetI;
6911 }
6912 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6913 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6914 if (p.finishing) {
6915 continue;
6916 }
6917 if (lastReparentPos < 0) {
6918 lastReparentPos = taskTopI;
6919 taskTop = p;
6920 } else {
6921 lastReparentPos--;
6922 }
6923 mHistory.remove(srcPos);
6924 p.task.numActivities--;
6925 p.task = task;
6926 mHistory.add(lastReparentPos, p);
6927 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6928 + " in to resetting task " + task);
6929 task.numActivities++;
6930 mWindowManager.moveAppToken(lastReparentPos, p);
6931 mWindowManager.setAppGroupId(p, p.task.taskId);
6932 if (VALIDATE_TOKENS) {
6933 mWindowManager.validateAppTokens(mHistory);
6934 }
6935 }
6936 replyChainEnd = -1;
6937
6938 // Now we've moved it in to place... but what if this is
6939 // a singleTop activity and we have put it on top of another
6940 // instance of the same activity? Then we drop the instance
6941 // below so it remains singleTop.
6942 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6943 for (int j=lastReparentPos-1; j>=0; j--) {
6944 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6945 if (p.finishing) {
6946 continue;
6947 }
6948 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6949 if (finishActivityLocked(p, j,
6950 Activity.RESULT_CANCELED, null, "replace")) {
6951 taskTopI--;
6952 lastReparentPos--;
6953 }
6954 }
6955 }
6956 }
6957 }
6958 }
6959
6960 target = below;
6961 targetI = i;
6962 }
6963
6964 return taskTop;
6965 }
6966
6967 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006968 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006969 */
6970 public void moveTaskToFront(int task) {
6971 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6972 "moveTaskToFront()");
6973
6974 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006975 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6976 Binder.getCallingUid(), "Task to front")) {
6977 return;
6978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006979 final long origId = Binder.clearCallingIdentity();
6980 try {
6981 int N = mRecentTasks.size();
6982 for (int i=0; i<N; i++) {
6983 TaskRecord tr = mRecentTasks.get(i);
6984 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006985 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006986 return;
6987 }
6988 }
6989 for (int i=mHistory.size()-1; i>=0; i--) {
6990 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
6991 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006992 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 return;
6994 }
6995 }
6996 } finally {
6997 Binder.restoreCallingIdentity(origId);
6998 }
6999 }
7000 }
7001
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007002 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007003 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
7004
7005 final int task = tr.taskId;
7006 int top = mHistory.size()-1;
7007
7008 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7009 // nothing to do!
7010 return;
7011 }
7012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 ArrayList moved = new ArrayList();
7014
7015 // Applying the affinities may have removed entries from the history,
7016 // so get the size again.
7017 top = mHistory.size()-1;
7018 int pos = top;
7019
7020 // Shift all activities with this task up to the top
7021 // of the stack, keeping them in the same internal order.
7022 while (pos >= 0) {
7023 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7024 if (localLOGV) Log.v(
7025 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7026 boolean first = true;
7027 if (r.task.taskId == task) {
7028 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
7029 mHistory.remove(pos);
7030 mHistory.add(top, r);
7031 moved.add(0, r);
7032 top--;
7033 if (first) {
7034 addRecentTask(r.task);
7035 first = false;
7036 }
7037 }
7038 pos--;
7039 }
7040
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007041 if (DEBUG_TRANSITION) Log.v(TAG,
7042 "Prepare to front transition: task=" + tr);
7043 if (reason != null &&
7044 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7045 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7046 HistoryRecord r = topRunningActivityLocked(null);
7047 if (r != null) {
7048 mNoAnimActivities.add(r);
7049 }
7050 } else {
7051 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7052 }
7053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 mWindowManager.moveAppTokensToTop(moved);
7055 if (VALIDATE_TOKENS) {
7056 mWindowManager.validateAppTokens(mHistory);
7057 }
7058
7059 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007060 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007061 }
7062
7063 private final void finishTaskMove(int task) {
7064 resumeTopActivityLocked(null);
7065 }
7066
7067 public void moveTaskToBack(int task) {
7068 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7069 "moveTaskToBack()");
7070
7071 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007072 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7073 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7074 Binder.getCallingUid(), "Task to back")) {
7075 return;
7076 }
7077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007079 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007080 Binder.restoreCallingIdentity(origId);
7081 }
7082 }
7083
7084 /**
7085 * Moves an activity, and all of the other activities within the same task, to the bottom
7086 * of the history stack. The activity's order within the task is unchanged.
7087 *
7088 * @param token A reference to the activity we wish to move
7089 * @param nonRoot If false then this only works if the activity is the root
7090 * of a task; if true it will work for any activity in a task.
7091 * @return Returns true if the move completed, false if not.
7092 */
7093 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7094 synchronized(this) {
7095 final long origId = Binder.clearCallingIdentity();
7096 int taskId = getTaskForActivityLocked(token, !nonRoot);
7097 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007098 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 }
7100 Binder.restoreCallingIdentity(origId);
7101 }
7102 return false;
7103 }
7104
7105 /**
7106 * Worker method for rearranging history stack. Implements the function of moving all
7107 * activities for a specific task (gathering them if disjoint) into a single group at the
7108 * bottom of the stack.
7109 *
7110 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7111 * to premeptively cancel the move.
7112 *
7113 * @param task The taskId to collect and move to the bottom.
7114 * @return Returns true if the move completed, false if not.
7115 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007116 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 Log.i(TAG, "moveTaskToBack: " + task);
7118
7119 // If we have a watcher, preflight the move before committing to it. First check
7120 // for *other* available tasks, but if none are available, then try again allowing the
7121 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007122 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 HistoryRecord next = topRunningActivityLocked(null, task);
7124 if (next == null) {
7125 next = topRunningActivityLocked(null, 0);
7126 }
7127 if (next != null) {
7128 // ask watcher if this is allowed
7129 boolean moveOK = true;
7130 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007131 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007132 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007133 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 }
7135 if (!moveOK) {
7136 return false;
7137 }
7138 }
7139 }
7140
7141 ArrayList moved = new ArrayList();
7142
7143 if (DEBUG_TRANSITION) Log.v(TAG,
7144 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145
7146 final int N = mHistory.size();
7147 int bottom = 0;
7148 int pos = 0;
7149
7150 // Shift all activities with this task down to the bottom
7151 // of the stack, keeping them in the same internal order.
7152 while (pos < N) {
7153 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7154 if (localLOGV) Log.v(
7155 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7156 if (r.task.taskId == task) {
7157 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
7158 mHistory.remove(pos);
7159 mHistory.add(bottom, r);
7160 moved.add(r);
7161 bottom++;
7162 }
7163 pos++;
7164 }
7165
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007166 if (reason != null &&
7167 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7168 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7169 HistoryRecord r = topRunningActivityLocked(null);
7170 if (r != null) {
7171 mNoAnimActivities.add(r);
7172 }
7173 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007174 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176 mWindowManager.moveAppTokensToBottom(moved);
7177 if (VALIDATE_TOKENS) {
7178 mWindowManager.validateAppTokens(mHistory);
7179 }
7180
7181 finishTaskMove(task);
7182 return true;
7183 }
7184
7185 public void moveTaskBackwards(int task) {
7186 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7187 "moveTaskBackwards()");
7188
7189 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007190 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7191 Binder.getCallingUid(), "Task backwards")) {
7192 return;
7193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 final long origId = Binder.clearCallingIdentity();
7195 moveTaskBackwardsLocked(task);
7196 Binder.restoreCallingIdentity(origId);
7197 }
7198 }
7199
7200 private final void moveTaskBackwardsLocked(int task) {
7201 Log.e(TAG, "moveTaskBackwards not yet implemented!");
7202 }
7203
7204 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7205 synchronized(this) {
7206 return getTaskForActivityLocked(token, onlyRoot);
7207 }
7208 }
7209
7210 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7211 final int N = mHistory.size();
7212 TaskRecord lastTask = null;
7213 for (int i=0; i<N; i++) {
7214 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7215 if (r == token) {
7216 if (!onlyRoot || lastTask != r.task) {
7217 return r.task.taskId;
7218 }
7219 return -1;
7220 }
7221 lastTask = r.task;
7222 }
7223
7224 return -1;
7225 }
7226
7227 /**
7228 * Returns the top activity in any existing task matching the given
7229 * Intent. Returns null if no such task is found.
7230 */
7231 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7232 ComponentName cls = intent.getComponent();
7233 if (info.targetActivity != null) {
7234 cls = new ComponentName(info.packageName, info.targetActivity);
7235 }
7236
7237 TaskRecord cp = null;
7238
7239 final int N = mHistory.size();
7240 for (int i=(N-1); i>=0; i--) {
7241 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7242 if (!r.finishing && r.task != cp
7243 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7244 cp = r.task;
7245 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
7246 // + "/aff=" + r.task.affinity + " to new cls="
7247 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7248 if (r.task.affinity != null) {
7249 if (r.task.affinity.equals(info.taskAffinity)) {
7250 //Log.i(TAG, "Found matching affinity!");
7251 return r;
7252 }
7253 } else if (r.task.intent != null
7254 && r.task.intent.getComponent().equals(cls)) {
7255 //Log.i(TAG, "Found matching class!");
7256 //dump();
7257 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7258 return r;
7259 } else if (r.task.affinityIntent != null
7260 && r.task.affinityIntent.getComponent().equals(cls)) {
7261 //Log.i(TAG, "Found matching class!");
7262 //dump();
7263 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7264 return r;
7265 }
7266 }
7267 }
7268
7269 return null;
7270 }
7271
7272 /**
7273 * Returns the first activity (starting from the top of the stack) that
7274 * is the same as the given activity. Returns null if no such activity
7275 * is found.
7276 */
7277 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7278 ComponentName cls = intent.getComponent();
7279 if (info.targetActivity != null) {
7280 cls = new ComponentName(info.packageName, info.targetActivity);
7281 }
7282
7283 final int N = mHistory.size();
7284 for (int i=(N-1); i>=0; i--) {
7285 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7286 if (!r.finishing) {
7287 if (r.intent.getComponent().equals(cls)) {
7288 //Log.i(TAG, "Found matching class!");
7289 //dump();
7290 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7291 return r;
7292 }
7293 }
7294 }
7295
7296 return null;
7297 }
7298
7299 public void finishOtherInstances(IBinder token, ComponentName className) {
7300 synchronized(this) {
7301 final long origId = Binder.clearCallingIdentity();
7302
7303 int N = mHistory.size();
7304 TaskRecord lastTask = null;
7305 for (int i=0; i<N; i++) {
7306 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7307 if (r.realActivity.equals(className)
7308 && r != token && lastTask != r.task) {
7309 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7310 null, "others")) {
7311 i--;
7312 N--;
7313 }
7314 }
7315 lastTask = r.task;
7316 }
7317
7318 Binder.restoreCallingIdentity(origId);
7319 }
7320 }
7321
7322 // =========================================================
7323 // THUMBNAILS
7324 // =========================================================
7325
7326 public void reportThumbnail(IBinder token,
7327 Bitmap thumbnail, CharSequence description) {
7328 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7329 final long origId = Binder.clearCallingIdentity();
7330 sendPendingThumbnail(null, token, thumbnail, description, true);
7331 Binder.restoreCallingIdentity(origId);
7332 }
7333
7334 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7335 Bitmap thumbnail, CharSequence description, boolean always) {
7336 TaskRecord task = null;
7337 ArrayList receivers = null;
7338
7339 //System.out.println("Send pending thumbnail: " + r);
7340
7341 synchronized(this) {
7342 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007343 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 if (index < 0) {
7345 return;
7346 }
7347 r = (HistoryRecord)mHistory.get(index);
7348 }
7349 if (thumbnail == null) {
7350 thumbnail = r.thumbnail;
7351 description = r.description;
7352 }
7353 if (thumbnail == null && !always) {
7354 // If there is no thumbnail, and this entry is not actually
7355 // going away, then abort for now and pick up the next
7356 // thumbnail we get.
7357 return;
7358 }
7359 task = r.task;
7360
7361 int N = mPendingThumbnails.size();
7362 int i=0;
7363 while (i<N) {
7364 PendingThumbnailsRecord pr =
7365 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7366 //System.out.println("Looking in " + pr.pendingRecords);
7367 if (pr.pendingRecords.remove(r)) {
7368 if (receivers == null) {
7369 receivers = new ArrayList();
7370 }
7371 receivers.add(pr);
7372 if (pr.pendingRecords.size() == 0) {
7373 pr.finished = true;
7374 mPendingThumbnails.remove(i);
7375 N--;
7376 continue;
7377 }
7378 }
7379 i++;
7380 }
7381 }
7382
7383 if (receivers != null) {
7384 final int N = receivers.size();
7385 for (int i=0; i<N; i++) {
7386 try {
7387 PendingThumbnailsRecord pr =
7388 (PendingThumbnailsRecord)receivers.get(i);
7389 pr.receiver.newThumbnail(
7390 task != null ? task.taskId : -1, thumbnail, description);
7391 if (pr.finished) {
7392 pr.receiver.finished();
7393 }
7394 } catch (Exception e) {
7395 Log.w(TAG, "Exception thrown when sending thumbnail", e);
7396 }
7397 }
7398 }
7399 }
7400
7401 // =========================================================
7402 // CONTENT PROVIDERS
7403 // =========================================================
7404
7405 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7406 List providers = null;
7407 try {
7408 providers = ActivityThread.getPackageManager().
7409 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007410 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 } catch (RemoteException ex) {
7412 }
7413 if (providers != null) {
7414 final int N = providers.size();
7415 for (int i=0; i<N; i++) {
7416 ProviderInfo cpi =
7417 (ProviderInfo)providers.get(i);
7418 ContentProviderRecord cpr =
7419 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7420 if (cpr == null) {
7421 cpr = new ContentProviderRecord(cpi, app.info);
7422 mProvidersByClass.put(cpi.name, cpr);
7423 }
7424 app.pubProviders.put(cpi.name, cpr);
7425 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007426 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 }
7428 }
7429 return providers;
7430 }
7431
7432 private final String checkContentProviderPermissionLocked(
7433 ProviderInfo cpi, ProcessRecord r, int mode) {
7434 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7435 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7436 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7437 cpi.exported ? -1 : cpi.applicationInfo.uid)
7438 == PackageManager.PERMISSION_GRANTED
7439 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7440 return null;
7441 }
7442 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7443 cpi.exported ? -1 : cpi.applicationInfo.uid)
7444 == PackageManager.PERMISSION_GRANTED) {
7445 return null;
7446 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007447
7448 PathPermission[] pps = cpi.pathPermissions;
7449 if (pps != null) {
7450 int i = pps.length;
7451 while (i > 0) {
7452 i--;
7453 PathPermission pp = pps[i];
7454 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7455 cpi.exported ? -1 : cpi.applicationInfo.uid)
7456 == PackageManager.PERMISSION_GRANTED
7457 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7458 return null;
7459 }
7460 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7461 cpi.exported ? -1 : cpi.applicationInfo.uid)
7462 == PackageManager.PERMISSION_GRANTED) {
7463 return null;
7464 }
7465 }
7466 }
7467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 String msg = "Permission Denial: opening provider " + cpi.name
7469 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7470 + ", uid=" + callingUid + ") requires "
7471 + cpi.readPermission + " or " + cpi.writePermission;
7472 Log.w(TAG, msg);
7473 return msg;
7474 }
7475
7476 private final ContentProviderHolder getContentProviderImpl(
7477 IApplicationThread caller, String name) {
7478 ContentProviderRecord cpr;
7479 ProviderInfo cpi = null;
7480
7481 synchronized(this) {
7482 ProcessRecord r = null;
7483 if (caller != null) {
7484 r = getRecordForAppLocked(caller);
7485 if (r == null) {
7486 throw new SecurityException(
7487 "Unable to find app for caller " + caller
7488 + " (pid=" + Binder.getCallingPid()
7489 + ") when getting content provider " + name);
7490 }
7491 }
7492
7493 // First check if this content provider has been published...
7494 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7495 if (cpr != null) {
7496 cpi = cpr.info;
7497 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7498 return new ContentProviderHolder(cpi,
7499 cpi.readPermission != null
7500 ? cpi.readPermission : cpi.writePermission);
7501 }
7502
7503 if (r != null && cpr.canRunHere(r)) {
7504 // This provider has been published or is in the process
7505 // of being published... but it is also allowed to run
7506 // in the caller's process, so don't make a connection
7507 // and just let the caller instantiate its own instance.
7508 if (cpr.provider != null) {
7509 // don't give caller the provider object, it needs
7510 // to make its own.
7511 cpr = new ContentProviderRecord(cpr);
7512 }
7513 return cpr;
7514 }
7515
7516 final long origId = Binder.clearCallingIdentity();
7517
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007518 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 // return it right away.
7520 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007521 if (DEBUG_PROVIDER) Log.v(TAG,
7522 "Adding provider requested by "
7523 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007524 + cpr.info.processName);
7525 Integer cnt = r.conProviders.get(cpr);
7526 if (cnt == null) {
7527 r.conProviders.put(cpr, new Integer(1));
7528 } else {
7529 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 cpr.clients.add(r);
7532 } else {
7533 cpr.externals++;
7534 }
7535
7536 if (cpr.app != null) {
7537 updateOomAdjLocked(cpr.app);
7538 }
7539
7540 Binder.restoreCallingIdentity(origId);
7541
7542 } else {
7543 try {
7544 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007545 resolveContentProvider(name,
7546 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 } catch (RemoteException ex) {
7548 }
7549 if (cpi == null) {
7550 return null;
7551 }
7552
7553 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7554 return new ContentProviderHolder(cpi,
7555 cpi.readPermission != null
7556 ? cpi.readPermission : cpi.writePermission);
7557 }
7558
7559 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7560 final boolean firstClass = cpr == null;
7561 if (firstClass) {
7562 try {
7563 ApplicationInfo ai =
7564 ActivityThread.getPackageManager().
7565 getApplicationInfo(
7566 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007567 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 if (ai == null) {
7569 Log.w(TAG, "No package info for content provider "
7570 + cpi.name);
7571 return null;
7572 }
7573 cpr = new ContentProviderRecord(cpi, ai);
7574 } catch (RemoteException ex) {
7575 // pm is in same process, this will never happen.
7576 }
7577 }
7578
7579 if (r != null && cpr.canRunHere(r)) {
7580 // If this is a multiprocess provider, then just return its
7581 // info and allow the caller to instantiate it. Only do
7582 // this if the provider is the same user as the caller's
7583 // process, or can run as root (so can be in any process).
7584 return cpr;
7585 }
7586
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007587 if (DEBUG_PROVIDER) {
7588 RuntimeException e = new RuntimeException("here");
7589 Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
7590 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 }
7592
7593 // This is single process, and our app is now connecting to it.
7594 // See if we are already in the process of launching this
7595 // provider.
7596 final int N = mLaunchingProviders.size();
7597 int i;
7598 for (i=0; i<N; i++) {
7599 if (mLaunchingProviders.get(i) == cpr) {
7600 break;
7601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 }
7603
7604 // If the provider is not already being launched, then get it
7605 // started.
7606 if (i >= N) {
7607 final long origId = Binder.clearCallingIdentity();
7608 ProcessRecord proc = startProcessLocked(cpi.processName,
7609 cpr.appInfo, false, 0, "content provider",
7610 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007611 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 if (proc == null) {
7613 Log.w(TAG, "Unable to launch app "
7614 + cpi.applicationInfo.packageName + "/"
7615 + cpi.applicationInfo.uid + " for provider "
7616 + name + ": process is bad");
7617 return null;
7618 }
7619 cpr.launchingApp = proc;
7620 mLaunchingProviders.add(cpr);
7621 Binder.restoreCallingIdentity(origId);
7622 }
7623
7624 // Make sure the provider is published (the same provider class
7625 // may be published under multiple names).
7626 if (firstClass) {
7627 mProvidersByClass.put(cpi.name, cpr);
7628 }
7629 mProvidersByName.put(name, cpr);
7630
7631 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007632 if (DEBUG_PROVIDER) Log.v(TAG,
7633 "Adding provider requested by "
7634 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007635 + cpr.info.processName);
7636 Integer cnt = r.conProviders.get(cpr);
7637 if (cnt == null) {
7638 r.conProviders.put(cpr, new Integer(1));
7639 } else {
7640 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 cpr.clients.add(r);
7643 } else {
7644 cpr.externals++;
7645 }
7646 }
7647 }
7648
7649 // Wait for the provider to be published...
7650 synchronized (cpr) {
7651 while (cpr.provider == null) {
7652 if (cpr.launchingApp == null) {
7653 Log.w(TAG, "Unable to launch app "
7654 + cpi.applicationInfo.packageName + "/"
7655 + cpi.applicationInfo.uid + " for provider "
7656 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007657 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007658 cpi.applicationInfo.packageName,
7659 cpi.applicationInfo.uid, name);
7660 return null;
7661 }
7662 try {
7663 cpr.wait();
7664 } catch (InterruptedException ex) {
7665 }
7666 }
7667 }
7668 return cpr;
7669 }
7670
7671 public final ContentProviderHolder getContentProvider(
7672 IApplicationThread caller, String name) {
7673 if (caller == null) {
7674 String msg = "null IApplicationThread when getting content provider "
7675 + name;
7676 Log.w(TAG, msg);
7677 throw new SecurityException(msg);
7678 }
7679
7680 return getContentProviderImpl(caller, name);
7681 }
7682
7683 private ContentProviderHolder getContentProviderExternal(String name) {
7684 return getContentProviderImpl(null, name);
7685 }
7686
7687 /**
7688 * Drop a content provider from a ProcessRecord's bookkeeping
7689 * @param cpr
7690 */
7691 public void removeContentProvider(IApplicationThread caller, String name) {
7692 synchronized (this) {
7693 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7694 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007695 // remove from mProvidersByClass
7696 if (DEBUG_PROVIDER) Log.v(TAG, name +
7697 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 return;
7699 }
7700 final ProcessRecord r = getRecordForAppLocked(caller);
7701 if (r == null) {
7702 throw new SecurityException(
7703 "Unable to find app for caller " + caller +
7704 " when removing content provider " + name);
7705 }
7706 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007707 ContentProviderRecord localCpr = (ContentProviderRecord)
7708 mProvidersByClass.get(cpr.info.name);
7709 if (DEBUG_PROVIDER) Log.v(TAG, "Removing provider requested by "
7710 + r.info.processName + " from process "
7711 + localCpr.appInfo.processName);
7712 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 //should not happen. taken care of as a local provider
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007714 Log.w(TAG, "removeContentProvider called on local provider: "
7715 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 return;
7717 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007718 Integer cnt = r.conProviders.get(localCpr);
7719 if (cnt == null || cnt.intValue() <= 1) {
7720 localCpr.clients.remove(r);
7721 r.conProviders.remove(localCpr);
7722 } else {
7723 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 }
7726 updateOomAdjLocked();
7727 }
7728 }
7729
7730 private void removeContentProviderExternal(String name) {
7731 synchronized (this) {
7732 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7733 if(cpr == null) {
7734 //remove from mProvidersByClass
7735 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
7736 return;
7737 }
7738
7739 //update content provider record entry info
7740 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7741 localCpr.externals--;
7742 if (localCpr.externals < 0) {
7743 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
7744 }
7745 updateOomAdjLocked();
7746 }
7747 }
7748
7749 public final void publishContentProviders(IApplicationThread caller,
7750 List<ContentProviderHolder> providers) {
7751 if (providers == null) {
7752 return;
7753 }
7754
7755 synchronized(this) {
7756 final ProcessRecord r = getRecordForAppLocked(caller);
7757 if (r == null) {
7758 throw new SecurityException(
7759 "Unable to find app for caller " + caller
7760 + " (pid=" + Binder.getCallingPid()
7761 + ") when publishing content providers");
7762 }
7763
7764 final long origId = Binder.clearCallingIdentity();
7765
7766 final int N = providers.size();
7767 for (int i=0; i<N; i++) {
7768 ContentProviderHolder src = providers.get(i);
7769 if (src == null || src.info == null || src.provider == null) {
7770 continue;
7771 }
7772 ContentProviderRecord dst =
7773 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7774 if (dst != null) {
7775 mProvidersByClass.put(dst.info.name, dst);
7776 String names[] = dst.info.authority.split(";");
7777 for (int j = 0; j < names.length; j++) {
7778 mProvidersByName.put(names[j], dst);
7779 }
7780
7781 int NL = mLaunchingProviders.size();
7782 int j;
7783 for (j=0; j<NL; j++) {
7784 if (mLaunchingProviders.get(j) == dst) {
7785 mLaunchingProviders.remove(j);
7786 j--;
7787 NL--;
7788 }
7789 }
7790 synchronized (dst) {
7791 dst.provider = src.provider;
7792 dst.app = r;
7793 dst.notifyAll();
7794 }
7795 updateOomAdjLocked(r);
7796 }
7797 }
7798
7799 Binder.restoreCallingIdentity(origId);
7800 }
7801 }
7802
7803 public static final void installSystemProviders() {
7804 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7805 List providers = mSelf.generateApplicationProvidersLocked(app);
7806 mSystemThread.installSystemProviders(providers);
7807 }
7808
7809 // =========================================================
7810 // GLOBAL MANAGEMENT
7811 // =========================================================
7812
7813 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7814 ApplicationInfo info, String customProcess) {
7815 String proc = customProcess != null ? customProcess : info.processName;
7816 BatteryStatsImpl.Uid.Proc ps = null;
7817 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7818 synchronized (stats) {
7819 ps = stats.getProcessStatsLocked(info.uid, proc);
7820 }
7821 return new ProcessRecord(ps, thread, info, proc);
7822 }
7823
7824 final ProcessRecord addAppLocked(ApplicationInfo info) {
7825 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7826
7827 if (app == null) {
7828 app = newProcessRecordLocked(null, info, null);
7829 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007830 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 }
7832
7833 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7834 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7835 app.persistent = true;
7836 app.maxAdj = CORE_SERVER_ADJ;
7837 }
7838 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7839 mPersistentStartingProcesses.add(app);
7840 startProcessLocked(app, "added application", app.processName);
7841 }
7842
7843 return app;
7844 }
7845
7846 public void unhandledBack() {
7847 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7848 "unhandledBack()");
7849
7850 synchronized(this) {
7851 int count = mHistory.size();
Dianne Hackborn03abb812010-01-04 18:43:19 -08007852 if (DEBUG_SWITCH) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 TAG, "Performing unhandledBack(): stack size = " + count);
7854 if (count > 1) {
7855 final long origId = Binder.clearCallingIdentity();
7856 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7857 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7858 Binder.restoreCallingIdentity(origId);
7859 }
7860 }
7861 }
7862
7863 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7864 String name = uri.getAuthority();
7865 ContentProviderHolder cph = getContentProviderExternal(name);
7866 ParcelFileDescriptor pfd = null;
7867 if (cph != null) {
7868 // We record the binder invoker's uid in thread-local storage before
7869 // going to the content provider to open the file. Later, in the code
7870 // that handles all permissions checks, we look for this uid and use
7871 // that rather than the Activity Manager's own uid. The effect is that
7872 // we do the check against the caller's permissions even though it looks
7873 // to the content provider like the Activity Manager itself is making
7874 // the request.
7875 sCallerIdentity.set(new Identity(
7876 Binder.getCallingPid(), Binder.getCallingUid()));
7877 try {
7878 pfd = cph.provider.openFile(uri, "r");
7879 } catch (FileNotFoundException e) {
7880 // do nothing; pfd will be returned null
7881 } finally {
7882 // Ensure that whatever happens, we clean up the identity state
7883 sCallerIdentity.remove();
7884 }
7885
7886 // We've got the fd now, so we're done with the provider.
7887 removeContentProviderExternal(name);
7888 } else {
7889 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7890 }
7891 return pfd;
7892 }
7893
7894 public void goingToSleep() {
7895 synchronized(this) {
7896 mSleeping = true;
7897 mWindowManager.setEventDispatching(false);
7898
7899 if (mResumedActivity != null) {
7900 pauseIfSleepingLocked();
7901 } else {
7902 Log.w(TAG, "goingToSleep with no resumed activity!");
7903 }
7904 }
7905 }
7906
Dianne Hackborn55280a92009-05-07 15:53:46 -07007907 public boolean shutdown(int timeout) {
7908 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7909 != PackageManager.PERMISSION_GRANTED) {
7910 throw new SecurityException("Requires permission "
7911 + android.Manifest.permission.SHUTDOWN);
7912 }
7913
7914 boolean timedout = false;
7915
7916 synchronized(this) {
7917 mShuttingDown = true;
7918 mWindowManager.setEventDispatching(false);
7919
7920 if (mResumedActivity != null) {
7921 pauseIfSleepingLocked();
7922 final long endTime = System.currentTimeMillis() + timeout;
7923 while (mResumedActivity != null || mPausingActivity != null) {
7924 long delay = endTime - System.currentTimeMillis();
7925 if (delay <= 0) {
7926 Log.w(TAG, "Activity manager shutdown timed out");
7927 timedout = true;
7928 break;
7929 }
7930 try {
7931 this.wait();
7932 } catch (InterruptedException e) {
7933 }
7934 }
7935 }
7936 }
7937
7938 mUsageStatsService.shutdown();
7939 mBatteryStatsService.shutdown();
7940
7941 return timedout;
7942 }
7943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007945 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 if (!mGoingToSleep.isHeld()) {
7947 mGoingToSleep.acquire();
7948 if (mLaunchingActivity.isHeld()) {
7949 mLaunchingActivity.release();
7950 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7951 }
7952 }
7953
7954 // If we are not currently pausing an activity, get the current
7955 // one to pause. If we are pausing one, we will just let that stuff
7956 // run and release the wake lock when all done.
7957 if (mPausingActivity == null) {
7958 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7959 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7960 startPausingLocked(false, true);
7961 }
7962 }
7963 }
7964
7965 public void wakingUp() {
7966 synchronized(this) {
7967 if (mGoingToSleep.isHeld()) {
7968 mGoingToSleep.release();
7969 }
7970 mWindowManager.setEventDispatching(true);
7971 mSleeping = false;
7972 resumeTopActivityLocked(null);
7973 }
7974 }
7975
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007976 public void stopAppSwitches() {
7977 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7978 != PackageManager.PERMISSION_GRANTED) {
7979 throw new SecurityException("Requires permission "
7980 + android.Manifest.permission.STOP_APP_SWITCHES);
7981 }
7982
7983 synchronized(this) {
7984 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
7985 + APP_SWITCH_DELAY_TIME;
7986 mDidAppSwitch = false;
7987 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7988 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7989 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
7990 }
7991 }
7992
7993 public void resumeAppSwitches() {
7994 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7995 != PackageManager.PERMISSION_GRANTED) {
7996 throw new SecurityException("Requires permission "
7997 + android.Manifest.permission.STOP_APP_SWITCHES);
7998 }
7999
8000 synchronized(this) {
8001 // Note that we don't execute any pending app switches... we will
8002 // let those wait until either the timeout, or the next start
8003 // activity request.
8004 mAppSwitchesAllowedTime = 0;
8005 }
8006 }
8007
8008 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8009 String name) {
8010 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8011 return true;
8012 }
8013
8014 final int perm = checkComponentPermission(
8015 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8016 callingUid, -1);
8017 if (perm == PackageManager.PERMISSION_GRANTED) {
8018 return true;
8019 }
8020
8021 Log.w(TAG, name + " request from " + callingUid + " stopped");
8022 return false;
8023 }
8024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 public void setDebugApp(String packageName, boolean waitForDebugger,
8026 boolean persistent) {
8027 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8028 "setDebugApp()");
8029
8030 // Note that this is not really thread safe if there are multiple
8031 // callers into it at the same time, but that's not a situation we
8032 // care about.
8033 if (persistent) {
8034 final ContentResolver resolver = mContext.getContentResolver();
8035 Settings.System.putString(
8036 resolver, Settings.System.DEBUG_APP,
8037 packageName);
8038 Settings.System.putInt(
8039 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8040 waitForDebugger ? 1 : 0);
8041 }
8042
8043 synchronized (this) {
8044 if (!persistent) {
8045 mOrigDebugApp = mDebugApp;
8046 mOrigWaitForDebugger = mWaitForDebugger;
8047 }
8048 mDebugApp = packageName;
8049 mWaitForDebugger = waitForDebugger;
8050 mDebugTransient = !persistent;
8051 if (packageName != null) {
8052 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008053 forceStopPackageLocked(packageName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 Binder.restoreCallingIdentity(origId);
8055 }
8056 }
8057 }
8058
8059 public void setAlwaysFinish(boolean enabled) {
8060 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8061 "setAlwaysFinish()");
8062
8063 Settings.System.putInt(
8064 mContext.getContentResolver(),
8065 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8066
8067 synchronized (this) {
8068 mAlwaysFinishActivities = enabled;
8069 }
8070 }
8071
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008072 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008074 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008076 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 }
8078 }
8079
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008080 public boolean isUserAMonkey() {
8081 // For now the fact that there is a controller implies
8082 // we have a monkey.
8083 synchronized (this) {
8084 return mController != null;
8085 }
8086 }
8087
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008088 public void registerActivityWatcher(IActivityWatcher watcher) {
8089 mWatchers.register(watcher);
8090 }
8091
8092 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8093 mWatchers.unregister(watcher);
8094 }
8095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 public final void enterSafeMode() {
8097 synchronized(this) {
8098 // It only makes sense to do this before the system is ready
8099 // and started launching other packages.
8100 if (!mSystemReady) {
8101 try {
8102 ActivityThread.getPackageManager().enterSafeMode();
8103 } catch (RemoteException e) {
8104 }
8105
8106 View v = LayoutInflater.from(mContext).inflate(
8107 com.android.internal.R.layout.safe_mode, null);
8108 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8109 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8110 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8111 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8112 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8113 lp.format = v.getBackground().getOpacity();
8114 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8115 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8116 ((WindowManager)mContext.getSystemService(
8117 Context.WINDOW_SERVICE)).addView(v, lp);
8118 }
8119 }
8120 }
8121
8122 public void noteWakeupAlarm(IIntentSender sender) {
8123 if (!(sender instanceof PendingIntentRecord)) {
8124 return;
8125 }
8126 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8127 synchronized (stats) {
8128 if (mBatteryStatsService.isOnBattery()) {
8129 mBatteryStatsService.enforceCallingPermission();
8130 PendingIntentRecord rec = (PendingIntentRecord)sender;
8131 int MY_UID = Binder.getCallingUid();
8132 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8133 BatteryStatsImpl.Uid.Pkg pkg =
8134 stats.getPackageStatsLocked(uid, rec.key.packageName);
8135 pkg.incWakeupsLocked();
8136 }
8137 }
8138 }
8139
8140 public boolean killPidsForMemory(int[] pids) {
8141 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8142 throw new SecurityException("killPidsForMemory only available to the system");
8143 }
8144
8145 // XXX Note: don't acquire main activity lock here, because the window
8146 // manager calls in with its locks held.
8147
8148 boolean killed = false;
8149 synchronized (mPidsSelfLocked) {
8150 int[] types = new int[pids.length];
8151 int worstType = 0;
8152 for (int i=0; i<pids.length; i++) {
8153 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8154 if (proc != null) {
8155 int type = proc.setAdj;
8156 types[i] = type;
8157 if (type > worstType) {
8158 worstType = type;
8159 }
8160 }
8161 }
8162
8163 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8164 // then constrain it so we will kill all hidden procs.
8165 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8166 worstType = HIDDEN_APP_MIN_ADJ;
8167 }
8168 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
8169 for (int i=0; i<pids.length; i++) {
8170 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8171 if (proc == null) {
8172 continue;
8173 }
8174 int adj = proc.setAdj;
8175 if (adj >= worstType) {
8176 Log.w(TAG, "Killing for memory: " + proc + " (adj "
8177 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008178 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 proc.processName, adj);
8180 killed = true;
8181 Process.killProcess(pids[i]);
8182 }
8183 }
8184 }
8185 return killed;
8186 }
8187
8188 public void reportPss(IApplicationThread caller, int pss) {
8189 Watchdog.PssRequestor req;
8190 String name;
8191 ProcessRecord callerApp;
8192 synchronized (this) {
8193 if (caller == null) {
8194 return;
8195 }
8196 callerApp = getRecordForAppLocked(caller);
8197 if (callerApp == null) {
8198 return;
8199 }
8200 callerApp.lastPss = pss;
8201 req = callerApp;
8202 name = callerApp.processName;
8203 }
8204 Watchdog.getInstance().reportPss(req, name, pss);
8205 if (!callerApp.persistent) {
8206 removeRequestedPss(callerApp);
8207 }
8208 }
8209
8210 public void requestPss(Runnable completeCallback) {
8211 ArrayList<ProcessRecord> procs;
8212 synchronized (this) {
8213 mRequestPssCallback = completeCallback;
8214 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008215 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8216 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 if (!proc.persistent) {
8218 mRequestPssList.add(proc);
8219 }
8220 }
8221 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8222 }
8223
8224 int oldPri = Process.getThreadPriority(Process.myTid());
8225 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8226 for (int i=procs.size()-1; i>=0; i--) {
8227 ProcessRecord proc = procs.get(i);
8228 proc.lastPss = 0;
8229 proc.requestPss();
8230 }
8231 Process.setThreadPriority(oldPri);
8232 }
8233
8234 void removeRequestedPss(ProcessRecord proc) {
8235 Runnable callback = null;
8236 synchronized (this) {
8237 if (mRequestPssList.remove(proc)) {
8238 if (mRequestPssList.size() == 0) {
8239 callback = mRequestPssCallback;
8240 mRequestPssCallback = null;
8241 }
8242 }
8243 }
8244
8245 if (callback != null) {
8246 callback.run();
8247 }
8248 }
8249
8250 public void collectPss(Watchdog.PssStats stats) {
8251 stats.mEmptyPss = 0;
8252 stats.mEmptyCount = 0;
8253 stats.mBackgroundPss = 0;
8254 stats.mBackgroundCount = 0;
8255 stats.mServicePss = 0;
8256 stats.mServiceCount = 0;
8257 stats.mVisiblePss = 0;
8258 stats.mVisibleCount = 0;
8259 stats.mForegroundPss = 0;
8260 stats.mForegroundCount = 0;
8261 stats.mNoPssCount = 0;
8262 synchronized (this) {
8263 int i;
8264 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8265 ? mProcDeaths.length : stats.mProcDeaths.length;
8266 int aggr = 0;
8267 for (i=0; i<NPD; i++) {
8268 aggr += mProcDeaths[i];
8269 stats.mProcDeaths[i] = aggr;
8270 }
8271 while (i<stats.mProcDeaths.length) {
8272 stats.mProcDeaths[i] = 0;
8273 i++;
8274 }
8275
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008276 for (i=mLruProcesses.size()-1; i>=0; i--) {
8277 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 if (proc.persistent) {
8279 continue;
8280 }
8281 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
8282 if (proc.lastPss == 0) {
8283 stats.mNoPssCount++;
8284 continue;
8285 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008286 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8287 if (proc.empty) {
8288 stats.mEmptyPss += proc.lastPss;
8289 stats.mEmptyCount++;
8290 } else {
8291 stats.mBackgroundPss += proc.lastPss;
8292 stats.mBackgroundCount++;
8293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8295 stats.mVisiblePss += proc.lastPss;
8296 stats.mVisibleCount++;
8297 } else {
8298 stats.mForegroundPss += proc.lastPss;
8299 stats.mForegroundCount++;
8300 }
8301 }
8302 }
8303 }
8304
8305 public final void startRunning(String pkg, String cls, String action,
8306 String data) {
8307 synchronized(this) {
8308 if (mStartRunning) {
8309 return;
8310 }
8311 mStartRunning = true;
8312 mTopComponent = pkg != null && cls != null
8313 ? new ComponentName(pkg, cls) : null;
8314 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8315 mTopData = data;
8316 if (!mSystemReady) {
8317 return;
8318 }
8319 }
8320
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008321 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 }
8323
8324 private void retrieveSettings() {
8325 final ContentResolver resolver = mContext.getContentResolver();
8326 String debugApp = Settings.System.getString(
8327 resolver, Settings.System.DEBUG_APP);
8328 boolean waitForDebugger = Settings.System.getInt(
8329 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8330 boolean alwaysFinishActivities = Settings.System.getInt(
8331 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8332
8333 Configuration configuration = new Configuration();
8334 Settings.System.getConfiguration(resolver, configuration);
8335
8336 synchronized (this) {
8337 mDebugApp = mOrigDebugApp = debugApp;
8338 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8339 mAlwaysFinishActivities = alwaysFinishActivities;
8340 // This happens before any activities are started, so we can
8341 // change mConfiguration in-place.
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008342 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008344 mConfigurationSeq = mConfiguration.seq = 1;
Dianne Hackborndc6b6352009-09-30 14:20:09 -07008345 if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 }
8347 }
8348
8349 public boolean testIsSystemReady() {
8350 // no need to synchronize(this) just to read & return the value
8351 return mSystemReady;
8352 }
8353
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008354 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008355 // In the simulator, startRunning will never have been called, which
8356 // normally sets a few crucial variables. Do it here instead.
8357 if (!Process.supportsProcesses()) {
8358 mStartRunning = true;
8359 mTopAction = Intent.ACTION_MAIN;
8360 }
8361
8362 synchronized(this) {
8363 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008364 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 return;
8366 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008367
8368 // Check to see if there are any update receivers to run.
8369 if (!mDidUpdate) {
8370 if (mWaitingUpdate) {
8371 return;
8372 }
8373 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8374 List<ResolveInfo> ris = null;
8375 try {
8376 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8377 intent, null, 0);
8378 } catch (RemoteException e) {
8379 }
8380 if (ris != null) {
8381 for (int i=ris.size()-1; i>=0; i--) {
8382 if ((ris.get(i).activityInfo.applicationInfo.flags
8383 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8384 ris.remove(i);
8385 }
8386 }
8387 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8388 for (int i=0; i<ris.size(); i++) {
8389 ActivityInfo ai = ris.get(i).activityInfo;
8390 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8391 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008392 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008393 finisher = new IIntentReceiver.Stub() {
8394 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008395 String data, Bundle extras, boolean ordered,
8396 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008397 throws RemoteException {
8398 synchronized (ActivityManagerService.this) {
8399 mDidUpdate = true;
8400 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008401 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008402 }
8403 };
8404 }
8405 Log.i(TAG, "Sending system update to: " + intent.getComponent());
8406 broadcastIntentLocked(null, null, intent, null, finisher,
8407 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008408 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008409 mWaitingUpdate = true;
8410 }
8411 }
8412 }
8413 if (mWaitingUpdate) {
8414 return;
8415 }
8416 mDidUpdate = true;
8417 }
8418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 mSystemReady = true;
8420 if (!mStartRunning) {
8421 return;
8422 }
8423 }
8424
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008425 ArrayList<ProcessRecord> procsToKill = null;
8426 synchronized(mPidsSelfLocked) {
8427 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8428 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8429 if (!isAllowedWhileBooting(proc.info)){
8430 if (procsToKill == null) {
8431 procsToKill = new ArrayList<ProcessRecord>();
8432 }
8433 procsToKill.add(proc);
8434 }
8435 }
8436 }
8437
8438 if (procsToKill != null) {
8439 synchronized(this) {
8440 for (int i=procsToKill.size()-1; i>=0; i--) {
8441 ProcessRecord proc = procsToKill.get(i);
8442 Log.i(TAG, "Removing system update proc: " + proc);
8443 removeProcessLocked(proc, true);
8444 }
8445 }
8446 }
8447
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008448 Log.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008449 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008450 SystemClock.uptimeMillis());
8451
8452 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008453 // Make sure we have no pre-ready processes sitting around.
8454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8456 ResolveInfo ri = mContext.getPackageManager()
8457 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008458 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008459 CharSequence errorMsg = null;
8460 if (ri != null) {
8461 ActivityInfo ai = ri.activityInfo;
8462 ApplicationInfo app = ai.applicationInfo;
8463 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8464 mTopAction = Intent.ACTION_FACTORY_TEST;
8465 mTopData = null;
8466 mTopComponent = new ComponentName(app.packageName,
8467 ai.name);
8468 } else {
8469 errorMsg = mContext.getResources().getText(
8470 com.android.internal.R.string.factorytest_not_system);
8471 }
8472 } else {
8473 errorMsg = mContext.getResources().getText(
8474 com.android.internal.R.string.factorytest_no_action);
8475 }
8476 if (errorMsg != null) {
8477 mTopAction = null;
8478 mTopData = null;
8479 mTopComponent = null;
8480 Message msg = Message.obtain();
8481 msg.what = SHOW_FACTORY_ERROR_MSG;
8482 msg.getData().putCharSequence("msg", errorMsg);
8483 mHandler.sendMessage(msg);
8484 }
8485 }
8486 }
8487
8488 retrieveSettings();
8489
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008490 if (goingCallback != null) goingCallback.run();
8491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 synchronized (this) {
8493 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8494 try {
8495 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008496 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497 if (apps != null) {
8498 int N = apps.size();
8499 int i;
8500 for (i=0; i<N; i++) {
8501 ApplicationInfo info
8502 = (ApplicationInfo)apps.get(i);
8503 if (info != null &&
8504 !info.packageName.equals("android")) {
8505 addAppLocked(info);
8506 }
8507 }
8508 }
8509 } catch (RemoteException ex) {
8510 // pm is in same process, this will never happen.
8511 }
8512 }
8513
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008514 // Start up initial activity.
8515 mBooting = true;
8516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 try {
8518 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8519 Message msg = Message.obtain();
8520 msg.what = SHOW_UID_ERROR_MSG;
8521 mHandler.sendMessage(msg);
8522 }
8523 } catch (RemoteException e) {
8524 }
8525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 resumeTopActivityLocked(null);
8527 }
8528 }
8529
Dan Egnorb7f03672009-12-09 16:22:32 -08008530 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008531 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008533 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008534 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535 startAppProblemLocked(app);
8536 app.stopFreezingAllLocked();
8537 return handleAppCrashLocked(app);
8538 }
8539
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008540 private ComponentName getErrorReportReceiver(ProcessRecord app) {
Doug Zongker43866e02010-01-07 12:09:54 -08008541 // check if error reporting is enabled in secure settings
8542 int enabled = Settings.Secure.getInt(mContext.getContentResolver(),
8543 Settings.Secure.SEND_ACTION_APP_ERROR, 0);
Jacek Surazskia2339432009-09-18 15:01:26 +02008544 if (enabled == 0) {
8545 return null;
8546 }
8547
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008548 IPackageManager pm = ActivityThread.getPackageManager();
Jacek Surazski82a73df2009-06-17 14:33:18 +02008549
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008550 try {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008551 // look for receiver in the installer package
8552 String candidate = pm.getInstallerPackageName(app.info.packageName);
8553 ComponentName result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8554 if (result != null) {
8555 return result;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008556 }
8557
Jacek Surazski82a73df2009-06-17 14:33:18 +02008558 // if the error app is on the system image, look for system apps
8559 // error receiver
8560 if ((app.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8561 candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
8562 result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8563 if (result != null) {
8564 return result;
8565 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008566 }
8567
Jacek Surazski82a73df2009-06-17 14:33:18 +02008568 // if there is a default receiver, try that
8569 candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
8570 return getErrorReportReceiver(pm, app.info.packageName, candidate);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008571 } catch (RemoteException e) {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008572 // should not happen
8573 Log.e(TAG, "error talking to PackageManager", e);
8574 return null;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008575 }
Jacek Surazski82a73df2009-06-17 14:33:18 +02008576 }
8577
8578 /**
8579 * Return activity in receiverPackage that handles ACTION_APP_ERROR.
8580 *
8581 * @param pm PackageManager isntance
8582 * @param errorPackage package which caused the error
8583 * @param receiverPackage candidate package to receive the error
8584 * @return activity component within receiverPackage which handles
8585 * ACTION_APP_ERROR, or null if not found
8586 */
8587 private ComponentName getErrorReportReceiver(IPackageManager pm, String errorPackage,
8588 String receiverPackage) throws RemoteException {
8589 if (receiverPackage == null || receiverPackage.length() == 0) {
8590 return null;
8591 }
8592
8593 // break the loop if it's the error report receiver package that crashed
8594 if (receiverPackage.equals(errorPackage)) {
8595 return null;
8596 }
8597
8598 Intent intent = new Intent(Intent.ACTION_APP_ERROR);
8599 intent.setPackage(receiverPackage);
8600 ResolveInfo info = pm.resolveIntent(intent, null, 0);
8601 if (info == null || info.activityInfo == null) {
8602 return null;
8603 }
8604 return new ComponentName(receiverPackage, info.activityInfo.name);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008605 }
8606
Dan Egnorb7f03672009-12-09 16:22:32 -08008607 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008608 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008610 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008611 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8612 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 startAppProblemLocked(app);
8614 app.stopFreezingAllLocked();
8615 }
8616
8617 /**
8618 * Generate a process error record, suitable for attachment to a ProcessRecord.
8619 *
8620 * @param app The ProcessRecord in which the error occurred.
8621 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8622 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008623 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 * @param shortMsg Short message describing the crash.
8625 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008626 * @param stackTrace Full crash stack trace, may be null.
8627 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008628 * @return Returns a fully-formed AppErrorStateInfo record.
8629 */
8630 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008631 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 report.condition = condition;
8635 report.processName = app.processName;
8636 report.pid = app.pid;
8637 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008638 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 report.shortMsg = shortMsg;
8640 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008641 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642
8643 return report;
8644 }
8645
Dan Egnor42471dd2010-01-07 17:25:22 -08008646 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 synchronized (this) {
8648 app.crashing = false;
8649 app.crashingReport = null;
8650 app.notResponding = false;
8651 app.notRespondingReport = null;
8652 if (app.anrDialog == fromDialog) {
8653 app.anrDialog = null;
8654 }
8655 if (app.waitDialog == fromDialog) {
8656 app.waitDialog = null;
8657 }
8658 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008659 handleAppCrashLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 Log.i(ActivityManagerService.TAG, "Killing process "
8661 + app.processName
8662 + " (pid=" + app.pid + ") at user's request");
8663 Process.killProcess(app.pid);
8664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008665 }
8666 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008667
Dan Egnorb7f03672009-12-09 16:22:32 -08008668 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 long now = SystemClock.uptimeMillis();
8670
8671 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8672 app.info.uid);
8673 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8674 // This process loses!
8675 Log.w(TAG, "Process " + app.info.processName
8676 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008677 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 app.info.processName, app.info.uid);
8679 killServicesLocked(app, false);
8680 for (int i=mHistory.size()-1; i>=0; i--) {
8681 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8682 if (r.app == app) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08008683 Log.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 + r.intent.getComponent().flattenToShortString());
8685 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8686 }
8687 }
8688 if (!app.persistent) {
8689 // We don't want to start this process again until the user
8690 // explicitly does so... but for persistent process, we really
8691 // need to keep it running. If a persistent process is actually
8692 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008693 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 app.info.processName);
8695 mBadProcesses.put(app.info.processName, app.info.uid, now);
8696 app.bad = true;
8697 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8698 app.removed = true;
8699 removeProcessLocked(app, false);
8700 return false;
8701 }
8702 }
8703
8704 // Bump up the crash count of any services currently running in the proc.
8705 if (app.services.size() != 0) {
8706 // Any services running in the application need to be placed
8707 // back in the pending list.
8708 Iterator it = app.services.iterator();
8709 while (it.hasNext()) {
8710 ServiceRecord sr = (ServiceRecord)it.next();
8711 sr.crashCount++;
8712 }
8713 }
8714
8715 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8716 return true;
8717 }
8718
8719 void startAppProblemLocked(ProcessRecord app) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008720 app.errorReportReceiver = getErrorReportReceiver(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 skipCurrentReceiverLocked(app);
8722 }
8723
8724 void skipCurrentReceiverLocked(ProcessRecord app) {
8725 boolean reschedule = false;
8726 BroadcastRecord r = app.curReceiver;
8727 if (r != null) {
8728 // The current broadcast is waiting for this app's receiver
8729 // to be finished. Looks like that's not going to happen, so
8730 // let the broadcast continue.
8731 logBroadcastReceiverDiscard(r);
8732 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8733 r.resultExtras, r.resultAbort, true);
8734 reschedule = true;
8735 }
8736 r = mPendingBroadcast;
8737 if (r != null && r.curApp == app) {
8738 if (DEBUG_BROADCAST) Log.v(TAG,
8739 "skip & discard pending app " + r);
8740 logBroadcastReceiverDiscard(r);
8741 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8742 r.resultExtras, r.resultAbort, true);
8743 reschedule = true;
8744 }
8745 if (reschedule) {
8746 scheduleBroadcastsLocked();
8747 }
8748 }
8749
Dan Egnor60d87622009-12-16 16:32:58 -08008750 /**
8751 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8752 * The application process will exit immediately after this call returns.
8753 * @param app object of the crashing app, null for the system server
8754 * @param crashInfo describing the exception
8755 */
8756 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8757 ProcessRecord r = findAppProcess(app);
8758
8759 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8760 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008761 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008762 crashInfo.exceptionClassName,
8763 crashInfo.exceptionMessage,
8764 crashInfo.throwFileName,
8765 crashInfo.throwLineNumber);
8766
Dan Egnor42471dd2010-01-07 17:25:22 -08008767 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008768
8769 crashApplication(r, crashInfo);
8770 }
8771
8772 /**
8773 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8774 * @param app object of the crashing app, null for the system server
8775 * @param tag reported by the caller
8776 * @param crashInfo describing the context of the error
8777 * @return true if the process should exit immediately (WTF is fatal)
8778 */
8779 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008780 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008781 ProcessRecord r = findAppProcess(app);
8782
8783 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8784 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008785 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008786 tag, crashInfo.exceptionMessage);
8787
Dan Egnor42471dd2010-01-07 17:25:22 -08008788 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008789
Doug Zongker43866e02010-01-07 12:09:54 -08008790 if (Settings.Secure.getInt(mContext.getContentResolver(),
8791 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008792 crashApplication(r, crashInfo);
8793 return true;
8794 } else {
8795 return false;
8796 }
8797 }
8798
8799 /**
8800 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8801 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8802 */
8803 private ProcessRecord findAppProcess(IBinder app) {
8804 if (app == null) {
8805 return null;
8806 }
8807
8808 synchronized (this) {
8809 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8810 final int NA = apps.size();
8811 for (int ia=0; ia<NA; ia++) {
8812 ProcessRecord p = apps.valueAt(ia);
8813 if (p.thread != null && p.thread.asBinder() == app) {
8814 return p;
8815 }
8816 }
8817 }
8818
8819 Log.w(TAG, "Can't find mystery application: " + app);
8820 return null;
8821 }
8822 }
8823
8824 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008825 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008826 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008827 * @param process which caused the error, null means the system server
8828 * @param activity which triggered the error, null if unknown
8829 * @param parent activity related to the error, null if unknown
8830 * @param subject line related to the error, null if absent
8831 * @param report in long form describing the error, null if absent
8832 * @param logFile to include in the report, null if none
8833 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008834 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008835 private void addErrorToDropBox(String eventType,
8836 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8837 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008838 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008839 String dropboxTag;
8840 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008841 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008842 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008843 dropboxTag = "system_app_" + eventType;
8844 } else {
8845 dropboxTag = "data_app_" + eventType;
8846 }
8847
8848 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8849 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8850 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008851 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008852 sb.append("Process: system_server\n");
8853 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008854 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008855 }
8856 if (process != null) {
8857 int flags = process.info.flags;
8858 IPackageManager pm = ActivityThread.getPackageManager();
8859 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8860 for (String pkg : process.pkgList) {
8861 sb.append("Package: ").append(pkg);
8862 try {
8863 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8864 if (pi != null) {
8865 sb.append(" v").append(pi.versionCode);
8866 if (pi.versionName != null) {
8867 sb.append(" (").append(pi.versionName).append(")");
8868 }
8869 }
8870 } catch (RemoteException e) {
8871 Log.e(TAG, "Error getting package info: " + pkg, e);
8872 }
8873 sb.append("\n");
8874 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008875 }
8876 if (activity != null) {
8877 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8878 }
8879 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8880 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8881 }
8882 if (parent != null && parent != activity) {
8883 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8884 }
8885 if (subject != null) {
8886 sb.append("Subject: ").append(subject).append("\n");
8887 }
8888 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8889 sb.append("\n");
8890 if (report != null) {
8891 sb.append(report);
8892 }
8893 if (logFile != null) {
8894 try {
8895 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8896 } catch (IOException e) {
8897 Log.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008898 }
8899 }
Dan Egnor60d87622009-12-16 16:32:58 -08008900 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008901 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08008902 }
8903 dbox.addText(dropboxTag, sb.toString());
8904 }
8905 }
8906
8907 /**
8908 * Bring up the "unexpected error" dialog box for a crashing app.
8909 * Deal with edge cases (intercepts from instrumented applications,
8910 * ActivityController, error intent receivers, that sort of thing).
8911 * @param r the application crashing
8912 * @param crashInfo describing the failure
8913 */
8914 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008915 long timeMillis = System.currentTimeMillis();
8916 String shortMsg = crashInfo.exceptionClassName;
8917 String longMsg = crashInfo.exceptionMessage;
8918 String stackTrace = crashInfo.stackTrace;
8919 if (shortMsg != null && longMsg != null) {
8920 longMsg = shortMsg + ": " + longMsg;
8921 } else if (shortMsg != null) {
8922 longMsg = shortMsg;
8923 }
8924
Dan Egnor60d87622009-12-16 16:32:58 -08008925 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008927 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 try {
8929 String name = r != null ? r.processName : null;
8930 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008931 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008932 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 Log.w(TAG, "Force-killing crashed app " + name
8934 + " at watcher's request");
8935 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008936 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 }
8938 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008939 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008940 }
8941 }
8942
8943 final long origId = Binder.clearCallingIdentity();
8944
8945 // If this process is running instrumentation, finish it.
8946 if (r != null && r.instrumentationClass != null) {
8947 Log.w(TAG, "Error in app " + r.processName
8948 + " running instrumentation " + r.instrumentationClass + ":");
8949 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
8950 if (longMsg != null) Log.w(TAG, " " + longMsg);
8951 Bundle info = new Bundle();
8952 info.putString("shortMsg", shortMsg);
8953 info.putString("longMsg", longMsg);
8954 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8955 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008956 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 }
8958
Dan Egnor60d87622009-12-16 16:32:58 -08008959 // If we can't identify the process or it's already exceeded its crash quota,
8960 // quit right away without showing a crash dialog.
8961 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008963 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 }
8965
8966 Message msg = Message.obtain();
8967 msg.what = SHOW_ERROR_MSG;
8968 HashMap data = new HashMap();
8969 data.put("result", result);
8970 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008971 msg.obj = data;
8972 mHandler.sendMessage(msg);
8973
8974 Binder.restoreCallingIdentity(origId);
8975 }
8976
8977 int res = result.get();
8978
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008979 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008980 synchronized (this) {
8981 if (r != null) {
8982 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8983 SystemClock.uptimeMillis());
8984 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008985 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008986 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008987 }
8988 }
8989
8990 if (appErrorIntent != null) {
8991 try {
8992 mContext.startActivity(appErrorIntent);
8993 } catch (ActivityNotFoundException e) {
8994 Log.w(TAG, "bug report receiver dissappeared", e);
8995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 }
Dan Egnorb7f03672009-12-09 16:22:32 -08008998
8999 Intent createAppErrorIntentLocked(ProcessRecord r,
9000 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9001 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009002 if (report == null) {
9003 return null;
9004 }
9005 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9006 result.setComponent(r.errorReportReceiver);
9007 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9008 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9009 return result;
9010 }
9011
Dan Egnorb7f03672009-12-09 16:22:32 -08009012 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9013 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009014 if (r.errorReportReceiver == null) {
9015 return null;
9016 }
9017
9018 if (!r.crashing && !r.notResponding) {
9019 return null;
9020 }
9021
Dan Egnorb7f03672009-12-09 16:22:32 -08009022 ApplicationErrorReport report = new ApplicationErrorReport();
9023 report.packageName = r.info.packageName;
9024 report.installerPackageName = r.errorReportReceiver.getPackageName();
9025 report.processName = r.processName;
9026 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009027 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009028
Dan Egnorb7f03672009-12-09 16:22:32 -08009029 if (r.crashing) {
9030 report.type = ApplicationErrorReport.TYPE_CRASH;
9031 report.crashInfo = crashInfo;
9032 } else if (r.notResponding) {
9033 report.type = ApplicationErrorReport.TYPE_ANR;
9034 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009035
Dan Egnorb7f03672009-12-09 16:22:32 -08009036 report.anrInfo.activity = r.notRespondingReport.tag;
9037 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9038 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009039 }
9040
Dan Egnorb7f03672009-12-09 16:22:32 -08009041 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009042 }
9043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9045 // assume our apps are happy - lazy create the list
9046 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9047
9048 synchronized (this) {
9049
9050 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009051 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9052 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9054 // This one's in trouble, so we'll generate a report for it
9055 // crashes are higher priority (in case there's a crash *and* an anr)
9056 ActivityManager.ProcessErrorStateInfo report = null;
9057 if (app.crashing) {
9058 report = app.crashingReport;
9059 } else if (app.notResponding) {
9060 report = app.notRespondingReport;
9061 }
9062
9063 if (report != null) {
9064 if (errList == null) {
9065 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9066 }
9067 errList.add(report);
9068 } else {
9069 Log.w(TAG, "Missing app error report, app = " + app.processName +
9070 " crashing = " + app.crashing +
9071 " notResponding = " + app.notResponding);
9072 }
9073 }
9074 }
9075 }
9076
9077 return errList;
9078 }
9079
9080 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9081 // Lazy instantiation of list
9082 List<ActivityManager.RunningAppProcessInfo> runList = null;
9083 synchronized (this) {
9084 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009085 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9086 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9088 // Generate process state info for running application
9089 ActivityManager.RunningAppProcessInfo currApp =
9090 new ActivityManager.RunningAppProcessInfo(app.processName,
9091 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009092 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009094 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009095 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9096 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9097 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009098 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9099 } else if (adj >= HOME_APP_ADJ) {
9100 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9101 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 } else if (adj >= SECONDARY_SERVER_ADJ) {
9103 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9104 } else if (adj >= VISIBLE_APP_ADJ) {
9105 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9106 } else {
9107 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9108 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009109 currApp.importanceReasonCode = app.adjTypeCode;
9110 if (app.adjSource instanceof ProcessRecord) {
9111 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9112 } else if (app.adjSource instanceof HistoryRecord) {
9113 HistoryRecord r = (HistoryRecord)app.adjSource;
9114 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9115 }
9116 if (app.adjTarget instanceof ComponentName) {
9117 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
9120 // + " lru=" + currApp.lru);
9121 if (runList == null) {
9122 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9123 }
9124 runList.add(currApp);
9125 }
9126 }
9127 }
9128 return runList;
9129 }
9130
9131 @Override
9132 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009133 if (checkCallingPermission(android.Manifest.permission.DUMP)
9134 != PackageManager.PERMISSION_GRANTED) {
9135 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9136 + Binder.getCallingPid()
9137 + ", uid=" + Binder.getCallingUid()
9138 + " without permission "
9139 + android.Manifest.permission.DUMP);
9140 return;
9141 }
9142
9143 boolean dumpAll = false;
9144
9145 int opti = 0;
9146 while (opti < args.length) {
9147 String opt = args[opti];
9148 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9149 break;
9150 }
9151 opti++;
9152 if ("-a".equals(opt)) {
9153 dumpAll = true;
9154 } else if ("-h".equals(opt)) {
9155 pw.println("Activity manager dump options:");
9156 pw.println(" [-a] [h- [cmd] ...");
9157 pw.println(" cmd may be one of:");
9158 pw.println(" activities: activity stack state");
9159 pw.println(" broadcasts: broadcast state");
9160 pw.println(" intents: pending intent state");
9161 pw.println(" processes: process state");
9162 pw.println(" providers: content provider state");
9163 pw.println(" services: service state");
9164 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009166 } else {
9167 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009169 }
9170
9171 // Is the caller requesting to dump a particular piece of data?
9172 if (opti < args.length) {
9173 String cmd = args[opti];
9174 opti++;
9175 if ("activities".equals(cmd) || "a".equals(cmd)) {
9176 synchronized (this) {
9177 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009179 return;
9180 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9181 synchronized (this) {
9182 dumpBroadcastsLocked(fd, pw, args, opti, true);
9183 }
9184 return;
9185 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9186 synchronized (this) {
9187 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9188 }
9189 return;
9190 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9191 synchronized (this) {
9192 dumpProcessesLocked(fd, pw, args, opti, true);
9193 }
9194 return;
9195 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9196 synchronized (this) {
9197 dumpProvidersLocked(fd, pw, args, opti, true);
9198 }
9199 return;
9200 } else if ("service".equals(cmd)) {
9201 dumpService(fd, pw, args, opti, true);
9202 return;
9203 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9204 synchronized (this) {
9205 dumpServicesLocked(fd, pw, args, opti, true);
9206 }
9207 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009209 }
9210
9211 // No piece of data specified, dump everything.
9212 synchronized (this) {
9213 boolean needSep;
9214 if (dumpAll) {
9215 pw.println("Providers in Current Activity Manager State:");
9216 }
9217 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9218 if (needSep) {
9219 pw.println(" ");
9220 }
9221 if (dumpAll) {
9222 pw.println("-------------------------------------------------------------------------------");
9223 pw.println("Broadcasts in Current Activity Manager State:");
9224 }
9225 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9226 if (needSep) {
9227 pw.println(" ");
9228 }
9229 if (dumpAll) {
9230 pw.println("-------------------------------------------------------------------------------");
9231 pw.println("Services in Current Activity Manager State:");
9232 }
9233 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9234 if (needSep) {
9235 pw.println(" ");
9236 }
9237 if (dumpAll) {
9238 pw.println("-------------------------------------------------------------------------------");
9239 pw.println("PendingIntents in Current Activity Manager State:");
9240 }
9241 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9242 if (needSep) {
9243 pw.println(" ");
9244 }
9245 if (dumpAll) {
9246 pw.println("-------------------------------------------------------------------------------");
9247 pw.println("Activities in Current Activity Manager State:");
9248 }
9249 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9250 if (needSep) {
9251 pw.println(" ");
9252 }
9253 if (dumpAll) {
9254 pw.println("-------------------------------------------------------------------------------");
9255 pw.println("Processes in Current Activity Manager State:");
9256 }
9257 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9258 }
9259 }
9260
9261 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9262 int opti, boolean dumpAll, boolean needHeader) {
9263 if (needHeader) {
9264 pw.println(" Activity stack:");
9265 }
9266 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9267 pw.println(" ");
9268 pw.println(" Running activities (most recent first):");
9269 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9270 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009272 pw.println(" Activities waiting for another to become visible:");
9273 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9274 }
9275 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009276 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009277 pw.println(" Activities waiting to stop:");
9278 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9279 }
9280 if (mFinishingActivities.size() > 0) {
9281 pw.println(" ");
9282 pw.println(" Activities waiting to finish:");
9283 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009286 pw.println(" ");
9287 pw.println(" mPausingActivity: " + mPausingActivity);
9288 pw.println(" mResumedActivity: " + mResumedActivity);
9289 pw.println(" mFocusedActivity: " + mFocusedActivity);
9290 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009292 if (dumpAll && mRecentTasks.size() > 0) {
9293 pw.println(" ");
9294 pw.println("Recent tasks in Current Activity Manager State:");
9295
9296 final int N = mRecentTasks.size();
9297 for (int i=0; i<N; i++) {
9298 TaskRecord tr = mRecentTasks.get(i);
9299 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9300 pw.println(tr);
9301 mRecentTasks.get(i).dump(pw, " ");
9302 }
9303 }
9304
9305 pw.println(" ");
9306 pw.println(" mCurTask: " + mCurTask);
9307
9308 return true;
9309 }
9310
9311 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9312 int opti, boolean dumpAll) {
9313 boolean needSep = false;
9314 int numPers = 0;
9315
9316 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9318 final int NA = procs.size();
9319 for (int ia=0; ia<NA; ia++) {
9320 if (!needSep) {
9321 pw.println(" All known processes:");
9322 needSep = true;
9323 }
9324 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009325 pw.print(r.persistent ? " *PERS*" : " *APP*");
9326 pw.print(" UID "); pw.print(procs.keyAt(ia));
9327 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009328 r.dump(pw, " ");
9329 if (r.persistent) {
9330 numPers++;
9331 }
9332 }
9333 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009334 }
9335
9336 if (mLruProcesses.size() > 0) {
9337 if (needSep) pw.println(" ");
9338 needSep = true;
9339 pw.println(" Running processes (most recent first):");
9340 dumpProcessList(pw, this, mLruProcesses, " ",
9341 "App ", "PERS", true);
9342 needSep = true;
9343 }
9344
9345 synchronized (mPidsSelfLocked) {
9346 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 if (needSep) pw.println(" ");
9348 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009349 pw.println(" PID mappings:");
9350 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9351 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9352 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009353 }
9354 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009355 }
9356
9357 if (mForegroundProcesses.size() > 0) {
9358 if (needSep) pw.println(" ");
9359 needSep = true;
9360 pw.println(" Foreground Processes:");
9361 for (int i=0; i<mForegroundProcesses.size(); i++) {
9362 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9363 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009364 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009365 }
9366
9367 if (mPersistentStartingProcesses.size() > 0) {
9368 if (needSep) pw.println(" ");
9369 needSep = true;
9370 pw.println(" Persisent processes that are starting:");
9371 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9372 "Starting Norm", "Restarting PERS", false);
9373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009375 if (mStartingProcesses.size() > 0) {
9376 if (needSep) pw.println(" ");
9377 needSep = true;
9378 pw.println(" Processes that are starting:");
9379 dumpProcessList(pw, this, mStartingProcesses, " ",
9380 "Starting Norm", "Starting PERS", false);
9381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009383 if (mRemovedProcesses.size() > 0) {
9384 if (needSep) pw.println(" ");
9385 needSep = true;
9386 pw.println(" Processes that are being removed:");
9387 dumpProcessList(pw, this, mRemovedProcesses, " ",
9388 "Removed Norm", "Removed PERS", false);
9389 }
9390
9391 if (mProcessesOnHold.size() > 0) {
9392 if (needSep) pw.println(" ");
9393 needSep = true;
9394 pw.println(" Processes that are on old until the system is ready:");
9395 dumpProcessList(pw, this, mProcessesOnHold, " ",
9396 "OnHold Norm", "OnHold PERS", false);
9397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009398
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009399 if (mProcessesToGc.size() > 0) {
9400 if (needSep) pw.println(" ");
9401 needSep = true;
9402 pw.println(" Processes that are waiting to GC:");
9403 long now = SystemClock.uptimeMillis();
9404 for (int i=0; i<mProcessesToGc.size(); i++) {
9405 ProcessRecord proc = mProcessesToGc.get(i);
9406 pw.print(" Process "); pw.println(proc);
9407 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9408 pw.print(", last gced=");
9409 pw.print(now-proc.lastRequestedGc);
9410 pw.print(" ms ago, last lowMem=");
9411 pw.print(now-proc.lastLowMemory);
9412 pw.println(" ms ago");
9413
9414 }
9415 }
9416
9417 if (mProcessCrashTimes.getMap().size() > 0) {
9418 if (needSep) pw.println(" ");
9419 needSep = true;
9420 pw.println(" Time since processes crashed:");
9421 long now = SystemClock.uptimeMillis();
9422 for (Map.Entry<String, SparseArray<Long>> procs
9423 : mProcessCrashTimes.getMap().entrySet()) {
9424 SparseArray<Long> uids = procs.getValue();
9425 final int N = uids.size();
9426 for (int i=0; i<N; i++) {
9427 pw.print(" Process "); pw.print(procs.getKey());
9428 pw.print(" uid "); pw.print(uids.keyAt(i));
9429 pw.print(": last crashed ");
9430 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009431 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009432 }
9433 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009435
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009436 if (mBadProcesses.getMap().size() > 0) {
9437 if (needSep) pw.println(" ");
9438 needSep = true;
9439 pw.println(" Bad processes:");
9440 for (Map.Entry<String, SparseArray<Long>> procs
9441 : mBadProcesses.getMap().entrySet()) {
9442 SparseArray<Long> uids = procs.getValue();
9443 final int N = uids.size();
9444 for (int i=0; i<N; i++) {
9445 pw.print(" Bad process "); pw.print(procs.getKey());
9446 pw.print(" uid "); pw.print(uids.keyAt(i));
9447 pw.print(": crashed at time ");
9448 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449 }
9450 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009453 pw.println(" ");
9454 pw.println(" mHomeProcess: " + mHomeProcess);
9455 pw.println(" mConfiguration: " + mConfiguration);
9456 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9457 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9458 || mOrigWaitForDebugger) {
9459 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9460 + " mDebugTransient=" + mDebugTransient
9461 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9462 }
9463 if (mAlwaysFinishActivities || mController != null) {
9464 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9465 + " mController=" + mController);
9466 }
9467 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 pw.println(" mStartRunning=" + mStartRunning
9470 + " mSystemReady=" + mSystemReady
9471 + " mBooting=" + mBooting
9472 + " mBooted=" + mBooted
9473 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009474 pw.println(" mGoingToSleep=" + mGoingToSleep);
9475 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009477
9478 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 }
9480
9481 /**
9482 * There are three ways to call this:
9483 * - no service specified: dump all the services
9484 * - a flattened component name that matched an existing service was specified as the
9485 * first arg: dump that one service
9486 * - the first arg isn't the flattened component name of an existing service:
9487 * dump all services whose component contains the first arg as a substring
9488 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009489 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9490 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009491 String[] newArgs;
9492 String componentNameString;
9493 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009494 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009495 componentNameString = null;
9496 newArgs = EMPTY_STRING_ARRAY;
9497 r = null;
9498 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009499 componentNameString = args[opti];
9500 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009501 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9502 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009503 newArgs = new String[args.length - opti];
9504 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009505 }
9506
9507 if (r != null) {
9508 dumpService(fd, pw, r, newArgs);
9509 } else {
9510 for (ServiceRecord r1 : mServices.values()) {
9511 if (componentNameString == null
9512 || r1.name.flattenToString().contains(componentNameString)) {
9513 dumpService(fd, pw, r1, newArgs);
9514 }
9515 }
9516 }
9517 }
9518
9519 /**
9520 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9521 * there is a thread associated with the service.
9522 */
9523 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9524 pw.println(" Service " + r.name.flattenToString());
9525 if (r.app != null && r.app.thread != null) {
9526 try {
9527 // flush anything that is already in the PrintWriter since the thread is going
9528 // to write to the file descriptor directly
9529 pw.flush();
9530 r.app.thread.dumpService(fd, r, args);
9531 pw.print("\n");
9532 } catch (RemoteException e) {
9533 pw.println("got a RemoteException while dumping the service");
9534 }
9535 }
9536 }
9537
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009538 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9539 int opti, boolean dumpAll) {
9540 boolean needSep = false;
9541
9542 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009543 if (mRegisteredReceivers.size() > 0) {
9544 pw.println(" ");
9545 pw.println(" Registered Receivers:");
9546 Iterator it = mRegisteredReceivers.values().iterator();
9547 while (it.hasNext()) {
9548 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009549 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 r.dump(pw, " ");
9551 }
9552 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 pw.println(" ");
9555 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009556 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009557 needSep = true;
9558 }
9559
9560 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9561 || mPendingBroadcast != null) {
9562 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009563 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009564 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009566 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9567 pw.println(" Broadcast #" + i + ":");
9568 mParallelBroadcasts.get(i).dump(pw, " ");
9569 }
9570 if (mOrderedBroadcasts.size() > 0) {
9571 pw.println(" ");
9572 pw.println(" Active serialized broadcasts:");
9573 }
9574 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9575 pw.println(" Serialized Broadcast #" + i + ":");
9576 mOrderedBroadcasts.get(i).dump(pw, " ");
9577 }
9578 pw.println(" ");
9579 pw.println(" Pending broadcast:");
9580 if (mPendingBroadcast != null) {
9581 mPendingBroadcast.dump(pw, " ");
9582 } else {
9583 pw.println(" (null)");
9584 }
9585 needSep = true;
9586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009588 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009589 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009590 pw.println(" Historical broadcasts:");
9591 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9592 BroadcastRecord r = mBroadcastHistory[i];
9593 if (r == null) {
9594 break;
9595 }
9596 pw.println(" Historical Broadcast #" + i + ":");
9597 r.dump(pw, " ");
9598 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009599 needSep = true;
9600 }
9601
9602 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009603 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009604 pw.println(" Sticky broadcasts:");
9605 StringBuilder sb = new StringBuilder(128);
9606 for (Map.Entry<String, ArrayList<Intent>> ent
9607 : mStickyBroadcasts.entrySet()) {
9608 pw.print(" * Sticky action "); pw.print(ent.getKey());
9609 pw.println(":");
9610 ArrayList<Intent> intents = ent.getValue();
9611 final int N = intents.size();
9612 for (int i=0; i<N; i++) {
9613 sb.setLength(0);
9614 sb.append(" Intent: ");
9615 intents.get(i).toShortString(sb, true, false);
9616 pw.println(sb.toString());
9617 Bundle bundle = intents.get(i).getExtras();
9618 if (bundle != null) {
9619 pw.print(" ");
9620 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 }
9622 }
9623 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009624 needSep = true;
9625 }
9626
9627 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009628 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009629 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 pw.println(" mHandler:");
9631 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009632 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009634
9635 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009636 }
9637
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009638 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9639 int opti, boolean dumpAll) {
9640 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009642 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 if (mServices.size() > 0) {
9644 pw.println(" Active services:");
9645 Iterator<ServiceRecord> it = mServices.values().iterator();
9646 while (it.hasNext()) {
9647 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009648 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 r.dump(pw, " ");
9650 }
9651 needSep = true;
9652 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009655 if (mPendingServices.size() > 0) {
9656 if (needSep) pw.println(" ");
9657 pw.println(" Pending services:");
9658 for (int i=0; i<mPendingServices.size(); i++) {
9659 ServiceRecord r = mPendingServices.get(i);
9660 pw.print(" * Pending "); pw.println(r);
9661 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009662 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009663 needSep = true;
9664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009665
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009666 if (mRestartingServices.size() > 0) {
9667 if (needSep) pw.println(" ");
9668 pw.println(" Restarting services:");
9669 for (int i=0; i<mRestartingServices.size(); i++) {
9670 ServiceRecord r = mRestartingServices.get(i);
9671 pw.print(" * Restarting "); pw.println(r);
9672 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009674 needSep = true;
9675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009677 if (mStoppingServices.size() > 0) {
9678 if (needSep) pw.println(" ");
9679 pw.println(" Stopping services:");
9680 for (int i=0; i<mStoppingServices.size(); i++) {
9681 ServiceRecord r = mStoppingServices.get(i);
9682 pw.print(" * Stopping "); pw.println(r);
9683 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009685 needSep = true;
9686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009688 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 if (mServiceConnections.size() > 0) {
9690 if (needSep) pw.println(" ");
9691 pw.println(" Connection bindings to services:");
9692 Iterator<ConnectionRecord> it
9693 = mServiceConnections.values().iterator();
9694 while (it.hasNext()) {
9695 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009696 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 r.dump(pw, " ");
9698 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009699 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 }
9701 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009702
9703 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 }
9705
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009706 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9707 int opti, boolean dumpAll) {
9708 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009710 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 if (mProvidersByClass.size() > 0) {
9712 if (needSep) pw.println(" ");
9713 pw.println(" Published content providers (by class):");
9714 Iterator it = mProvidersByClass.entrySet().iterator();
9715 while (it.hasNext()) {
9716 Map.Entry e = (Map.Entry)it.next();
9717 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009718 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009719 r.dump(pw, " ");
9720 }
9721 needSep = true;
9722 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009723
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009724 if (mProvidersByName.size() > 0) {
9725 pw.println(" ");
9726 pw.println(" Authority to provider mappings:");
9727 Iterator it = mProvidersByName.entrySet().iterator();
9728 while (it.hasNext()) {
9729 Map.Entry e = (Map.Entry)it.next();
9730 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9731 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9732 pw.println(r);
9733 }
9734 needSep = true;
9735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009736 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009737
9738 if (mLaunchingProviders.size() > 0) {
9739 if (needSep) pw.println(" ");
9740 pw.println(" Launching content providers:");
9741 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9742 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9743 pw.println(mLaunchingProviders.get(i));
9744 }
9745 needSep = true;
9746 }
9747
9748 if (mGrantedUriPermissions.size() > 0) {
9749 pw.println();
9750 pw.println("Granted Uri Permissions:");
9751 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9752 int uid = mGrantedUriPermissions.keyAt(i);
9753 HashMap<Uri, UriPermission> perms
9754 = mGrantedUriPermissions.valueAt(i);
9755 pw.print(" * UID "); pw.print(uid);
9756 pw.println(" holds:");
9757 for (UriPermission perm : perms.values()) {
9758 pw.print(" "); pw.println(perm);
9759 perm.dump(pw, " ");
9760 }
9761 }
9762 needSep = true;
9763 }
9764
9765 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 }
9767
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009768 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9769 int opti, boolean dumpAll) {
9770 boolean needSep = false;
9771
9772 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 if (this.mIntentSenderRecords.size() > 0) {
9774 Iterator<WeakReference<PendingIntentRecord>> it
9775 = mIntentSenderRecords.values().iterator();
9776 while (it.hasNext()) {
9777 WeakReference<PendingIntentRecord> ref = it.next();
9778 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009779 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009781 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 rec.dump(pw, " ");
9783 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009784 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 }
9786 }
9787 }
9788 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009789
9790 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 }
9792
9793 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009794 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009795 TaskRecord lastTask = null;
9796 for (int i=list.size()-1; i>=0; i--) {
9797 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009798 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799 if (lastTask != r.task) {
9800 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009801 pw.print(prefix);
9802 pw.print(full ? "* " : " ");
9803 pw.println(lastTask);
9804 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009805 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009808 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9809 pw.print(" #"); pw.print(i); pw.print(": ");
9810 pw.println(r);
9811 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009812 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009814 }
9815 }
9816
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009817 private static String buildOomTag(String prefix, String space, int val, int base) {
9818 if (val == base) {
9819 if (space == null) return prefix;
9820 return prefix + " ";
9821 }
9822 return prefix + "+" + Integer.toString(val-base);
9823 }
9824
9825 private static final int dumpProcessList(PrintWriter pw,
9826 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 String prefix, String normalLabel, String persistentLabel,
9828 boolean inclOomAdj) {
9829 int numPers = 0;
9830 for (int i=list.size()-1; i>=0; i--) {
9831 ProcessRecord r = (ProcessRecord)list.get(i);
9832 if (false) {
9833 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9834 + " #" + i + ":");
9835 r.dump(pw, prefix + " ");
9836 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009837 String oomAdj;
9838 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009839 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009840 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009841 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9842 } else if (r.setAdj >= HOME_APP_ADJ) {
9843 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9844 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9845 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9846 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9847 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9848 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9849 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9850 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9851 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009852 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009853 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009854 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009855 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009856 } else {
9857 oomAdj = Integer.toString(r.setAdj);
9858 }
9859 String schedGroup;
9860 switch (r.setSchedGroup) {
9861 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9862 schedGroup = "B";
9863 break;
9864 case Process.THREAD_GROUP_DEFAULT:
9865 schedGroup = "F";
9866 break;
9867 default:
9868 schedGroup = Integer.toString(r.setSchedGroup);
9869 break;
9870 }
9871 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009873 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009874 if (r.adjSource != null || r.adjTarget != null) {
9875 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009876 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 } else {
9879 pw.println(String.format("%s%s #%2d: %s",
9880 prefix, (r.persistent ? persistentLabel : normalLabel),
9881 i, r.toString()));
9882 }
9883 if (r.persistent) {
9884 numPers++;
9885 }
9886 }
9887 return numPers;
9888 }
9889
9890 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
9891 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009892 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009893 long uptime = SystemClock.uptimeMillis();
9894 long realtime = SystemClock.elapsedRealtime();
9895
9896 if (isCheckinRequest) {
9897 // short checkin version
9898 pw.println(uptime + "," + realtime);
9899 pw.flush();
9900 } else {
9901 pw.println("Applications Memory Usage (kB):");
9902 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9903 }
9904 for (int i = list.size() - 1 ; i >= 0 ; i--) {
9905 ProcessRecord r = (ProcessRecord)list.get(i);
9906 if (r.thread != null) {
9907 if (!isCheckinRequest) {
9908 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9909 pw.flush();
9910 }
9911 try {
9912 r.thread.asBinder().dump(fd, args);
9913 } catch (RemoteException e) {
9914 if (!isCheckinRequest) {
9915 pw.println("Got RemoteException!");
9916 pw.flush();
9917 }
9918 }
9919 }
9920 }
9921 }
9922
9923 /**
9924 * Searches array of arguments for the specified string
9925 * @param args array of argument strings
9926 * @param value value to search for
9927 * @return true if the value is contained in the array
9928 */
9929 private static boolean scanArgs(String[] args, String value) {
9930 if (args != null) {
9931 for (String arg : args) {
9932 if (value.equals(arg)) {
9933 return true;
9934 }
9935 }
9936 }
9937 return false;
9938 }
9939
Dianne Hackborn75b03852009-06-12 15:43:26 -07009940 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009941 int count = mHistory.size();
9942
9943 // convert the token to an entry in the history.
9944 HistoryRecord r = null;
9945 int index = -1;
9946 for (int i=count-1; i>=0; i--) {
9947 Object o = mHistory.get(i);
9948 if (o == token) {
9949 r = (HistoryRecord)o;
9950 index = i;
9951 break;
9952 }
9953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009954
9955 return index;
9956 }
9957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 private final void killServicesLocked(ProcessRecord app,
9959 boolean allowRestart) {
9960 // Report disconnected services.
9961 if (false) {
9962 // XXX we are letting the client link to the service for
9963 // death notifications.
9964 if (app.services.size() > 0) {
9965 Iterator it = app.services.iterator();
9966 while (it.hasNext()) {
9967 ServiceRecord r = (ServiceRecord)it.next();
9968 if (r.connections.size() > 0) {
9969 Iterator<ConnectionRecord> jt
9970 = r.connections.values().iterator();
9971 while (jt.hasNext()) {
9972 ConnectionRecord c = jt.next();
9973 if (c.binding.client != app) {
9974 try {
9975 //c.conn.connected(r.className, null);
9976 } catch (Exception e) {
9977 // todo: this should be asynchronous!
9978 Log.w(TAG, "Exception thrown disconnected servce "
9979 + r.shortName
9980 + " from app " + app.processName, e);
9981 }
9982 }
9983 }
9984 }
9985 }
9986 }
9987 }
9988
9989 // Clean up any connections this application has to other services.
9990 if (app.connections.size() > 0) {
9991 Iterator<ConnectionRecord> it = app.connections.iterator();
9992 while (it.hasNext()) {
9993 ConnectionRecord r = it.next();
9994 removeConnectionLocked(r, app, null);
9995 }
9996 }
9997 app.connections.clear();
9998
9999 if (app.services.size() != 0) {
10000 // Any services running in the application need to be placed
10001 // back in the pending list.
10002 Iterator it = app.services.iterator();
10003 while (it.hasNext()) {
10004 ServiceRecord sr = (ServiceRecord)it.next();
10005 synchronized (sr.stats.getBatteryStats()) {
10006 sr.stats.stopLaunchedLocked();
10007 }
10008 sr.app = null;
10009 sr.executeNesting = 0;
10010 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010011
10012 boolean hasClients = sr.bindings.size() > 0;
10013 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 Iterator<IntentBindRecord> bindings
10015 = sr.bindings.values().iterator();
10016 while (bindings.hasNext()) {
10017 IntentBindRecord b = bindings.next();
10018 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
10019 + ": shouldUnbind=" + b.hasBound);
10020 b.binder = null;
10021 b.requested = b.received = b.hasBound = false;
10022 }
10023 }
10024
10025 if (sr.crashCount >= 2) {
10026 Log.w(TAG, "Service crashed " + sr.crashCount
10027 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010028 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010029 sr.crashCount, sr.shortName, app.pid);
10030 bringDownServiceLocked(sr, true);
10031 } else if (!allowRestart) {
10032 bringDownServiceLocked(sr, true);
10033 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010034 boolean canceled = scheduleServiceRestartLocked(sr, true);
10035
10036 // Should the service remain running? Note that in the
10037 // extreme case of so many attempts to deliver a command
10038 // that it failed, that we also will stop it here.
10039 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10040 if (sr.pendingStarts.size() == 0) {
10041 sr.startRequested = false;
10042 if (!hasClients) {
10043 // Whoops, no reason to restart!
10044 bringDownServiceLocked(sr, true);
10045 }
10046 }
10047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010048 }
10049 }
10050
10051 if (!allowRestart) {
10052 app.services.clear();
10053 }
10054 }
10055
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010056 // Make sure we have no more records on the stopping list.
10057 int i = mStoppingServices.size();
10058 while (i > 0) {
10059 i--;
10060 ServiceRecord sr = mStoppingServices.get(i);
10061 if (sr.app == app) {
10062 mStoppingServices.remove(i);
10063 }
10064 }
10065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 app.executingServices.clear();
10067 }
10068
10069 private final void removeDyingProviderLocked(ProcessRecord proc,
10070 ContentProviderRecord cpr) {
10071 synchronized (cpr) {
10072 cpr.launchingApp = null;
10073 cpr.notifyAll();
10074 }
10075
10076 mProvidersByClass.remove(cpr.info.name);
10077 String names[] = cpr.info.authority.split(";");
10078 for (int j = 0; j < names.length; j++) {
10079 mProvidersByName.remove(names[j]);
10080 }
10081
10082 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10083 while (cit.hasNext()) {
10084 ProcessRecord capp = cit.next();
10085 if (!capp.persistent && capp.thread != null
10086 && capp.pid != 0
10087 && capp.pid != MY_PID) {
10088 Log.i(TAG, "Killing app " + capp.processName
10089 + " (pid " + capp.pid
10090 + ") because provider " + cpr.info.name
10091 + " is in dying process " + proc.processName);
10092 Process.killProcess(capp.pid);
10093 }
10094 }
10095
10096 mLaunchingProviders.remove(cpr);
10097 }
10098
10099 /**
10100 * Main code for cleaning up a process when it has gone away. This is
10101 * called both as a result of the process dying, or directly when stopping
10102 * a process when running in single process mode.
10103 */
10104 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10105 boolean restarting, int index) {
10106 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010107 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010108 }
10109
Dianne Hackborn36124872009-10-08 16:22:03 -070010110 mProcessesToGc.remove(app);
10111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 // Dismiss any open dialogs.
10113 if (app.crashDialog != null) {
10114 app.crashDialog.dismiss();
10115 app.crashDialog = null;
10116 }
10117 if (app.anrDialog != null) {
10118 app.anrDialog.dismiss();
10119 app.anrDialog = null;
10120 }
10121 if (app.waitDialog != null) {
10122 app.waitDialog.dismiss();
10123 app.waitDialog = null;
10124 }
10125
10126 app.crashing = false;
10127 app.notResponding = false;
10128
10129 app.resetPackageList();
10130 app.thread = null;
10131 app.forcingToForeground = null;
10132 app.foregroundServices = false;
10133
10134 killServicesLocked(app, true);
10135
10136 boolean restart = false;
10137
10138 int NL = mLaunchingProviders.size();
10139
10140 // Remove published content providers.
10141 if (!app.pubProviders.isEmpty()) {
10142 Iterator it = app.pubProviders.values().iterator();
10143 while (it.hasNext()) {
10144 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10145 cpr.provider = null;
10146 cpr.app = null;
10147
10148 // See if someone is waiting for this provider... in which
10149 // case we don't remove it, but just let it restart.
10150 int i = 0;
10151 if (!app.bad) {
10152 for (; i<NL; i++) {
10153 if (mLaunchingProviders.get(i) == cpr) {
10154 restart = true;
10155 break;
10156 }
10157 }
10158 } else {
10159 i = NL;
10160 }
10161
10162 if (i >= NL) {
10163 removeDyingProviderLocked(app, cpr);
10164 NL = mLaunchingProviders.size();
10165 }
10166 }
10167 app.pubProviders.clear();
10168 }
10169
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010170 // Take care of any launching providers waiting for this process.
10171 if (checkAppInLaunchingProvidersLocked(app, false)) {
10172 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 // Unregister from connected content providers.
10176 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010177 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 while (it.hasNext()) {
10179 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10180 cpr.clients.remove(app);
10181 }
10182 app.conProviders.clear();
10183 }
10184
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010185 // At this point there may be remaining entries in mLaunchingProviders
10186 // where we were the only one waiting, so they are no longer of use.
10187 // Look for these and clean up if found.
10188 // XXX Commented out for now. Trying to figure out a way to reproduce
10189 // the actual situation to identify what is actually going on.
10190 if (false) {
10191 for (int i=0; i<NL; i++) {
10192 ContentProviderRecord cpr = (ContentProviderRecord)
10193 mLaunchingProviders.get(i);
10194 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10195 synchronized (cpr) {
10196 cpr.launchingApp = null;
10197 cpr.notifyAll();
10198 }
10199 }
10200 }
10201 }
10202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 skipCurrentReceiverLocked(app);
10204
10205 // Unregister any receivers.
10206 if (app.receivers.size() > 0) {
10207 Iterator<ReceiverList> it = app.receivers.iterator();
10208 while (it.hasNext()) {
10209 removeReceiverLocked(it.next());
10210 }
10211 app.receivers.clear();
10212 }
10213
Christopher Tate181fafa2009-05-14 11:12:14 -070010214 // If the app is undergoing backup, tell the backup manager about it
10215 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
10216 if (DEBUG_BACKUP) Log.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
10217 try {
10218 IBackupManager bm = IBackupManager.Stub.asInterface(
10219 ServiceManager.getService(Context.BACKUP_SERVICE));
10220 bm.agentDisconnected(app.info.packageName);
10221 } catch (RemoteException e) {
10222 // can't happen; backup manager is local
10223 }
10224 }
10225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 // If the caller is restarting this app, then leave it in its
10227 // current lists and let the caller take care of it.
10228 if (restarting) {
10229 return;
10230 }
10231
10232 if (!app.persistent) {
10233 if (DEBUG_PROCESSES) Log.v(TAG,
10234 "Removing non-persistent process during cleanup: " + app);
10235 mProcessNames.remove(app.processName, app.info.uid);
10236 } else if (!app.removed) {
10237 // This app is persistent, so we need to keep its record around.
10238 // If it is not already on the pending app list, add it there
10239 // and start a new process for it.
10240 app.thread = null;
10241 app.forcingToForeground = null;
10242 app.foregroundServices = false;
10243 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10244 mPersistentStartingProcesses.add(app);
10245 restart = true;
10246 }
10247 }
10248 mProcessesOnHold.remove(app);
10249
The Android Open Source Project4df24232009-03-05 14:34:35 -080010250 if (app == mHomeProcess) {
10251 mHomeProcess = null;
10252 }
10253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 if (restart) {
10255 // We have components that still need to be running in the
10256 // process, so re-launch it.
10257 mProcessNames.put(app.processName, app.info.uid, app);
10258 startProcessLocked(app, "restart", app.processName);
10259 } else if (app.pid > 0 && app.pid != MY_PID) {
10260 // Goodbye!
10261 synchronized (mPidsSelfLocked) {
10262 mPidsSelfLocked.remove(app.pid);
10263 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10264 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010265 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 }
10267 }
10268
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010269 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10270 // Look through the content providers we are waiting to have launched,
10271 // and if any run in this process then either schedule a restart of
10272 // the process or kill the client waiting for it if this process has
10273 // gone bad.
10274 int NL = mLaunchingProviders.size();
10275 boolean restart = false;
10276 for (int i=0; i<NL; i++) {
10277 ContentProviderRecord cpr = (ContentProviderRecord)
10278 mLaunchingProviders.get(i);
10279 if (cpr.launchingApp == app) {
10280 if (!alwaysBad && !app.bad) {
10281 restart = true;
10282 } else {
10283 removeDyingProviderLocked(app, cpr);
10284 NL = mLaunchingProviders.size();
10285 }
10286 }
10287 }
10288 return restart;
10289 }
10290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 // =========================================================
10292 // SERVICES
10293 // =========================================================
10294
10295 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10296 ActivityManager.RunningServiceInfo info =
10297 new ActivityManager.RunningServiceInfo();
10298 info.service = r.name;
10299 if (r.app != null) {
10300 info.pid = r.app.pid;
10301 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010302 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 info.process = r.processName;
10304 info.foreground = r.isForeground;
10305 info.activeSince = r.createTime;
10306 info.started = r.startRequested;
10307 info.clientCount = r.connections.size();
10308 info.crashCount = r.crashCount;
10309 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010310 if (r.isForeground) {
10311 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10312 }
10313 if (r.startRequested) {
10314 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10315 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010316 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010317 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10318 }
10319 if (r.app != null && r.app.persistent) {
10320 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10321 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010322 for (ConnectionRecord conn : r.connections.values()) {
10323 if (conn.clientLabel != 0) {
10324 info.clientPackage = conn.binding.client.info.packageName;
10325 info.clientLabel = conn.clientLabel;
10326 break;
10327 }
10328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 return info;
10330 }
10331
10332 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10333 int flags) {
10334 synchronized (this) {
10335 ArrayList<ActivityManager.RunningServiceInfo> res
10336 = new ArrayList<ActivityManager.RunningServiceInfo>();
10337
10338 if (mServices.size() > 0) {
10339 Iterator<ServiceRecord> it = mServices.values().iterator();
10340 while (it.hasNext() && res.size() < maxNum) {
10341 res.add(makeRunningServiceInfoLocked(it.next()));
10342 }
10343 }
10344
10345 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10346 ServiceRecord r = mRestartingServices.get(i);
10347 ActivityManager.RunningServiceInfo info =
10348 makeRunningServiceInfoLocked(r);
10349 info.restarting = r.nextRestartTime;
10350 res.add(info);
10351 }
10352
10353 return res;
10354 }
10355 }
10356
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010357 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10358 synchronized (this) {
10359 ServiceRecord r = mServices.get(name);
10360 if (r != null) {
10361 for (ConnectionRecord conn : r.connections.values()) {
10362 if (conn.clientIntent != null) {
10363 return conn.clientIntent;
10364 }
10365 }
10366 }
10367 }
10368 return null;
10369 }
10370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 private final ServiceRecord findServiceLocked(ComponentName name,
10372 IBinder token) {
10373 ServiceRecord r = mServices.get(name);
10374 return r == token ? r : null;
10375 }
10376
10377 private final class ServiceLookupResult {
10378 final ServiceRecord record;
10379 final String permission;
10380
10381 ServiceLookupResult(ServiceRecord _record, String _permission) {
10382 record = _record;
10383 permission = _permission;
10384 }
10385 };
10386
10387 private ServiceLookupResult findServiceLocked(Intent service,
10388 String resolvedType) {
10389 ServiceRecord r = null;
10390 if (service.getComponent() != null) {
10391 r = mServices.get(service.getComponent());
10392 }
10393 if (r == null) {
10394 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10395 r = mServicesByIntent.get(filter);
10396 }
10397
10398 if (r == null) {
10399 try {
10400 ResolveInfo rInfo =
10401 ActivityThread.getPackageManager().resolveService(
10402 service, resolvedType, 0);
10403 ServiceInfo sInfo =
10404 rInfo != null ? rInfo.serviceInfo : null;
10405 if (sInfo == null) {
10406 return null;
10407 }
10408
10409 ComponentName name = new ComponentName(
10410 sInfo.applicationInfo.packageName, sInfo.name);
10411 r = mServices.get(name);
10412 } catch (RemoteException ex) {
10413 // pm is in same process, this will never happen.
10414 }
10415 }
10416 if (r != null) {
10417 int callingPid = Binder.getCallingPid();
10418 int callingUid = Binder.getCallingUid();
10419 if (checkComponentPermission(r.permission,
10420 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10421 != PackageManager.PERMISSION_GRANTED) {
10422 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10423 + " from pid=" + callingPid
10424 + ", uid=" + callingUid
10425 + " requires " + r.permission);
10426 return new ServiceLookupResult(null, r.permission);
10427 }
10428 return new ServiceLookupResult(r, null);
10429 }
10430 return null;
10431 }
10432
10433 private class ServiceRestarter implements Runnable {
10434 private ServiceRecord mService;
10435
10436 void setService(ServiceRecord service) {
10437 mService = service;
10438 }
10439
10440 public void run() {
10441 synchronized(ActivityManagerService.this) {
10442 performServiceRestartLocked(mService);
10443 }
10444 }
10445 }
10446
10447 private ServiceLookupResult retrieveServiceLocked(Intent service,
10448 String resolvedType, int callingPid, int callingUid) {
10449 ServiceRecord r = null;
10450 if (service.getComponent() != null) {
10451 r = mServices.get(service.getComponent());
10452 }
10453 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10454 r = mServicesByIntent.get(filter);
10455 if (r == null) {
10456 try {
10457 ResolveInfo rInfo =
10458 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010459 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 ServiceInfo sInfo =
10461 rInfo != null ? rInfo.serviceInfo : null;
10462 if (sInfo == null) {
10463 Log.w(TAG, "Unable to start service " + service +
10464 ": not found");
10465 return null;
10466 }
10467
10468 ComponentName name = new ComponentName(
10469 sInfo.applicationInfo.packageName, sInfo.name);
10470 r = mServices.get(name);
10471 if (r == null) {
10472 filter = new Intent.FilterComparison(service.cloneFilter());
10473 ServiceRestarter res = new ServiceRestarter();
10474 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10475 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10476 synchronized (stats) {
10477 ss = stats.getServiceStatsLocked(
10478 sInfo.applicationInfo.uid, sInfo.packageName,
10479 sInfo.name);
10480 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010481 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482 res.setService(r);
10483 mServices.put(name, r);
10484 mServicesByIntent.put(filter, r);
10485
10486 // Make sure this component isn't in the pending list.
10487 int N = mPendingServices.size();
10488 for (int i=0; i<N; i++) {
10489 ServiceRecord pr = mPendingServices.get(i);
10490 if (pr.name.equals(name)) {
10491 mPendingServices.remove(i);
10492 i--;
10493 N--;
10494 }
10495 }
10496 }
10497 } catch (RemoteException ex) {
10498 // pm is in same process, this will never happen.
10499 }
10500 }
10501 if (r != null) {
10502 if (checkComponentPermission(r.permission,
10503 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10504 != PackageManager.PERMISSION_GRANTED) {
10505 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10506 + " from pid=" + Binder.getCallingPid()
10507 + ", uid=" + Binder.getCallingUid()
10508 + " requires " + r.permission);
10509 return new ServiceLookupResult(null, r.permission);
10510 }
10511 return new ServiceLookupResult(r, null);
10512 }
10513 return null;
10514 }
10515
10516 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10517 long now = SystemClock.uptimeMillis();
10518 if (r.executeNesting == 0 && r.app != null) {
10519 if (r.app.executingServices.size() == 0) {
10520 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10521 msg.obj = r.app;
10522 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10523 }
10524 r.app.executingServices.add(r);
10525 }
10526 r.executeNesting++;
10527 r.executingStart = now;
10528 }
10529
10530 private final void sendServiceArgsLocked(ServiceRecord r,
10531 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010532 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 if (N == 0) {
10534 return;
10535 }
10536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010537 int i = 0;
10538 while (i < N) {
10539 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010540 ServiceRecord.StartItem si = r.pendingStarts.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010542 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010543 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010544 // If somehow we got a dummy start at the front, then
10545 // just drop it here.
10546 i++;
10547 continue;
10548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010549 bumpServiceExecutingLocked(r);
10550 if (!oomAdjusted) {
10551 oomAdjusted = true;
10552 updateOomAdjLocked(r.app);
10553 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010554 int flags = 0;
10555 if (si.deliveryCount > 0) {
10556 flags |= Service.START_FLAG_RETRY;
10557 }
10558 if (si.doneExecutingCount > 0) {
10559 flags |= Service.START_FLAG_REDELIVERY;
10560 }
10561 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10562 si.deliveredTime = SystemClock.uptimeMillis();
10563 r.deliveredStarts.add(si);
10564 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010565 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010566 } catch (RemoteException e) {
10567 // Remote process gone... we'll let the normal cleanup take
10568 // care of this.
10569 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 } catch (Exception e) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010571 Log.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010572 break;
10573 }
10574 }
10575 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010576 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010577 } else {
10578 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010580 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 }
10582 }
10583 }
10584
10585 private final boolean requestServiceBindingLocked(ServiceRecord r,
10586 IntentBindRecord i, boolean rebind) {
10587 if (r.app == null || r.app.thread == null) {
10588 // If service is not currently running, can't yet bind.
10589 return false;
10590 }
10591 if ((!i.requested || rebind) && i.apps.size() > 0) {
10592 try {
10593 bumpServiceExecutingLocked(r);
10594 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
10595 + ": shouldUnbind=" + i.hasBound);
10596 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10597 if (!rebind) {
10598 i.requested = true;
10599 }
10600 i.hasBound = true;
10601 i.doRebind = false;
10602 } catch (RemoteException e) {
10603 return false;
10604 }
10605 }
10606 return true;
10607 }
10608
10609 private final void requestServiceBindingsLocked(ServiceRecord r) {
10610 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10611 while (bindings.hasNext()) {
10612 IntentBindRecord i = bindings.next();
10613 if (!requestServiceBindingLocked(r, i, false)) {
10614 break;
10615 }
10616 }
10617 }
10618
10619 private final void realStartServiceLocked(ServiceRecord r,
10620 ProcessRecord app) throws RemoteException {
10621 if (app.thread == null) {
10622 throw new RemoteException();
10623 }
10624
10625 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010626 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010627
10628 app.services.add(r);
10629 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010630 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631
10632 boolean created = false;
10633 try {
10634 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
10635 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010636 mStringBuilder.setLength(0);
10637 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010638 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010640 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 synchronized (r.stats.getBatteryStats()) {
10642 r.stats.startLaunchedLocked();
10643 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010644 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010646 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010647 created = true;
10648 } finally {
10649 if (!created) {
10650 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010651 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 }
10653 }
10654
10655 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010656
10657 // If the service is in the started state, and there are no
10658 // pending arguments, then fake up one so its onStartCommand() will
10659 // be called.
10660 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10661 r.lastStartId++;
10662 if (r.lastStartId < 1) {
10663 r.lastStartId = 1;
10664 }
10665 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10666 }
10667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010668 sendServiceArgsLocked(r, true);
10669 }
10670
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010671 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10672 boolean allowCancel) {
10673 boolean canceled = false;
10674
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010675 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010676 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010677 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010678
10679 // Any delivered but not yet finished starts should be put back
10680 // on the pending list.
10681 final int N = r.deliveredStarts.size();
10682 if (N > 0) {
10683 for (int i=N-1; i>=0; i--) {
10684 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10685 if (si.intent == null) {
10686 // We'll generate this again if needed.
10687 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10688 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10689 r.pendingStarts.add(0, si);
10690 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10691 dur *= 2;
10692 if (minDuration < dur) minDuration = dur;
10693 if (resetTime < dur) resetTime = dur;
10694 } else {
10695 Log.w(TAG, "Canceling start item " + si.intent + " in service "
10696 + r.name);
10697 canceled = true;
10698 }
10699 }
10700 r.deliveredStarts.clear();
10701 }
10702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 r.totalRestartCount++;
10704 if (r.restartDelay == 0) {
10705 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010706 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 } else {
10708 // If it has been a "reasonably long time" since the service
10709 // was started, then reset our restart duration back to
10710 // the beginning, so we don't infinitely increase the duration
10711 // on a service that just occasionally gets killed (which is
10712 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010713 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010714 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010715 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010717 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010718 if (r.restartDelay < minDuration) {
10719 r.restartDelay = minDuration;
10720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 }
10722 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010723
10724 r.nextRestartTime = now + r.restartDelay;
10725
10726 // Make sure that we don't end up restarting a bunch of services
10727 // all at the same time.
10728 boolean repeat;
10729 do {
10730 repeat = false;
10731 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10732 ServiceRecord r2 = mRestartingServices.get(i);
10733 if (r2 != r && r.nextRestartTime
10734 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10735 && r.nextRestartTime
10736 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10737 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10738 r.restartDelay = r.nextRestartTime - now;
10739 repeat = true;
10740 break;
10741 }
10742 }
10743 } while (repeat);
10744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010745 if (!mRestartingServices.contains(r)) {
10746 mRestartingServices.add(r);
10747 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010748
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010749 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010752 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
10754 Log.w(TAG, "Scheduling restart of crashed service "
10755 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010756 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 r.shortName, r.restartDelay);
10758
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010759 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760 }
10761
10762 final void performServiceRestartLocked(ServiceRecord r) {
10763 if (!mRestartingServices.contains(r)) {
10764 return;
10765 }
10766 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10767 }
10768
10769 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10770 if (r.restartDelay == 0) {
10771 return false;
10772 }
10773 r.resetRestartCounter();
10774 mRestartingServices.remove(r);
10775 mHandler.removeCallbacks(r.restarter);
10776 return true;
10777 }
10778
10779 private final boolean bringUpServiceLocked(ServiceRecord r,
10780 int intentFlags, boolean whileRestarting) {
10781 //Log.i(TAG, "Bring up service:");
10782 //r.dump(" ");
10783
Dianne Hackborn36124872009-10-08 16:22:03 -070010784 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 sendServiceArgsLocked(r, false);
10786 return true;
10787 }
10788
10789 if (!whileRestarting && r.restartDelay > 0) {
10790 // If waiting for a restart, then do nothing.
10791 return true;
10792 }
10793
10794 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
10795 + " " + r.intent);
10796
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010797 // We are now bringing the service up, so no longer in the
10798 // restarting state.
10799 mRestartingServices.remove(r);
10800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 final String appName = r.processName;
10802 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10803 if (app != null && app.thread != null) {
10804 try {
10805 realStartServiceLocked(r, app);
10806 return true;
10807 } catch (RemoteException e) {
10808 Log.w(TAG, "Exception when starting service " + r.shortName, e);
10809 }
10810
10811 // If a dead object exception was thrown -- fall through to
10812 // restart the application.
10813 }
10814
Dianne Hackborn36124872009-10-08 16:22:03 -070010815 // Not running -- get it started, and enqueue this service record
10816 // to be executed when the app comes up.
10817 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10818 "service", r.name, false) == null) {
10819 Log.w(TAG, "Unable to launch app "
10820 + r.appInfo.packageName + "/"
10821 + r.appInfo.uid + " for service "
10822 + r.intent.getIntent() + ": process is bad");
10823 bringDownServiceLocked(r, true);
10824 return false;
10825 }
10826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010828 mPendingServices.add(r);
10829 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 return true;
10832 }
10833
10834 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
10835 //Log.i(TAG, "Bring down service:");
10836 //r.dump(" ");
10837
10838 // Does it still need to run?
10839 if (!force && r.startRequested) {
10840 return;
10841 }
10842 if (r.connections.size() > 0) {
10843 if (!force) {
10844 // XXX should probably keep a count of the number of auto-create
10845 // connections directly in the service.
10846 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10847 while (it.hasNext()) {
10848 ConnectionRecord cr = it.next();
10849 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10850 return;
10851 }
10852 }
10853 }
10854
10855 // Report to all of the connections that the service is no longer
10856 // available.
10857 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10858 while (it.hasNext()) {
10859 ConnectionRecord c = it.next();
10860 try {
10861 // todo: shouldn't be a synchronous call!
10862 c.conn.connected(r.name, null);
10863 } catch (Exception e) {
10864 Log.w(TAG, "Failure disconnecting service " + r.name +
10865 " to connection " + c.conn.asBinder() +
10866 " (in " + c.binding.client.processName + ")", e);
10867 }
10868 }
10869 }
10870
10871 // Tell the service that it has been unbound.
10872 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10873 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10874 while (it.hasNext()) {
10875 IntentBindRecord ibr = it.next();
10876 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
10877 + ": hasBound=" + ibr.hasBound);
10878 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10879 try {
10880 bumpServiceExecutingLocked(r);
10881 updateOomAdjLocked(r.app);
10882 ibr.hasBound = false;
10883 r.app.thread.scheduleUnbindService(r,
10884 ibr.intent.getIntent());
10885 } catch (Exception e) {
10886 Log.w(TAG, "Exception when unbinding service "
10887 + r.shortName, e);
10888 serviceDoneExecutingLocked(r, true);
10889 }
10890 }
10891 }
10892 }
10893
10894 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
10895 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010896 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010897 System.identityHashCode(r), r.shortName,
10898 (r.app != null) ? r.app.pid : -1);
10899
10900 mServices.remove(r.name);
10901 mServicesByIntent.remove(r.intent);
10902 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
10903 r.totalRestartCount = 0;
10904 unscheduleServiceRestartLocked(r);
10905
10906 // Also make sure it is not on the pending list.
10907 int N = mPendingServices.size();
10908 for (int i=0; i<N; i++) {
10909 if (mPendingServices.get(i) == r) {
10910 mPendingServices.remove(i);
10911 if (DEBUG_SERVICE) Log.v(
10912 TAG, "Removed pending service: " + r.shortName);
10913 i--;
10914 N--;
10915 }
10916 }
10917
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010918 r.cancelNotification();
10919 r.isForeground = false;
10920 r.foregroundId = 0;
10921 r.foregroundNoti = null;
10922
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010923 // Clear start entries.
10924 r.deliveredStarts.clear();
10925 r.pendingStarts.clear();
10926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 if (r.app != null) {
10928 synchronized (r.stats.getBatteryStats()) {
10929 r.stats.stopLaunchedLocked();
10930 }
10931 r.app.services.remove(r);
10932 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 try {
Dianne Hackborna1e989b2009-09-01 19:54:29 -070010934 if (DEBUG_SERVICE) Log.v(TAG,
10935 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 bumpServiceExecutingLocked(r);
10937 mStoppingServices.add(r);
10938 updateOomAdjLocked(r.app);
10939 r.app.thread.scheduleStopService(r);
10940 } catch (Exception e) {
10941 Log.w(TAG, "Exception when stopping service "
10942 + r.shortName, e);
10943 serviceDoneExecutingLocked(r, true);
10944 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010945 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 } else {
10947 if (DEBUG_SERVICE) Log.v(
10948 TAG, "Removed service that has no process: " + r.shortName);
10949 }
10950 } else {
10951 if (DEBUG_SERVICE) Log.v(
10952 TAG, "Removed service that is not running: " + r.shortName);
10953 }
10954 }
10955
10956 ComponentName startServiceLocked(IApplicationThread caller,
10957 Intent service, String resolvedType,
10958 int callingPid, int callingUid) {
10959 synchronized(this) {
10960 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
10961 + " type=" + resolvedType + " args=" + service.getExtras());
10962
10963 if (caller != null) {
10964 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10965 if (callerApp == null) {
10966 throw new SecurityException(
10967 "Unable to find app for caller " + caller
10968 + " (pid=" + Binder.getCallingPid()
10969 + ") when starting service " + service);
10970 }
10971 }
10972
10973 ServiceLookupResult res =
10974 retrieveServiceLocked(service, resolvedType,
10975 callingPid, callingUid);
10976 if (res == null) {
10977 return null;
10978 }
10979 if (res.record == null) {
10980 return new ComponentName("!", res.permission != null
10981 ? res.permission : "private to package");
10982 }
10983 ServiceRecord r = res.record;
10984 if (unscheduleServiceRestartLocked(r)) {
10985 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
10986 + r.shortName);
10987 }
10988 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010989 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 r.lastStartId++;
10991 if (r.lastStartId < 1) {
10992 r.lastStartId = 1;
10993 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010994 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 r.lastActivity = SystemClock.uptimeMillis();
10996 synchronized (r.stats.getBatteryStats()) {
10997 r.stats.startRunningLocked();
10998 }
10999 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11000 return new ComponentName("!", "Service process is bad");
11001 }
11002 return r.name;
11003 }
11004 }
11005
11006 public ComponentName startService(IApplicationThread caller, Intent service,
11007 String resolvedType) {
11008 // Refuse possible leaked file descriptors
11009 if (service != null && service.hasFileDescriptors() == true) {
11010 throw new IllegalArgumentException("File descriptors passed in Intent");
11011 }
11012
11013 synchronized(this) {
11014 final int callingPid = Binder.getCallingPid();
11015 final int callingUid = Binder.getCallingUid();
11016 final long origId = Binder.clearCallingIdentity();
11017 ComponentName res = startServiceLocked(caller, service,
11018 resolvedType, callingPid, callingUid);
11019 Binder.restoreCallingIdentity(origId);
11020 return res;
11021 }
11022 }
11023
11024 ComponentName startServiceInPackage(int uid,
11025 Intent service, String resolvedType) {
11026 synchronized(this) {
11027 final long origId = Binder.clearCallingIdentity();
11028 ComponentName res = startServiceLocked(null, service,
11029 resolvedType, -1, uid);
11030 Binder.restoreCallingIdentity(origId);
11031 return res;
11032 }
11033 }
11034
11035 public int stopService(IApplicationThread caller, Intent service,
11036 String resolvedType) {
11037 // Refuse possible leaked file descriptors
11038 if (service != null && service.hasFileDescriptors() == true) {
11039 throw new IllegalArgumentException("File descriptors passed in Intent");
11040 }
11041
11042 synchronized(this) {
11043 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
11044 + " type=" + resolvedType);
11045
11046 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11047 if (caller != null && callerApp == null) {
11048 throw new SecurityException(
11049 "Unable to find app for caller " + caller
11050 + " (pid=" + Binder.getCallingPid()
11051 + ") when stopping service " + service);
11052 }
11053
11054 // If this service is active, make sure it is stopped.
11055 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11056 if (r != null) {
11057 if (r.record != null) {
11058 synchronized (r.record.stats.getBatteryStats()) {
11059 r.record.stats.stopRunningLocked();
11060 }
11061 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011062 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 final long origId = Binder.clearCallingIdentity();
11064 bringDownServiceLocked(r.record, false);
11065 Binder.restoreCallingIdentity(origId);
11066 return 1;
11067 }
11068 return -1;
11069 }
11070 }
11071
11072 return 0;
11073 }
11074
11075 public IBinder peekService(Intent service, String resolvedType) {
11076 // Refuse possible leaked file descriptors
11077 if (service != null && service.hasFileDescriptors() == true) {
11078 throw new IllegalArgumentException("File descriptors passed in Intent");
11079 }
11080
11081 IBinder ret = null;
11082
11083 synchronized(this) {
11084 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11085
11086 if (r != null) {
11087 // r.record is null if findServiceLocked() failed the caller permission check
11088 if (r.record == null) {
11089 throw new SecurityException(
11090 "Permission Denial: Accessing service " + r.record.name
11091 + " from pid=" + Binder.getCallingPid()
11092 + ", uid=" + Binder.getCallingUid()
11093 + " requires " + r.permission);
11094 }
11095 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11096 if (ib != null) {
11097 ret = ib.binder;
11098 }
11099 }
11100 }
11101
11102 return ret;
11103 }
11104
11105 public boolean stopServiceToken(ComponentName className, IBinder token,
11106 int startId) {
11107 synchronized(this) {
11108 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
11109 + " " + token + " startId=" + startId);
11110 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011111 if (r != null) {
11112 if (startId >= 0) {
11113 // Asked to only stop if done with all work. Note that
11114 // to avoid leaks, we will take this as dropping all
11115 // start items up to and including this one.
11116 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11117 if (si != null) {
11118 while (r.deliveredStarts.size() > 0) {
11119 if (r.deliveredStarts.remove(0) == si) {
11120 break;
11121 }
11122 }
11123 }
11124
11125 if (r.lastStartId != startId) {
11126 return false;
11127 }
11128
11129 if (r.deliveredStarts.size() > 0) {
11130 Log.w(TAG, "stopServiceToken startId " + startId
11131 + " is last, but have " + r.deliveredStarts.size()
11132 + " remaining args");
11133 }
11134 }
11135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 synchronized (r.stats.getBatteryStats()) {
11137 r.stats.stopRunningLocked();
11138 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011139 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 }
11141 final long origId = Binder.clearCallingIdentity();
11142 bringDownServiceLocked(r, false);
11143 Binder.restoreCallingIdentity(origId);
11144 return true;
11145 }
11146 }
11147 return false;
11148 }
11149
11150 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011151 int id, Notification notification, boolean removeNotification) {
11152 final long origId = Binder.clearCallingIdentity();
11153 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 synchronized(this) {
11155 ServiceRecord r = findServiceLocked(className, token);
11156 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011157 if (id != 0) {
11158 if (notification == null) {
11159 throw new IllegalArgumentException("null notification");
11160 }
11161 if (r.foregroundId != id) {
11162 r.cancelNotification();
11163 r.foregroundId = id;
11164 }
11165 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11166 r.foregroundNoti = notification;
11167 r.isForeground = true;
11168 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 if (r.app != null) {
11170 updateServiceForegroundLocked(r.app, true);
11171 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011172 } else {
11173 if (r.isForeground) {
11174 r.isForeground = false;
11175 if (r.app != null) {
11176 updateServiceForegroundLocked(r.app, true);
11177 }
11178 }
11179 if (removeNotification) {
11180 r.cancelNotification();
11181 r.foregroundId = 0;
11182 r.foregroundNoti = null;
11183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 }
11185 }
11186 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011187 } finally {
11188 Binder.restoreCallingIdentity(origId);
11189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011190 }
11191
11192 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11193 boolean anyForeground = false;
11194 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11195 if (sr.isForeground) {
11196 anyForeground = true;
11197 break;
11198 }
11199 }
11200 if (anyForeground != proc.foregroundServices) {
11201 proc.foregroundServices = anyForeground;
11202 if (oomAdj) {
11203 updateOomAdjLocked();
11204 }
11205 }
11206 }
11207
11208 public int bindService(IApplicationThread caller, IBinder token,
11209 Intent service, String resolvedType,
11210 IServiceConnection connection, int flags) {
11211 // Refuse possible leaked file descriptors
11212 if (service != null && service.hasFileDescriptors() == true) {
11213 throw new IllegalArgumentException("File descriptors passed in Intent");
11214 }
11215
11216 synchronized(this) {
11217 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
11218 + " type=" + resolvedType + " conn=" + connection.asBinder()
11219 + " flags=0x" + Integer.toHexString(flags));
11220 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11221 if (callerApp == null) {
11222 throw new SecurityException(
11223 "Unable to find app for caller " + caller
11224 + " (pid=" + Binder.getCallingPid()
11225 + ") when binding service " + service);
11226 }
11227
11228 HistoryRecord activity = null;
11229 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011230 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 if (aindex < 0) {
11232 Log.w(TAG, "Binding with unknown activity: " + token);
11233 return 0;
11234 }
11235 activity = (HistoryRecord)mHistory.get(aindex);
11236 }
11237
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011238 int clientLabel = 0;
11239 PendingIntent clientIntent = null;
11240
11241 if (callerApp.info.uid == Process.SYSTEM_UID) {
11242 // Hacky kind of thing -- allow system stuff to tell us
11243 // what they are, so we can report this elsewhere for
11244 // others to know why certain services are running.
11245 try {
11246 clientIntent = (PendingIntent)service.getParcelableExtra(
11247 Intent.EXTRA_CLIENT_INTENT);
11248 } catch (RuntimeException e) {
11249 }
11250 if (clientIntent != null) {
11251 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11252 if (clientLabel != 0) {
11253 // There are no useful extras in the intent, trash them.
11254 // System code calling with this stuff just needs to know
11255 // this will happen.
11256 service = service.cloneFilter();
11257 }
11258 }
11259 }
11260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 ServiceLookupResult res =
11262 retrieveServiceLocked(service, resolvedType,
11263 Binder.getCallingPid(), Binder.getCallingUid());
11264 if (res == null) {
11265 return 0;
11266 }
11267 if (res.record == null) {
11268 return -1;
11269 }
11270 ServiceRecord s = res.record;
11271
11272 final long origId = Binder.clearCallingIdentity();
11273
11274 if (unscheduleServiceRestartLocked(s)) {
11275 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
11276 + s.shortName);
11277 }
11278
11279 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11280 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011281 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282
11283 IBinder binder = connection.asBinder();
11284 s.connections.put(binder, c);
11285 b.connections.add(c);
11286 if (activity != null) {
11287 if (activity.connections == null) {
11288 activity.connections = new HashSet<ConnectionRecord>();
11289 }
11290 activity.connections.add(c);
11291 }
11292 b.client.connections.add(c);
11293 mServiceConnections.put(binder, c);
11294
11295 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11296 s.lastActivity = SystemClock.uptimeMillis();
11297 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11298 return 0;
11299 }
11300 }
11301
11302 if (s.app != null) {
11303 // This could have made the service more important.
11304 updateOomAdjLocked(s.app);
11305 }
11306
11307 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
11308 + ": received=" + b.intent.received
11309 + " apps=" + b.intent.apps.size()
11310 + " doRebind=" + b.intent.doRebind);
11311
11312 if (s.app != null && b.intent.received) {
11313 // Service is already running, so we can immediately
11314 // publish the connection.
11315 try {
11316 c.conn.connected(s.name, b.intent.binder);
11317 } catch (Exception e) {
11318 Log.w(TAG, "Failure sending service " + s.shortName
11319 + " to connection " + c.conn.asBinder()
11320 + " (in " + c.binding.client.processName + ")", e);
11321 }
11322
11323 // If this is the first app connected back to this binding,
11324 // and the service had previously asked to be told when
11325 // rebound, then do so.
11326 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11327 requestServiceBindingLocked(s, b.intent, true);
11328 }
11329 } else if (!b.intent.requested) {
11330 requestServiceBindingLocked(s, b.intent, false);
11331 }
11332
11333 Binder.restoreCallingIdentity(origId);
11334 }
11335
11336 return 1;
11337 }
11338
11339 private void removeConnectionLocked(
11340 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11341 IBinder binder = c.conn.asBinder();
11342 AppBindRecord b = c.binding;
11343 ServiceRecord s = b.service;
11344 s.connections.remove(binder);
11345 b.connections.remove(c);
11346 if (c.activity != null && c.activity != skipAct) {
11347 if (c.activity.connections != null) {
11348 c.activity.connections.remove(c);
11349 }
11350 }
11351 if (b.client != skipApp) {
11352 b.client.connections.remove(c);
11353 }
11354 mServiceConnections.remove(binder);
11355
11356 if (b.connections.size() == 0) {
11357 b.intent.apps.remove(b.client);
11358 }
11359
11360 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
11361 + ": shouldUnbind=" + b.intent.hasBound);
11362 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11363 && b.intent.hasBound) {
11364 try {
11365 bumpServiceExecutingLocked(s);
11366 updateOomAdjLocked(s.app);
11367 b.intent.hasBound = false;
11368 // Assume the client doesn't want to know about a rebind;
11369 // we will deal with that later if it asks for one.
11370 b.intent.doRebind = false;
11371 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11372 } catch (Exception e) {
11373 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
11374 serviceDoneExecutingLocked(s, true);
11375 }
11376 }
11377
11378 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11379 bringDownServiceLocked(s, false);
11380 }
11381 }
11382
11383 public boolean unbindService(IServiceConnection connection) {
11384 synchronized (this) {
11385 IBinder binder = connection.asBinder();
11386 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
11387 ConnectionRecord r = mServiceConnections.get(binder);
11388 if (r == null) {
11389 Log.w(TAG, "Unbind failed: could not find connection for "
11390 + connection.asBinder());
11391 return false;
11392 }
11393
11394 final long origId = Binder.clearCallingIdentity();
11395
11396 removeConnectionLocked(r, null, null);
11397
11398 if (r.binding.service.app != null) {
11399 // This could have made the service less important.
11400 updateOomAdjLocked(r.binding.service.app);
11401 }
11402
11403 Binder.restoreCallingIdentity(origId);
11404 }
11405
11406 return true;
11407 }
11408
11409 public void publishService(IBinder token, Intent intent, IBinder service) {
11410 // Refuse possible leaked file descriptors
11411 if (intent != null && intent.hasFileDescriptors() == true) {
11412 throw new IllegalArgumentException("File descriptors passed in Intent");
11413 }
11414
11415 synchronized(this) {
11416 if (!(token instanceof ServiceRecord)) {
11417 throw new IllegalArgumentException("Invalid service token");
11418 }
11419 ServiceRecord r = (ServiceRecord)token;
11420
11421 final long origId = Binder.clearCallingIdentity();
11422
11423 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
11424 + " " + intent + ": " + service);
11425 if (r != null) {
11426 Intent.FilterComparison filter
11427 = new Intent.FilterComparison(intent);
11428 IntentBindRecord b = r.bindings.get(filter);
11429 if (b != null && !b.received) {
11430 b.binder = service;
11431 b.requested = true;
11432 b.received = true;
11433 if (r.connections.size() > 0) {
11434 Iterator<ConnectionRecord> it
11435 = r.connections.values().iterator();
11436 while (it.hasNext()) {
11437 ConnectionRecord c = it.next();
11438 if (!filter.equals(c.binding.intent.intent)) {
11439 if (DEBUG_SERVICE) Log.v(
11440 TAG, "Not publishing to: " + c);
11441 if (DEBUG_SERVICE) Log.v(
11442 TAG, "Bound intent: " + c.binding.intent.intent);
11443 if (DEBUG_SERVICE) Log.v(
11444 TAG, "Published intent: " + intent);
11445 continue;
11446 }
11447 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
11448 try {
11449 c.conn.connected(r.name, service);
11450 } catch (Exception e) {
11451 Log.w(TAG, "Failure sending service " + r.name +
11452 " to connection " + c.conn.asBinder() +
11453 " (in " + c.binding.client.processName + ")", e);
11454 }
11455 }
11456 }
11457 }
11458
11459 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11460
11461 Binder.restoreCallingIdentity(origId);
11462 }
11463 }
11464 }
11465
11466 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11467 // Refuse possible leaked file descriptors
11468 if (intent != null && intent.hasFileDescriptors() == true) {
11469 throw new IllegalArgumentException("File descriptors passed in Intent");
11470 }
11471
11472 synchronized(this) {
11473 if (!(token instanceof ServiceRecord)) {
11474 throw new IllegalArgumentException("Invalid service token");
11475 }
11476 ServiceRecord r = (ServiceRecord)token;
11477
11478 final long origId = Binder.clearCallingIdentity();
11479
11480 if (r != null) {
11481 Intent.FilterComparison filter
11482 = new Intent.FilterComparison(intent);
11483 IntentBindRecord b = r.bindings.get(filter);
11484 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
11485 + " at " + b + ": apps="
11486 + (b != null ? b.apps.size() : 0));
11487 if (b != null) {
11488 if (b.apps.size() > 0) {
11489 // Applications have already bound since the last
11490 // unbind, so just rebind right here.
11491 requestServiceBindingLocked(r, b, true);
11492 } else {
11493 // Note to tell the service the next time there is
11494 // a new client.
11495 b.doRebind = true;
11496 }
11497 }
11498
11499 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11500
11501 Binder.restoreCallingIdentity(origId);
11502 }
11503 }
11504 }
11505
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011506 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011507 synchronized(this) {
11508 if (!(token instanceof ServiceRecord)) {
11509 throw new IllegalArgumentException("Invalid service token");
11510 }
11511 ServiceRecord r = (ServiceRecord)token;
11512 boolean inStopping = mStoppingServices.contains(token);
11513 if (r != null) {
11514 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
11515 + ": nesting=" + r.executeNesting
11516 + ", inStopping=" + inStopping);
11517 if (r != token) {
11518 Log.w(TAG, "Done executing service " + r.name
11519 + " with incorrect token: given " + token
11520 + ", expected " + r);
11521 return;
11522 }
11523
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011524 if (type == 1) {
11525 // This is a call from a service start... take care of
11526 // book-keeping.
11527 r.callStart = true;
11528 switch (res) {
11529 case Service.START_STICKY_COMPATIBILITY:
11530 case Service.START_STICKY: {
11531 // We are done with the associated start arguments.
11532 r.findDeliveredStart(startId, true);
11533 // Don't stop if killed.
11534 r.stopIfKilled = false;
11535 break;
11536 }
11537 case Service.START_NOT_STICKY: {
11538 // We are done with the associated start arguments.
11539 r.findDeliveredStart(startId, true);
11540 if (r.lastStartId == startId) {
11541 // There is no more work, and this service
11542 // doesn't want to hang around if killed.
11543 r.stopIfKilled = true;
11544 }
11545 break;
11546 }
11547 case Service.START_REDELIVER_INTENT: {
11548 // We'll keep this item until they explicitly
11549 // call stop for it, but keep track of the fact
11550 // that it was delivered.
11551 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11552 if (si != null) {
11553 si.deliveryCount = 0;
11554 si.doneExecutingCount++;
11555 // Don't stop if killed.
11556 r.stopIfKilled = true;
11557 }
11558 break;
11559 }
11560 default:
11561 throw new IllegalArgumentException(
11562 "Unknown service start result: " + res);
11563 }
11564 if (res == Service.START_STICKY_COMPATIBILITY) {
11565 r.callStart = false;
11566 }
11567 }
11568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 final long origId = Binder.clearCallingIdentity();
11570 serviceDoneExecutingLocked(r, inStopping);
11571 Binder.restoreCallingIdentity(origId);
11572 } else {
11573 Log.w(TAG, "Done executing unknown service " + r.name
11574 + " with token " + token);
11575 }
11576 }
11577 }
11578
11579 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11580 r.executeNesting--;
11581 if (r.executeNesting <= 0 && r.app != null) {
11582 r.app.executingServices.remove(r);
11583 if (r.app.executingServices.size() == 0) {
11584 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11585 }
11586 if (inStopping) {
11587 mStoppingServices.remove(r);
11588 }
11589 updateOomAdjLocked(r.app);
11590 }
11591 }
11592
11593 void serviceTimeout(ProcessRecord proc) {
11594 synchronized(this) {
11595 if (proc.executingServices.size() == 0 || proc.thread == null) {
11596 return;
11597 }
11598 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11599 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11600 ServiceRecord timeout = null;
11601 long nextTime = 0;
11602 while (it.hasNext()) {
11603 ServiceRecord sr = it.next();
11604 if (sr.executingStart < maxTime) {
11605 timeout = sr;
11606 break;
11607 }
11608 if (sr.executingStart > nextTime) {
11609 nextTime = sr.executingStart;
11610 }
11611 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011612 if (timeout != null && mLruProcesses.contains(proc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 Log.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011614 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011615 } else {
11616 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11617 msg.obj = proc;
11618 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11619 }
11620 }
11621 }
11622
11623 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011624 // BACKUP AND RESTORE
11625 // =========================================================
11626
11627 // Cause the target app to be launched if necessary and its backup agent
11628 // instantiated. The backup agent will invoke backupAgentCreated() on the
11629 // activity manager to announce its creation.
11630 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
11631 if (DEBUG_BACKUP) Log.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
11632 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11633
11634 synchronized(this) {
11635 // !!! TODO: currently no check here that we're already bound
11636 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11637 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11638 synchronized (stats) {
11639 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11640 }
11641
11642 BackupRecord r = new BackupRecord(ss, app, backupMode);
11643 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11644 // startProcessLocked() returns existing proc's record if it's already running
11645 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011646 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011647 if (proc == null) {
11648 Log.e(TAG, "Unable to start backup agent process " + r);
11649 return false;
11650 }
11651
11652 r.app = proc;
11653 mBackupTarget = r;
11654 mBackupAppName = app.packageName;
11655
Christopher Tate6fa95972009-06-05 18:43:55 -070011656 // Try not to kill the process during backup
11657 updateOomAdjLocked(proc);
11658
Christopher Tate181fafa2009-05-14 11:12:14 -070011659 // If the process is already attached, schedule the creation of the backup agent now.
11660 // If it is not yet live, this will be done when it attaches to the framework.
11661 if (proc.thread != null) {
11662 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc already running: " + proc);
11663 try {
11664 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11665 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011666 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011667 }
11668 } else {
11669 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc not running, waiting for attach");
11670 }
11671 // Invariants: at this point, the target app process exists and the application
11672 // is either already running or in the process of coming up. mBackupTarget and
11673 // mBackupAppName describe the app, so that when it binds back to the AM we
11674 // know that it's scheduled for a backup-agent operation.
11675 }
11676
11677 return true;
11678 }
11679
11680 // A backup agent has just come up
11681 public void backupAgentCreated(String agentPackageName, IBinder agent) {
11682 if (DEBUG_BACKUP) Log.v(TAG, "backupAgentCreated: " + agentPackageName
11683 + " = " + agent);
11684
11685 synchronized(this) {
11686 if (!agentPackageName.equals(mBackupAppName)) {
11687 Log.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
11688 return;
11689 }
11690
Christopher Tate043dadc2009-06-02 16:11:00 -070011691 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011692 try {
11693 IBackupManager bm = IBackupManager.Stub.asInterface(
11694 ServiceManager.getService(Context.BACKUP_SERVICE));
11695 bm.agentConnected(agentPackageName, agent);
11696 } catch (RemoteException e) {
11697 // can't happen; the backup manager service is local
11698 } catch (Exception e) {
11699 Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11700 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011701 } finally {
11702 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011703 }
11704 }
11705 }
11706
11707 // done with this agent
11708 public void unbindBackupAgent(ApplicationInfo appInfo) {
11709 if (DEBUG_BACKUP) Log.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011710 if (appInfo == null) {
11711 Log.w(TAG, "unbind backup agent for null app");
11712 return;
11713 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011714
11715 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011716 if (mBackupAppName == null) {
11717 Log.w(TAG, "Unbinding backup agent with no active backup");
11718 return;
11719 }
11720
Christopher Tate181fafa2009-05-14 11:12:14 -070011721 if (!mBackupAppName.equals(appInfo.packageName)) {
11722 Log.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
11723 return;
11724 }
11725
Christopher Tate6fa95972009-06-05 18:43:55 -070011726 ProcessRecord proc = mBackupTarget.app;
11727 mBackupTarget = null;
11728 mBackupAppName = null;
11729
11730 // Not backing this app up any more; reset its OOM adjustment
11731 updateOomAdjLocked(proc);
11732
Christopher Tatec7b31e32009-06-10 15:49:30 -070011733 // If the app crashed during backup, 'thread' will be null here
11734 if (proc.thread != null) {
11735 try {
11736 proc.thread.scheduleDestroyBackupAgent(appInfo);
11737 } catch (Exception e) {
11738 Log.e(TAG, "Exception when unbinding backup agent:");
11739 e.printStackTrace();
11740 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011741 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011742 }
11743 }
11744 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 // BROADCASTS
11746 // =========================================================
11747
11748 private final List getStickies(String action, IntentFilter filter,
11749 List cur) {
11750 final ContentResolver resolver = mContext.getContentResolver();
11751 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11752 if (list == null) {
11753 return cur;
11754 }
11755 int N = list.size();
11756 for (int i=0; i<N; i++) {
11757 Intent intent = list.get(i);
11758 if (filter.match(resolver, intent, true, TAG) >= 0) {
11759 if (cur == null) {
11760 cur = new ArrayList<Intent>();
11761 }
11762 cur.add(intent);
11763 }
11764 }
11765 return cur;
11766 }
11767
11768 private final void scheduleBroadcastsLocked() {
11769 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
11770 + mBroadcastsScheduled);
11771
11772 if (mBroadcastsScheduled) {
11773 return;
11774 }
11775 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11776 mBroadcastsScheduled = true;
11777 }
11778
11779 public Intent registerReceiver(IApplicationThread caller,
11780 IIntentReceiver receiver, IntentFilter filter, String permission) {
11781 synchronized(this) {
11782 ProcessRecord callerApp = null;
11783 if (caller != null) {
11784 callerApp = getRecordForAppLocked(caller);
11785 if (callerApp == null) {
11786 throw new SecurityException(
11787 "Unable to find app for caller " + caller
11788 + " (pid=" + Binder.getCallingPid()
11789 + ") when registering receiver " + receiver);
11790 }
11791 }
11792
11793 List allSticky = null;
11794
11795 // Look for any matching sticky broadcasts...
11796 Iterator actions = filter.actionsIterator();
11797 if (actions != null) {
11798 while (actions.hasNext()) {
11799 String action = (String)actions.next();
11800 allSticky = getStickies(action, filter, allSticky);
11801 }
11802 } else {
11803 allSticky = getStickies(null, filter, allSticky);
11804 }
11805
11806 // The first sticky in the list is returned directly back to
11807 // the client.
11808 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11809
11810 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
11811 + ": " + sticky);
11812
11813 if (receiver == null) {
11814 return sticky;
11815 }
11816
11817 ReceiverList rl
11818 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11819 if (rl == null) {
11820 rl = new ReceiverList(this, callerApp,
11821 Binder.getCallingPid(),
11822 Binder.getCallingUid(), receiver);
11823 if (rl.app != null) {
11824 rl.app.receivers.add(rl);
11825 } else {
11826 try {
11827 receiver.asBinder().linkToDeath(rl, 0);
11828 } catch (RemoteException e) {
11829 return sticky;
11830 }
11831 rl.linkedToDeath = true;
11832 }
11833 mRegisteredReceivers.put(receiver.asBinder(), rl);
11834 }
11835 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11836 rl.add(bf);
11837 if (!bf.debugCheck()) {
11838 Log.w(TAG, "==> For Dynamic broadast");
11839 }
11840 mReceiverResolver.addFilter(bf);
11841
11842 // Enqueue broadcasts for all existing stickies that match
11843 // this filter.
11844 if (allSticky != null) {
11845 ArrayList receivers = new ArrayList();
11846 receivers.add(bf);
11847
11848 int N = allSticky.size();
11849 for (int i=0; i<N; i++) {
11850 Intent intent = (Intent)allSticky.get(i);
11851 BroadcastRecord r = new BroadcastRecord(intent, null,
11852 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011853 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 if (mParallelBroadcasts.size() == 0) {
11855 scheduleBroadcastsLocked();
11856 }
11857 mParallelBroadcasts.add(r);
11858 }
11859 }
11860
11861 return sticky;
11862 }
11863 }
11864
11865 public void unregisterReceiver(IIntentReceiver receiver) {
11866 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
11867
11868 boolean doNext = false;
11869
11870 synchronized(this) {
11871 ReceiverList rl
11872 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11873 if (rl != null) {
11874 if (rl.curBroadcast != null) {
11875 BroadcastRecord r = rl.curBroadcast;
11876 doNext = finishReceiverLocked(
11877 receiver.asBinder(), r.resultCode, r.resultData,
11878 r.resultExtras, r.resultAbort, true);
11879 }
11880
11881 if (rl.app != null) {
11882 rl.app.receivers.remove(rl);
11883 }
11884 removeReceiverLocked(rl);
11885 if (rl.linkedToDeath) {
11886 rl.linkedToDeath = false;
11887 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11888 }
11889 }
11890 }
11891
11892 if (!doNext) {
11893 return;
11894 }
11895
11896 final long origId = Binder.clearCallingIdentity();
11897 processNextBroadcast(false);
11898 trimApplications();
11899 Binder.restoreCallingIdentity(origId);
11900 }
11901
11902 void removeReceiverLocked(ReceiverList rl) {
11903 mRegisteredReceivers.remove(rl.receiver.asBinder());
11904 int N = rl.size();
11905 for (int i=0; i<N; i++) {
11906 mReceiverResolver.removeFilter(rl.get(i));
11907 }
11908 }
11909
11910 private final int broadcastIntentLocked(ProcessRecord callerApp,
11911 String callerPackage, Intent intent, String resolvedType,
11912 IIntentReceiver resultTo, int resultCode, String resultData,
11913 Bundle map, String requiredPermission,
11914 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11915 intent = new Intent(intent);
11916
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011917 if (DEBUG_BROADCAST_LIGHT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11919 + " ordered=" + ordered);
11920 if ((resultTo != null) && !ordered) {
11921 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
11922 }
11923
11924 // Handle special intents: if this broadcast is from the package
11925 // manager about a package being removed, we need to remove all of
11926 // its activities from the history stack.
11927 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
11928 intent.getAction());
11929 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11930 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011931 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011932 || uidRemoved) {
11933 if (checkComponentPermission(
11934 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
11935 callingPid, callingUid, -1)
11936 == PackageManager.PERMISSION_GRANTED) {
11937 if (uidRemoved) {
11938 final Bundle intentExtras = intent.getExtras();
11939 final int uid = intentExtras != null
11940 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11941 if (uid >= 0) {
11942 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11943 synchronized (bs) {
11944 bs.removeUidStatsLocked(uid);
11945 }
11946 }
11947 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011948 // If resources are unvailble just force stop all
11949 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011950 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011951 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11952 if (list != null && (list.length > 0)) {
11953 for (String pkg : list) {
11954 forceStopPackageLocked(pkg, -1, false, true);
11955 }
11956 }
11957 } else {
11958 Uri data = intent.getData();
11959 String ssp;
11960 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11961 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11962 forceStopPackageLocked(ssp,
11963 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 }
11966 }
11967 }
11968 } else {
11969 String msg = "Permission Denial: " + intent.getAction()
11970 + " broadcast from " + callerPackage + " (pid=" + callingPid
11971 + ", uid=" + callingUid + ")"
11972 + " requires "
11973 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
11974 Log.w(TAG, msg);
11975 throw new SecurityException(msg);
11976 }
11977 }
11978
11979 /*
11980 * If this is the time zone changed action, queue up a message that will reset the timezone
11981 * of all currently running processes. This message will get queued up before the broadcast
11982 * happens.
11983 */
11984 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11985 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11986 }
11987
Dianne Hackborn854060af2009-07-09 18:14:31 -070011988 /*
11989 * Prevent non-system code (defined here to be non-persistent
11990 * processes) from sending protected broadcasts.
11991 */
11992 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11993 || callingUid == Process.SHELL_UID || callingUid == 0) {
11994 // Always okay.
11995 } else if (callerApp == null || !callerApp.persistent) {
11996 try {
11997 if (ActivityThread.getPackageManager().isProtectedBroadcast(
11998 intent.getAction())) {
11999 String msg = "Permission Denial: not allowed to send broadcast "
12000 + intent.getAction() + " from pid="
12001 + callingPid + ", uid=" + callingUid;
12002 Log.w(TAG, msg);
12003 throw new SecurityException(msg);
12004 }
12005 } catch (RemoteException e) {
12006 Log.w(TAG, "Remote exception", e);
12007 return BROADCAST_SUCCESS;
12008 }
12009 }
12010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012011 // Add to the sticky list if requested.
12012 if (sticky) {
12013 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12014 callingPid, callingUid)
12015 != PackageManager.PERMISSION_GRANTED) {
12016 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12017 + callingPid + ", uid=" + callingUid
12018 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12019 Log.w(TAG, msg);
12020 throw new SecurityException(msg);
12021 }
12022 if (requiredPermission != null) {
12023 Log.w(TAG, "Can't broadcast sticky intent " + intent
12024 + " and enforce permission " + requiredPermission);
12025 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12026 }
12027 if (intent.getComponent() != null) {
12028 throw new SecurityException(
12029 "Sticky broadcasts can't target a specific component");
12030 }
12031 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12032 if (list == null) {
12033 list = new ArrayList<Intent>();
12034 mStickyBroadcasts.put(intent.getAction(), list);
12035 }
12036 int N = list.size();
12037 int i;
12038 for (i=0; i<N; i++) {
12039 if (intent.filterEquals(list.get(i))) {
12040 // This sticky already exists, replace it.
12041 list.set(i, new Intent(intent));
12042 break;
12043 }
12044 }
12045 if (i >= N) {
12046 list.add(new Intent(intent));
12047 }
12048 }
12049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012050 // Figure out who all will receive this broadcast.
12051 List receivers = null;
12052 List<BroadcastFilter> registeredReceivers = null;
12053 try {
12054 if (intent.getComponent() != null) {
12055 // Broadcast is going to one specific receiver class...
12056 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012057 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 if (ai != null) {
12059 receivers = new ArrayList();
12060 ResolveInfo ri = new ResolveInfo();
12061 ri.activityInfo = ai;
12062 receivers.add(ri);
12063 }
12064 } else {
12065 // Need to resolve the intent to interested receivers...
12066 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12067 == 0) {
12068 receivers =
12069 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012070 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012071 }
Mihai Preda074edef2009-05-18 17:13:31 +020012072 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012073 }
12074 } catch (RemoteException ex) {
12075 // pm is in same process, this will never happen.
12076 }
12077
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012078 final boolean replacePending =
12079 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12080
12081 if (DEBUG_BROADCAST) Log.v(TAG, "Enqueing broadcast: " + intent.getAction()
12082 + " replacePending=" + replacePending);
12083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012084 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12085 if (!ordered && NR > 0) {
12086 // If we are not serializing this broadcast, then send the
12087 // registered receivers separately so they don't wait for the
12088 // components to be launched.
12089 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12090 callerPackage, callingPid, callingUid, requiredPermission,
12091 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012092 ordered, sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012093 if (DEBUG_BROADCAST) Log.v(
12094 TAG, "Enqueueing parallel broadcast " + r
12095 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012096 boolean replaced = false;
12097 if (replacePending) {
12098 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12099 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
12100 if (DEBUG_BROADCAST) Log.v(TAG,
12101 "***** DROPPING PARALLEL: " + intent);
12102 mParallelBroadcasts.set(i, r);
12103 replaced = true;
12104 break;
12105 }
12106 }
12107 }
12108 if (!replaced) {
12109 mParallelBroadcasts.add(r);
12110 scheduleBroadcastsLocked();
12111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012112 registeredReceivers = null;
12113 NR = 0;
12114 }
12115
12116 // Merge into one list.
12117 int ir = 0;
12118 if (receivers != null) {
12119 // A special case for PACKAGE_ADDED: do not allow the package
12120 // being added to see this broadcast. This prevents them from
12121 // using this as a back door to get run as soon as they are
12122 // installed. Maybe in the future we want to have a special install
12123 // broadcast or such for apps, but we'd like to deliberately make
12124 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012125 String skipPackages[] = null;
12126 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12127 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12128 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12129 Uri data = intent.getData();
12130 if (data != null) {
12131 String pkgName = data.getSchemeSpecificPart();
12132 if (pkgName != null) {
12133 skipPackages = new String[] { pkgName };
12134 }
12135 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012136 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012137 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012138 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012139 if (skipPackages != null && (skipPackages.length > 0)) {
12140 for (String skipPackage : skipPackages) {
12141 if (skipPackage != null) {
12142 int NT = receivers.size();
12143 for (int it=0; it<NT; it++) {
12144 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12145 if (curt.activityInfo.packageName.equals(skipPackage)) {
12146 receivers.remove(it);
12147 it--;
12148 NT--;
12149 }
12150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012151 }
12152 }
12153 }
12154
12155 int NT = receivers != null ? receivers.size() : 0;
12156 int it = 0;
12157 ResolveInfo curt = null;
12158 BroadcastFilter curr = null;
12159 while (it < NT && ir < NR) {
12160 if (curt == null) {
12161 curt = (ResolveInfo)receivers.get(it);
12162 }
12163 if (curr == null) {
12164 curr = registeredReceivers.get(ir);
12165 }
12166 if (curr.getPriority() >= curt.priority) {
12167 // Insert this broadcast record into the final list.
12168 receivers.add(it, curr);
12169 ir++;
12170 curr = null;
12171 it++;
12172 NT++;
12173 } else {
12174 // Skip to the next ResolveInfo in the final list.
12175 it++;
12176 curt = null;
12177 }
12178 }
12179 }
12180 while (ir < NR) {
12181 if (receivers == null) {
12182 receivers = new ArrayList();
12183 }
12184 receivers.add(registeredReceivers.get(ir));
12185 ir++;
12186 }
12187
12188 if ((receivers != null && receivers.size() > 0)
12189 || resultTo != null) {
12190 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12191 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012192 receivers, resultTo, resultCode, resultData, map, ordered,
12193 sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 if (DEBUG_BROADCAST) Log.v(
12195 TAG, "Enqueueing ordered broadcast " + r
12196 + ": prev had " + mOrderedBroadcasts.size());
12197 if (DEBUG_BROADCAST) {
12198 int seq = r.intent.getIntExtra("seq", -1);
12199 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
12200 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012201 boolean replaced = false;
12202 if (replacePending) {
12203 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12204 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
12205 if (DEBUG_BROADCAST) Log.v(TAG,
12206 "***** DROPPING ORDERED: " + intent);
12207 mOrderedBroadcasts.set(i, r);
12208 replaced = true;
12209 break;
12210 }
12211 }
12212 }
12213 if (!replaced) {
12214 mOrderedBroadcasts.add(r);
12215 scheduleBroadcastsLocked();
12216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 }
12218
12219 return BROADCAST_SUCCESS;
12220 }
12221
12222 public final int broadcastIntent(IApplicationThread caller,
12223 Intent intent, String resolvedType, IIntentReceiver resultTo,
12224 int resultCode, String resultData, Bundle map,
12225 String requiredPermission, boolean serialized, boolean sticky) {
12226 // Refuse possible leaked file descriptors
12227 if (intent != null && intent.hasFileDescriptors() == true) {
12228 throw new IllegalArgumentException("File descriptors passed in Intent");
12229 }
12230
12231 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012232 int flags = intent.getFlags();
12233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 if (!mSystemReady) {
12235 // if the caller really truly claims to know what they're doing, go
12236 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012237 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12238 intent = new Intent(intent);
12239 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12240 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
12241 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12242 + " before boot completion");
12243 throw new IllegalStateException("Cannot broadcast before boot completed");
12244 }
12245 }
12246
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012247 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12248 throw new IllegalArgumentException(
12249 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12250 }
12251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012252 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12253 final int callingPid = Binder.getCallingPid();
12254 final int callingUid = Binder.getCallingUid();
12255 final long origId = Binder.clearCallingIdentity();
12256 int res = broadcastIntentLocked(callerApp,
12257 callerApp != null ? callerApp.info.packageName : null,
12258 intent, resolvedType, resultTo,
12259 resultCode, resultData, map, requiredPermission, serialized,
12260 sticky, callingPid, callingUid);
12261 Binder.restoreCallingIdentity(origId);
12262 return res;
12263 }
12264 }
12265
12266 int broadcastIntentInPackage(String packageName, int uid,
12267 Intent intent, String resolvedType, IIntentReceiver resultTo,
12268 int resultCode, String resultData, Bundle map,
12269 String requiredPermission, boolean serialized, boolean sticky) {
12270 synchronized(this) {
12271 final long origId = Binder.clearCallingIdentity();
12272 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12273 resultTo, resultCode, resultData, map, requiredPermission,
12274 serialized, sticky, -1, uid);
12275 Binder.restoreCallingIdentity(origId);
12276 return res;
12277 }
12278 }
12279
12280 public final void unbroadcastIntent(IApplicationThread caller,
12281 Intent intent) {
12282 // Refuse possible leaked file descriptors
12283 if (intent != null && intent.hasFileDescriptors() == true) {
12284 throw new IllegalArgumentException("File descriptors passed in Intent");
12285 }
12286
12287 synchronized(this) {
12288 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12289 != PackageManager.PERMISSION_GRANTED) {
12290 String msg = "Permission Denial: unbroadcastIntent() from pid="
12291 + Binder.getCallingPid()
12292 + ", uid=" + Binder.getCallingUid()
12293 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12294 Log.w(TAG, msg);
12295 throw new SecurityException(msg);
12296 }
12297 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12298 if (list != null) {
12299 int N = list.size();
12300 int i;
12301 for (i=0; i<N; i++) {
12302 if (intent.filterEquals(list.get(i))) {
12303 list.remove(i);
12304 break;
12305 }
12306 }
12307 }
12308 }
12309 }
12310
12311 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12312 String resultData, Bundle resultExtras, boolean resultAbort,
12313 boolean explicit) {
12314 if (mOrderedBroadcasts.size() == 0) {
12315 if (explicit) {
12316 Log.w(TAG, "finishReceiver called but no pending broadcasts");
12317 }
12318 return false;
12319 }
12320 BroadcastRecord r = mOrderedBroadcasts.get(0);
12321 if (r.receiver == null) {
12322 if (explicit) {
12323 Log.w(TAG, "finishReceiver called but none active");
12324 }
12325 return false;
12326 }
12327 if (r.receiver != receiver) {
12328 Log.w(TAG, "finishReceiver called but active receiver is different");
12329 return false;
12330 }
12331 int state = r.state;
12332 r.state = r.IDLE;
12333 if (state == r.IDLE) {
12334 if (explicit) {
12335 Log.w(TAG, "finishReceiver called but state is IDLE");
12336 }
12337 }
12338 r.receiver = null;
12339 r.intent.setComponent(null);
12340 if (r.curApp != null) {
12341 r.curApp.curReceiver = null;
12342 }
12343 if (r.curFilter != null) {
12344 r.curFilter.receiverList.curBroadcast = null;
12345 }
12346 r.curFilter = null;
12347 r.curApp = null;
12348 r.curComponent = null;
12349 r.curReceiver = null;
12350 mPendingBroadcast = null;
12351
12352 r.resultCode = resultCode;
12353 r.resultData = resultData;
12354 r.resultExtras = resultExtras;
12355 r.resultAbort = resultAbort;
12356
12357 // We will process the next receiver right now if this is finishing
12358 // an app receiver (which is always asynchronous) or after we have
12359 // come back from calling a receiver.
12360 return state == BroadcastRecord.APP_RECEIVE
12361 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12362 }
12363
12364 public void finishReceiver(IBinder who, int resultCode, String resultData,
12365 Bundle resultExtras, boolean resultAbort) {
12366 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
12367
12368 // Refuse possible leaked file descriptors
12369 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12370 throw new IllegalArgumentException("File descriptors passed in Bundle");
12371 }
12372
12373 boolean doNext;
12374
12375 final long origId = Binder.clearCallingIdentity();
12376
12377 synchronized(this) {
12378 doNext = finishReceiverLocked(
12379 who, resultCode, resultData, resultExtras, resultAbort, true);
12380 }
12381
12382 if (doNext) {
12383 processNextBroadcast(false);
12384 }
12385 trimApplications();
12386
12387 Binder.restoreCallingIdentity(origId);
12388 }
12389
12390 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12391 if (r.nextReceiver > 0) {
12392 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12393 if (curReceiver instanceof BroadcastFilter) {
12394 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012395 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012396 System.identityHashCode(r),
12397 r.intent.getAction(),
12398 r.nextReceiver - 1,
12399 System.identityHashCode(bf));
12400 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012401 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402 System.identityHashCode(r),
12403 r.intent.getAction(),
12404 r.nextReceiver - 1,
12405 ((ResolveInfo)curReceiver).toString());
12406 }
12407 } else {
12408 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
12409 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012410 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411 System.identityHashCode(r),
12412 r.intent.getAction(),
12413 r.nextReceiver,
12414 "NONE");
12415 }
12416 }
12417
12418 private final void broadcastTimeout() {
12419 synchronized (this) {
12420 if (mOrderedBroadcasts.size() == 0) {
12421 return;
12422 }
12423 long now = SystemClock.uptimeMillis();
12424 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012425 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 if (DEBUG_BROADCAST) Log.v(TAG,
12427 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012428 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012430 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012431 return;
12432 }
12433
12434 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012435 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436 r.anrCount++;
12437
12438 // Current receiver has passed its expiration date.
12439 if (r.nextReceiver <= 0) {
12440 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12441 return;
12442 }
12443
12444 ProcessRecord app = null;
12445
12446 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12447 Log.w(TAG, "Receiver during timeout: " + curReceiver);
12448 logBroadcastReceiverDiscard(r);
12449 if (curReceiver instanceof BroadcastFilter) {
12450 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12451 if (bf.receiverList.pid != 0
12452 && bf.receiverList.pid != MY_PID) {
12453 synchronized (this.mPidsSelfLocked) {
12454 app = this.mPidsSelfLocked.get(
12455 bf.receiverList.pid);
12456 }
12457 }
12458 } else {
12459 app = r.curApp;
12460 }
12461
12462 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012463 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012464 }
12465
12466 if (mPendingBroadcast == r) {
12467 mPendingBroadcast = null;
12468 }
12469
12470 // Move on to the next receiver.
12471 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12472 r.resultExtras, r.resultAbort, true);
12473 scheduleBroadcastsLocked();
12474 }
12475 }
12476
12477 private final void processCurBroadcastLocked(BroadcastRecord r,
12478 ProcessRecord app) throws RemoteException {
12479 if (app.thread == null) {
12480 throw new RemoteException();
12481 }
12482 r.receiver = app.thread.asBinder();
12483 r.curApp = app;
12484 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012485 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012486
12487 // Tell the application to launch this receiver.
12488 r.intent.setComponent(r.curComponent);
12489
12490 boolean started = false;
12491 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012492 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493 "Delivering to component " + r.curComponent
12494 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012495 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012496 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12497 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12498 started = true;
12499 } finally {
12500 if (!started) {
12501 r.receiver = null;
12502 r.curApp = null;
12503 app.curReceiver = null;
12504 }
12505 }
12506
12507 }
12508
12509 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012510 Intent intent, int resultCode, String data, Bundle extras,
12511 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 if (app != null && app.thread != null) {
12513 // If we have an app thread, do the call through that so it is
12514 // correctly ordered with other one-way calls.
12515 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012516 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012517 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012518 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 }
12520 }
12521
12522 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12523 BroadcastFilter filter, boolean ordered) {
12524 boolean skip = false;
12525 if (filter.requiredPermission != null) {
12526 int perm = checkComponentPermission(filter.requiredPermission,
12527 r.callingPid, r.callingUid, -1);
12528 if (perm != PackageManager.PERMISSION_GRANTED) {
12529 Log.w(TAG, "Permission Denial: broadcasting "
12530 + r.intent.toString()
12531 + " from " + r.callerPackage + " (pid="
12532 + r.callingPid + ", uid=" + r.callingUid + ")"
12533 + " requires " + filter.requiredPermission
12534 + " due to registered receiver " + filter);
12535 skip = true;
12536 }
12537 }
12538 if (r.requiredPermission != null) {
12539 int perm = checkComponentPermission(r.requiredPermission,
12540 filter.receiverList.pid, filter.receiverList.uid, -1);
12541 if (perm != PackageManager.PERMISSION_GRANTED) {
12542 Log.w(TAG, "Permission Denial: receiving "
12543 + r.intent.toString()
12544 + " to " + filter.receiverList.app
12545 + " (pid=" + filter.receiverList.pid
12546 + ", uid=" + filter.receiverList.uid + ")"
12547 + " requires " + r.requiredPermission
12548 + " due to sender " + r.callerPackage
12549 + " (uid " + r.callingUid + ")");
12550 skip = true;
12551 }
12552 }
12553
12554 if (!skip) {
12555 // If this is not being sent as an ordered broadcast, then we
12556 // don't want to touch the fields that keep track of the current
12557 // state of ordered broadcasts.
12558 if (ordered) {
12559 r.receiver = filter.receiverList.receiver.asBinder();
12560 r.curFilter = filter;
12561 filter.receiverList.curBroadcast = r;
12562 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012563 if (filter.receiverList.app != null) {
12564 // Bump hosting application to no longer be in background
12565 // scheduling class. Note that we can't do that if there
12566 // isn't an app... but we can only be in that case for
12567 // things that directly call the IActivityManager API, which
12568 // are already core system stuff so don't matter for this.
12569 r.curApp = filter.receiverList.app;
12570 filter.receiverList.app.curReceiver = r;
12571 updateOomAdjLocked();
12572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012573 }
12574 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012575 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012577 Log.i(TAG, "Delivering to " + filter.receiverList.app
12578 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012579 }
12580 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12581 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012582 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012583 if (ordered) {
12584 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12585 }
12586 } catch (RemoteException e) {
12587 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
12588 if (ordered) {
12589 r.receiver = null;
12590 r.curFilter = null;
12591 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012592 if (filter.receiverList.app != null) {
12593 filter.receiverList.app.curReceiver = null;
12594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012595 }
12596 }
12597 }
12598 }
12599
Dianne Hackborn12527f92009-11-11 17:39:50 -080012600 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12601 if (r.callingUid < 0) {
12602 // This was from a registerReceiver() call; ignore it.
12603 return;
12604 }
12605 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12606 MAX_BROADCAST_HISTORY-1);
12607 r.finishTime = SystemClock.uptimeMillis();
12608 mBroadcastHistory[0] = r;
12609 }
12610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012611 private final void processNextBroadcast(boolean fromMsg) {
12612 synchronized(this) {
12613 BroadcastRecord r;
12614
12615 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
12616 + mParallelBroadcasts.size() + " broadcasts, "
12617 + mOrderedBroadcasts.size() + " serialized broadcasts");
12618
12619 updateCpuStats();
12620
12621 if (fromMsg) {
12622 mBroadcastsScheduled = false;
12623 }
12624
12625 // First, deliver any non-serialized broadcasts right away.
12626 while (mParallelBroadcasts.size() > 0) {
12627 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012628 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012629 final int N = r.receivers.size();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012630 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing parallel broadcast "
12631 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012632 for (int i=0; i<N; i++) {
12633 Object target = r.receivers.get(i);
12634 if (DEBUG_BROADCAST) Log.v(TAG,
12635 "Delivering non-serialized to registered "
12636 + target + ": " + r);
12637 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12638 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012639 addBroadcastToHistoryLocked(r);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012640 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Done with parallel broadcast "
12641 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 }
12643
12644 // Now take care of the next serialized one...
12645
12646 // If we are waiting for a process to come up to handle the next
12647 // broadcast, then do nothing at this point. Just in case, we
12648 // check that the process we're waiting for still exists.
12649 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012650 if (DEBUG_BROADCAST_LIGHT) {
12651 Log.v(TAG, "processNextBroadcast: waiting for "
12652 + mPendingBroadcast.curApp);
12653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654
12655 boolean isDead;
12656 synchronized (mPidsSelfLocked) {
12657 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12658 }
12659 if (!isDead) {
12660 // It's still alive, so keep waiting
12661 return;
12662 } else {
12663 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
12664 + " died before responding to broadcast");
12665 mPendingBroadcast = null;
12666 }
12667 }
12668
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012669 boolean looped = false;
12670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671 do {
12672 if (mOrderedBroadcasts.size() == 0) {
12673 // No more broadcasts pending, so all done!
12674 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012675 if (looped) {
12676 // If we had finished the last ordered broadcast, then
12677 // make sure all processes have correct oom and sched
12678 // adjustments.
12679 updateOomAdjLocked();
12680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012681 return;
12682 }
12683 r = mOrderedBroadcasts.get(0);
12684 boolean forceReceive = false;
12685
12686 // Ensure that even if something goes awry with the timeout
12687 // detection, we catch "hung" broadcasts here, discard them,
12688 // and continue to make progress.
12689 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12690 long now = SystemClock.uptimeMillis();
12691 if (r.dispatchTime > 0) {
12692 if ((numReceivers > 0) &&
12693 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
12694 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
12695 + " now=" + now
12696 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012697 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012698 + " intent=" + r.intent
12699 + " numReceivers=" + numReceivers
12700 + " nextReceiver=" + r.nextReceiver
12701 + " state=" + r.state);
12702 broadcastTimeout(); // forcibly finish this broadcast
12703 forceReceive = true;
12704 r.state = BroadcastRecord.IDLE;
12705 }
12706 }
12707
12708 if (r.state != BroadcastRecord.IDLE) {
12709 if (DEBUG_BROADCAST) Log.d(TAG,
12710 "processNextBroadcast() called when not idle (state="
12711 + r.state + ")");
12712 return;
12713 }
12714
12715 if (r.receivers == null || r.nextReceiver >= numReceivers
12716 || r.resultAbort || forceReceive) {
12717 // No more receivers for this broadcast! Send the final
12718 // result if requested...
12719 if (r.resultTo != null) {
12720 try {
12721 if (DEBUG_BROADCAST) {
12722 int seq = r.intent.getIntExtra("seq", -1);
12723 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
12724 + " seq=" + seq + " app=" + r.callerApp);
12725 }
12726 performReceive(r.callerApp, r.resultTo,
12727 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012728 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012729 } catch (RemoteException e) {
12730 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
12731 }
12732 }
12733
12734 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
12735 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12736
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012737 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Finished with ordered broadcast "
12738 + r);
12739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012741 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012742 mOrderedBroadcasts.remove(0);
12743 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012744 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 continue;
12746 }
12747 } while (r == null);
12748
12749 // Get the next receiver...
12750 int recIdx = r.nextReceiver++;
12751
12752 // Keep track of when this receiver started, and make sure there
12753 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012754 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012756 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012758 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing ordered broadcast "
12759 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012760 if (DEBUG_BROADCAST) Log.v(TAG,
12761 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012762 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012763 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012764 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 }
12766
12767 Object nextReceiver = r.receivers.get(recIdx);
12768 if (nextReceiver instanceof BroadcastFilter) {
12769 // Simple case: this is a registered receiver who gets
12770 // a direct call.
12771 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
12772 if (DEBUG_BROADCAST) Log.v(TAG,
12773 "Delivering serialized to registered "
12774 + filter + ": " + r);
12775 deliverToRegisteredReceiver(r, filter, r.ordered);
12776 if (r.receiver == null || !r.ordered) {
12777 // The receiver has already finished, so schedule to
12778 // process the next one.
12779 r.state = BroadcastRecord.IDLE;
12780 scheduleBroadcastsLocked();
12781 }
12782 return;
12783 }
12784
12785 // Hard case: need to instantiate the receiver, possibly
12786 // starting its application process to host it.
12787
12788 ResolveInfo info =
12789 (ResolveInfo)nextReceiver;
12790
12791 boolean skip = false;
12792 int perm = checkComponentPermission(info.activityInfo.permission,
12793 r.callingPid, r.callingUid,
12794 info.activityInfo.exported
12795 ? -1 : info.activityInfo.applicationInfo.uid);
12796 if (perm != PackageManager.PERMISSION_GRANTED) {
12797 Log.w(TAG, "Permission Denial: broadcasting "
12798 + r.intent.toString()
12799 + " from " + r.callerPackage + " (pid=" + r.callingPid
12800 + ", uid=" + r.callingUid + ")"
12801 + " requires " + info.activityInfo.permission
12802 + " due to receiver " + info.activityInfo.packageName
12803 + "/" + info.activityInfo.name);
12804 skip = true;
12805 }
12806 if (r.callingUid != Process.SYSTEM_UID &&
12807 r.requiredPermission != null) {
12808 try {
12809 perm = ActivityThread.getPackageManager().
12810 checkPermission(r.requiredPermission,
12811 info.activityInfo.applicationInfo.packageName);
12812 } catch (RemoteException e) {
12813 perm = PackageManager.PERMISSION_DENIED;
12814 }
12815 if (perm != PackageManager.PERMISSION_GRANTED) {
12816 Log.w(TAG, "Permission Denial: receiving "
12817 + r.intent + " to "
12818 + info.activityInfo.applicationInfo.packageName
12819 + " requires " + r.requiredPermission
12820 + " due to sender " + r.callerPackage
12821 + " (uid " + r.callingUid + ")");
12822 skip = true;
12823 }
12824 }
12825 if (r.curApp != null && r.curApp.crashing) {
12826 // If the target process is crashing, just skip it.
12827 skip = true;
12828 }
12829
12830 if (skip) {
12831 r.receiver = null;
12832 r.curFilter = null;
12833 r.state = BroadcastRecord.IDLE;
12834 scheduleBroadcastsLocked();
12835 return;
12836 }
12837
12838 r.state = BroadcastRecord.APP_RECEIVE;
12839 String targetProcess = info.activityInfo.processName;
12840 r.curComponent = new ComponentName(
12841 info.activityInfo.applicationInfo.packageName,
12842 info.activityInfo.name);
12843 r.curReceiver = info.activityInfo;
12844
12845 // Is this receiver's application already running?
12846 ProcessRecord app = getProcessRecordLocked(targetProcess,
12847 info.activityInfo.applicationInfo.uid);
12848 if (app != null && app.thread != null) {
12849 try {
12850 processCurBroadcastLocked(r, app);
12851 return;
12852 } catch (RemoteException e) {
12853 Log.w(TAG, "Exception when sending broadcast to "
12854 + r.curComponent, e);
12855 }
12856
12857 // If a dead object exception was thrown -- fall through to
12858 // restart the application.
12859 }
12860
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012861 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012862 if ((r.curApp=startProcessLocked(targetProcess,
12863 info.activityInfo.applicationInfo, true,
12864 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012865 "broadcast", r.curComponent,
12866 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12867 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012868 // Ah, this recipient is unavailable. Finish it if necessary,
12869 // and mark the broadcast record as ready for the next.
12870 Log.w(TAG, "Unable to launch app "
12871 + info.activityInfo.applicationInfo.packageName + "/"
12872 + info.activityInfo.applicationInfo.uid + " for broadcast "
12873 + r.intent + ": process is bad");
12874 logBroadcastReceiverDiscard(r);
12875 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12876 r.resultExtras, r.resultAbort, true);
12877 scheduleBroadcastsLocked();
12878 r.state = BroadcastRecord.IDLE;
12879 return;
12880 }
12881
12882 mPendingBroadcast = r;
12883 }
12884 }
12885
12886 // =========================================================
12887 // INSTRUMENTATION
12888 // =========================================================
12889
12890 public boolean startInstrumentation(ComponentName className,
12891 String profileFile, int flags, Bundle arguments,
12892 IInstrumentationWatcher watcher) {
12893 // Refuse possible leaked file descriptors
12894 if (arguments != null && arguments.hasFileDescriptors()) {
12895 throw new IllegalArgumentException("File descriptors passed in Bundle");
12896 }
12897
12898 synchronized(this) {
12899 InstrumentationInfo ii = null;
12900 ApplicationInfo ai = null;
12901 try {
12902 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012903 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012905 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906 } catch (PackageManager.NameNotFoundException e) {
12907 }
12908 if (ii == null) {
12909 reportStartInstrumentationFailure(watcher, className,
12910 "Unable to find instrumentation info for: " + className);
12911 return false;
12912 }
12913 if (ai == null) {
12914 reportStartInstrumentationFailure(watcher, className,
12915 "Unable to find instrumentation target package: " + ii.targetPackage);
12916 return false;
12917 }
12918
12919 int match = mContext.getPackageManager().checkSignatures(
12920 ii.targetPackage, ii.packageName);
12921 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12922 String msg = "Permission Denial: starting instrumentation "
12923 + className + " from pid="
12924 + Binder.getCallingPid()
12925 + ", uid=" + Binder.getCallingPid()
12926 + " not allowed because package " + ii.packageName
12927 + " does not have a signature matching the target "
12928 + ii.targetPackage;
12929 reportStartInstrumentationFailure(watcher, className, msg);
12930 throw new SecurityException(msg);
12931 }
12932
12933 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012934 forceStopPackageLocked(ii.targetPackage, -1, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012935 ProcessRecord app = addAppLocked(ai);
12936 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012937 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012938 app.instrumentationProfileFile = profileFile;
12939 app.instrumentationArguments = arguments;
12940 app.instrumentationWatcher = watcher;
12941 app.instrumentationResultClass = className;
12942 Binder.restoreCallingIdentity(origId);
12943 }
12944
12945 return true;
12946 }
12947
12948 /**
12949 * Report errors that occur while attempting to start Instrumentation. Always writes the
12950 * error to the logs, but if somebody is watching, send the report there too. This enables
12951 * the "am" command to report errors with more information.
12952 *
12953 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12954 * @param cn The component name of the instrumentation.
12955 * @param report The error report.
12956 */
12957 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12958 ComponentName cn, String report) {
12959 Log.w(TAG, report);
12960 try {
12961 if (watcher != null) {
12962 Bundle results = new Bundle();
12963 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12964 results.putString("Error", report);
12965 watcher.instrumentationStatus(cn, -1, results);
12966 }
12967 } catch (RemoteException e) {
12968 Log.w(TAG, e);
12969 }
12970 }
12971
12972 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12973 if (app.instrumentationWatcher != null) {
12974 try {
12975 // NOTE: IInstrumentationWatcher *must* be oneway here
12976 app.instrumentationWatcher.instrumentationFinished(
12977 app.instrumentationClass,
12978 resultCode,
12979 results);
12980 } catch (RemoteException e) {
12981 }
12982 }
12983 app.instrumentationWatcher = null;
12984 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012985 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012986 app.instrumentationProfileFile = null;
12987 app.instrumentationArguments = null;
12988
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012989 forceStopPackageLocked(app.processName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012990 }
12991
12992 public void finishInstrumentation(IApplicationThread target,
12993 int resultCode, Bundle results) {
12994 // Refuse possible leaked file descriptors
12995 if (results != null && results.hasFileDescriptors()) {
12996 throw new IllegalArgumentException("File descriptors passed in Intent");
12997 }
12998
12999 synchronized(this) {
13000 ProcessRecord app = getRecordForAppLocked(target);
13001 if (app == null) {
13002 Log.w(TAG, "finishInstrumentation: no app for " + target);
13003 return;
13004 }
13005 final long origId = Binder.clearCallingIdentity();
13006 finishInstrumentationLocked(app, resultCode, results);
13007 Binder.restoreCallingIdentity(origId);
13008 }
13009 }
13010
13011 // =========================================================
13012 // CONFIGURATION
13013 // =========================================================
13014
13015 public ConfigurationInfo getDeviceConfigurationInfo() {
13016 ConfigurationInfo config = new ConfigurationInfo();
13017 synchronized (this) {
13018 config.reqTouchScreen = mConfiguration.touchscreen;
13019 config.reqKeyboardType = mConfiguration.keyboard;
13020 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013021 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13022 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013023 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13024 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013025 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13026 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013027 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13028 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013029 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013030 }
13031 return config;
13032 }
13033
13034 public Configuration getConfiguration() {
13035 Configuration ci;
13036 synchronized(this) {
13037 ci = new Configuration(mConfiguration);
13038 }
13039 return ci;
13040 }
13041
13042 public void updateConfiguration(Configuration values) {
13043 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13044 "updateConfiguration()");
13045
13046 synchronized(this) {
13047 if (values == null && mWindowManager != null) {
13048 // sentinel: fetch the current configuration from the window manager
13049 values = mWindowManager.computeNewConfiguration();
13050 }
13051
13052 final long origId = Binder.clearCallingIdentity();
13053 updateConfigurationLocked(values, null);
13054 Binder.restoreCallingIdentity(origId);
13055 }
13056 }
13057
13058 /**
13059 * Do either or both things: (1) change the current configuration, and (2)
13060 * make sure the given activity is running with the (now) current
13061 * configuration. Returns true if the activity has been left running, or
13062 * false if <var>starting</var> is being destroyed to match the new
13063 * configuration.
13064 */
13065 public boolean updateConfigurationLocked(Configuration values,
13066 HistoryRecord starting) {
13067 int changes = 0;
13068
13069 boolean kept = true;
13070
13071 if (values != null) {
13072 Configuration newConfig = new Configuration(mConfiguration);
13073 changes = newConfig.updateFrom(values);
13074 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013075 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013076 Log.i(TAG, "Updating configuration to: " + values);
13077 }
13078
Doug Zongker2bec3d42009-12-04 12:52:44 -080013079 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013080
13081 if (values.locale != null) {
13082 saveLocaleLocked(values.locale,
13083 !values.locale.equals(mConfiguration.locale),
13084 values.userSetLocale);
13085 }
13086
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013087 mConfigurationSeq++;
13088 if (mConfigurationSeq <= 0) {
13089 mConfigurationSeq = 1;
13090 }
13091 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013092 mConfiguration = newConfig;
Dianne Hackborna8f60182009-09-01 19:01:50 -070013093 Log.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013094
13095 AttributeCache ac = AttributeCache.instance();
13096 if (ac != null) {
13097 ac.updateConfiguration(mConfiguration);
13098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013099
13100 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13101 msg.obj = new Configuration(mConfiguration);
13102 mHandler.sendMessage(msg);
13103
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013104 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13105 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013106 try {
13107 if (app.thread != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013108 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending to proc "
13109 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 app.thread.scheduleConfigurationChanged(mConfiguration);
13111 }
13112 } catch (Exception e) {
13113 }
13114 }
13115 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013116 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13117 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013118 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13119 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013120 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13121 broadcastIntentLocked(null, null,
13122 new Intent(Intent.ACTION_LOCALE_CHANGED),
13123 null, null, 0, null, null,
13124 null, false, false, MY_PID, Process.SYSTEM_UID);
13125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013126 }
13127 }
13128
13129 if (changes != 0 && starting == null) {
13130 // If the configuration changed, and the caller is not already
13131 // in the process of starting an activity, then find the top
13132 // activity to check if its configuration needs to change.
13133 starting = topRunningActivityLocked(null);
13134 }
13135
13136 if (starting != null) {
13137 kept = ensureActivityConfigurationLocked(starting, changes);
13138 if (kept) {
13139 // If this didn't result in the starting activity being
13140 // destroyed, then we need to make sure at this point that all
13141 // other activities are made visible.
13142 if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
13143 + ", ensuring others are correct.");
13144 ensureActivitiesVisibleLocked(starting, changes);
13145 }
13146 }
13147
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013148 if (values != null && mWindowManager != null) {
13149 mWindowManager.setNewConfiguration(mConfiguration);
13150 }
13151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013152 return kept;
13153 }
13154
13155 private final boolean relaunchActivityLocked(HistoryRecord r,
13156 int changes, boolean andResume) {
13157 List<ResultInfo> results = null;
13158 List<Intent> newIntents = null;
13159 if (andResume) {
13160 results = r.results;
13161 newIntents = r.newIntents;
13162 }
13163 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
13164 + " with results=" + results + " newIntents=" + newIntents
13165 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013166 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13167 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013168 r.task.taskId, r.shortComponentName);
13169
13170 r.startFreezingScreenLocked(r.app, 0);
13171
13172 try {
13173 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
13174 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013175 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013176 // Note: don't need to call pauseIfSleepingLocked() here, because
13177 // the caller will only pass in 'andResume' if this activity is
13178 // currently resumed, which implies we aren't sleeping.
13179 } catch (RemoteException e) {
13180 return false;
13181 }
13182
13183 if (andResume) {
13184 r.results = null;
13185 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013186 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013187 }
13188
13189 return true;
13190 }
13191
13192 /**
13193 * Make sure the given activity matches the current configuration. Returns
13194 * false if the activity had to be destroyed. Returns true if the
13195 * configuration is the same, or the activity will remain running as-is
13196 * for whatever reason. Ensures the HistoryRecord is updated with the
13197 * correct configuration and all other bookkeeping is handled.
13198 */
13199 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13200 int globalChanges) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013201 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13202 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203
13204 // Short circuit: if the two configurations are the exact same
13205 // object (the common case), then there is nothing to do.
13206 Configuration newConfig = mConfiguration;
13207 if (r.configuration == newConfig) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013208 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13209 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210 return true;
13211 }
13212
13213 // We don't worry about activities that are finishing.
13214 if (r.finishing) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013215 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 "Configuration doesn't matter in finishing " + r);
13217 r.stopFreezingScreenLocked(false);
13218 return true;
13219 }
13220
13221 // Okay we now are going to make this activity have the new config.
13222 // But then we need to figure out how it needs to deal with that.
13223 Configuration oldConfig = r.configuration;
13224 r.configuration = newConfig;
13225
13226 // If the activity isn't currently running, just leave the new
13227 // configuration and it will pick that up next time it starts.
13228 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013229 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 "Configuration doesn't matter not running " + r);
13231 r.stopFreezingScreenLocked(false);
13232 return true;
13233 }
13234
13235 // If the activity isn't persistent, there is a chance we will
13236 // need to restart it.
13237 if (!r.persistent) {
13238
13239 // Figure out what has changed between the two configurations.
13240 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013241 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
13242 Log.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013243 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013244 + Integer.toHexString(r.info.configChanges)
13245 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013246 }
13247 if ((changes&(~r.info.configChanges)) != 0) {
13248 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13249 r.configChangeFlags |= changes;
13250 r.startFreezingScreenLocked(r.app, globalChanges);
13251 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013252 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13253 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013254 destroyActivityLocked(r, true);
13255 } else if (r.state == ActivityState.PAUSING) {
13256 // A little annoying: we are waiting for this activity to
13257 // finish pausing. Let's not do anything now, but just
13258 // flag that it needs to be restarted when done pausing.
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013259 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13260 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013261 r.configDestroy = true;
13262 return true;
13263 } else if (r.state == ActivityState.RESUMED) {
13264 // Try to optimize this case: the configuration is changing
13265 // and we need to restart the top, resumed activity.
13266 // Instead of doing the normal handshaking, just say
13267 // "restart!".
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013268 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13269 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013270 relaunchActivityLocked(r, r.configChangeFlags, true);
13271 r.configChangeFlags = 0;
13272 } else {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013273 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13274 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275 relaunchActivityLocked(r, r.configChangeFlags, false);
13276 r.configChangeFlags = 0;
13277 }
13278
13279 // All done... tell the caller we weren't able to keep this
13280 // activity around.
13281 return false;
13282 }
13283 }
13284
13285 // Default case: the activity can handle this new configuration, so
13286 // hand it over. Note that we don't need to give it the new
13287 // configuration, since we always send configuration changes to all
13288 // process when they happen so it can just use whatever configuration
13289 // it last got.
13290 if (r.app != null && r.app.thread != null) {
13291 try {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013292 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013293 r.app.thread.scheduleActivityConfigurationChanged(r);
13294 } catch (RemoteException e) {
13295 // If process died, whatever.
13296 }
13297 }
13298 r.stopFreezingScreenLocked(false);
13299
13300 return true;
13301 }
13302
13303 /**
13304 * Save the locale. You must be inside a synchronized (this) block.
13305 */
13306 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13307 if(isDiff) {
13308 SystemProperties.set("user.language", l.getLanguage());
13309 SystemProperties.set("user.region", l.getCountry());
13310 }
13311
13312 if(isPersist) {
13313 SystemProperties.set("persist.sys.language", l.getLanguage());
13314 SystemProperties.set("persist.sys.country", l.getCountry());
13315 SystemProperties.set("persist.sys.localevar", l.getVariant());
13316 }
13317 }
13318
13319 // =========================================================
13320 // LIFETIME MANAGEMENT
13321 // =========================================================
13322
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013323 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13324 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013325 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013326 // This adjustment has already been computed. If we are calling
13327 // from the top, we may have already computed our adjustment with
13328 // an earlier hidden adjustment that isn't really for us... if
13329 // so, use the new hidden adjustment.
13330 if (!recursed && app.hidden) {
13331 app.curAdj = hiddenAdj;
13332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013333 return app.curAdj;
13334 }
13335
13336 if (app.thread == null) {
13337 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013338 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013339 return (app.curAdj=EMPTY_APP_ADJ);
13340 }
13341
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013342 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13343 // The max adjustment doesn't allow this app to be anything
13344 // below foreground, so it is not worth doing work for it.
13345 app.adjType = "fixed";
13346 app.adjSeq = mAdjSeq;
13347 app.curRawAdj = app.maxAdj;
13348 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13349 return (app.curAdj=app.maxAdj);
13350 }
13351
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013352 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013353 app.adjSource = null;
13354 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013355 app.empty = false;
13356 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013357
The Android Open Source Project4df24232009-03-05 14:34:35 -080013358 // Determine the importance of the process, starting with most
13359 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013361 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013362 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013363 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013364 // The last app on the list is the foreground app.
13365 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013366 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013367 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013368 } else if (app.instrumentationClass != null) {
13369 // Don't want to kill running instrumentation.
13370 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013371 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013372 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013373 } else if (app.persistentActivities > 0) {
13374 // Special persistent activities... shouldn't be used these days.
13375 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013376 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013377 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 } else if (app.curReceiver != null ||
13379 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13380 // An app that is currently receiving a broadcast also
13381 // counts as being in the foreground.
13382 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013383 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013384 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 } else if (app.executingServices.size() > 0) {
13386 // An app that is currently executing a service callback also
13387 // counts as being in the foreground.
13388 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013389 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013390 app.adjType = "exec-service";
13391 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 // The user is aware of this app, so make it visible.
13393 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013394 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013395 app.adjType = "foreground-service";
13396 } else if (app.forcingToForeground != null) {
13397 // The user is aware of this app, so make it visible.
13398 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013399 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013400 app.adjType = "force-foreground";
13401 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013402 } else if (app == mHomeProcess) {
13403 // This process is hosting what we currently consider to be the
13404 // home app, so we don't want to let it go into the background.
13405 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013406 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013407 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408 } else if ((N=app.activities.size()) != 0) {
13409 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013410 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013411 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013412 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013413 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013414 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 for (int j=0; j<N; j++) {
13416 if (((HistoryRecord)app.activities.get(j)).visible) {
13417 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013418 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013420 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013421 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 break;
13423 }
13424 }
13425 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013426 // A very not-needed process. If this is lower in the lru list,
13427 // we will push it in to the empty bucket.
13428 app.hidden = true;
13429 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013430 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013431 adj = hiddenAdj;
13432 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013433 }
13434
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013435 //Log.i(TAG, "OOM " + app + ": initial adj=" + adj);
13436
The Android Open Source Project4df24232009-03-05 14:34:35 -080013437 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013438 // there are applications dependent on our services or providers, but
13439 // this gives us a baseline and makes sure we don't get into an
13440 // infinite recursion.
13441 app.adjSeq = mAdjSeq;
13442 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013443
Christopher Tate6fa95972009-06-05 18:43:55 -070013444 if (mBackupTarget != null && app == mBackupTarget.app) {
13445 // If possible we want to avoid killing apps while they're being backed up
13446 if (adj > BACKUP_APP_ADJ) {
13447 if (DEBUG_BACKUP) Log.v(TAG, "oom BACKUP_APP_ADJ for " + app);
13448 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013449 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013450 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013451 }
13452 }
13453
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013454 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13455 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 final long now = SystemClock.uptimeMillis();
13457 // This process is more important if the top activity is
13458 // bound to the service.
13459 Iterator jt = app.services.iterator();
13460 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13461 ServiceRecord s = (ServiceRecord)jt.next();
13462 if (s.startRequested) {
13463 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13464 // This service has seen some activity within
13465 // recent memory, so we will keep its process ahead
13466 // of the background processes.
13467 if (adj > SECONDARY_SERVER_ADJ) {
13468 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013469 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013470 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013471 }
13472 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013473 // If we have let the service slide into the background
13474 // state, still have some text describing what it is doing
13475 // even though the service no longer has an impact.
13476 if (adj > SECONDARY_SERVER_ADJ) {
13477 app.adjType = "started-bg-services";
13478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013479 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013480 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13481 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013482 Iterator<ConnectionRecord> kt
13483 = s.connections.values().iterator();
13484 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13485 // XXX should compute this based on the max of
13486 // all connected clients.
13487 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013488 if (cr.binding.client == app) {
13489 // Binding to ourself is not interesting.
13490 continue;
13491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013492 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13493 ProcessRecord client = cr.binding.client;
13494 int myHiddenAdj = hiddenAdj;
13495 if (myHiddenAdj > client.hiddenAdj) {
13496 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13497 myHiddenAdj = client.hiddenAdj;
13498 } else {
13499 myHiddenAdj = VISIBLE_APP_ADJ;
13500 }
13501 }
13502 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013503 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013504 if (adj > clientAdj) {
13505 adj = clientAdj > VISIBLE_APP_ADJ
13506 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013507 if (!client.hidden) {
13508 app.hidden = false;
13509 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013510 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013511 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13512 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013513 app.adjSource = cr.binding.client;
13514 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013516 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13517 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13518 schedGroup = Process.THREAD_GROUP_DEFAULT;
13519 }
13520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013521 }
13522 HistoryRecord a = cr.activity;
13523 //if (a != null) {
13524 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
13525 //}
13526 if (a != null && adj > FOREGROUND_APP_ADJ &&
13527 (a.state == ActivityState.RESUMED
13528 || a.state == ActivityState.PAUSING)) {
13529 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013530 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013531 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013532 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013533 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13534 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013535 app.adjSource = a;
13536 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013537 }
13538 }
13539 }
13540 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013541
13542 // Finally, f this process has active services running in it, we
13543 // would like to avoid killing it unless it would prevent the current
13544 // application from running. By default we put the process in
13545 // with the rest of the background processes; as we scan through
13546 // its services we may bump it up from there.
13547 if (adj > hiddenAdj) {
13548 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013549 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013550 app.adjType = "bg-services";
13551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013552 }
13553
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013554 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13555 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013557 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13558 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013559 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13560 if (cpr.clients.size() != 0) {
13561 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13562 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13563 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013564 if (client == app) {
13565 // Being our own client is not interesting.
13566 continue;
13567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 int myHiddenAdj = hiddenAdj;
13569 if (myHiddenAdj > client.hiddenAdj) {
13570 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13571 myHiddenAdj = client.hiddenAdj;
13572 } else {
13573 myHiddenAdj = FOREGROUND_APP_ADJ;
13574 }
13575 }
13576 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013577 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013578 if (adj > clientAdj) {
13579 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013580 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013581 if (!client.hidden) {
13582 app.hidden = false;
13583 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013584 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013585 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13586 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013587 app.adjSource = client;
13588 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013589 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013590 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13591 schedGroup = Process.THREAD_GROUP_DEFAULT;
13592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013593 }
13594 }
13595 // If the provider has external (non-framework) process
13596 // dependencies, ensure that its adjustment is at least
13597 // FOREGROUND_APP_ADJ.
13598 if (cpr.externals != 0) {
13599 if (adj > FOREGROUND_APP_ADJ) {
13600 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013601 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013602 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013603 app.adjType = "provider";
13604 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 }
13606 }
13607 }
13608 }
13609
13610 app.curRawAdj = adj;
13611
13612 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
13613 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13614 if (adj > app.maxAdj) {
13615 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013616 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13617 schedGroup = Process.THREAD_GROUP_DEFAULT;
13618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013619 }
13620
13621 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013622 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 return adj;
13625 }
13626
13627 /**
13628 * Ask a given process to GC right now.
13629 */
13630 final void performAppGcLocked(ProcessRecord app) {
13631 try {
13632 app.lastRequestedGc = SystemClock.uptimeMillis();
13633 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013634 if (app.reportLowMemory) {
13635 app.reportLowMemory = false;
13636 app.thread.scheduleLowMemory();
13637 } else {
13638 app.thread.processInBackground();
13639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013640 }
13641 } catch (Exception e) {
13642 // whatever.
13643 }
13644 }
13645
13646 /**
13647 * Returns true if things are idle enough to perform GCs.
13648 */
13649 private final boolean canGcNow() {
13650 return mParallelBroadcasts.size() == 0
13651 && mOrderedBroadcasts.size() == 0
13652 && (mSleeping || (mResumedActivity != null &&
13653 mResumedActivity.idle));
13654 }
13655
13656 /**
13657 * Perform GCs on all processes that are waiting for it, but only
13658 * if things are idle.
13659 */
13660 final void performAppGcsLocked() {
13661 final int N = mProcessesToGc.size();
13662 if (N <= 0) {
13663 return;
13664 }
13665 if (canGcNow()) {
13666 while (mProcessesToGc.size() > 0) {
13667 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013668 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13669 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13670 <= SystemClock.uptimeMillis()) {
13671 // To avoid spamming the system, we will GC processes one
13672 // at a time, waiting a few seconds between each.
13673 performAppGcLocked(proc);
13674 scheduleAppGcsLocked();
13675 return;
13676 } else {
13677 // It hasn't been long enough since we last GCed this
13678 // process... put it in the list to wait for its time.
13679 addProcessToGcListLocked(proc);
13680 break;
13681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 }
13683 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013684
13685 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013686 }
13687 }
13688
13689 /**
13690 * If all looks good, perform GCs on all processes waiting for them.
13691 */
13692 final void performAppGcsIfAppropriateLocked() {
13693 if (canGcNow()) {
13694 performAppGcsLocked();
13695 return;
13696 }
13697 // Still not idle, wait some more.
13698 scheduleAppGcsLocked();
13699 }
13700
13701 /**
13702 * Schedule the execution of all pending app GCs.
13703 */
13704 final void scheduleAppGcsLocked() {
13705 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013706
13707 if (mProcessesToGc.size() > 0) {
13708 // Schedule a GC for the time to the next process.
13709 ProcessRecord proc = mProcessesToGc.get(0);
13710 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13711
13712 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13713 long now = SystemClock.uptimeMillis();
13714 if (when < (now+GC_TIMEOUT)) {
13715 when = now + GC_TIMEOUT;
13716 }
13717 mHandler.sendMessageAtTime(msg, when);
13718 }
13719 }
13720
13721 /**
13722 * Add a process to the array of processes waiting to be GCed. Keeps the
13723 * list in sorted order by the last GC time. The process can't already be
13724 * on the list.
13725 */
13726 final void addProcessToGcListLocked(ProcessRecord proc) {
13727 boolean added = false;
13728 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13729 if (mProcessesToGc.get(i).lastRequestedGc <
13730 proc.lastRequestedGc) {
13731 added = true;
13732 mProcessesToGc.add(i+1, proc);
13733 break;
13734 }
13735 }
13736 if (!added) {
13737 mProcessesToGc.add(0, proc);
13738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013739 }
13740
13741 /**
13742 * Set up to ask a process to GC itself. This will either do it
13743 * immediately, or put it on the list of processes to gc the next
13744 * time things are idle.
13745 */
13746 final void scheduleAppGcLocked(ProcessRecord app) {
13747 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013748 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013749 return;
13750 }
13751 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013752 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013753 scheduleAppGcsLocked();
13754 }
13755 }
13756
13757 private final boolean updateOomAdjLocked(
13758 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13759 app.hiddenAdj = hiddenAdj;
13760
13761 if (app.thread == null) {
13762 return true;
13763 }
13764
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013765 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013766
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013767 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013768 if (app.curRawAdj != app.setRawAdj) {
13769 if (app.curRawAdj > FOREGROUND_APP_ADJ
13770 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13771 // If this app is transitioning from foreground to
13772 // non-foreground, have it do a gc.
13773 scheduleAppGcLocked(app);
13774 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13775 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13776 // Likewise do a gc when an app is moving in to the
13777 // background (such as a service stopping).
13778 scheduleAppGcLocked(app);
13779 }
13780 app.setRawAdj = app.curRawAdj;
13781 }
13782 if (adj != app.setAdj) {
13783 if (Process.setOomAdj(app.pid, adj)) {
13784 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
13785 TAG, "Set app " + app.processName +
13786 " oom adj to " + adj);
13787 app.setAdj = adj;
13788 } else {
13789 return false;
13790 }
13791 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013792 if (app.setSchedGroup != app.curSchedGroup) {
13793 app.setSchedGroup = app.curSchedGroup;
13794 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG,
13795 "Setting process group of " + app.processName
13796 + " to " + app.curSchedGroup);
13797 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013798 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013799 try {
13800 Process.setProcessGroup(app.pid, app.curSchedGroup);
13801 } catch (Exception e) {
13802 Log.w(TAG, "Failed setting process group of " + app.pid
13803 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013804 e.printStackTrace();
13805 } finally {
13806 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013807 }
13808 }
13809 if (false) {
13810 if (app.thread != null) {
13811 try {
13812 app.thread.setSchedulingGroup(app.curSchedGroup);
13813 } catch (RemoteException e) {
13814 }
13815 }
13816 }
13817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 }
13819
13820 return true;
13821 }
13822
13823 private final HistoryRecord resumedAppLocked() {
13824 HistoryRecord resumedActivity = mResumedActivity;
13825 if (resumedActivity == null || resumedActivity.app == null) {
13826 resumedActivity = mPausingActivity;
13827 if (resumedActivity == null || resumedActivity.app == null) {
13828 resumedActivity = topRunningActivityLocked(null);
13829 }
13830 }
13831 return resumedActivity;
13832 }
13833
13834 private final boolean updateOomAdjLocked(ProcessRecord app) {
13835 final HistoryRecord TOP_ACT = resumedAppLocked();
13836 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13837 int curAdj = app.curAdj;
13838 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13839 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13840
13841 mAdjSeq++;
13842
13843 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13844 if (res) {
13845 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13846 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13847 if (nowHidden != wasHidden) {
13848 // Changed to/from hidden state, so apps after it in the LRU
13849 // list may also be changed.
13850 updateOomAdjLocked();
13851 }
13852 }
13853 return res;
13854 }
13855
13856 private final boolean updateOomAdjLocked() {
13857 boolean didOomAdj = true;
13858 final HistoryRecord TOP_ACT = resumedAppLocked();
13859 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13860
13861 if (false) {
13862 RuntimeException e = new RuntimeException();
13863 e.fillInStackTrace();
13864 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
13865 }
13866
13867 mAdjSeq++;
13868
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013869 // Let's determine how many processes we have running vs.
13870 // how many slots we have for background processes; we may want
13871 // to put multiple processes in a slot of there are enough of
13872 // them.
13873 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13874 int factor = (mLruProcesses.size()-4)/numSlots;
13875 if (factor < 1) factor = 1;
13876 int step = 0;
13877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013878 // First try updating the OOM adjustment for each of the
13879 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013880 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013881 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13882 while (i > 0) {
13883 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013884 ProcessRecord app = mLruProcesses.get(i);
13885 //Log.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013886 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013887 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013888 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013889 step++;
13890 if (step >= factor) {
13891 step = 0;
13892 curHiddenAdj++;
13893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013894 }
13895 } else {
13896 didOomAdj = false;
13897 }
13898 }
13899
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013900 // If we return false, we will fall back on killing processes to
13901 // have a fixed limit. Do this if a limit has been requested; else
13902 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013903 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13904 }
13905
13906 private final void trimApplications() {
13907 synchronized (this) {
13908 int i;
13909
13910 // First remove any unused application processes whose package
13911 // has been removed.
13912 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13913 final ProcessRecord app = mRemovedProcesses.get(i);
13914 if (app.activities.size() == 0
13915 && app.curReceiver == null && app.services.size() == 0) {
13916 Log.i(
13917 TAG, "Exiting empty application process "
13918 + app.processName + " ("
13919 + (app.thread != null ? app.thread.asBinder() : null)
13920 + ")\n");
13921 if (app.pid > 0 && app.pid != MY_PID) {
13922 Process.killProcess(app.pid);
13923 } else {
13924 try {
13925 app.thread.scheduleExit();
13926 } catch (Exception e) {
13927 // Ignore exceptions.
13928 }
13929 }
13930 cleanUpApplicationRecordLocked(app, false, -1);
13931 mRemovedProcesses.remove(i);
13932
13933 if (app.persistent) {
13934 if (app.persistent) {
13935 addAppLocked(app.info);
13936 }
13937 }
13938 }
13939 }
13940
13941 // Now try updating the OOM adjustment for each of the
13942 // application processes based on their current state.
13943 // If the setOomAdj() API is not supported, then go with our
13944 // back-up plan...
13945 if (!updateOomAdjLocked()) {
13946
13947 // Count how many processes are running services.
13948 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013949 for (i=mLruProcesses.size()-1; i>=0; i--) {
13950 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013951
13952 if (app.persistent || app.services.size() != 0
13953 || app.curReceiver != null
13954 || app.persistentActivities > 0) {
13955 // Don't count processes holding services against our
13956 // maximum process count.
13957 if (localLOGV) Log.v(
13958 TAG, "Not trimming app " + app + " with services: "
13959 + app.services);
13960 numServiceProcs++;
13961 }
13962 }
13963
13964 int curMaxProcs = mProcessLimit;
13965 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13966 if (mAlwaysFinishActivities) {
13967 curMaxProcs = 1;
13968 }
13969 curMaxProcs += numServiceProcs;
13970
13971 // Quit as many processes as we can to get down to the desired
13972 // process count. First remove any processes that no longer
13973 // have activites running in them.
13974 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013975 i<mLruProcesses.size()
13976 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013977 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013978 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013979 // Quit an application only if it is not currently
13980 // running any activities.
13981 if (!app.persistent && app.activities.size() == 0
13982 && app.curReceiver == null && app.services.size() == 0) {
13983 Log.i(
13984 TAG, "Exiting empty application process "
13985 + app.processName + " ("
13986 + (app.thread != null ? app.thread.asBinder() : null)
13987 + ")\n");
13988 if (app.pid > 0 && app.pid != MY_PID) {
13989 Process.killProcess(app.pid);
13990 } else {
13991 try {
13992 app.thread.scheduleExit();
13993 } catch (Exception e) {
13994 // Ignore exceptions.
13995 }
13996 }
13997 // todo: For now we assume the application is not buggy
13998 // or evil, and will quit as a result of our request.
13999 // Eventually we need to drive this off of the death
14000 // notification, and kill the process if it takes too long.
14001 cleanUpApplicationRecordLocked(app, false, i);
14002 i--;
14003 }
14004 }
14005
14006 // If we still have too many processes, now from the least
14007 // recently used process we start finishing activities.
14008 if (Config.LOGV) Log.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014009 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014010 " of " + curMaxProcs + " processes");
14011 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014012 i<mLruProcesses.size()
14013 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014014 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014015 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014016 // Quit the application only if we have a state saved for
14017 // all of its activities.
14018 boolean canQuit = !app.persistent && app.curReceiver == null
14019 && app.services.size() == 0
14020 && app.persistentActivities == 0;
14021 int NUMA = app.activities.size();
14022 int j;
14023 if (Config.LOGV) Log.v(
14024 TAG, "Looking to quit " + app.processName);
14025 for (j=0; j<NUMA && canQuit; j++) {
14026 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14027 if (Config.LOGV) Log.v(
14028 TAG, " " + r.intent.getComponent().flattenToShortString()
14029 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14030 canQuit = (r.haveState || !r.stateNotNeeded)
14031 && !r.visible && r.stopped;
14032 }
14033 if (canQuit) {
14034 // Finish all of the activities, and then the app itself.
14035 for (j=0; j<NUMA; j++) {
14036 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14037 if (!r.finishing) {
14038 destroyActivityLocked(r, false);
14039 }
14040 r.resultTo = null;
14041 }
14042 Log.i(TAG, "Exiting application process "
14043 + app.processName + " ("
14044 + (app.thread != null ? app.thread.asBinder() : null)
14045 + ")\n");
14046 if (app.pid > 0 && app.pid != MY_PID) {
14047 Process.killProcess(app.pid);
14048 } else {
14049 try {
14050 app.thread.scheduleExit();
14051 } catch (Exception e) {
14052 // Ignore exceptions.
14053 }
14054 }
14055 // todo: For now we assume the application is not buggy
14056 // or evil, and will quit as a result of our request.
14057 // Eventually we need to drive this off of the death
14058 // notification, and kill the process if it takes too long.
14059 cleanUpApplicationRecordLocked(app, false, i);
14060 i--;
14061 //dump();
14062 }
14063 }
14064
14065 }
14066
14067 int curMaxActivities = MAX_ACTIVITIES;
14068 if (mAlwaysFinishActivities) {
14069 curMaxActivities = 1;
14070 }
14071
14072 // Finally, if there are too many activities now running, try to
14073 // finish as many as we can to get back down to the limit.
14074 for ( i=0;
14075 i<mLRUActivities.size()
14076 && mLRUActivities.size() > curMaxActivities;
14077 i++) {
14078 final HistoryRecord r
14079 = (HistoryRecord)mLRUActivities.get(i);
14080
14081 // We can finish this one if we have its icicle saved and
14082 // it is not persistent.
14083 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14084 && r.stopped && !r.persistent && !r.finishing) {
14085 final int origSize = mLRUActivities.size();
14086 destroyActivityLocked(r, true);
14087
14088 // This will remove it from the LRU list, so keep
14089 // our index at the same value. Note that this check to
14090 // see if the size changes is just paranoia -- if
14091 // something unexpected happens, we don't want to end up
14092 // in an infinite loop.
14093 if (origSize > mLRUActivities.size()) {
14094 i--;
14095 }
14096 }
14097 }
14098 }
14099 }
14100
14101 /** This method sends the specified signal to each of the persistent apps */
14102 public void signalPersistentProcesses(int sig) throws RemoteException {
14103 if (sig != Process.SIGNAL_USR1) {
14104 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14105 }
14106
14107 synchronized (this) {
14108 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14109 != PackageManager.PERMISSION_GRANTED) {
14110 throw new SecurityException("Requires permission "
14111 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14112 }
14113
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014114 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14115 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014116 if (r.thread != null && r.persistent) {
14117 Process.sendSignal(r.pid, sig);
14118 }
14119 }
14120 }
14121 }
14122
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014123 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014124 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014125
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014126 try {
14127 synchronized (this) {
14128 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14129 // its own permission.
14130 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14131 != PackageManager.PERMISSION_GRANTED) {
14132 throw new SecurityException("Requires permission "
14133 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014134 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014135
14136 if (start && fd == null) {
14137 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014138 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014139
14140 ProcessRecord proc = null;
14141 try {
14142 int pid = Integer.parseInt(process);
14143 synchronized (mPidsSelfLocked) {
14144 proc = mPidsSelfLocked.get(pid);
14145 }
14146 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014147 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014148
14149 if (proc == null) {
14150 HashMap<String, SparseArray<ProcessRecord>> all
14151 = mProcessNames.getMap();
14152 SparseArray<ProcessRecord> procs = all.get(process);
14153 if (procs != null && procs.size() > 0) {
14154 proc = procs.valueAt(0);
14155 }
14156 }
14157
14158 if (proc == null || proc.thread == null) {
14159 throw new IllegalArgumentException("Unknown process: " + process);
14160 }
14161
14162 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14163 if (isSecure) {
14164 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14165 throw new SecurityException("Process not debuggable: " + proc);
14166 }
14167 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014168
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014169 proc.thread.profilerControl(start, path, fd);
14170 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014171 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014172 }
14173 } catch (RemoteException e) {
14174 throw new IllegalStateException("Process disappeared");
14175 } finally {
14176 if (fd != null) {
14177 try {
14178 fd.close();
14179 } catch (IOException e) {
14180 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014181 }
14182 }
14183 }
14184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014185 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14186 public void monitor() {
14187 synchronized (this) { }
14188 }
14189}