blob: 3ecfd8a1b6359dec2336693e0d3e6c177502e9c4 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.app.IActivityWatcher;
39import android.app.IApplicationThread;
40import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IServiceConnection;
42import android.app.IThumbnailReceiver;
43import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070044import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.PendingIntent;
46import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070047import android.app.Service;
Christopher Tate181fafa2009-05-14 11:12:14 -070048import android.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020049import android.content.ActivityNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.ComponentName;
51import android.content.ContentResolver;
52import android.content.Context;
53import android.content.Intent;
54import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070055import android.content.IIntentReceiver;
56import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070057import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.pm.ActivityInfo;
59import android.content.pm.ApplicationInfo;
60import android.content.pm.ConfigurationInfo;
61import android.content.pm.IPackageDataObserver;
62import android.content.pm.IPackageManager;
63import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080064import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070066import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.ProviderInfo;
68import android.content.pm.ResolveInfo;
69import android.content.pm.ServiceInfo;
70import android.content.res.Configuration;
71import android.graphics.Bitmap;
72import android.net.Uri;
73import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080074import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080075import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070076import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080077import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080079import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.FileUtils;
81import android.os.Handler;
82import android.os.IBinder;
83import android.os.IPermissionController;
84import android.os.Looper;
85import android.os.Message;
86import android.os.Parcel;
87import android.os.ParcelFileDescriptor;
88import android.os.PowerManager;
89import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070090import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import android.os.RemoteException;
92import android.os.ServiceManager;
93import android.os.SystemClock;
94import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.provider.Settings;
96import android.text.TextUtils;
97import android.util.Config;
98import android.util.EventLog;
99import android.util.Log;
100import android.util.PrintWriterPrinter;
101import android.util.SparseArray;
102import android.view.Gravity;
103import android.view.LayoutInflater;
104import android.view.View;
105import android.view.WindowManager;
106import android.view.WindowManagerPolicy;
107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.io.File;
109import java.io.FileDescriptor;
110import java.io.FileInputStream;
111import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200112import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.io.PrintWriter;
114import java.lang.IllegalStateException;
115import java.lang.ref.WeakReference;
116import java.util.ArrayList;
117import java.util.HashMap;
118import java.util.HashSet;
119import java.util.Iterator;
120import java.util.List;
121import java.util.Locale;
122import java.util.Map;
123
124public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
125 static final String TAG = "ActivityManager";
126 static final boolean DEBUG = false;
127 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
128 static final boolean DEBUG_SWITCH = localLOGV || false;
129 static final boolean DEBUG_TASKS = localLOGV || false;
130 static final boolean DEBUG_PAUSE = localLOGV || false;
131 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
132 static final boolean DEBUG_TRANSITION = localLOGV || false;
133 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700134 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 static final boolean DEBUG_SERVICE = localLOGV || false;
136 static final boolean DEBUG_VISBILITY = localLOGV || false;
137 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700138 static final boolean DEBUG_PROVIDER = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700140 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700141 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700142 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 static final boolean VALIDATE_TOKENS = false;
144 static final boolean SHOW_ACTIVITY_START_TIME = true;
145
146 // Control over CPU and battery monitoring.
147 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
148 static final boolean MONITOR_CPU_USAGE = true;
149 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
150 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
151 static final boolean MONITOR_THREAD_CPU_USAGE = false;
152
Dianne Hackborn1655be42009-05-08 14:29:01 -0700153 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700154 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 private static final String SYSTEM_SECURE = "ro.secure";
157
158 // This is the maximum number of application processes we would like
159 // to have running. Due to the asynchronous nature of things, we can
160 // temporarily go beyond this limit.
161 static final int MAX_PROCESSES = 2;
162
163 // Set to false to leave processes running indefinitely, relying on
164 // the kernel killing them as resources are required.
165 static final boolean ENFORCE_PROCESS_LIMIT = false;
166
167 // This is the maximum number of activities that we would like to have
168 // running at a given time.
169 static final int MAX_ACTIVITIES = 20;
170
171 // Maximum number of recent tasks that we can remember.
172 static final int MAX_RECENT_TASKS = 20;
173
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700174 // Amount of time after a call to stopAppSwitches() during which we will
175 // prevent further untrusted switches from happening.
176 static final long APP_SWITCH_DELAY_TIME = 5*1000;
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 // How long until we reset a task when the user returns to it. Currently
179 // 30 minutes.
180 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
181
182 // Set to true to disable the icon that is shown while a new activity
183 // is being started.
184 static final boolean SHOW_APP_STARTING_ICON = true;
185
186 // How long we wait until giving up on the last activity to pause. This
187 // is short because it directly impacts the responsiveness of starting the
188 // next activity.
189 static final int PAUSE_TIMEOUT = 500;
190
191 /**
192 * How long we can hold the launch wake lock before giving up.
193 */
194 static final int LAUNCH_TIMEOUT = 10*1000;
195
196 // How long we wait for a launched process to attach to the activity manager
197 // before we decide it's never going to come up for real.
198 static final int PROC_START_TIMEOUT = 10*1000;
199
200 // How long we wait until giving up on the last activity telling us it
201 // is idle.
202 static final int IDLE_TIMEOUT = 10*1000;
203
204 // How long to wait after going idle before forcing apps to GC.
205 static final int GC_TIMEOUT = 5*1000;
206
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700207 // The minimum amount of time between successive GC requests for a process.
208 static final int GC_MIN_INTERVAL = 60*1000;
209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 // How long we wait until giving up on an activity telling us it has
211 // finished destroying itself.
212 static final int DESTROY_TIMEOUT = 10*1000;
213
214 // How long we allow a receiver to run before giving up on it.
215 static final int BROADCAST_TIMEOUT = 10*1000;
216
217 // How long we wait for a service to finish executing.
218 static final int SERVICE_TIMEOUT = 20*1000;
219
220 // How long a service needs to be running until restarting its process
221 // is no longer considered to be a relaunch of the service.
222 static final int SERVICE_RESTART_DURATION = 5*1000;
223
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700224 // How long a service needs to be running until it will start back at
225 // SERVICE_RESTART_DURATION after being killed.
226 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
227
228 // Multiplying factor to increase restart duration time by, for each time
229 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
230 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
231
232 // The minimum amount of time between restarting services that we allow.
233 // That is, when multiple services are restarting, we won't allow each
234 // to restart less than this amount of time from the last one.
235 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 // Maximum amount of time for there to be no activity on a service before
238 // we consider it non-essential and allow its process to go on the
239 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700240 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241
242 // How long we wait until we timeout on key dispatching.
243 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
244
245 // The minimum time we allow between crashes, for us to consider this
246 // application to be bad and stop and its services and reject broadcasts.
247 static final int MIN_CRASH_INTERVAL = 60*1000;
248
249 // How long we wait until we timeout on key dispatching during instrumentation.
250 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
251
252 // OOM adjustments for processes in various states:
253
254 // This is a process without anything currently running in it. Definitely
255 // the first to go! Value set in system/rootdir/init.rc on startup.
256 // This value is initalized in the constructor, careful when refering to
257 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800258 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259
260 // This is a process only hosting activities that are not visible,
261 // so it can be killed without any disruption. Value set in
262 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800263 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 static int HIDDEN_APP_MIN_ADJ;
265
The Android Open Source Project4df24232009-03-05 14:34:35 -0800266 // This is a process holding the home application -- we want to try
267 // avoiding killing it, even if it would normally be in the background,
268 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800270
Christopher Tate6fa95972009-06-05 18:43:55 -0700271 // This is a process currently hosting a backup operation. Killing it
272 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800273 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 // This is a process holding a secondary server -- killing it will not
276 // have much of an impact as far as the user is concerned. Value set in
277 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
280 // This is a process only hosting activities that are visible to the
281 // user, so we'd prefer they don't disappear. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // This is the process running the current foreground app. We'd really
286 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // This is a process running a core server, such as telephony. Definitely
290 // don't want to kill it, but doing so is not completely fatal.
291 static final int CORE_SERVER_ADJ = -12;
292
293 // The system process runs at the default adjustment.
294 static final int SYSTEM_ADJ = -16;
295
296 // Memory pages are 4K.
297 static final int PAGE_SIZE = 4*1024;
298
Jacek Surazski82a73df2009-06-17 14:33:18 +0200299 // System property defining error report receiver for system apps
300 static final String SYSTEM_APPS_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.system.apps";
301
302 // System property defining default error report receiver
303 static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int EMPTY_APP_MEM;
307 static final int HIDDEN_APP_MEM;
308 static final int HOME_APP_MEM;
309 static final int BACKUP_APP_MEM;
310 static final int SECONDARY_SERVER_MEM;
311 static final int VISIBLE_APP_MEM;
312 static final int FOREGROUND_APP_MEM;
313
314 // The minimum number of hidden apps we want to be able to keep around,
315 // without empty apps being able to push them out of memory.
316 static final int MIN_HIDDEN_APPS = 2;
317
318 // We put empty content processes after any hidden processes that have
319 // been idle for less than 30 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
321
322 // We put empty content processes after any hidden processes that have
323 // been idle for less than 60 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
325
326 static {
327 // These values are set in system/rootdir/init.rc on startup.
328 FOREGROUND_APP_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
330 VISIBLE_APP_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
332 SECONDARY_SERVER_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
334 BACKUP_APP_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
336 HOME_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
338 HIDDEN_APP_MIN_ADJ =
339 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
340 EMPTY_APP_ADJ =
341 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
342 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
343 FOREGROUND_APP_MEM =
344 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
345 VISIBLE_APP_MEM =
346 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
347 SECONDARY_SERVER_MEM =
348 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
349 BACKUP_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
351 HOME_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
353 HIDDEN_APP_MEM =
354 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
355 EMPTY_APP_MEM =
356 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358
Dan Egnor42471dd2010-01-07 17:25:22 -0800359 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360
361 static final String[] EMPTY_STRING_ARRAY = new String[0];
362
363 enum ActivityState {
364 INITIALIZING,
365 RESUMED,
366 PAUSING,
367 PAUSED,
368 STOPPING,
369 STOPPED,
370 FINISHING,
371 DESTROYING,
372 DESTROYED
373 }
374
375 /**
376 * The back history of all previous (and possibly still
377 * running) activities. It contains HistoryRecord objects.
378 */
379 final ArrayList mHistory = new ArrayList();
380
381 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700382 * Description of a request to start a new activity, which has been held
383 * due to app switches being disabled.
384 */
385 class PendingActivityLaunch {
386 HistoryRecord r;
387 HistoryRecord sourceRecord;
388 Uri[] grantedUriPermissions;
389 int grantedMode;
390 boolean onlyIfNeeded;
391 }
392
393 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
394 = new ArrayList<PendingActivityLaunch>();
395
396 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 * List of all active broadcasts that are to be executed immediately
398 * (without waiting for another broadcast to finish). Currently this only
399 * contains broadcasts to registered receivers, to avoid spinning up
400 * a bunch of processes to execute IntentReceiver components.
401 */
402 final ArrayList<BroadcastRecord> mParallelBroadcasts
403 = new ArrayList<BroadcastRecord>();
404
405 /**
406 * List of all active broadcasts that are to be executed one at a time.
407 * The object at the top of the list is the currently activity broadcasts;
408 * those after it are waiting for the top to finish..
409 */
410 final ArrayList<BroadcastRecord> mOrderedBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800414 * Historical data of past broadcasts, for debugging.
415 */
416 static final int MAX_BROADCAST_HISTORY = 100;
417 final BroadcastRecord[] mBroadcastHistory
418 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
419
420 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 * Set when we current have a BROADCAST_INTENT_MSG in flight.
422 */
423 boolean mBroadcastsScheduled = false;
424
425 /**
426 * Set to indicate whether to issue an onUserLeaving callback when a
427 * newly launched activity is being brought in front of us.
428 */
429 boolean mUserLeaving = false;
430
431 /**
432 * When we are in the process of pausing an activity, before starting the
433 * next one, this variable holds the activity that is currently being paused.
434 */
435 HistoryRecord mPausingActivity = null;
436
437 /**
438 * Current activity that is resumed, or null if there is none.
439 */
440 HistoryRecord mResumedActivity = null;
441
442 /**
443 * Activity we have told the window manager to have key focus.
444 */
445 HistoryRecord mFocusedActivity = null;
446
447 /**
448 * This is the last activity that we put into the paused state. This is
449 * used to determine if we need to do an activity transition while sleeping,
450 * when we normally hold the top activity paused.
451 */
452 HistoryRecord mLastPausedActivity = null;
453
454 /**
455 * List of activities that are waiting for a new activity
456 * to become visible before completing whatever operation they are
457 * supposed to do.
458 */
459 final ArrayList mWaitingVisibleActivities = new ArrayList();
460
461 /**
462 * List of activities that are ready to be stopped, but waiting
463 * for the next activity to settle down before doing so. It contains
464 * HistoryRecord objects.
465 */
466 final ArrayList<HistoryRecord> mStoppingActivities
467 = new ArrayList<HistoryRecord>();
468
469 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700470 * Animations that for the current transition have requested not to
471 * be considered for the transition animation.
472 */
473 final ArrayList<HistoryRecord> mNoAnimActivities
474 = new ArrayList<HistoryRecord>();
475
476 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 * List of intents that were used to start the most recent tasks.
478 */
479 final ArrayList<TaskRecord> mRecentTasks
480 = new ArrayList<TaskRecord>();
481
482 /**
483 * List of activities that are ready to be finished, but waiting
484 * for the previous activity to settle down before doing so. It contains
485 * HistoryRecord objects.
486 */
487 final ArrayList mFinishingActivities = new ArrayList();
488
489 /**
490 * All of the applications we currently have running organized by name.
491 * The keys are strings of the application package name (as
492 * returned by the package manager), and the keys are ApplicationRecord
493 * objects.
494 */
495 final ProcessMap<ProcessRecord> mProcessNames
496 = new ProcessMap<ProcessRecord>();
497
498 /**
499 * The last time that various processes have crashed.
500 */
501 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
502
503 /**
504 * Set of applications that we consider to be bad, and will reject
505 * incoming broadcasts from (which the user has no control over).
506 * Processes are added to this set when they have crashed twice within
507 * a minimum amount of time; they are removed from it when they are
508 * later restarted (hopefully due to some user action). The value is the
509 * time it was added to the list.
510 */
511 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
512
513 /**
514 * All of the processes we currently have running organized by pid.
515 * The keys are the pid running the application.
516 *
517 * <p>NOTE: This object is protected by its own lock, NOT the global
518 * activity manager lock!
519 */
520 final SparseArray<ProcessRecord> mPidsSelfLocked
521 = new SparseArray<ProcessRecord>();
522
523 /**
524 * All of the processes that have been forced to be foreground. The key
525 * is the pid of the caller who requested it (we hold a death
526 * link on it).
527 */
528 abstract class ForegroundToken implements IBinder.DeathRecipient {
529 int pid;
530 IBinder token;
531 }
532 final SparseArray<ForegroundToken> mForegroundProcesses
533 = new SparseArray<ForegroundToken>();
534
535 /**
536 * List of records for processes that someone had tried to start before the
537 * system was ready. We don't start them at that point, but ensure they
538 * are started by the time booting is complete.
539 */
540 final ArrayList<ProcessRecord> mProcessesOnHold
541 = new ArrayList<ProcessRecord>();
542
543 /**
544 * List of records for processes that we have started and are waiting
545 * for them to call back. This is really only needed when running in
546 * single processes mode, in which case we do not have a unique pid for
547 * each process.
548 */
549 final ArrayList<ProcessRecord> mStartingProcesses
550 = new ArrayList<ProcessRecord>();
551
552 /**
553 * List of persistent applications that are in the process
554 * of being started.
555 */
556 final ArrayList<ProcessRecord> mPersistentStartingProcesses
557 = new ArrayList<ProcessRecord>();
558
559 /**
560 * Processes that are being forcibly torn down.
561 */
562 final ArrayList<ProcessRecord> mRemovedProcesses
563 = new ArrayList<ProcessRecord>();
564
565 /**
566 * List of running applications, sorted by recent usage.
567 * The first entry in the list is the least recently used.
568 * It contains ApplicationRecord objects. This list does NOT include
569 * any persistent application records (since we never want to exit them).
570 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800571 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 = new ArrayList<ProcessRecord>();
573
574 /**
575 * List of processes that should gc as soon as things are idle.
576 */
577 final ArrayList<ProcessRecord> mProcessesToGc
578 = new ArrayList<ProcessRecord>();
579
580 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800581 * This is the process holding what we currently consider to be
582 * the "home" activity.
583 */
584 private ProcessRecord mHomeProcess;
585
586 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 * List of running activities, sorted by recent usage.
588 * The first entry in the list is the least recently used.
589 * It contains HistoryRecord objects.
590 */
591 private final ArrayList mLRUActivities = new ArrayList();
592
593 /**
594 * Set of PendingResultRecord objects that are currently active.
595 */
596 final HashSet mPendingResultRecords = new HashSet();
597
598 /**
599 * Set of IntentSenderRecord objects that are currently active.
600 */
601 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
602 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
603
604 /**
605 * Intent broadcast that we have tried to start, but are
606 * waiting for its application's process to be created. We only
607 * need one (instead of a list) because we always process broadcasts
608 * one at a time, so no others can be started while waiting for this
609 * one.
610 */
611 BroadcastRecord mPendingBroadcast = null;
612
613 /**
614 * Keeps track of all IIntentReceivers that have been registered for
615 * broadcasts. Hash keys are the receiver IBinder, hash value is
616 * a ReceiverList.
617 */
618 final HashMap mRegisteredReceivers = new HashMap();
619
620 /**
621 * Resolver for broadcast intents to registered receivers.
622 * Holds BroadcastFilter (subclass of IntentFilter).
623 */
624 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
625 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
626 @Override
627 protected boolean allowFilterResult(
628 BroadcastFilter filter, List<BroadcastFilter> dest) {
629 IBinder target = filter.receiverList.receiver.asBinder();
630 for (int i=dest.size()-1; i>=0; i--) {
631 if (dest.get(i).receiverList.receiver.asBinder() == target) {
632 return false;
633 }
634 }
635 return true;
636 }
637 };
638
639 /**
640 * State of all active sticky broadcasts. Keys are the action of the
641 * sticky Intent, values are an ArrayList of all broadcasted intents with
642 * that action (which should usually be one).
643 */
644 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
645 new HashMap<String, ArrayList<Intent>>();
646
647 /**
648 * All currently running services.
649 */
650 final HashMap<ComponentName, ServiceRecord> mServices =
651 new HashMap<ComponentName, ServiceRecord>();
652
653 /**
654 * All currently running services indexed by the Intent used to start them.
655 */
656 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
657 new HashMap<Intent.FilterComparison, ServiceRecord>();
658
659 /**
660 * All currently bound service connections. Keys are the IBinder of
661 * the client's IServiceConnection.
662 */
663 final HashMap<IBinder, ConnectionRecord> mServiceConnections
664 = new HashMap<IBinder, ConnectionRecord>();
665
666 /**
667 * List of services that we have been asked to start,
668 * but haven't yet been able to. It is used to hold start requests
669 * while waiting for their corresponding application thread to get
670 * going.
671 */
672 final ArrayList<ServiceRecord> mPendingServices
673 = new ArrayList<ServiceRecord>();
674
675 /**
676 * List of services that are scheduled to restart following a crash.
677 */
678 final ArrayList<ServiceRecord> mRestartingServices
679 = new ArrayList<ServiceRecord>();
680
681 /**
682 * List of services that are in the process of being stopped.
683 */
684 final ArrayList<ServiceRecord> mStoppingServices
685 = new ArrayList<ServiceRecord>();
686
687 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700688 * Backup/restore process management
689 */
690 String mBackupAppName = null;
691 BackupRecord mBackupTarget = null;
692
693 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 * List of PendingThumbnailsRecord objects of clients who are still
695 * waiting to receive all of the thumbnails for a task.
696 */
697 final ArrayList mPendingThumbnails = new ArrayList();
698
699 /**
700 * List of HistoryRecord objects that have been finished and must
701 * still report back to a pending thumbnail receiver.
702 */
703 final ArrayList mCancelledThumbnails = new ArrayList();
704
705 /**
706 * All of the currently running global content providers. Keys are a
707 * string containing the provider name and values are a
708 * ContentProviderRecord object containing the data about it. Note
709 * that a single provider may be published under multiple names, so
710 * there may be multiple entries here for a single one in mProvidersByClass.
711 */
712 final HashMap mProvidersByName = new HashMap();
713
714 /**
715 * All of the currently running global content providers. Keys are a
716 * string containing the provider's implementation class and values are a
717 * ContentProviderRecord object containing the data about it.
718 */
719 final HashMap mProvidersByClass = new HashMap();
720
721 /**
722 * List of content providers who have clients waiting for them. The
723 * application is currently being launched and the provider will be
724 * removed from this list once it is published.
725 */
726 final ArrayList mLaunchingProviders = new ArrayList();
727
728 /**
729 * Global set of specific Uri permissions that have been granted.
730 */
731 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
732 = new SparseArray<HashMap<Uri, UriPermission>>();
733
734 /**
735 * Thread-local storage used to carry caller permissions over through
736 * indirect content-provider access.
737 * @see #ActivityManagerService.openContentUri()
738 */
739 private class Identity {
740 public int pid;
741 public int uid;
742
743 Identity(int _pid, int _uid) {
744 pid = _pid;
745 uid = _uid;
746 }
747 }
748 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
749
750 /**
751 * All information we have collected about the runtime performance of
752 * any user id that can impact battery performance.
753 */
754 final BatteryStatsService mBatteryStatsService;
755
756 /**
757 * information about component usage
758 */
759 final UsageStatsService mUsageStatsService;
760
761 /**
762 * Current configuration information. HistoryRecord objects are given
763 * a reference to this object to indicate which configuration they are
764 * currently running in, so this object must be kept immutable.
765 */
766 Configuration mConfiguration = new Configuration();
767
768 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700769 * Hardware-reported OpenGLES version.
770 */
771 final int GL_ES_VERSION;
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * List of initialization arguments to pass to all processes when binding applications to them.
775 * For example, references to the commonly used services.
776 */
777 HashMap<String, IBinder> mAppBindArgs;
778
779 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700780 * Temporary to avoid allocations. Protected by main lock.
781 */
782 final StringBuilder mStringBuilder = new StringBuilder(256);
783
784 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 * Used to control how we initialize the service.
786 */
787 boolean mStartRunning = false;
788 ComponentName mTopComponent;
789 String mTopAction;
790 String mTopData;
791 boolean mSystemReady = false;
792 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700793 boolean mWaitingUpdate = false;
794 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795
796 Context mContext;
797
798 int mFactoryTest;
799
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700800 boolean mCheckedForSetup;
801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700803 * The time at which we will allow normal application switches again,
804 * after a call to {@link #stopAppSwitches()}.
805 */
806 long mAppSwitchesAllowedTime;
807
808 /**
809 * This is set to true after the first switch after mAppSwitchesAllowedTime
810 * is set; any switches after that will clear the time.
811 */
812 boolean mDidAppSwitch;
813
814 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * Set while we are wanting to sleep, to prevent any
816 * activities from being started/resumed.
817 */
818 boolean mSleeping = false;
819
820 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700821 * Set if we are shutting down the system, similar to sleeping.
822 */
823 boolean mShuttingDown = false;
824
825 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 * Set when the system is going to sleep, until we have
827 * successfully paused the current activity and released our wake lock.
828 * At that point the system is allowed to actually sleep.
829 */
830 PowerManager.WakeLock mGoingToSleep;
831
832 /**
833 * We don't want to allow the device to go to sleep while in the process
834 * of launching an activity. This is primarily to allow alarm intent
835 * receivers to launch an activity and get that to run before the device
836 * goes back to sleep.
837 */
838 PowerManager.WakeLock mLaunchingActivity;
839
840 /**
841 * Task identifier that activities are currently being started
842 * in. Incremented each time a new task is created.
843 * todo: Replace this with a TokenSpace class that generates non-repeating
844 * integers that won't wrap.
845 */
846 int mCurTask = 1;
847
848 /**
849 * Current sequence id for oom_adj computation traversal.
850 */
851 int mAdjSeq = 0;
852
853 /**
854 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
855 * is set, indicating the user wants processes started in such a way
856 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
857 * running in each process (thus no pre-initialized process, etc).
858 */
859 boolean mSimpleProcessManagement = false;
860
861 /**
862 * System monitoring: number of processes that died since the last
863 * N procs were started.
864 */
865 int[] mProcDeaths = new int[20];
866
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700867 /**
868 * This is set if we had to do a delayed dexopt of an app before launching
869 * it, to increasing the ANR timeouts in that case.
870 */
871 boolean mDidDexOpt;
872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 String mDebugApp = null;
874 boolean mWaitForDebugger = false;
875 boolean mDebugTransient = false;
876 String mOrigDebugApp = null;
877 boolean mOrigWaitForDebugger = false;
878 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700879 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700881 final RemoteCallbackList<IActivityWatcher> mWatchers
882 = new RemoteCallbackList<IActivityWatcher>();
883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 /**
885 * Callback of last caller to {@link #requestPss}.
886 */
887 Runnable mRequestPssCallback;
888
889 /**
890 * Remaining processes for which we are waiting results from the last
891 * call to {@link #requestPss}.
892 */
893 final ArrayList<ProcessRecord> mRequestPssList
894 = new ArrayList<ProcessRecord>();
895
896 /**
897 * Runtime statistics collection thread. This object's lock is used to
898 * protect all related state.
899 */
900 final Thread mProcessStatsThread;
901
902 /**
903 * Used to collect process stats when showing not responding dialog.
904 * Protected by mProcessStatsThread.
905 */
906 final ProcessStats mProcessStats = new ProcessStats(
907 MONITOR_THREAD_CPU_USAGE);
908 long mLastCpuTime = 0;
909 long mLastWriteTime = 0;
910
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700911 long mInitialStartTime = 0;
912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 /**
914 * Set to true after the system has finished booting.
915 */
916 boolean mBooted = false;
917
918 int mProcessLimit = 0;
919
920 WindowManagerService mWindowManager;
921
922 static ActivityManagerService mSelf;
923 static ActivityThread mSystemThread;
924
925 private final class AppDeathRecipient implements IBinder.DeathRecipient {
926 final ProcessRecord mApp;
927 final int mPid;
928 final IApplicationThread mAppThread;
929
930 AppDeathRecipient(ProcessRecord app, int pid,
931 IApplicationThread thread) {
932 if (localLOGV) Log.v(
933 TAG, "New death recipient " + this
934 + " for thread " + thread.asBinder());
935 mApp = app;
936 mPid = pid;
937 mAppThread = thread;
938 }
939
940 public void binderDied() {
941 if (localLOGV) Log.v(
942 TAG, "Death received in " + this
943 + " for thread " + mAppThread.asBinder());
944 removeRequestedPss(mApp);
945 synchronized(ActivityManagerService.this) {
946 appDiedLocked(mApp, mPid, mAppThread);
947 }
948 }
949 }
950
951 static final int SHOW_ERROR_MSG = 1;
952 static final int SHOW_NOT_RESPONDING_MSG = 2;
953 static final int SHOW_FACTORY_ERROR_MSG = 3;
954 static final int UPDATE_CONFIGURATION_MSG = 4;
955 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
956 static final int WAIT_FOR_DEBUGGER_MSG = 6;
957 static final int BROADCAST_INTENT_MSG = 7;
958 static final int BROADCAST_TIMEOUT_MSG = 8;
959 static final int PAUSE_TIMEOUT_MSG = 9;
960 static final int IDLE_TIMEOUT_MSG = 10;
961 static final int IDLE_NOW_MSG = 11;
962 static final int SERVICE_TIMEOUT_MSG = 12;
963 static final int UPDATE_TIME_ZONE = 13;
964 static final int SHOW_UID_ERROR_MSG = 14;
965 static final int IM_FEELING_LUCKY_MSG = 15;
966 static final int LAUNCH_TIMEOUT_MSG = 16;
967 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 static final int RESUME_TOP_ACTIVITY_MSG = 19;
969 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700970 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700971 static final int KILL_APPLICATION_MSG = 22;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972
973 AlertDialog mUidAlert;
974
975 final Handler mHandler = new Handler() {
976 //public Handler() {
977 // if (localLOGV) Log.v(TAG, "Handler started!");
978 //}
979
980 public void handleMessage(Message msg) {
981 switch (msg.what) {
982 case SHOW_ERROR_MSG: {
983 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 synchronized (ActivityManagerService.this) {
985 ProcessRecord proc = (ProcessRecord)data.get("app");
986 if (proc != null && proc.crashDialog != null) {
987 Log.e(TAG, "App already has crash dialog: " + proc);
988 return;
989 }
990 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700991 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800992 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 d.show();
994 proc.crashDialog = d;
995 } else {
996 // The device is asleep, so just pretend that the user
997 // saw a crash dialog and hit "force quit".
998 res.set(0);
999 }
1000 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001001
1002 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 } break;
1004 case SHOW_NOT_RESPONDING_MSG: {
1005 synchronized (ActivityManagerService.this) {
1006 HashMap data = (HashMap) msg.obj;
1007 ProcessRecord proc = (ProcessRecord)data.get("app");
1008 if (proc != null && proc.anrDialog != null) {
1009 Log.e(TAG, "App already has anr dialog: " + proc);
1010 return;
1011 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001012
1013 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1014 null, null, 0, null, null, null,
1015 false, false, MY_PID, Process.SYSTEM_UID);
1016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1018 mContext, proc, (HistoryRecord)data.get("activity"));
1019 d.show();
1020 proc.anrDialog = d;
1021 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001022
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001023 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 } break;
1025 case SHOW_FACTORY_ERROR_MSG: {
1026 Dialog d = new FactoryErrorDialog(
1027 mContext, msg.getData().getCharSequence("msg"));
1028 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001029 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 } break;
1031 case UPDATE_CONFIGURATION_MSG: {
1032 final ContentResolver resolver = mContext.getContentResolver();
1033 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1034 } break;
1035 case GC_BACKGROUND_PROCESSES_MSG: {
1036 synchronized (ActivityManagerService.this) {
1037 performAppGcsIfAppropriateLocked();
1038 }
1039 } break;
1040 case WAIT_FOR_DEBUGGER_MSG: {
1041 synchronized (ActivityManagerService.this) {
1042 ProcessRecord app = (ProcessRecord)msg.obj;
1043 if (msg.arg1 != 0) {
1044 if (!app.waitedForDebugger) {
1045 Dialog d = new AppWaitingForDebuggerDialog(
1046 ActivityManagerService.this,
1047 mContext, app);
1048 app.waitDialog = d;
1049 app.waitedForDebugger = true;
1050 d.show();
1051 }
1052 } else {
1053 if (app.waitDialog != null) {
1054 app.waitDialog.dismiss();
1055 app.waitDialog = null;
1056 }
1057 }
1058 }
1059 } break;
1060 case BROADCAST_INTENT_MSG: {
1061 if (DEBUG_BROADCAST) Log.v(
1062 TAG, "Received BROADCAST_INTENT_MSG");
1063 processNextBroadcast(true);
1064 } break;
1065 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001066 if (mDidDexOpt) {
1067 mDidDexOpt = false;
1068 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1069 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1070 return;
1071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 broadcastTimeout();
1073 } break;
1074 case PAUSE_TIMEOUT_MSG: {
1075 IBinder token = (IBinder)msg.obj;
1076 // We don't at this point know if the activity is fullscreen,
1077 // so we need to be conservative and assume it isn't.
1078 Log.w(TAG, "Activity pause timeout for " + token);
1079 activityPaused(token, null, true);
1080 } break;
1081 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001082 if (mDidDexOpt) {
1083 mDidDexOpt = false;
1084 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1085 nmsg.obj = msg.obj;
1086 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1087 return;
1088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 // We don't at this point know if the activity is fullscreen,
1090 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001091 IBinder token = (IBinder)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 Log.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001093 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 } break;
1095 case DESTROY_TIMEOUT_MSG: {
1096 IBinder token = (IBinder)msg.obj;
1097 // We don't at this point know if the activity is fullscreen,
1098 // so we need to be conservative and assume it isn't.
1099 Log.w(TAG, "Activity destroy timeout for " + token);
1100 activityDestroyed(token);
1101 } break;
1102 case IDLE_NOW_MSG: {
1103 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001104 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 } break;
1106 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001107 if (mDidDexOpt) {
1108 mDidDexOpt = false;
1109 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1110 nmsg.obj = msg.obj;
1111 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1112 return;
1113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 serviceTimeout((ProcessRecord)msg.obj);
1115 } break;
1116 case UPDATE_TIME_ZONE: {
1117 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001118 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1119 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 if (r.thread != null) {
1121 try {
1122 r.thread.updateTimeZone();
1123 } catch (RemoteException ex) {
1124 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
1125 }
1126 }
1127 }
1128 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001129 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 case SHOW_UID_ERROR_MSG: {
1131 // XXX This is a temporary dialog, no need to localize.
1132 AlertDialog d = new BaseErrorDialog(mContext);
1133 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1134 d.setCancelable(false);
1135 d.setTitle("System UIDs Inconsistent");
1136 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1137 d.setButton("I'm Feeling Lucky",
1138 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1139 mUidAlert = d;
1140 d.show();
1141 } break;
1142 case IM_FEELING_LUCKY_MSG: {
1143 if (mUidAlert != null) {
1144 mUidAlert.dismiss();
1145 mUidAlert = null;
1146 }
1147 } break;
1148 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001149 if (mDidDexOpt) {
1150 mDidDexOpt = false;
1151 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1152 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1153 return;
1154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 synchronized (ActivityManagerService.this) {
1156 if (mLaunchingActivity.isHeld()) {
1157 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1158 mLaunchingActivity.release();
1159 }
1160 }
1161 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 case RESUME_TOP_ACTIVITY_MSG: {
1163 synchronized (ActivityManagerService.this) {
1164 resumeTopActivityLocked(null);
1165 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001166 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001168 if (mDidDexOpt) {
1169 mDidDexOpt = false;
1170 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1171 nmsg.obj = msg.obj;
1172 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1173 return;
1174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 ProcessRecord app = (ProcessRecord)msg.obj;
1176 synchronized (ActivityManagerService.this) {
1177 processStartTimedOutLocked(app);
1178 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001179 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001180 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1181 synchronized (ActivityManagerService.this) {
1182 doPendingActivityLaunchesLocked(true);
1183 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001184 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001185 case KILL_APPLICATION_MSG: {
1186 synchronized (ActivityManagerService.this) {
1187 int uid = msg.arg1;
1188 boolean restart = (msg.arg2 == 1);
1189 String pkg = (String) msg.obj;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08001190 forceStopPackageLocked(pkg, uid, restart, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001191 }
1192 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 }
1194 }
1195 };
1196
1197 public static void setSystemProcess() {
1198 try {
1199 ActivityManagerService m = mSelf;
1200
1201 ServiceManager.addService("activity", m);
1202 ServiceManager.addService("meminfo", new MemBinder(m));
1203 if (MONITOR_CPU_USAGE) {
1204 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 ServiceManager.addService("permission", new PermissionController(m));
1207
1208 ApplicationInfo info =
1209 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001210 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001211 mSystemThread.installSystemApplicationInfo(info);
1212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 synchronized (mSelf) {
1214 ProcessRecord app = mSelf.newProcessRecordLocked(
1215 mSystemThread.getApplicationThread(), info,
1216 info.processName);
1217 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001218 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 app.maxAdj = SYSTEM_ADJ;
1220 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1221 synchronized (mSelf.mPidsSelfLocked) {
1222 mSelf.mPidsSelfLocked.put(app.pid, app);
1223 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001224 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 }
1226 } catch (PackageManager.NameNotFoundException e) {
1227 throw new RuntimeException(
1228 "Unable to find android system package", e);
1229 }
1230 }
1231
1232 public void setWindowManager(WindowManagerService wm) {
1233 mWindowManager = wm;
1234 }
1235
1236 public static final Context main(int factoryTest) {
1237 AThread thr = new AThread();
1238 thr.start();
1239
1240 synchronized (thr) {
1241 while (thr.mService == null) {
1242 try {
1243 thr.wait();
1244 } catch (InterruptedException e) {
1245 }
1246 }
1247 }
1248
1249 ActivityManagerService m = thr.mService;
1250 mSelf = m;
1251 ActivityThread at = ActivityThread.systemMain();
1252 mSystemThread = at;
1253 Context context = at.getSystemContext();
1254 m.mContext = context;
1255 m.mFactoryTest = factoryTest;
1256 PowerManager pm =
1257 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1258 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1259 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1260 m.mLaunchingActivity.setReferenceCounted(false);
1261
1262 m.mBatteryStatsService.publish(context);
1263 m.mUsageStatsService.publish(context);
1264
1265 synchronized (thr) {
1266 thr.mReady = true;
1267 thr.notifyAll();
1268 }
1269
1270 m.startRunning(null, null, null, null);
1271
1272 return context;
1273 }
1274
1275 public static ActivityManagerService self() {
1276 return mSelf;
1277 }
1278
1279 static class AThread extends Thread {
1280 ActivityManagerService mService;
1281 boolean mReady = false;
1282
1283 public AThread() {
1284 super("ActivityManager");
1285 }
1286
1287 public void run() {
1288 Looper.prepare();
1289
1290 android.os.Process.setThreadPriority(
1291 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1292
1293 ActivityManagerService m = new ActivityManagerService();
1294
1295 synchronized (this) {
1296 mService = m;
1297 notifyAll();
1298 }
1299
1300 synchronized (this) {
1301 while (!mReady) {
1302 try {
1303 wait();
1304 } catch (InterruptedException e) {
1305 }
1306 }
1307 }
1308
1309 Looper.loop();
1310 }
1311 }
1312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 static class MemBinder extends Binder {
1314 ActivityManagerService mActivityManagerService;
1315 MemBinder(ActivityManagerService activityManagerService) {
1316 mActivityManagerService = activityManagerService;
1317 }
1318
1319 @Override
1320 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1321 ActivityManagerService service = mActivityManagerService;
1322 ArrayList<ProcessRecord> procs;
1323 synchronized (mActivityManagerService) {
1324 if (args != null && args.length > 0
1325 && args[0].charAt(0) != '-') {
1326 procs = new ArrayList<ProcessRecord>();
1327 int pid = -1;
1328 try {
1329 pid = Integer.parseInt(args[0]);
1330 } catch (NumberFormatException e) {
1331
1332 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001333 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1334 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 if (proc.pid == pid) {
1336 procs.add(proc);
1337 } else if (proc.processName.equals(args[0])) {
1338 procs.add(proc);
1339 }
1340 }
1341 if (procs.size() <= 0) {
1342 pw.println("No process found for: " + args[0]);
1343 return;
1344 }
1345 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001346 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 }
1348 }
1349 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1350 }
1351 }
1352
1353 static class CpuBinder extends Binder {
1354 ActivityManagerService mActivityManagerService;
1355 CpuBinder(ActivityManagerService activityManagerService) {
1356 mActivityManagerService = activityManagerService;
1357 }
1358
1359 @Override
1360 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1361 synchronized (mActivityManagerService.mProcessStatsThread) {
1362 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1363 }
1364 }
1365 }
1366
1367 private ActivityManagerService() {
1368 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1369 if (v != null && Integer.getInteger(v) != 0) {
1370 mSimpleProcessManagement = true;
1371 }
1372 v = System.getenv("ANDROID_DEBUG_APP");
1373 if (v != null) {
1374 mSimpleProcessManagement = true;
1375 }
1376
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001377 Log.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
1378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 File dataDir = Environment.getDataDirectory();
1380 File systemDir = new File(dataDir, "system");
1381 systemDir.mkdirs();
1382 mBatteryStatsService = new BatteryStatsService(new File(
1383 systemDir, "batterystats.bin").toString());
1384 mBatteryStatsService.getActiveStatistics().readLocked();
1385 mBatteryStatsService.getActiveStatistics().writeLocked();
1386
1387 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001388 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389
Jack Palevichb90d28c2009-07-22 15:35:24 -07001390 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1391 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 mConfiguration.makeDefault();
1394 mProcessStats.init();
1395
1396 // Add ourself to the Watchdog monitors.
1397 Watchdog.getInstance().addMonitor(this);
1398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 mProcessStatsThread = new Thread("ProcessStats") {
1400 public void run() {
1401 while (true) {
1402 try {
1403 try {
1404 synchronized(this) {
1405 final long now = SystemClock.uptimeMillis();
1406 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1407 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
1408 //Log.i(TAG, "Cpu delay=" + nextCpuDelay
1409 // + ", write delay=" + nextWriteDelay);
1410 if (nextWriteDelay < nextCpuDelay) {
1411 nextCpuDelay = nextWriteDelay;
1412 }
1413 if (nextCpuDelay > 0) {
1414 this.wait(nextCpuDelay);
1415 }
1416 }
1417 } catch (InterruptedException e) {
1418 }
1419
1420 updateCpuStatsNow();
1421 } catch (Exception e) {
1422 Log.e(TAG, "Unexpected exception collecting process stats", e);
1423 }
1424 }
1425 }
1426 };
1427 mProcessStatsThread.start();
1428 }
1429
1430 @Override
1431 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1432 throws RemoteException {
1433 try {
1434 return super.onTransact(code, data, reply, flags);
1435 } catch (RuntimeException e) {
1436 // The activity manager only throws security exceptions, so let's
1437 // log all others.
1438 if (!(e instanceof SecurityException)) {
1439 Log.e(TAG, "Activity Manager Crash", e);
1440 }
1441 throw e;
1442 }
1443 }
1444
1445 void updateCpuStats() {
1446 synchronized (mProcessStatsThread) {
1447 final long now = SystemClock.uptimeMillis();
1448 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1449 mProcessStatsThread.notify();
1450 }
1451 }
1452 }
1453
1454 void updateCpuStatsNow() {
1455 synchronized (mProcessStatsThread) {
1456 final long now = SystemClock.uptimeMillis();
1457 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 if (MONITOR_CPU_USAGE &&
1460 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1461 mLastCpuTime = now;
1462 haveNewCpuStats = true;
1463 mProcessStats.update();
1464 //Log.i(TAG, mProcessStats.printCurrentState());
1465 //Log.i(TAG, "Total CPU usage: "
1466 // + mProcessStats.getTotalCpuPercent() + "%");
1467
1468 // Log the cpu usage if the property is set.
1469 if ("true".equals(SystemProperties.get("events.cpu"))) {
1470 int user = mProcessStats.getLastUserTime();
1471 int system = mProcessStats.getLastSystemTime();
1472 int iowait = mProcessStats.getLastIoWaitTime();
1473 int irq = mProcessStats.getLastIrqTime();
1474 int softIrq = mProcessStats.getLastSoftIrqTime();
1475 int idle = mProcessStats.getLastIdleTime();
1476
1477 int total = user + system + iowait + irq + softIrq + idle;
1478 if (total == 0) total = 1;
1479
Doug Zongker2bec3d42009-12-04 12:52:44 -08001480 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 ((user+system+iowait+irq+softIrq) * 100) / total,
1482 (user * 100) / total,
1483 (system * 100) / total,
1484 (iowait * 100) / total,
1485 (irq * 100) / total,
1486 (softIrq * 100) / total);
1487 }
1488 }
1489
Amith Yamasanie43530a2009-08-21 13:11:37 -07001490 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001491 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001492 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 synchronized(mPidsSelfLocked) {
1494 if (haveNewCpuStats) {
1495 if (mBatteryStatsService.isOnBattery()) {
1496 final int N = mProcessStats.countWorkingStats();
1497 for (int i=0; i<N; i++) {
1498 ProcessStats.Stats st
1499 = mProcessStats.getWorkingStats(i);
1500 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1501 if (pr != null) {
1502 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1503 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001504 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001505 } else {
1506 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001507 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001508 if (ps != null) {
1509 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001510 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 }
1513 }
1514 }
1515 }
1516 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1519 mLastWriteTime = now;
1520 mBatteryStatsService.getActiveStatistics().writeLocked();
1521 }
1522 }
1523 }
1524 }
1525
1526 /**
1527 * Initialize the application bind args. These are passed to each
1528 * process when the bindApplication() IPC is sent to the process. They're
1529 * lazily setup to make sure the services are running when they're asked for.
1530 */
1531 private HashMap<String, IBinder> getCommonServicesLocked() {
1532 if (mAppBindArgs == null) {
1533 mAppBindArgs = new HashMap<String, IBinder>();
1534
1535 // Setup the application init args
1536 mAppBindArgs.put("package", ServiceManager.getService("package"));
1537 mAppBindArgs.put("window", ServiceManager.getService("window"));
1538 mAppBindArgs.put(Context.ALARM_SERVICE,
1539 ServiceManager.getService(Context.ALARM_SERVICE));
1540 }
1541 return mAppBindArgs;
1542 }
1543
1544 private final void setFocusedActivityLocked(HistoryRecord r) {
1545 if (mFocusedActivity != r) {
1546 mFocusedActivity = r;
1547 mWindowManager.setFocusedApp(r, true);
1548 }
1549 }
1550
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001551 private final void updateLruProcessLocked(ProcessRecord app,
1552 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001554 int lrui = mLruProcesses.indexOf(app);
1555 if (lrui >= 0) mLruProcesses.remove(lrui);
1556
1557 int i = mLruProcesses.size()-1;
1558 int skipTop = 0;
1559
1560 // compute the new weight for this process.
1561 if (updateActivityTime) {
1562 app.lastActivityTime = SystemClock.uptimeMillis();
1563 }
1564 if (app.activities.size() > 0) {
1565 // If this process has activities, we more strongly want to keep
1566 // it around.
1567 app.lruWeight = app.lastActivityTime;
1568 } else if (app.pubProviders.size() > 0) {
1569 // If this process contains content providers, we want to keep
1570 // it a little more strongly.
1571 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1572 // Also don't let it kick out the first few "real" hidden processes.
1573 skipTop = MIN_HIDDEN_APPS;
1574 } else {
1575 // If this process doesn't have activities, we less strongly
1576 // want to keep it around, and generally want to avoid getting
1577 // in front of any very recently used activities.
1578 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1579 // Also don't let it kick out the first few "real" hidden processes.
1580 skipTop = MIN_HIDDEN_APPS;
1581 }
1582 while (i >= 0) {
1583 ProcessRecord p = mLruProcesses.get(i);
1584 // If this app shouldn't be in front of the first N background
1585 // apps, then skip over that many that are currently hidden.
1586 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1587 skipTop--;
1588 }
1589 if (p.lruWeight <= app.lruWeight){
1590 mLruProcesses.add(i+1, app);
1591 break;
1592 }
1593 i--;
1594 }
1595 if (i < 0) {
1596 mLruProcesses.add(0, app);
1597 }
1598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 //Log.i(TAG, "Putting proc to front: " + app.processName);
1600 if (oomAdj) {
1601 updateOomAdjLocked();
1602 }
1603 }
1604
1605 private final boolean updateLRUListLocked(HistoryRecord r) {
1606 final boolean hadit = mLRUActivities.remove(r);
1607 mLRUActivities.add(r);
1608 return hadit;
1609 }
1610
1611 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1612 int i = mHistory.size()-1;
1613 while (i >= 0) {
1614 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1615 if (!r.finishing && r != notTop) {
1616 return r;
1617 }
1618 i--;
1619 }
1620 return null;
1621 }
1622
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001623 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1624 int i = mHistory.size()-1;
1625 while (i >= 0) {
1626 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1627 if (!r.finishing && !r.delayedResume && r != notTop) {
1628 return r;
1629 }
1630 i--;
1631 }
1632 return null;
1633 }
1634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 /**
1636 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001637 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 *
1639 * @param token If non-null, any history records matching this token will be skipped.
1640 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1641 *
1642 * @return Returns the HistoryRecord of the next activity on the stack.
1643 */
1644 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1645 int i = mHistory.size()-1;
1646 while (i >= 0) {
1647 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1648 // Note: the taskId check depends on real taskId fields being non-zero
1649 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1650 return r;
1651 }
1652 i--;
1653 }
1654 return null;
1655 }
1656
1657 private final ProcessRecord getProcessRecordLocked(
1658 String processName, int uid) {
1659 if (uid == Process.SYSTEM_UID) {
1660 // The system gets to run in any process. If there are multiple
1661 // processes with the same uid, just pick the first (this
1662 // should never happen).
1663 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1664 processName);
1665 return procs != null ? procs.valueAt(0) : null;
1666 }
1667 ProcessRecord proc = mProcessNames.get(processName, uid);
1668 return proc;
1669 }
1670
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001671 private void ensurePackageDexOpt(String packageName) {
1672 IPackageManager pm = ActivityThread.getPackageManager();
1673 try {
1674 if (pm.performDexOpt(packageName)) {
1675 mDidDexOpt = true;
1676 }
1677 } catch (RemoteException e) {
1678 }
1679 }
1680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 private boolean isNextTransitionForward() {
1682 int transit = mWindowManager.getPendingAppTransition();
1683 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1684 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1685 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1686 }
1687
1688 private final boolean realStartActivityLocked(HistoryRecord r,
1689 ProcessRecord app, boolean andResume, boolean checkConfig)
1690 throws RemoteException {
1691
1692 r.startFreezingScreenLocked(app, 0);
1693 mWindowManager.setAppVisibility(r, true);
1694
1695 // Have the window manager re-evaluate the orientation of
1696 // the screen based on the new activity order. Note that
1697 // as a result of this, it can call back into the activity
1698 // manager with a new orientation. We don't care about that,
1699 // because the activity is not currently running so we are
1700 // just restarting it anyway.
1701 if (checkConfig) {
1702 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001703 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 r.mayFreezeScreenLocked(app) ? r : null);
1705 updateConfigurationLocked(config, r);
1706 }
1707
1708 r.app = app;
1709
1710 if (localLOGV) Log.v(TAG, "Launching: " + r);
1711
1712 int idx = app.activities.indexOf(r);
1713 if (idx < 0) {
1714 app.activities.add(r);
1715 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001716 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717
1718 try {
1719 if (app.thread == null) {
1720 throw new RemoteException();
1721 }
1722 List<ResultInfo> results = null;
1723 List<Intent> newIntents = null;
1724 if (andResume) {
1725 results = r.results;
1726 newIntents = r.newIntents;
1727 }
1728 if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
1729 + " icicle=" + r.icicle
1730 + " with results=" + results + " newIntents=" + newIntents
1731 + " andResume=" + andResume);
1732 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001733 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 System.identityHashCode(r),
1735 r.task.taskId, r.shortComponentName);
1736 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001737 if (r.isHomeActivity) {
1738 mHomeProcess = app;
1739 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001740 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001742 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 r.info, r.icicle, results, newIntents, !andResume,
1744 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 } catch (RemoteException e) {
1746 if (r.launchFailed) {
1747 // This is the second time we failed -- finish activity
1748 // and give up.
1749 Log.e(TAG, "Second failure launching "
1750 + r.intent.getComponent().flattenToShortString()
1751 + ", giving up", e);
1752 appDiedLocked(app, app.pid, app.thread);
1753 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1754 "2nd-crash");
1755 return false;
1756 }
1757
1758 // This is the first time we failed -- restart process and
1759 // retry.
1760 app.activities.remove(r);
1761 throw e;
1762 }
1763
1764 r.launchFailed = false;
1765 if (updateLRUListLocked(r)) {
1766 Log.w(TAG, "Activity " + r
1767 + " being launched, but already in LRU list");
1768 }
1769
1770 if (andResume) {
1771 // As part of the process of launching, ActivityThread also performs
1772 // a resume.
1773 r.state = ActivityState.RESUMED;
1774 r.icicle = null;
1775 r.haveState = false;
1776 r.stopped = false;
1777 mResumedActivity = r;
1778 r.task.touchActiveTime();
1779 completeResumeLocked(r);
1780 pauseIfSleepingLocked();
1781 } else {
1782 // This activity is not starting in the resumed state... which
1783 // should look like we asked it to pause+stop (but remain visible),
1784 // and it has done so and reported back the current icicle and
1785 // other state.
1786 r.state = ActivityState.STOPPED;
1787 r.stopped = true;
1788 }
1789
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001790 // Launch the new version setup screen if needed. We do this -after-
1791 // launching the initial activity (that is, home), so that it can have
1792 // a chance to initialize itself while in the background, making the
1793 // switch back to it faster and look better.
1794 startSetupActivityLocked();
1795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 return true;
1797 }
1798
1799 private final void startSpecificActivityLocked(HistoryRecord r,
1800 boolean andResume, boolean checkConfig) {
1801 // Is this activity's application already running?
1802 ProcessRecord app = getProcessRecordLocked(r.processName,
1803 r.info.applicationInfo.uid);
1804
1805 if (r.startTime == 0) {
1806 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001807 if (mInitialStartTime == 0) {
1808 mInitialStartTime = r.startTime;
1809 }
1810 } else if (mInitialStartTime == 0) {
1811 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
1813
1814 if (app != null && app.thread != null) {
1815 try {
1816 realStartActivityLocked(r, app, andResume, checkConfig);
1817 return;
1818 } catch (RemoteException e) {
1819 Log.w(TAG, "Exception when starting activity "
1820 + r.intent.getComponent().flattenToShortString(), e);
1821 }
1822
1823 // If a dead object exception was thrown -- fall through to
1824 // restart the application.
1825 }
1826
1827 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001828 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 }
1830
1831 private final ProcessRecord startProcessLocked(String processName,
1832 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001833 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1835 // We don't have to do anything more if:
1836 // (1) There is an existing application record; and
1837 // (2) The caller doesn't think it is dead, OR there is no thread
1838 // object attached to it so we know it couldn't have crashed; and
1839 // (3) There is a pid assigned to it, so it is either starting or
1840 // already running.
1841 if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
1842 + " app=" + app + " knownToBeDead=" + knownToBeDead
1843 + " thread=" + (app != null ? app.thread : null)
1844 + " pid=" + (app != null ? app.pid : -1));
1845 if (app != null &&
1846 (!knownToBeDead || app.thread == null) && app.pid > 0) {
1847 return app;
1848 }
1849
1850 String hostingNameStr = hostingName != null
1851 ? hostingName.flattenToShortString() : null;
1852
1853 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1854 // If we are in the background, then check to see if this process
1855 // is bad. If so, we will just silently fail.
1856 if (mBadProcesses.get(info.processName, info.uid) != null) {
1857 return null;
1858 }
1859 } else {
1860 // When the user is explicitly starting a process, then clear its
1861 // crash count so that we won't make it bad until they see at
1862 // least one crash dialog again, and make the process good again
1863 // if it had been bad.
1864 mProcessCrashTimes.remove(info.processName, info.uid);
1865 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001866 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 info.processName);
1868 mBadProcesses.remove(info.processName, info.uid);
1869 if (app != null) {
1870 app.bad = false;
1871 }
1872 }
1873 }
1874
1875 if (app == null) {
1876 app = newProcessRecordLocked(null, info, processName);
1877 mProcessNames.put(processName, info.uid, app);
1878 } else {
1879 // If this is a new package in the process, add the package to the list
1880 app.addPackage(info.packageName);
1881 }
1882
1883 // If the system is not ready yet, then hold off on starting this
1884 // process until it is.
1885 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001886 && !isAllowedWhileBooting(info)
1887 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 if (!mProcessesOnHold.contains(app)) {
1889 mProcessesOnHold.add(app);
1890 }
1891 return app;
1892 }
1893
1894 startProcessLocked(app, hostingType, hostingNameStr);
1895 return (app.pid != 0) ? app : null;
1896 }
1897
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001898 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1899 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1900 }
1901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 private final void startProcessLocked(ProcessRecord app,
1903 String hostingType, String hostingNameStr) {
1904 if (app.pid > 0 && app.pid != MY_PID) {
1905 synchronized (mPidsSelfLocked) {
1906 mPidsSelfLocked.remove(app.pid);
1907 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1908 }
1909 app.pid = 0;
1910 }
1911
1912 mProcessesOnHold.remove(app);
1913
1914 updateCpuStats();
1915
1916 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1917 mProcDeaths[0] = 0;
1918
1919 try {
1920 int uid = app.info.uid;
1921 int[] gids = null;
1922 try {
1923 gids = mContext.getPackageManager().getPackageGids(
1924 app.info.packageName);
1925 } catch (PackageManager.NameNotFoundException e) {
1926 Log.w(TAG, "Unable to retrieve gids", e);
1927 }
1928 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1929 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1930 && mTopComponent != null
1931 && app.processName.equals(mTopComponent.getPackageName())) {
1932 uid = 0;
1933 }
1934 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1935 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1936 uid = 0;
1937 }
1938 }
1939 int debugFlags = 0;
1940 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1941 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1942 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001943 // Run the app in safe mode if its manifest requests so or the
1944 // system is booted in safe mode.
1945 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1946 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001947 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1950 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1951 }
1952 if ("1".equals(SystemProperties.get("debug.assert"))) {
1953 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1954 }
1955 int pid = Process.start("android.app.ActivityThread",
1956 mSimpleProcessManagement ? app.processName : null, uid, uid,
1957 gids, debugFlags, null);
1958 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1959 synchronized (bs) {
1960 if (bs.isOnBattery()) {
1961 app.batteryStats.incStartsLocked();
1962 }
1963 }
1964
Doug Zongker2bec3d42009-12-04 12:52:44 -08001965 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 app.processName, hostingType,
1967 hostingNameStr != null ? hostingNameStr : "");
1968
1969 if (app.persistent) {
1970 Watchdog.getInstance().processStarted(app, app.processName, pid);
1971 }
1972
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001973 StringBuilder buf = mStringBuilder;
1974 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 buf.append("Start proc ");
1976 buf.append(app.processName);
1977 buf.append(" for ");
1978 buf.append(hostingType);
1979 if (hostingNameStr != null) {
1980 buf.append(" ");
1981 buf.append(hostingNameStr);
1982 }
1983 buf.append(": pid=");
1984 buf.append(pid);
1985 buf.append(" uid=");
1986 buf.append(uid);
1987 buf.append(" gids={");
1988 if (gids != null) {
1989 for (int gi=0; gi<gids.length; gi++) {
1990 if (gi != 0) buf.append(", ");
1991 buf.append(gids[gi]);
1992
1993 }
1994 }
1995 buf.append("}");
1996 Log.i(TAG, buf.toString());
1997 if (pid == 0 || pid == MY_PID) {
1998 // Processes are being emulated with threads.
1999 app.pid = MY_PID;
2000 app.removed = false;
2001 mStartingProcesses.add(app);
2002 } else if (pid > 0) {
2003 app.pid = pid;
2004 app.removed = false;
2005 synchronized (mPidsSelfLocked) {
2006 this.mPidsSelfLocked.put(pid, app);
2007 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2008 msg.obj = app;
2009 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2010 }
2011 } else {
2012 app.pid = 0;
2013 RuntimeException e = new RuntimeException(
2014 "Failure starting process " + app.processName
2015 + ": returned pid=" + pid);
2016 Log.e(TAG, e.getMessage(), e);
2017 }
2018 } catch (RuntimeException e) {
2019 // XXX do better error recovery.
2020 app.pid = 0;
2021 Log.e(TAG, "Failure starting process " + app.processName, e);
2022 }
2023 }
2024
2025 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2026 if (mPausingActivity != null) {
2027 RuntimeException e = new RuntimeException();
2028 Log.e(TAG, "Trying to pause when pause is already pending for "
2029 + mPausingActivity, e);
2030 }
2031 HistoryRecord prev = mResumedActivity;
2032 if (prev == null) {
2033 RuntimeException e = new RuntimeException();
2034 Log.e(TAG, "Trying to pause when nothing is resumed", e);
2035 resumeTopActivityLocked(null);
2036 return;
2037 }
2038 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
2039 mResumedActivity = null;
2040 mPausingActivity = prev;
2041 mLastPausedActivity = prev;
2042 prev.state = ActivityState.PAUSING;
2043 prev.task.touchActiveTime();
2044
2045 updateCpuStats();
2046
2047 if (prev.app != null && prev.app.thread != null) {
2048 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
2049 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002050 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 System.identityHashCode(prev),
2052 prev.shortComponentName);
2053 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2054 prev.configChangeFlags);
2055 updateUsageStats(prev, false);
2056 } catch (Exception e) {
2057 // Ignore exception, if process died other code will cleanup.
2058 Log.w(TAG, "Exception thrown during pause", e);
2059 mPausingActivity = null;
2060 mLastPausedActivity = null;
2061 }
2062 } else {
2063 mPausingActivity = null;
2064 mLastPausedActivity = null;
2065 }
2066
2067 // If we are not going to sleep, we want to ensure the device is
2068 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002069 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 mLaunchingActivity.acquire();
2071 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2072 // To be safe, don't allow the wake lock to be held for too long.
2073 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2074 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2075 }
2076 }
2077
2078
2079 if (mPausingActivity != null) {
2080 // Have the window manager pause its key dispatching until the new
2081 // activity has started. If we're pausing the activity just because
2082 // the screen is being turned off and the UI is sleeping, don't interrupt
2083 // key dispatch; the same activity will pick it up again on wakeup.
2084 if (!uiSleeping) {
2085 prev.pauseKeyDispatchingLocked();
2086 } else {
2087 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
2088 }
2089
2090 // Schedule a pause timeout in case the app doesn't respond.
2091 // We don't give it much time because this directly impacts the
2092 // responsiveness seen by the user.
2093 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2094 msg.obj = prev;
2095 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
2096 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
2097 } else {
2098 // This activity failed to schedule the
2099 // pause, so just treat it as being paused now.
2100 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
2101 resumeTopActivityLocked(null);
2102 }
2103 }
2104
2105 private final void completePauseLocked() {
2106 HistoryRecord prev = mPausingActivity;
2107 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
2108
2109 if (prev != null) {
2110 if (prev.finishing) {
2111 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
2112 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2113 } else if (prev.app != null) {
2114 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
2115 if (prev.waitingVisible) {
2116 prev.waitingVisible = false;
2117 mWaitingVisibleActivities.remove(prev);
2118 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
2119 TAG, "Complete pause, no longer waiting: " + prev);
2120 }
2121 if (prev.configDestroy) {
2122 // The previous is being paused because the configuration
2123 // is changing, which means it is actually stopping...
2124 // To juggle the fact that we are also starting a new
2125 // instance right now, we need to first completely stop
2126 // the current instance before starting the new one.
2127 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
2128 destroyActivityLocked(prev, true);
2129 } else {
2130 mStoppingActivities.add(prev);
2131 if (mStoppingActivities.size() > 3) {
2132 // If we already have a few activities waiting to stop,
2133 // then give up on things going idle and start clearing
2134 // them out.
2135 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
2136 Message msg = Message.obtain();
2137 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2138 mHandler.sendMessage(msg);
2139 }
2140 }
2141 } else {
2142 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
2143 prev = null;
2144 }
2145 mPausingActivity = null;
2146 }
2147
Dianne Hackborn55280a92009-05-07 15:53:46 -07002148 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 resumeTopActivityLocked(prev);
2150 } else {
2151 if (mGoingToSleep.isHeld()) {
2152 mGoingToSleep.release();
2153 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002154 if (mShuttingDown) {
2155 notifyAll();
2156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 }
2158
2159 if (prev != null) {
2160 prev.resumeKeyDispatchingLocked();
2161 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002162
2163 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2164 long diff = 0;
2165 synchronized (mProcessStatsThread) {
2166 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2167 }
2168 if (diff > 0) {
2169 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2170 synchronized (bsi) {
2171 BatteryStatsImpl.Uid.Proc ps =
2172 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2173 prev.info.packageName);
2174 if (ps != null) {
2175 ps.addForegroundTimeLocked(diff);
2176 }
2177 }
2178 }
2179 }
2180 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
2182
2183 /**
2184 * Once we know that we have asked an application to put an activity in
2185 * the resumed state (either by launching it or explicitly telling it),
2186 * this function updates the rest of our state to match that fact.
2187 */
2188 private final void completeResumeLocked(HistoryRecord next) {
2189 next.idle = false;
2190 next.results = null;
2191 next.newIntents = null;
2192
2193 // schedule an idle timeout in case the app doesn't do it for us.
2194 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2195 msg.obj = next;
2196 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2197
2198 if (false) {
2199 // The activity was never told to pause, so just keep
2200 // things going as-is. To maintain our own state,
2201 // we need to emulate it coming back and saying it is
2202 // idle.
2203 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2204 msg.obj = next;
2205 mHandler.sendMessage(msg);
2206 }
2207
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002208 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 next.thumbnail = null;
2211 setFocusedActivityLocked(next);
2212 next.resumeKeyDispatchingLocked();
2213 ensureActivitiesVisibleLocked(null, 0);
2214 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002215 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002216
2217 // Mark the point when the activity is resuming
2218 // TODO: To be more accurate, the mark should be before the onCreate,
2219 // not after the onResume. But for subsequent starts, onResume is fine.
2220 if (next.app != null) {
2221 synchronized (mProcessStatsThread) {
2222 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2223 }
2224 } else {
2225 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 }
2228
2229 /**
2230 * Make sure that all activities that need to be visible (that is, they
2231 * currently can be seen by the user) actually are.
2232 */
2233 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2234 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2235 if (DEBUG_VISBILITY) Log.v(
2236 TAG, "ensureActivitiesVisible behind " + top
2237 + " configChanges=0x" + Integer.toHexString(configChanges));
2238
2239 // If the top activity is not fullscreen, then we need to
2240 // make sure any activities under it are now visible.
2241 final int count = mHistory.size();
2242 int i = count-1;
2243 while (mHistory.get(i) != top) {
2244 i--;
2245 }
2246 HistoryRecord r;
2247 boolean behindFullscreen = false;
2248 for (; i>=0; i--) {
2249 r = (HistoryRecord)mHistory.get(i);
2250 if (DEBUG_VISBILITY) Log.v(
2251 TAG, "Make visible? " + r + " finishing=" + r.finishing
2252 + " state=" + r.state);
2253 if (r.finishing) {
2254 continue;
2255 }
2256
2257 final boolean doThisProcess = onlyThisProcess == null
2258 || onlyThisProcess.equals(r.processName);
2259
2260 // First: if this is not the current activity being started, make
2261 // sure it matches the current configuration.
2262 if (r != starting && doThisProcess) {
2263 ensureActivityConfigurationLocked(r, 0);
2264 }
2265
2266 if (r.app == null || r.app.thread == null) {
2267 if (onlyThisProcess == null
2268 || onlyThisProcess.equals(r.processName)) {
2269 // This activity needs to be visible, but isn't even
2270 // running... get it started, but don't resume it
2271 // at this point.
2272 if (DEBUG_VISBILITY) Log.v(
2273 TAG, "Start and freeze screen for " + r);
2274 if (r != starting) {
2275 r.startFreezingScreenLocked(r.app, configChanges);
2276 }
2277 if (!r.visible) {
2278 if (DEBUG_VISBILITY) Log.v(
2279 TAG, "Starting and making visible: " + r);
2280 mWindowManager.setAppVisibility(r, true);
2281 }
2282 if (r != starting) {
2283 startSpecificActivityLocked(r, false, false);
2284 }
2285 }
2286
2287 } else if (r.visible) {
2288 // If this activity is already visible, then there is nothing
2289 // else to do here.
2290 if (DEBUG_VISBILITY) Log.v(
2291 TAG, "Skipping: already visible at " + r);
2292 r.stopFreezingScreenLocked(false);
2293
2294 } else if (onlyThisProcess == null) {
2295 // This activity is not currently visible, but is running.
2296 // Tell it to become visible.
2297 r.visible = true;
2298 if (r.state != ActivityState.RESUMED && r != starting) {
2299 // If this activity is paused, tell it
2300 // to now show its window.
2301 if (DEBUG_VISBILITY) Log.v(
2302 TAG, "Making visible and scheduling visibility: " + r);
2303 try {
2304 mWindowManager.setAppVisibility(r, true);
2305 r.app.thread.scheduleWindowVisibility(r, true);
2306 r.stopFreezingScreenLocked(false);
2307 } catch (Exception e) {
2308 // Just skip on any failure; we'll make it
2309 // visible when it next restarts.
2310 Log.w(TAG, "Exception thrown making visibile: "
2311 + r.intent.getComponent(), e);
2312 }
2313 }
2314 }
2315
2316 // Aggregate current change flags.
2317 configChanges |= r.configChangeFlags;
2318
2319 if (r.fullscreen) {
2320 // At this point, nothing else needs to be shown
2321 if (DEBUG_VISBILITY) Log.v(
2322 TAG, "Stopping: fullscreen at " + r);
2323 behindFullscreen = true;
2324 i--;
2325 break;
2326 }
2327 }
2328
2329 // Now for any activities that aren't visible to the user, make
2330 // sure they no longer are keeping the screen frozen.
2331 while (i >= 0) {
2332 r = (HistoryRecord)mHistory.get(i);
2333 if (DEBUG_VISBILITY) Log.v(
2334 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2335 + " state=" + r.state
2336 + " behindFullscreen=" + behindFullscreen);
2337 if (!r.finishing) {
2338 if (behindFullscreen) {
2339 if (r.visible) {
2340 if (DEBUG_VISBILITY) Log.v(
2341 TAG, "Making invisible: " + r);
2342 r.visible = false;
2343 try {
2344 mWindowManager.setAppVisibility(r, false);
2345 if ((r.state == ActivityState.STOPPING
2346 || r.state == ActivityState.STOPPED)
2347 && r.app != null && r.app.thread != null) {
2348 if (DEBUG_VISBILITY) Log.v(
2349 TAG, "Scheduling invisibility: " + r);
2350 r.app.thread.scheduleWindowVisibility(r, false);
2351 }
2352 } catch (Exception e) {
2353 // Just skip on any failure; we'll make it
2354 // visible when it next restarts.
2355 Log.w(TAG, "Exception thrown making hidden: "
2356 + r.intent.getComponent(), e);
2357 }
2358 } else {
2359 if (DEBUG_VISBILITY) Log.v(
2360 TAG, "Already invisible: " + r);
2361 }
2362 } else if (r.fullscreen) {
2363 if (DEBUG_VISBILITY) Log.v(
2364 TAG, "Now behindFullscreen: " + r);
2365 behindFullscreen = true;
2366 }
2367 }
2368 i--;
2369 }
2370 }
2371
2372 /**
2373 * Version of ensureActivitiesVisible that can easily be called anywhere.
2374 */
2375 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2376 int configChanges) {
2377 HistoryRecord r = topRunningActivityLocked(null);
2378 if (r != null) {
2379 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2380 }
2381 }
2382
2383 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2384 if (resumed) {
2385 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2386 } else {
2387 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2388 }
2389 }
2390
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002391 private boolean startHomeActivityLocked() {
2392 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2393 && mTopAction == null) {
2394 // We are running in factory test mode, but unable to find
2395 // the factory test app, so just sit around displaying the
2396 // error message and don't try to start anything.
2397 return false;
2398 }
2399 Intent intent = new Intent(
2400 mTopAction,
2401 mTopData != null ? Uri.parse(mTopData) : null);
2402 intent.setComponent(mTopComponent);
2403 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2404 intent.addCategory(Intent.CATEGORY_HOME);
2405 }
2406 ActivityInfo aInfo =
2407 intent.resolveActivityInfo(mContext.getPackageManager(),
2408 STOCK_PM_FLAGS);
2409 if (aInfo != null) {
2410 intent.setComponent(new ComponentName(
2411 aInfo.applicationInfo.packageName, aInfo.name));
2412 // Don't do this if the home app is currently being
2413 // instrumented.
2414 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2415 aInfo.applicationInfo.uid);
2416 if (app == null || app.instrumentationClass == null) {
2417 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2418 startActivityLocked(null, intent, null, null, 0, aInfo,
2419 null, null, 0, 0, 0, false, false);
2420 }
2421 }
2422
2423
2424 return true;
2425 }
2426
2427 /**
2428 * Starts the "new version setup screen" if appropriate.
2429 */
2430 private void startSetupActivityLocked() {
2431 // Only do this once per boot.
2432 if (mCheckedForSetup) {
2433 return;
2434 }
2435
2436 // We will show this screen if the current one is a different
2437 // version than the last one shown, and we are not running in
2438 // low-level factory test mode.
2439 final ContentResolver resolver = mContext.getContentResolver();
2440 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2441 Settings.Secure.getInt(resolver,
2442 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2443 mCheckedForSetup = true;
2444
2445 // See if we should be showing the platform update setup UI.
2446 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2447 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2448 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2449
2450 // We don't allow third party apps to replace this.
2451 ResolveInfo ri = null;
2452 for (int i=0; ris != null && i<ris.size(); i++) {
2453 if ((ris.get(i).activityInfo.applicationInfo.flags
2454 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2455 ri = ris.get(i);
2456 break;
2457 }
2458 }
2459
2460 if (ri != null) {
2461 String vers = ri.activityInfo.metaData != null
2462 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2463 : null;
2464 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2465 vers = ri.activityInfo.applicationInfo.metaData.getString(
2466 Intent.METADATA_SETUP_VERSION);
2467 }
2468 String lastVers = Settings.Secure.getString(
2469 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2470 if (vers != null && !vers.equals(lastVers)) {
2471 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2472 intent.setComponent(new ComponentName(
2473 ri.activityInfo.packageName, ri.activityInfo.name));
2474 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2475 null, null, 0, 0, 0, false, false);
2476 }
2477 }
2478 }
2479 }
2480
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002481 private void reportResumedActivityLocked(HistoryRecord r) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002482 //Log.i(TAG, "**** REPORT RESUME: " + r);
2483
2484 final int identHash = System.identityHashCode(r);
2485 updateUsageStats(r, true);
2486
2487 int i = mWatchers.beginBroadcast();
2488 while (i > 0) {
2489 i--;
2490 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2491 if (w != null) {
2492 try {
2493 w.activityResuming(identHash);
2494 } catch (RemoteException e) {
2495 }
2496 }
2497 }
2498 mWatchers.finishBroadcast();
2499 }
2500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 /**
2502 * Ensure that the top activity in the stack is resumed.
2503 *
2504 * @param prev The previously resumed activity, for when in the process
2505 * of pausing; can be null to call from elsewhere.
2506 *
2507 * @return Returns true if something is being resumed, or false if
2508 * nothing happened.
2509 */
2510 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2511 // Find the first activity that is not finishing.
2512 HistoryRecord next = topRunningActivityLocked(null);
2513
2514 // Remember how we'll process this pause/resume situation, and ensure
2515 // that the state is reset however we wind up proceeding.
2516 final boolean userLeaving = mUserLeaving;
2517 mUserLeaving = false;
2518
2519 if (next == null) {
2520 // There are no more activities! Let's just start up the
2521 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002522 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 }
2524
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002525 next.delayedResume = false;
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 // If the top activity is the resumed one, nothing to do.
2528 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2529 // Make sure we have executed any pending transitions, since there
2530 // should be nothing left to do at this point.
2531 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002532 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 return false;
2534 }
2535
2536 // If we are sleeping, and there is no resumed activity, and the top
2537 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002538 if ((mSleeping || mShuttingDown)
2539 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 // Make sure we have executed any pending transitions, since there
2541 // should be nothing left to do at this point.
2542 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002543 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 return false;
2545 }
2546
2547 // The activity may be waiting for stop, but that is no longer
2548 // appropriate for it.
2549 mStoppingActivities.remove(next);
2550 mWaitingVisibleActivities.remove(next);
2551
2552 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2553
2554 // If we are currently pausing an activity, then don't do anything
2555 // until that is done.
2556 if (mPausingActivity != null) {
2557 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2558 return false;
2559 }
2560
2561 // We need to start pausing the current activity so the top one
2562 // can be resumed...
2563 if (mResumedActivity != null) {
2564 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2565 startPausingLocked(userLeaving, false);
2566 return true;
2567 }
2568
2569 if (prev != null && prev != next) {
2570 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2571 prev.waitingVisible = true;
2572 mWaitingVisibleActivities.add(prev);
2573 if (DEBUG_SWITCH) Log.v(
2574 TAG, "Resuming top, waiting visible to hide: " + prev);
2575 } else {
2576 // The next activity is already visible, so hide the previous
2577 // activity's windows right now so we can show the new one ASAP.
2578 // We only do this if the previous is finishing, which should mean
2579 // it is on top of the one being resumed so hiding it quickly
2580 // is good. Otherwise, we want to do the normal route of allowing
2581 // the resumed activity to be shown so we can decide if the
2582 // previous should actually be hidden depending on whether the
2583 // new one is found to be full-screen or not.
2584 if (prev.finishing) {
2585 mWindowManager.setAppVisibility(prev, false);
2586 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2587 + prev + ", waitingVisible="
2588 + (prev != null ? prev.waitingVisible : null)
2589 + ", nowVisible=" + next.nowVisible);
2590 } else {
2591 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2592 + prev + ", waitingVisible="
2593 + (prev != null ? prev.waitingVisible : null)
2594 + ", nowVisible=" + next.nowVisible);
2595 }
2596 }
2597 }
2598
2599 // We are starting up the next activity, so tell the window manager
2600 // that the previous one will be hidden soon. This way it can know
2601 // to ignore it when computing the desired screen orientation.
2602 if (prev != null) {
2603 if (prev.finishing) {
2604 if (DEBUG_TRANSITION) Log.v(TAG,
2605 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002606 if (mNoAnimActivities.contains(prev)) {
2607 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2608 } else {
2609 mWindowManager.prepareAppTransition(prev.task == next.task
2610 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2611 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 mWindowManager.setAppWillBeHidden(prev);
2614 mWindowManager.setAppVisibility(prev, false);
2615 } else {
2616 if (DEBUG_TRANSITION) Log.v(TAG,
2617 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002618 if (mNoAnimActivities.contains(next)) {
2619 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2620 } else {
2621 mWindowManager.prepareAppTransition(prev.task == next.task
2622 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2623 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 }
2626 if (false) {
2627 mWindowManager.setAppWillBeHidden(prev);
2628 mWindowManager.setAppVisibility(prev, false);
2629 }
2630 } else if (mHistory.size() > 1) {
2631 if (DEBUG_TRANSITION) Log.v(TAG,
2632 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002633 if (mNoAnimActivities.contains(next)) {
2634 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2635 } else {
2636 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 }
2639
2640 if (next.app != null && next.app.thread != null) {
2641 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2642
2643 // This activity is now becoming visible.
2644 mWindowManager.setAppVisibility(next, true);
2645
2646 HistoryRecord lastResumedActivity = mResumedActivity;
2647 ActivityState lastState = next.state;
2648
2649 updateCpuStats();
2650
2651 next.state = ActivityState.RESUMED;
2652 mResumedActivity = next;
2653 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002654 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 updateLRUListLocked(next);
2656
2657 // Have the window manager re-evaluate the orientation of
2658 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002659 boolean updated;
2660 synchronized (this) {
2661 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2662 mConfiguration,
2663 next.mayFreezeScreenLocked(next.app) ? next : null);
2664 if (config != null) {
2665 /*
2666 * Explicitly restore the locale to the one from the
2667 * old configuration, since the one that comes back from
2668 * the window manager has the default (boot) locale.
2669 *
2670 * It looks like previously the locale picker only worked
2671 * by coincidence: usually it would do its setting of
2672 * the locale after the activity transition, so it didn't
2673 * matter that this lost it. With the synchronized
2674 * block now keeping them from happening at the same time,
2675 * this one always would happen second and undo what the
2676 * locale picker had just done.
2677 */
2678 config.locale = mConfiguration.locale;
2679 next.frozenBeforeDestroy = true;
2680 }
2681 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002683 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 // The configuration update wasn't able to keep the existing
2685 // instance of the activity, and instead started a new one.
2686 // We should be all done, but let's just make sure our activity
2687 // is still at the top and schedule another run if something
2688 // weird happened.
2689 HistoryRecord nextNext = topRunningActivityLocked(null);
2690 if (DEBUG_SWITCH) Log.i(TAG,
2691 "Activity config changed during resume: " + next
2692 + ", new next: " + nextNext);
2693 if (nextNext != next) {
2694 // Do over!
2695 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2696 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002697 setFocusedActivityLocked(next);
2698 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002700 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 return true;
2702 }
2703
2704 try {
2705 // Deliver all pending results.
2706 ArrayList a = next.results;
2707 if (a != null) {
2708 final int N = a.size();
2709 if (!next.finishing && N > 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002710 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 TAG, "Delivering results to " + next
2712 + ": " + a);
2713 next.app.thread.scheduleSendResult(next, a);
2714 }
2715 }
2716
2717 if (next.newIntents != null) {
2718 next.app.thread.scheduleNewIntent(next.newIntents, next);
2719 }
2720
Doug Zongker2bec3d42009-12-04 12:52:44 -08002721 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 System.identityHashCode(next),
2723 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724
2725 next.app.thread.scheduleResumeActivity(next,
2726 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 pauseIfSleepingLocked();
2729
2730 } catch (Exception e) {
2731 // Whoops, need to restart this activity!
2732 next.state = lastState;
2733 mResumedActivity = lastResumedActivity;
Dianne Hackborn03abb812010-01-04 18:43:19 -08002734 Log.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735 if (!next.hasBeenLaunched) {
2736 next.hasBeenLaunched = true;
2737 } else {
2738 if (SHOW_APP_STARTING_ICON) {
2739 mWindowManager.setAppStartingWindow(
2740 next, next.packageName, next.theme,
2741 next.nonLocalizedLabel,
2742 next.labelRes, next.icon, null, true);
2743 }
2744 }
2745 startSpecificActivityLocked(next, true, false);
2746 return true;
2747 }
2748
2749 // From this point on, if something goes wrong there is no way
2750 // to recover the activity.
2751 try {
2752 next.visible = true;
2753 completeResumeLocked(next);
2754 } catch (Exception e) {
2755 // If any exception gets thrown, toss away this
2756 // activity and try the next one.
2757 Log.w(TAG, "Exception thrown during resume of " + next, e);
2758 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2759 "resume-exception");
2760 return true;
2761 }
2762
2763 // Didn't need to use the icicle, and it is now out of date.
2764 next.icicle = null;
2765 next.haveState = false;
2766 next.stopped = false;
2767
2768 } else {
2769 // Whoops, need to restart this activity!
2770 if (!next.hasBeenLaunched) {
2771 next.hasBeenLaunched = true;
2772 } else {
2773 if (SHOW_APP_STARTING_ICON) {
2774 mWindowManager.setAppStartingWindow(
2775 next, next.packageName, next.theme,
2776 next.nonLocalizedLabel,
2777 next.labelRes, next.icon, null, true);
2778 }
2779 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2780 }
2781 startSpecificActivityLocked(next, true, true);
2782 }
2783
2784 return true;
2785 }
2786
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002787 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2788 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 final int NH = mHistory.size();
2790
2791 int addPos = -1;
2792
2793 if (!newTask) {
2794 // If starting in an existing task, find where that is...
2795 HistoryRecord next = null;
2796 boolean startIt = true;
2797 for (int i = NH-1; i >= 0; i--) {
2798 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2799 if (p.finishing) {
2800 continue;
2801 }
2802 if (p.task == r.task) {
2803 // Here it is! Now, if this is not yet visible to the
2804 // user, then just add it without starting; it will
2805 // get started when the user navigates back to it.
2806 addPos = i+1;
2807 if (!startIt) {
2808 mHistory.add(addPos, r);
2809 r.inHistory = true;
2810 r.task.numActivities++;
2811 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2812 r.info.screenOrientation, r.fullscreen);
2813 if (VALIDATE_TOKENS) {
2814 mWindowManager.validateAppTokens(mHistory);
2815 }
2816 return;
2817 }
2818 break;
2819 }
2820 if (p.fullscreen) {
2821 startIt = false;
2822 }
2823 next = p;
2824 }
2825 }
2826
2827 // Place a new activity at top of stack, so it is next to interact
2828 // with the user.
2829 if (addPos < 0) {
2830 addPos = mHistory.size();
2831 }
2832
2833 // If we are not placing the new activity frontmost, we do not want
2834 // to deliver the onUserLeaving callback to the actual frontmost
2835 // activity
2836 if (addPos < NH) {
2837 mUserLeaving = false;
2838 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2839 }
2840
2841 // Slot the activity into the history stack and proceed
2842 mHistory.add(addPos, r);
2843 r.inHistory = true;
2844 r.frontOfTask = newTask;
2845 r.task.numActivities++;
2846 if (NH > 0) {
2847 // We want to show the starting preview window if we are
2848 // switching to a new task, or the next activity's process is
2849 // not currently running.
2850 boolean showStartingIcon = newTask;
2851 ProcessRecord proc = r.app;
2852 if (proc == null) {
2853 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2854 }
2855 if (proc == null || proc.thread == null) {
2856 showStartingIcon = true;
2857 }
2858 if (DEBUG_TRANSITION) Log.v(TAG,
2859 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002860 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2861 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2862 mNoAnimActivities.add(r);
2863 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2864 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2865 mNoAnimActivities.remove(r);
2866 } else {
2867 mWindowManager.prepareAppTransition(newTask
2868 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2869 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2870 mNoAnimActivities.remove(r);
2871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 mWindowManager.addAppToken(
2873 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2874 boolean doShow = true;
2875 if (newTask) {
2876 // Even though this activity is starting fresh, we still need
2877 // to reset it to make sure we apply affinities to move any
2878 // existing activities from other tasks in to it.
2879 // If the caller has requested that the target task be
2880 // reset, then do so.
2881 if ((r.intent.getFlags()
2882 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2883 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002884 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 }
2886 }
2887 if (SHOW_APP_STARTING_ICON && doShow) {
2888 // Figure out if we are transitioning from another activity that is
2889 // "has the same starting icon" as the next one. This allows the
2890 // window manager to keep the previous window it had previously
2891 // created, if it still had one.
2892 HistoryRecord prev = mResumedActivity;
2893 if (prev != null) {
2894 // We don't want to reuse the previous starting preview if:
2895 // (1) The current activity is in a different task.
2896 if (prev.task != r.task) prev = null;
2897 // (2) The current activity is already displayed.
2898 else if (prev.nowVisible) prev = null;
2899 }
2900 mWindowManager.setAppStartingWindow(
2901 r, r.packageName, r.theme, r.nonLocalizedLabel,
2902 r.labelRes, r.icon, prev, showStartingIcon);
2903 }
2904 } else {
2905 // If this is the first activity, don't do any fancy animations,
2906 // because there is nothing for it to animate on top of.
2907 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2908 r.info.screenOrientation, r.fullscreen);
2909 }
2910 if (VALIDATE_TOKENS) {
2911 mWindowManager.validateAppTokens(mHistory);
2912 }
2913
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002914 if (doResume) {
2915 resumeTopActivityLocked(null);
2916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 }
2918
2919 /**
2920 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002921 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2922 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 * an instance of that activity in the stack and, if found, finish all
2924 * activities on top of it and return the instance.
2925 *
2926 * @param newR Description of the new activity being started.
2927 * @return Returns the old activity that should be continue to be used,
2928 * or null if none was found.
2929 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002930 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002931 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002933
2934 // First find the requested task.
2935 while (i > 0) {
2936 i--;
2937 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2938 if (r.task.taskId == taskId) {
2939 i++;
2940 break;
2941 }
2942 }
2943
2944 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 while (i > 0) {
2946 i--;
2947 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2948 if (r.finishing) {
2949 continue;
2950 }
2951 if (r.task.taskId != taskId) {
2952 return null;
2953 }
2954 if (r.realActivity.equals(newR.realActivity)) {
2955 // Here it is! Now finish everything in front...
2956 HistoryRecord ret = r;
2957 if (doClear) {
2958 while (i < (mHistory.size()-1)) {
2959 i++;
2960 r = (HistoryRecord)mHistory.get(i);
2961 if (r.finishing) {
2962 continue;
2963 }
2964 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2965 null, "clear")) {
2966 i--;
2967 }
2968 }
2969 }
2970
2971 // Finally, if this is a normal launch mode (that is, not
2972 // expecting onNewIntent()), then we will finish the current
2973 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002974 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2975 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002977 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 if (index >= 0) {
2979 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2980 null, "clear");
2981 }
2982 return null;
2983 }
2984 }
2985
2986 return ret;
2987 }
2988 }
2989
2990 return null;
2991 }
2992
2993 /**
2994 * Find the activity in the history stack within the given task. Returns
2995 * the index within the history at which it's found, or < 0 if not found.
2996 */
2997 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
2998 int i = mHistory.size();
2999 while (i > 0) {
3000 i--;
3001 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3002 if (candidate.task.taskId != task) {
3003 break;
3004 }
3005 if (candidate.realActivity.equals(r.realActivity)) {
3006 return i;
3007 }
3008 }
3009
3010 return -1;
3011 }
3012
3013 /**
3014 * Reorder the history stack so that the activity at the given index is
3015 * brought to the front.
3016 */
3017 private final HistoryRecord moveActivityToFrontLocked(int where) {
3018 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3019 int top = mHistory.size();
3020 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3021 mHistory.add(top, newTop);
3022 oldTop.frontOfTask = false;
3023 newTop.frontOfTask = true;
3024 return newTop;
3025 }
3026
3027 /**
3028 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3029 * method will be called at the proper time.
3030 */
3031 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3032 boolean sent = false;
3033 if (r.state == ActivityState.RESUMED
3034 && r.app != null && r.app.thread != null) {
3035 try {
3036 ArrayList<Intent> ar = new ArrayList<Intent>();
3037 ar.add(new Intent(intent));
3038 r.app.thread.scheduleNewIntent(ar, r);
3039 sent = true;
3040 } catch (Exception e) {
3041 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
3042 }
3043 }
3044 if (!sent) {
3045 r.addNewIntentLocked(new Intent(intent));
3046 }
3047 }
3048
3049 private final void logStartActivity(int tag, HistoryRecord r,
3050 TaskRecord task) {
3051 EventLog.writeEvent(tag,
3052 System.identityHashCode(r), task.taskId,
3053 r.shortComponentName, r.intent.getAction(),
3054 r.intent.getType(), r.intent.getDataString(),
3055 r.intent.getFlags());
3056 }
3057
3058 private final int startActivityLocked(IApplicationThread caller,
3059 Intent intent, String resolvedType,
3060 Uri[] grantedUriPermissions,
3061 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3062 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003063 int callingPid, int callingUid, boolean onlyIfNeeded,
3064 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 Log.i(TAG, "Starting activity: " + intent);
3066
3067 HistoryRecord sourceRecord = null;
3068 HistoryRecord resultRecord = null;
3069 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003070 int index = indexOfTokenLocked(resultTo);
The Android Open Source Project10592532009-03-18 17:39:46 -07003071 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3073 if (index >= 0) {
3074 sourceRecord = (HistoryRecord)mHistory.get(index);
3075 if (requestCode >= 0 && !sourceRecord.finishing) {
3076 resultRecord = sourceRecord;
3077 }
3078 }
3079 }
3080
3081 int launchFlags = intent.getFlags();
3082
3083 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3084 && sourceRecord != null) {
3085 // Transfer the result target from the source activity to the new
3086 // one being started, including any failures.
3087 if (requestCode >= 0) {
3088 return START_FORWARD_AND_REQUEST_CONFLICT;
3089 }
3090 resultRecord = sourceRecord.resultTo;
3091 resultWho = sourceRecord.resultWho;
3092 requestCode = sourceRecord.requestCode;
3093 sourceRecord.resultTo = null;
3094 if (resultRecord != null) {
3095 resultRecord.removeResultsLocked(
3096 sourceRecord, resultWho, requestCode);
3097 }
3098 }
3099
3100 int err = START_SUCCESS;
3101
3102 if (intent.getComponent() == null) {
3103 // We couldn't find a class that can handle the given Intent.
3104 // That's the end of that!
3105 err = START_INTENT_NOT_RESOLVED;
3106 }
3107
3108 if (err == START_SUCCESS && aInfo == null) {
3109 // We couldn't find the specific class specified in the Intent.
3110 // Also the end of the line.
3111 err = START_CLASS_NOT_FOUND;
3112 }
3113
3114 ProcessRecord callerApp = null;
3115 if (err == START_SUCCESS && caller != null) {
3116 callerApp = getRecordForAppLocked(caller);
3117 if (callerApp != null) {
3118 callingPid = callerApp.pid;
3119 callingUid = callerApp.info.uid;
3120 } else {
3121 Log.w(TAG, "Unable to find app for caller " + caller
3122 + " (pid=" + callingPid + ") when starting: "
3123 + intent.toString());
3124 err = START_PERMISSION_DENIED;
3125 }
3126 }
3127
3128 if (err != START_SUCCESS) {
3129 if (resultRecord != null) {
3130 sendActivityResultLocked(-1,
3131 resultRecord, resultWho, requestCode,
3132 Activity.RESULT_CANCELED, null);
3133 }
3134 return err;
3135 }
3136
3137 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3138 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3139 if (perm != PackageManager.PERMISSION_GRANTED) {
3140 if (resultRecord != null) {
3141 sendActivityResultLocked(-1,
3142 resultRecord, resultWho, requestCode,
3143 Activity.RESULT_CANCELED, null);
3144 }
3145 String msg = "Permission Denial: starting " + intent.toString()
3146 + " from " + callerApp + " (pid=" + callingPid
3147 + ", uid=" + callingUid + ")"
3148 + " requires " + aInfo.permission;
3149 Log.w(TAG, msg);
3150 throw new SecurityException(msg);
3151 }
3152
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003153 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003154 boolean abort = false;
3155 try {
3156 // The Intent we give to the watcher has the extra data
3157 // stripped off, since it can contain private information.
3158 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003159 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 aInfo.applicationInfo.packageName);
3161 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003162 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 }
3164
3165 if (abort) {
3166 if (resultRecord != null) {
3167 sendActivityResultLocked(-1,
3168 resultRecord, resultWho, requestCode,
3169 Activity.RESULT_CANCELED, null);
3170 }
3171 // We pretend to the caller that it was really started, but
3172 // they will just get a cancel result.
3173 return START_SUCCESS;
3174 }
3175 }
3176
3177 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3178 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003179 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003181 if (mResumedActivity == null
3182 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3183 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3184 PendingActivityLaunch pal = new PendingActivityLaunch();
3185 pal.r = r;
3186 pal.sourceRecord = sourceRecord;
3187 pal.grantedUriPermissions = grantedUriPermissions;
3188 pal.grantedMode = grantedMode;
3189 pal.onlyIfNeeded = onlyIfNeeded;
3190 mPendingActivityLaunches.add(pal);
3191 return START_SWITCHES_CANCELED;
3192 }
3193 }
3194
3195 if (mDidAppSwitch) {
3196 // This is the second allowed switch since we stopped switches,
3197 // so now just generally allow switches. Use case: user presses
3198 // home (switches disabled, switch to home, mDidAppSwitch now true);
3199 // user taps a home icon (coming from home so allowed, we hit here
3200 // and now allow anyone to switch again).
3201 mAppSwitchesAllowedTime = 0;
3202 } else {
3203 mDidAppSwitch = true;
3204 }
3205
3206 doPendingActivityLaunchesLocked(false);
3207
3208 return startActivityUncheckedLocked(r, sourceRecord,
3209 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3210 }
3211
3212 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3213 final int N = mPendingActivityLaunches.size();
3214 if (N <= 0) {
3215 return;
3216 }
3217 for (int i=0; i<N; i++) {
3218 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3219 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3220 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3221 doResume && i == (N-1));
3222 }
3223 mPendingActivityLaunches.clear();
3224 }
3225
3226 private final int startActivityUncheckedLocked(HistoryRecord r,
3227 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3228 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3229 final Intent intent = r.intent;
3230 final int callingUid = r.launchedFromUid;
3231
3232 int launchFlags = intent.getFlags();
3233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 // We'll invoke onUserLeaving before onPause only if the launching
3235 // activity did not explicitly state that this is an automated launch.
3236 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
3237 if (DEBUG_USER_LEAVING) Log.v(TAG,
3238 "startActivity() => mUserLeaving=" + mUserLeaving);
3239
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003240 // If the caller has asked not to resume at this point, we make note
3241 // of this in the record so that we can skip it when trying to find
3242 // the top running activity.
3243 if (!doResume) {
3244 r.delayedResume = true;
3245 }
3246
3247 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3248 != 0 ? r : null;
3249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 // If the onlyIfNeeded flag is set, then we can do this if the activity
3251 // being launched is the same as the one making the call... or, as
3252 // a special case, if we do not know the caller then we count the
3253 // current top activity as the caller.
3254 if (onlyIfNeeded) {
3255 HistoryRecord checkedCaller = sourceRecord;
3256 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003257 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
3259 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3260 // Caller is not the same as launcher, so always needed.
3261 onlyIfNeeded = false;
3262 }
3263 }
3264
3265 if (grantedUriPermissions != null && callingUid > 0) {
3266 for (int i=0; i<grantedUriPermissions.length; i++) {
3267 grantUriPermissionLocked(callingUid, r.packageName,
3268 grantedUriPermissions[i], grantedMode, r);
3269 }
3270 }
3271
3272 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3273 intent, r);
3274
3275 if (sourceRecord == null) {
3276 // This activity is not being started from another... in this
3277 // case we -always- start a new task.
3278 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
3279 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
3280 + intent);
3281 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3282 }
3283 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3284 // The original activity who is starting us is running as a single
3285 // instance... this new activity it is starting must go on its
3286 // own task.
3287 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3288 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3289 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3290 // The activity being started is a single instance... it always
3291 // gets launched into its own task.
3292 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3293 }
3294
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003295 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 // For whatever reason this activity is being launched into a new
3297 // task... yet the caller has requested a result back. Well, that
3298 // is pretty messed up, so instead immediately send back a cancel
3299 // and let the new task continue launched as normal without a
3300 // dependency on its originator.
3301 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3302 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003303 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 Activity.RESULT_CANCELED, null);
3305 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 }
3307
3308 boolean addingToTask = false;
3309 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3310 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3311 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3312 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3313 // If bring to front is requested, and no result is requested, and
3314 // we can find a task that was started with this same
3315 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003316 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 // See if there is a task to bring to the front. If this is
3318 // a SINGLE_INSTANCE activity, there can be one and only one
3319 // instance of it in the history, and it is always in its own
3320 // unique task, so we do a special search.
3321 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3322 ? findTaskLocked(intent, r.info)
3323 : findActivityLocked(intent, r.info);
3324 if (taskTop != null) {
3325 if (taskTop.task.intent == null) {
3326 // This task was started because of movement of
3327 // the activity based on affinity... now that we
3328 // are actually launching it, we can assign the
3329 // base intent.
3330 taskTop.task.setIntent(intent, r.info);
3331 }
3332 // If the target task is not in the front, then we need
3333 // to bring it to the front... except... well, with
3334 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3335 // to have the same behavior as if a new instance was
3336 // being started, which means not bringing it to the front
3337 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003338 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 if (curTop.task != taskTop.task) {
3340 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3341 boolean callerAtFront = sourceRecord == null
3342 || curTop.task == sourceRecord.task;
3343 if (callerAtFront) {
3344 // We really do want to push this one into the
3345 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003346 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348 }
3349 // If the caller has requested that the target task be
3350 // reset, then do so.
3351 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3352 taskTop = resetTaskIfNeededLocked(taskTop, r);
3353 }
3354 if (onlyIfNeeded) {
3355 // We don't need to start a new activity, and
3356 // the client said not to do anything if that
3357 // is the case, so this is it! And for paranoia, make
3358 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003359 if (doResume) {
3360 resumeTopActivityLocked(null);
3361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 return START_RETURN_INTENT_TO_CALLER;
3363 }
3364 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3365 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3366 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3367 // In this situation we want to remove all activities
3368 // from the task up to the one being started. In most
3369 // cases this means we are resetting the task to its
3370 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003371 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003372 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 if (top != null) {
3374 if (top.frontOfTask) {
3375 // Activity aliases may mean we use different
3376 // intents for the top activity, so make sure
3377 // the task now has the identity of the new
3378 // intent.
3379 top.task.setIntent(r.intent, r.info);
3380 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003381 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 deliverNewIntentLocked(top, r.intent);
3383 } else {
3384 // A special case: we need to
3385 // start the activity because it is not currently
3386 // running, and the caller has asked to clear the
3387 // current task to have this activity at the top.
3388 addingToTask = true;
3389 // Now pretend like this activity is being started
3390 // by the top of its task, so it is put in the
3391 // right place.
3392 sourceRecord = taskTop;
3393 }
3394 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3395 // In this case the top activity on the task is the
3396 // same as the one being launched, so we take that
3397 // as a request to bring the task to the foreground.
3398 // If the top activity in the task is the root
3399 // activity, deliver this new intent to it if it
3400 // desires.
3401 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3402 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003403 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 if (taskTop.frontOfTask) {
3405 taskTop.task.setIntent(r.intent, r.info);
3406 }
3407 deliverNewIntentLocked(taskTop, r.intent);
3408 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3409 // In this case we are launching the root activity
3410 // of the task, but with a different intent. We
3411 // should start a new instance on top.
3412 addingToTask = true;
3413 sourceRecord = taskTop;
3414 }
3415 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3416 // In this case an activity is being launched in to an
3417 // existing task, without resetting that task. This
3418 // is typically the situation of launching an activity
3419 // from a notification or shortcut. We want to place
3420 // the new activity on top of the current task.
3421 addingToTask = true;
3422 sourceRecord = taskTop;
3423 } else if (!taskTop.task.rootWasReset) {
3424 // In this case we are launching in to an existing task
3425 // that has not yet been started from its front door.
3426 // The current task has been brought to the front.
3427 // Ideally, we'd probably like to place this new task
3428 // at the bottom of its stack, but that's a little hard
3429 // to do with the current organization of the code so
3430 // for now we'll just drop it.
3431 taskTop.task.setIntent(r.intent, r.info);
3432 }
3433 if (!addingToTask) {
3434 // We didn't do anything... but it was needed (a.k.a., client
3435 // don't use that intent!) And for paranoia, make
3436 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003437 if (doResume) {
3438 resumeTopActivityLocked(null);
3439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 return START_TASK_TO_FRONT;
3441 }
3442 }
3443 }
3444 }
3445
3446 //String uri = r.intent.toURI();
3447 //Intent intent2 = new Intent(uri);
3448 //Log.i(TAG, "Given intent: " + r.intent);
3449 //Log.i(TAG, "URI is: " + uri);
3450 //Log.i(TAG, "To intent: " + intent2);
3451
3452 if (r.packageName != null) {
3453 // If the activity being launched is the same as the one currently
3454 // at the top, then we need to check if it should only be launched
3455 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003456 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3457 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 if (top.realActivity.equals(r.realActivity)) {
3459 if (top.app != null && top.app.thread != null) {
3460 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3461 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3462 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003463 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 // For paranoia, make sure we have correctly
3465 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003466 if (doResume) {
3467 resumeTopActivityLocked(null);
3468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 if (onlyIfNeeded) {
3470 // We don't need to start a new activity, and
3471 // the client said not to do anything if that
3472 // is the case, so this is it!
3473 return START_RETURN_INTENT_TO_CALLER;
3474 }
3475 deliverNewIntentLocked(top, r.intent);
3476 return START_DELIVERED_TO_TOP;
3477 }
3478 }
3479 }
3480 }
3481
3482 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003483 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003485 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 Activity.RESULT_CANCELED, null);
3487 }
3488 return START_CLASS_NOT_FOUND;
3489 }
3490
3491 boolean newTask = false;
3492
3493 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003494 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3496 // todo: should do better management of integers.
3497 mCurTask++;
3498 if (mCurTask <= 0) {
3499 mCurTask = 1;
3500 }
3501 r.task = new TaskRecord(mCurTask, r.info, intent,
3502 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3503 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3504 + " in new task " + r.task);
3505 newTask = true;
3506 addRecentTask(r.task);
3507
3508 } else if (sourceRecord != null) {
3509 if (!addingToTask &&
3510 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3511 // In this case, we are adding the activity to an existing
3512 // task, but the caller has asked to clear that task if the
3513 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003514 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003515 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003517 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 deliverNewIntentLocked(top, r.intent);
3519 // For paranoia, make sure we have correctly
3520 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003521 if (doResume) {
3522 resumeTopActivityLocked(null);
3523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 return START_DELIVERED_TO_TOP;
3525 }
3526 } else if (!addingToTask &&
3527 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3528 // In this case, we are launching an activity in our own task
3529 // that may already be running somewhere in the history, and
3530 // we want to shuffle it to the front of the stack if so.
3531 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3532 if (where >= 0) {
3533 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003534 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003536 if (doResume) {
3537 resumeTopActivityLocked(null);
3538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 return START_DELIVERED_TO_TOP;
3540 }
3541 }
3542 // An existing activity is starting this new activity, so we want
3543 // to keep the new one in the same task as the one that is starting
3544 // it.
3545 r.task = sourceRecord.task;
3546 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3547 + " in existing task " + r.task);
3548
3549 } else {
3550 // This not being started from an existing activity, and not part
3551 // of a new task... just put it in the top task, though these days
3552 // this case should never happen.
3553 final int N = mHistory.size();
3554 HistoryRecord prev =
3555 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3556 r.task = prev != null
3557 ? prev.task
3558 : new TaskRecord(mCurTask, r.info, intent,
3559 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3560 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3561 + " in new guessed " + r.task);
3562 }
3563 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003564 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003566 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003567 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 return START_SUCCESS;
3569 }
3570
3571 public final int startActivity(IApplicationThread caller,
3572 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3573 int grantedMode, IBinder resultTo,
3574 String resultWho, int requestCode, boolean onlyIfNeeded,
3575 boolean debug) {
3576 // Refuse possible leaked file descriptors
3577 if (intent != null && intent.hasFileDescriptors()) {
3578 throw new IllegalArgumentException("File descriptors passed in Intent");
3579 }
3580
The Android Open Source Project4df24232009-03-05 14:34:35 -08003581 final boolean componentSpecified = intent.getComponent() != null;
3582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 // Don't modify the client's object!
3584 intent = new Intent(intent);
3585
3586 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 ActivityInfo aInfo;
3588 try {
3589 ResolveInfo rInfo =
3590 ActivityThread.getPackageManager().resolveIntent(
3591 intent, resolvedType,
3592 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003593 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 aInfo = rInfo != null ? rInfo.activityInfo : null;
3595 } catch (RemoteException e) {
3596 aInfo = null;
3597 }
3598
3599 if (aInfo != null) {
3600 // Store the found target back into the intent, because now that
3601 // we have it we never want to do this again. For example, if the
3602 // user navigates back to this point in the history, we should
3603 // always restart the exact same activity.
3604 intent.setComponent(new ComponentName(
3605 aInfo.applicationInfo.packageName, aInfo.name));
3606
3607 // Don't debug things in the system process
3608 if (debug) {
3609 if (!aInfo.processName.equals("system")) {
3610 setDebugApp(aInfo.processName, true, false);
3611 }
3612 }
3613 }
3614
3615 synchronized(this) {
3616 final long origId = Binder.clearCallingIdentity();
3617 int res = startActivityLocked(caller, intent, resolvedType,
3618 grantedUriPermissions, grantedMode, aInfo,
3619 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003620 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 Binder.restoreCallingIdentity(origId);
3622 return res;
3623 }
3624 }
3625
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003626 public int startActivityIntentSender(IApplicationThread caller,
3627 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003628 IBinder resultTo, String resultWho, int requestCode,
3629 int flagsMask, int flagsValues) {
3630 // Refuse possible leaked file descriptors
3631 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3632 throw new IllegalArgumentException("File descriptors passed in Intent");
3633 }
3634
3635 IIntentSender sender = intent.getTarget();
3636 if (!(sender instanceof PendingIntentRecord)) {
3637 throw new IllegalArgumentException("Bad PendingIntent object");
3638 }
3639
3640 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003641
3642 synchronized (this) {
3643 // If this is coming from the currently resumed activity, it is
3644 // effectively saying that app switches are allowed at this point.
3645 if (mResumedActivity != null
3646 && mResumedActivity.info.applicationInfo.uid ==
3647 Binder.getCallingUid()) {
3648 mAppSwitchesAllowedTime = 0;
3649 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003650 }
3651
3652 return pir.sendInner(0, fillInIntent, resolvedType,
3653 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3654 }
3655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 public boolean startNextMatchingActivity(IBinder callingActivity,
3657 Intent intent) {
3658 // Refuse possible leaked file descriptors
3659 if (intent != null && intent.hasFileDescriptors() == true) {
3660 throw new IllegalArgumentException("File descriptors passed in Intent");
3661 }
3662
3663 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003664 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 if (index < 0) {
3666 return false;
3667 }
3668 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3669 if (r.app == null || r.app.thread == null) {
3670 // The caller is not running... d'oh!
3671 return false;
3672 }
3673 intent = new Intent(intent);
3674 // The caller is not allowed to change the data.
3675 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3676 // And we are resetting to find the next component...
3677 intent.setComponent(null);
3678
3679 ActivityInfo aInfo = null;
3680 try {
3681 List<ResolveInfo> resolves =
3682 ActivityThread.getPackageManager().queryIntentActivities(
3683 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003684 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685
3686 // Look for the original activity in the list...
3687 final int N = resolves != null ? resolves.size() : 0;
3688 for (int i=0; i<N; i++) {
3689 ResolveInfo rInfo = resolves.get(i);
3690 if (rInfo.activityInfo.packageName.equals(r.packageName)
3691 && rInfo.activityInfo.name.equals(r.info.name)) {
3692 // We found the current one... the next matching is
3693 // after it.
3694 i++;
3695 if (i<N) {
3696 aInfo = resolves.get(i).activityInfo;
3697 }
3698 break;
3699 }
3700 }
3701 } catch (RemoteException e) {
3702 }
3703
3704 if (aInfo == null) {
3705 // Nobody who is next!
3706 return false;
3707 }
3708
3709 intent.setComponent(new ComponentName(
3710 aInfo.applicationInfo.packageName, aInfo.name));
3711 intent.setFlags(intent.getFlags()&~(
3712 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3713 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3714 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3715 Intent.FLAG_ACTIVITY_NEW_TASK));
3716
3717 // Okay now we need to start the new activity, replacing the
3718 // currently running activity. This is a little tricky because
3719 // we want to start the new one as if the current one is finished,
3720 // but not finish the current one first so that there is no flicker.
3721 // And thus...
3722 final boolean wasFinishing = r.finishing;
3723 r.finishing = true;
3724
3725 // Propagate reply information over to the new activity.
3726 final HistoryRecord resultTo = r.resultTo;
3727 final String resultWho = r.resultWho;
3728 final int requestCode = r.requestCode;
3729 r.resultTo = null;
3730 if (resultTo != null) {
3731 resultTo.removeResultsLocked(r, resultWho, requestCode);
3732 }
3733
3734 final long origId = Binder.clearCallingIdentity();
3735 // XXX we are not dealing with propagating grantedUriPermissions...
3736 // those are not yet exposed to user code, so there is no need.
3737 int res = startActivityLocked(r.app.thread, intent,
3738 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003739 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 Binder.restoreCallingIdentity(origId);
3741
3742 r.finishing = wasFinishing;
3743 if (res != START_SUCCESS) {
3744 return false;
3745 }
3746 return true;
3747 }
3748 }
3749
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003750 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 Intent intent, String resolvedType, IBinder resultTo,
3752 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003753
3754 // This is so super not safe, that only the system (or okay root)
3755 // can do it.
3756 final int callingUid = Binder.getCallingUid();
3757 if (callingUid != 0 && callingUid != Process.myUid()) {
3758 throw new SecurityException(
3759 "startActivityInPackage only available to the system");
3760 }
3761
The Android Open Source Project4df24232009-03-05 14:34:35 -08003762 final boolean componentSpecified = intent.getComponent() != null;
3763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 // Don't modify the client's object!
3765 intent = new Intent(intent);
3766
3767 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003768 ActivityInfo aInfo;
3769 try {
3770 ResolveInfo rInfo =
3771 ActivityThread.getPackageManager().resolveIntent(
3772 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003773 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 aInfo = rInfo != null ? rInfo.activityInfo : null;
3775 } catch (RemoteException e) {
3776 aInfo = null;
3777 }
3778
3779 if (aInfo != null) {
3780 // Store the found target back into the intent, because now that
3781 // we have it we never want to do this again. For example, if the
3782 // user navigates back to this point in the history, we should
3783 // always restart the exact same activity.
3784 intent.setComponent(new ComponentName(
3785 aInfo.applicationInfo.packageName, aInfo.name));
3786 }
3787
3788 synchronized(this) {
3789 return startActivityLocked(null, intent, resolvedType,
3790 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003791 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 }
3793 }
3794
3795 private final void addRecentTask(TaskRecord task) {
3796 // Remove any existing entries that are the same kind of task.
3797 int N = mRecentTasks.size();
3798 for (int i=0; i<N; i++) {
3799 TaskRecord tr = mRecentTasks.get(i);
3800 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3801 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3802 mRecentTasks.remove(i);
3803 i--;
3804 N--;
3805 if (task.intent == null) {
3806 // If the new recent task we are adding is not fully
3807 // specified, then replace it with the existing recent task.
3808 task = tr;
3809 }
3810 }
3811 }
3812 if (N >= MAX_RECENT_TASKS) {
3813 mRecentTasks.remove(N-1);
3814 }
3815 mRecentTasks.add(0, task);
3816 }
3817
3818 public void setRequestedOrientation(IBinder token,
3819 int requestedOrientation) {
3820 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003821 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 if (index < 0) {
3823 return;
3824 }
3825 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3826 final long origId = Binder.clearCallingIdentity();
3827 mWindowManager.setAppOrientation(r, requestedOrientation);
3828 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003829 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 r.mayFreezeScreenLocked(r.app) ? r : null);
3831 if (config != null) {
3832 r.frozenBeforeDestroy = true;
3833 if (!updateConfigurationLocked(config, r)) {
3834 resumeTopActivityLocked(null);
3835 }
3836 }
3837 Binder.restoreCallingIdentity(origId);
3838 }
3839 }
3840
3841 public int getRequestedOrientation(IBinder token) {
3842 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003843 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 if (index < 0) {
3845 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3846 }
3847 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3848 return mWindowManager.getAppOrientation(r);
3849 }
3850 }
3851
3852 private final void stopActivityLocked(HistoryRecord r) {
3853 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3854 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3855 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3856 if (!r.finishing) {
3857 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3858 "no-history");
3859 }
3860 } else if (r.app != null && r.app.thread != null) {
3861 if (mFocusedActivity == r) {
3862 setFocusedActivityLocked(topRunningActivityLocked(null));
3863 }
3864 r.resumeKeyDispatchingLocked();
3865 try {
3866 r.stopped = false;
3867 r.state = ActivityState.STOPPING;
3868 if (DEBUG_VISBILITY) Log.v(
3869 TAG, "Stopping visible=" + r.visible + " for " + r);
3870 if (!r.visible) {
3871 mWindowManager.setAppVisibility(r, false);
3872 }
3873 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3874 } catch (Exception e) {
3875 // Maybe just ignore exceptions here... if the process
3876 // has crashed, our death notification will clean things
3877 // up.
3878 Log.w(TAG, "Exception thrown during pause", e);
3879 // Just in case, assume it to be stopped.
3880 r.stopped = true;
3881 r.state = ActivityState.STOPPED;
3882 if (r.configDestroy) {
3883 destroyActivityLocked(r, true);
3884 }
3885 }
3886 }
3887 }
3888
3889 /**
3890 * @return Returns true if the activity is being finished, false if for
3891 * some reason it is being left as-is.
3892 */
3893 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3894 Intent resultData, String reason) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003895 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 TAG, "Finishing activity: token=" + token
3897 + ", result=" + resultCode + ", data=" + resultData);
3898
Dianne Hackborn75b03852009-06-12 15:43:26 -07003899 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900 if (index < 0) {
3901 return false;
3902 }
3903 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3904
3905 // Is this the last activity left?
3906 boolean lastActivity = true;
3907 for (int i=mHistory.size()-1; i>=0; i--) {
3908 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3909 if (!p.finishing && p != r) {
3910 lastActivity = false;
3911 break;
3912 }
3913 }
3914
3915 // If this is the last activity, but it is the home activity, then
3916 // just don't finish it.
3917 if (lastActivity) {
3918 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3919 return false;
3920 }
3921 }
3922
3923 finishActivityLocked(r, index, resultCode, resultData, reason);
3924 return true;
3925 }
3926
3927 /**
3928 * @return Returns true if this activity has been removed from the history
3929 * list, or false if it is still in the list and will be removed later.
3930 */
3931 private final boolean finishActivityLocked(HistoryRecord r, int index,
3932 int resultCode, Intent resultData, String reason) {
3933 if (r.finishing) {
3934 Log.w(TAG, "Duplicate finish request for " + r);
3935 return false;
3936 }
3937
3938 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08003939 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 System.identityHashCode(r),
3941 r.task.taskId, r.shortComponentName, reason);
3942 r.task.numActivities--;
3943 if (r.frontOfTask && index < (mHistory.size()-1)) {
3944 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3945 if (next.task == r.task) {
3946 next.frontOfTask = true;
3947 }
3948 }
3949
3950 r.pauseKeyDispatchingLocked();
3951 if (mFocusedActivity == r) {
3952 setFocusedActivityLocked(topRunningActivityLocked(null));
3953 }
3954
3955 // send the result
3956 HistoryRecord resultTo = r.resultTo;
3957 if (resultTo != null) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003958 if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
3959 + " who=" + r.resultWho + " req=" + r.requestCode
3960 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 if (r.info.applicationInfo.uid > 0) {
3962 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3963 r.packageName, resultData, r);
3964 }
3965 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3966 resultData);
3967 r.resultTo = null;
3968 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003969 else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970
3971 // Make sure this HistoryRecord is not holding on to other resources,
3972 // because clients have remote IPC references to this object so we
3973 // can't assume that will go away and want to avoid circular IPC refs.
3974 r.results = null;
3975 r.pendingResults = null;
3976 r.newIntents = null;
3977 r.icicle = null;
3978
3979 if (mPendingThumbnails.size() > 0) {
3980 // There are clients waiting to receive thumbnails so, in case
3981 // this is an activity that someone is waiting for, add it
3982 // to the pending list so we can correctly update the clients.
3983 mCancelledThumbnails.add(r);
3984 }
3985
3986 if (mResumedActivity == r) {
3987 boolean endTask = index <= 0
3988 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3989 if (DEBUG_TRANSITION) Log.v(TAG,
3990 "Prepare close transition: finishing " + r);
3991 mWindowManager.prepareAppTransition(endTask
3992 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3993 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
3994
3995 // Tell window manager to prepare for this one to be removed.
3996 mWindowManager.setAppVisibility(r, false);
3997
3998 if (mPausingActivity == null) {
3999 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
4000 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
4001 startPausingLocked(false, false);
4002 }
4003
4004 } else if (r.state != ActivityState.PAUSING) {
4005 // If the activity is PAUSING, we will complete the finish once
4006 // it is done pausing; else we can just directly finish it here.
4007 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
4008 return finishCurrentActivityLocked(r, index,
4009 FINISH_AFTER_PAUSE) == null;
4010 } else {
4011 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
4012 }
4013
4014 return false;
4015 }
4016
4017 private static final int FINISH_IMMEDIATELY = 0;
4018 private static final int FINISH_AFTER_PAUSE = 1;
4019 private static final int FINISH_AFTER_VISIBLE = 2;
4020
4021 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4022 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004023 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 if (index < 0) {
4025 return null;
4026 }
4027
4028 return finishCurrentActivityLocked(r, index, mode);
4029 }
4030
4031 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4032 int index, int mode) {
4033 // First things first: if this activity is currently visible,
4034 // and the resumed activity is not yet visible, then hold off on
4035 // finishing until the resumed one becomes visible.
4036 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4037 if (!mStoppingActivities.contains(r)) {
4038 mStoppingActivities.add(r);
4039 if (mStoppingActivities.size() > 3) {
4040 // If we already have a few activities waiting to stop,
4041 // then give up on things going idle and start clearing
4042 // them out.
4043 Message msg = Message.obtain();
4044 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4045 mHandler.sendMessage(msg);
4046 }
4047 }
4048 r.state = ActivityState.STOPPING;
4049 updateOomAdjLocked();
4050 return r;
4051 }
4052
4053 // make sure the record is cleaned out of other places.
4054 mStoppingActivities.remove(r);
4055 mWaitingVisibleActivities.remove(r);
4056 if (mResumedActivity == r) {
4057 mResumedActivity = null;
4058 }
4059 final ActivityState prevState = r.state;
4060 r.state = ActivityState.FINISHING;
4061
4062 if (mode == FINISH_IMMEDIATELY
4063 || prevState == ActivityState.STOPPED
4064 || prevState == ActivityState.INITIALIZING) {
4065 // If this activity is already stopped, we can just finish
4066 // it right now.
4067 return destroyActivityLocked(r, true) ? null : r;
4068 } else {
4069 // Need to go through the full pause cycle to get this
4070 // activity into the stopped state and then finish it.
4071 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
4072 mFinishingActivities.add(r);
4073 resumeTopActivityLocked(null);
4074 }
4075 return r;
4076 }
4077
4078 /**
4079 * This is the internal entry point for handling Activity.finish().
4080 *
4081 * @param token The Binder token referencing the Activity we want to finish.
4082 * @param resultCode Result code, if any, from this Activity.
4083 * @param resultData Result data (Intent), if any, from this Activity.
4084 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004085 * @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 -08004086 */
4087 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4088 // Refuse possible leaked file descriptors
4089 if (resultData != null && resultData.hasFileDescriptors() == true) {
4090 throw new IllegalArgumentException("File descriptors passed in Intent");
4091 }
4092
4093 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004094 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 // Find the first activity that is not finishing.
4096 HistoryRecord next = topRunningActivityLocked(token, 0);
4097 if (next != null) {
4098 // ask watcher if this is allowed
4099 boolean resumeOK = true;
4100 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004101 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004103 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 }
4105
4106 if (!resumeOK) {
4107 return false;
4108 }
4109 }
4110 }
4111 final long origId = Binder.clearCallingIdentity();
4112 boolean res = requestFinishActivityLocked(token, resultCode,
4113 resultData, "app-request");
4114 Binder.restoreCallingIdentity(origId);
4115 return res;
4116 }
4117 }
4118
4119 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4120 String resultWho, int requestCode, int resultCode, Intent data) {
4121
4122 if (callingUid > 0) {
4123 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4124 data, r);
4125 }
4126
The Android Open Source Project10592532009-03-18 17:39:46 -07004127 if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
4128 + " : who=" + resultWho + " req=" + requestCode
4129 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4131 try {
4132 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4133 list.add(new ResultInfo(resultWho, requestCode,
4134 resultCode, data));
4135 r.app.thread.scheduleSendResult(r, list);
4136 return;
4137 } catch (Exception e) {
4138 Log.w(TAG, "Exception thrown sending result to " + r, e);
4139 }
4140 }
4141
4142 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4143 }
4144
4145 public final void finishSubActivity(IBinder token, String resultWho,
4146 int requestCode) {
4147 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004148 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 if (index < 0) {
4150 return;
4151 }
4152 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4153
4154 final long origId = Binder.clearCallingIdentity();
4155
4156 int i;
4157 for (i=mHistory.size()-1; i>=0; i--) {
4158 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4159 if (r.resultTo == self && r.requestCode == requestCode) {
4160 if ((r.resultWho == null && resultWho == null) ||
4161 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4162 finishActivityLocked(r, i,
4163 Activity.RESULT_CANCELED, null, "request-sub");
4164 }
4165 }
4166 }
4167
4168 Binder.restoreCallingIdentity(origId);
4169 }
4170 }
4171
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004172 public void overridePendingTransition(IBinder token, String packageName,
4173 int enterAnim, int exitAnim) {
4174 synchronized(this) {
4175 int index = indexOfTokenLocked(token);
4176 if (index < 0) {
4177 return;
4178 }
4179 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4180
4181 final long origId = Binder.clearCallingIdentity();
4182
4183 if (self.state == ActivityState.RESUMED
4184 || self.state == ActivityState.PAUSING) {
4185 mWindowManager.overridePendingAppTransition(packageName,
4186 enterAnim, exitAnim);
4187 }
4188
4189 Binder.restoreCallingIdentity(origId);
4190 }
4191 }
4192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 /**
4194 * Perform clean-up of service connections in an activity record.
4195 */
4196 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4197 // Throw away any services that have been bound by this activity.
4198 if (r.connections != null) {
4199 Iterator<ConnectionRecord> it = r.connections.iterator();
4200 while (it.hasNext()) {
4201 ConnectionRecord c = it.next();
4202 removeConnectionLocked(c, null, r);
4203 }
4204 r.connections = null;
4205 }
4206 }
4207
4208 /**
4209 * Perform the common clean-up of an activity record. This is called both
4210 * as part of destroyActivityLocked() (when destroying the client-side
4211 * representation) and cleaning things up as a result of its hosting
4212 * processing going away, in which case there is no remaining client-side
4213 * state to destroy so only the cleanup here is needed.
4214 */
4215 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4216 if (mResumedActivity == r) {
4217 mResumedActivity = null;
4218 }
4219 if (mFocusedActivity == r) {
4220 mFocusedActivity = null;
4221 }
4222
4223 r.configDestroy = false;
4224 r.frozenBeforeDestroy = false;
4225
4226 // Make sure this record is no longer in the pending finishes list.
4227 // This could happen, for example, if we are trimming activities
4228 // down to the max limit while they are still waiting to finish.
4229 mFinishingActivities.remove(r);
4230 mWaitingVisibleActivities.remove(r);
4231
4232 // Remove any pending results.
4233 if (r.finishing && r.pendingResults != null) {
4234 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4235 PendingIntentRecord rec = apr.get();
4236 if (rec != null) {
4237 cancelIntentSenderLocked(rec, false);
4238 }
4239 }
4240 r.pendingResults = null;
4241 }
4242
4243 if (cleanServices) {
4244 cleanUpActivityServicesLocked(r);
4245 }
4246
4247 if (mPendingThumbnails.size() > 0) {
4248 // There are clients waiting to receive thumbnails so, in case
4249 // this is an activity that someone is waiting for, add it
4250 // to the pending list so we can correctly update the clients.
4251 mCancelledThumbnails.add(r);
4252 }
4253
4254 // Get rid of any pending idle timeouts.
4255 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4256 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4257 }
4258
4259 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4260 if (r.state != ActivityState.DESTROYED) {
4261 mHistory.remove(r);
4262 r.inHistory = false;
4263 r.state = ActivityState.DESTROYED;
4264 mWindowManager.removeAppToken(r);
4265 if (VALIDATE_TOKENS) {
4266 mWindowManager.validateAppTokens(mHistory);
4267 }
4268 cleanUpActivityServicesLocked(r);
4269 removeActivityUriPermissionsLocked(r);
4270 }
4271 }
4272
4273 /**
4274 * Destroy the current CLIENT SIDE instance of an activity. This may be
4275 * called both when actually finishing an activity, or when performing
4276 * a configuration switch where we destroy the current client-side object
4277 * but then create a new client-side object for this same HistoryRecord.
4278 */
4279 private final boolean destroyActivityLocked(HistoryRecord r,
4280 boolean removeFromApp) {
4281 if (DEBUG_SWITCH) Log.v(
4282 TAG, "Removing activity: token=" + r
4283 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004284 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 System.identityHashCode(r),
4286 r.task.taskId, r.shortComponentName);
4287
4288 boolean removedFromHistory = false;
4289
4290 cleanUpActivityLocked(r, false);
4291
Dianne Hackborn03abb812010-01-04 18:43:19 -08004292 final boolean hadApp = r.app != null;
4293
4294 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 if (removeFromApp) {
4296 int idx = r.app.activities.indexOf(r);
4297 if (idx >= 0) {
4298 r.app.activities.remove(idx);
4299 }
4300 if (r.persistent) {
4301 decPersistentCountLocked(r.app);
4302 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004303 if (r.app.activities.size() == 0) {
4304 // No longer have activities, so update location in
4305 // LRU list.
4306 updateLruProcessLocked(r.app, true, false);
4307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 }
4309
4310 boolean skipDestroy = false;
4311
4312 try {
4313 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
4314 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4315 r.configChangeFlags);
4316 } catch (Exception e) {
4317 // We can just ignore exceptions here... if the process
4318 // has crashed, our death notification will clean things
4319 // up.
4320 //Log.w(TAG, "Exception thrown during finish", e);
4321 if (r.finishing) {
4322 removeActivityFromHistoryLocked(r);
4323 removedFromHistory = true;
4324 skipDestroy = true;
4325 }
4326 }
4327
4328 r.app = null;
4329 r.nowVisible = false;
4330
4331 if (r.finishing && !skipDestroy) {
4332 r.state = ActivityState.DESTROYING;
4333 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4334 msg.obj = r;
4335 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4336 } else {
4337 r.state = ActivityState.DESTROYED;
4338 }
4339 } else {
4340 // remove this record from the history.
4341 if (r.finishing) {
4342 removeActivityFromHistoryLocked(r);
4343 removedFromHistory = true;
4344 } else {
4345 r.state = ActivityState.DESTROYED;
4346 }
4347 }
4348
4349 r.configChangeFlags = 0;
4350
Dianne Hackborn03abb812010-01-04 18:43:19 -08004351 if (!mLRUActivities.remove(r) && hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4353 }
4354
4355 return removedFromHistory;
4356 }
4357
Dianne Hackborn03abb812010-01-04 18:43:19 -08004358 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 int i = list.size();
4360 if (localLOGV) Log.v(
4361 TAG, "Removing app " + app + " from list " + list
4362 + " with " + i + " entries");
4363 while (i > 0) {
4364 i--;
4365 HistoryRecord r = (HistoryRecord)list.get(i);
4366 if (localLOGV) Log.v(
4367 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4368 if (r.app == app) {
4369 if (localLOGV) Log.v(TAG, "Removing this entry!");
4370 list.remove(i);
4371 }
4372 }
4373 }
4374
4375 /**
4376 * Main function for removing an existing process from the activity manager
4377 * as a result of that process going away. Clears out all connections
4378 * to the process.
4379 */
4380 private final void handleAppDiedLocked(ProcessRecord app,
4381 boolean restarting) {
4382 cleanUpApplicationRecordLocked(app, restarting, -1);
4383 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004384 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 }
4386
4387 // Just in case...
4388 if (mPausingActivity != null && mPausingActivity.app == app) {
4389 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
4390 mPausingActivity = null;
4391 }
4392 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4393 mLastPausedActivity = null;
4394 }
4395
4396 // Remove this application's activities from active lists.
4397 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4398 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4399 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4400 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4401
4402 boolean atTop = true;
4403 boolean hasVisibleActivities = false;
4404
4405 // Clean out the history list.
4406 int i = mHistory.size();
4407 if (localLOGV) Log.v(
4408 TAG, "Removing app " + app + " from history with " + i + " entries");
4409 while (i > 0) {
4410 i--;
4411 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4412 if (localLOGV) Log.v(
4413 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4414 if (r.app == app) {
4415 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4416 if (localLOGV) Log.v(
4417 TAG, "Removing this entry! frozen=" + r.haveState
4418 + " finishing=" + r.finishing);
4419 mHistory.remove(i);
4420
4421 r.inHistory = false;
4422 mWindowManager.removeAppToken(r);
4423 if (VALIDATE_TOKENS) {
4424 mWindowManager.validateAppTokens(mHistory);
4425 }
4426 removeActivityUriPermissionsLocked(r);
4427
4428 } else {
4429 // We have the current state for this activity, so
4430 // it can be restarted later when needed.
4431 if (localLOGV) Log.v(
4432 TAG, "Keeping entry, setting app to null");
4433 if (r.visible) {
4434 hasVisibleActivities = true;
4435 }
4436 r.app = null;
4437 r.nowVisible = false;
4438 if (!r.haveState) {
4439 r.icicle = null;
4440 }
4441 }
4442
4443 cleanUpActivityLocked(r, true);
4444 r.state = ActivityState.STOPPED;
4445 }
4446 atTop = false;
4447 }
4448
4449 app.activities.clear();
4450
4451 if (app.instrumentationClass != null) {
4452 Log.w(TAG, "Crash of app " + app.processName
4453 + " running instrumentation " + app.instrumentationClass);
4454 Bundle info = new Bundle();
4455 info.putString("shortMsg", "Process crashed.");
4456 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4457 }
4458
4459 if (!restarting) {
4460 if (!resumeTopActivityLocked(null)) {
4461 // If there was nothing to resume, and we are not already
4462 // restarting this process, but there is a visible activity that
4463 // is hosted by the process... then make sure all visible
4464 // activities are running, taking care of restarting this
4465 // process.
4466 if (hasVisibleActivities) {
4467 ensureActivitiesVisibleLocked(null, 0);
4468 }
4469 }
4470 }
4471 }
4472
4473 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4474 IBinder threadBinder = thread.asBinder();
4475
4476 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004477 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4478 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4480 return i;
4481 }
4482 }
4483 return -1;
4484 }
4485
4486 private final ProcessRecord getRecordForAppLocked(
4487 IApplicationThread thread) {
4488 if (thread == null) {
4489 return null;
4490 }
4491
4492 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004493 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 }
4495
4496 private final void appDiedLocked(ProcessRecord app, int pid,
4497 IApplicationThread thread) {
4498
4499 mProcDeaths[0]++;
4500
4501 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4502 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4503 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004504 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 if (localLOGV) Log.v(
4506 TAG, "Dying app: " + app + ", pid: " + pid
4507 + ", thread: " + thread.asBinder());
4508 boolean doLowMem = app.instrumentationClass == null;
4509 handleAppDiedLocked(app, false);
4510
4511 if (doLowMem) {
4512 // If there are no longer any background processes running,
4513 // and the app that died was not running instrumentation,
4514 // then tell everyone we are now low on memory.
4515 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004516 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4517 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4519 haveBg = true;
4520 break;
4521 }
4522 }
4523
4524 if (!haveBg) {
4525 Log.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004526 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004527 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004528 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4529 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004530 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004531 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4532 // The low memory report is overriding any current
4533 // state for a GC request. Make sure to do
4534 // visible/foreground processes first.
4535 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4536 rec.lastRequestedGc = 0;
4537 } else {
4538 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004540 rec.reportLowMemory = true;
4541 rec.lastLowMemory = now;
4542 mProcessesToGc.remove(rec);
4543 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 }
4545 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004546 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 }
4548 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004549 } else if (DEBUG_PROCESSES) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 Log.d(TAG, "Received spurious death notification for thread "
4551 + thread.asBinder());
4552 }
4553 }
4554
Dan Egnor42471dd2010-01-07 17:25:22 -08004555 /**
4556 * If a stack trace dump file is configured, dump process stack traces.
4557 * @param pids of dalvik VM processes to dump stack traces for
4558 * @return file containing stack traces, or null if no dump file is configured
4559 */
4560 private static File dumpStackTraces(ArrayList<Integer> pids) {
4561 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4562 if (tracesPath == null || tracesPath.length() == 0) {
4563 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004564 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004565
4566 File tracesFile = new File(tracesPath);
4567 try {
4568 File tracesDir = tracesFile.getParentFile();
4569 if (!tracesDir.exists()) tracesFile.mkdirs();
4570 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4571
4572 if (tracesFile.exists()) tracesFile.delete();
4573 tracesFile.createNewFile();
4574 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4575 } catch (IOException e) {
4576 Log.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
4577 return null;
4578 }
4579
4580 // Use a FileObserver to detect when traces finish writing.
4581 // The order of traces is considered important to maintain for legibility.
4582 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4583 public synchronized void onEvent(int event, String path) { notify(); }
4584 };
4585
4586 try {
4587 observer.startWatching();
4588 int num = pids.size();
4589 for (int i = 0; i < num; i++) {
4590 synchronized (observer) {
4591 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4592 observer.wait(200); // Wait for write-close, give up after 200msec
4593 }
4594 }
4595 } catch (InterruptedException e) {
4596 Log.wtf(TAG, e);
4597 } finally {
4598 observer.stopWatching();
4599 }
4600
4601 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 }
4603
Dan Egnor42471dd2010-01-07 17:25:22 -08004604 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4605 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 if (app.notResponding || app.crashing) {
4607 return;
4608 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004611 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4612 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613
Dan Egnor42471dd2010-01-07 17:25:22 -08004614 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4615 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4616 pids.add(app.pid);
4617
4618 int parentPid = app.pid;
4619 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4620 if (parentPid != app.pid) pids.add(parentPid);
4621
4622 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4623
4624 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4625 ProcessRecord r = mLruProcesses.get(i);
4626 if (r != null && r.thread != null) {
4627 int pid = r.pid;
4628 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 }
4630 }
4631
Dan Egnor42471dd2010-01-07 17:25:22 -08004632 File tracesFile = dumpStackTraces(pids);
4633
4634 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004635 StringBuilder info = mStringBuilder;
4636 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004637 info.append("ANR in ").append(app.processName);
4638 if (activity != null && activity.shortComponentName != null) {
4639 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 if (annotation != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004642 info.append("\nReason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004644 if (parent != null && parent != activity) {
4645 info.append("\nParent: ").append(parent.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647
Dan Egnor42471dd2010-01-07 17:25:22 -08004648 String cpuInfo = null;
4649 if (MONITOR_CPU_USAGE) {
4650 updateCpuStatsNow();
4651 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4652 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 }
4654
Dan Egnor42471dd2010-01-07 17:25:22 -08004655 Log.e(TAG, info.toString());
4656 if (tracesFile == null) {
4657 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4658 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4659 }
4660
4661 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4662
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004663 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004665 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4666 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004668 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4669 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
4671 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004672 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 }
4674 }
4675
Dan Egnor42471dd2010-01-07 17:25:22 -08004676 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4677 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4678 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4679 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4680 Process.killProcess(app.pid);
4681 return;
4682 }
4683
4684 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004685 makeAppNotRespondingLocked(app,
4686 activity != null ? activity.shortComponentName : null,
4687 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004688 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004689
4690 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 Message msg = Message.obtain();
4692 HashMap map = new HashMap();
4693 msg.what = SHOW_NOT_RESPONDING_MSG;
4694 msg.obj = map;
4695 map.put("app", app);
4696 if (activity != null) {
4697 map.put("activity", activity);
4698 }
4699
4700 mHandler.sendMessage(msg);
4701 return;
4702 }
4703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 private final void decPersistentCountLocked(ProcessRecord app)
4705 {
4706 app.persistentActivities--;
4707 if (app.persistentActivities > 0) {
4708 // Still more of 'em...
4709 return;
4710 }
4711 if (app.persistent) {
4712 // Ah, but the application itself is persistent. Whatever!
4713 return;
4714 }
4715
4716 // App is no longer persistent... make sure it and the ones
4717 // following it in the LRU list have the correc oom_adj.
4718 updateOomAdjLocked();
4719 }
4720
4721 public void setPersistent(IBinder token, boolean isPersistent) {
4722 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4723 != PackageManager.PERMISSION_GRANTED) {
4724 String msg = "Permission Denial: setPersistent() from pid="
4725 + Binder.getCallingPid()
4726 + ", uid=" + Binder.getCallingUid()
4727 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4728 Log.w(TAG, msg);
4729 throw new SecurityException(msg);
4730 }
4731
4732 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004733 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 if (index < 0) {
4735 return;
4736 }
4737 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4738 ProcessRecord app = r.app;
4739
4740 if (localLOGV) Log.v(
4741 TAG, "Setting persistence " + isPersistent + ": " + r);
4742
4743 if (isPersistent) {
4744 if (r.persistent) {
4745 // Okay okay, I heard you already!
4746 if (localLOGV) Log.v(TAG, "Already persistent!");
4747 return;
4748 }
4749 r.persistent = true;
4750 app.persistentActivities++;
4751 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4752 if (app.persistentActivities > 1) {
4753 // We aren't the first...
4754 if (localLOGV) Log.v(TAG, "Not the first!");
4755 return;
4756 }
4757 if (app.persistent) {
4758 // This would be redundant.
4759 if (localLOGV) Log.v(TAG, "App is persistent!");
4760 return;
4761 }
4762
4763 // App is now persistent... make sure it and the ones
4764 // following it now have the correct oom_adj.
4765 final long origId = Binder.clearCallingIdentity();
4766 updateOomAdjLocked();
4767 Binder.restoreCallingIdentity(origId);
4768
4769 } else {
4770 if (!r.persistent) {
4771 // Okay okay, I heard you already!
4772 return;
4773 }
4774 r.persistent = false;
4775 final long origId = Binder.clearCallingIdentity();
4776 decPersistentCountLocked(app);
4777 Binder.restoreCallingIdentity(origId);
4778
4779 }
4780 }
4781 }
4782
4783 public boolean clearApplicationUserData(final String packageName,
4784 final IPackageDataObserver observer) {
4785 int uid = Binder.getCallingUid();
4786 int pid = Binder.getCallingPid();
4787 long callingId = Binder.clearCallingIdentity();
4788 try {
4789 IPackageManager pm = ActivityThread.getPackageManager();
4790 int pkgUid = -1;
4791 synchronized(this) {
4792 try {
4793 pkgUid = pm.getPackageUid(packageName);
4794 } catch (RemoteException e) {
4795 }
4796 if (pkgUid == -1) {
4797 Log.w(TAG, "Invalid packageName:" + packageName);
4798 return false;
4799 }
4800 if (uid == pkgUid || checkComponentPermission(
4801 android.Manifest.permission.CLEAR_APP_USER_DATA,
4802 pid, uid, -1)
4803 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004804 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004805 } else {
4806 throw new SecurityException(pid+" does not have permission:"+
4807 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4808 "for process:"+packageName);
4809 }
4810 }
4811
4812 try {
4813 //clear application user data
4814 pm.clearApplicationUserData(packageName, observer);
4815 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4816 Uri.fromParts("package", packageName, null));
4817 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4818 broadcastIntentLocked(null, null, intent,
4819 null, null, 0, null, null, null,
4820 false, false, MY_PID, Process.SYSTEM_UID);
4821 } catch (RemoteException e) {
4822 }
4823 } finally {
4824 Binder.restoreCallingIdentity(callingId);
4825 }
4826 return true;
4827 }
4828
Dianne Hackborn03abb812010-01-04 18:43:19 -08004829 public void killBackgroundProcesses(final String packageName) {
4830 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4831 != PackageManager.PERMISSION_GRANTED &&
4832 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4833 != PackageManager.PERMISSION_GRANTED) {
4834 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 + Binder.getCallingPid()
4836 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004837 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 Log.w(TAG, msg);
4839 throw new SecurityException(msg);
4840 }
4841
4842 long callingId = Binder.clearCallingIdentity();
4843 try {
4844 IPackageManager pm = ActivityThread.getPackageManager();
4845 int pkgUid = -1;
4846 synchronized(this) {
4847 try {
4848 pkgUid = pm.getPackageUid(packageName);
4849 } catch (RemoteException e) {
4850 }
4851 if (pkgUid == -1) {
4852 Log.w(TAG, "Invalid packageName: " + packageName);
4853 return;
4854 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004855 killPackageProcessesLocked(packageName, pkgUid,
4856 SECONDARY_SERVER_ADJ, false);
4857 }
4858 } finally {
4859 Binder.restoreCallingIdentity(callingId);
4860 }
4861 }
4862
4863 public void forceStopPackage(final String packageName) {
4864 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4865 != PackageManager.PERMISSION_GRANTED) {
4866 String msg = "Permission Denial: forceStopPackage() from pid="
4867 + Binder.getCallingPid()
4868 + ", uid=" + Binder.getCallingUid()
4869 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4870 Log.w(TAG, msg);
4871 throw new SecurityException(msg);
4872 }
4873
4874 long callingId = Binder.clearCallingIdentity();
4875 try {
4876 IPackageManager pm = ActivityThread.getPackageManager();
4877 int pkgUid = -1;
4878 synchronized(this) {
4879 try {
4880 pkgUid = pm.getPackageUid(packageName);
4881 } catch (RemoteException e) {
4882 }
4883 if (pkgUid == -1) {
4884 Log.w(TAG, "Invalid packageName: " + packageName);
4885 return;
4886 }
4887 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 }
4889 } finally {
4890 Binder.restoreCallingIdentity(callingId);
4891 }
4892 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004893
4894 /*
4895 * The pkg name and uid have to be specified.
4896 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
4897 */
4898 public void killApplicationWithUid(String pkg, int uid) {
4899 if (pkg == null) {
4900 return;
4901 }
4902 // Make sure the uid is valid.
4903 if (uid < 0) {
4904 Log.w(TAG, "Invalid uid specified for pkg : " + pkg);
4905 return;
4906 }
4907 int callerUid = Binder.getCallingUid();
4908 // Only the system server can kill an application
4909 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07004910 // Post an aysnc message to kill the application
4911 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
4912 msg.arg1 = uid;
4913 msg.arg2 = 0;
4914 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07004915 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004916 } else {
4917 throw new SecurityException(callerUid + " cannot kill pkg: " +
4918 pkg);
4919 }
4920 }
4921
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004922 public void closeSystemDialogs(String reason) {
4923 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
4924 if (reason != null) {
4925 intent.putExtra("reason", reason);
4926 }
4927
4928 final int uid = Binder.getCallingUid();
4929 final long origId = Binder.clearCallingIdentity();
4930 synchronized (this) {
4931 int i = mWatchers.beginBroadcast();
4932 while (i > 0) {
4933 i--;
4934 IActivityWatcher w = mWatchers.getBroadcastItem(i);
4935 if (w != null) {
4936 try {
4937 w.closingSystemDialogs(reason);
4938 } catch (RemoteException e) {
4939 }
4940 }
4941 }
4942 mWatchers.finishBroadcast();
4943
Dianne Hackbornffa42482009-09-23 22:20:11 -07004944 mWindowManager.closeSystemDialogs(reason);
4945
4946 for (i=mHistory.size()-1; i>=0; i--) {
4947 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4948 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4949 finishActivityLocked(r, i,
4950 Activity.RESULT_CANCELED, null, "close-sys");
4951 }
4952 }
4953
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07004954 broadcastIntentLocked(null, null, intent, null,
4955 null, 0, null, null, null, false, false, -1, uid);
4956 }
4957 Binder.restoreCallingIdentity(origId);
4958 }
4959
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004960 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004961 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004962 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
4963 for (int i=pids.length-1; i>=0; i--) {
4964 infos[i] = new Debug.MemoryInfo();
4965 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004966 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07004967 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07004968 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07004969
4970 public void killApplicationProcess(String processName, int uid) {
4971 if (processName == null) {
4972 return;
4973 }
4974
4975 int callerUid = Binder.getCallingUid();
4976 // Only the system server can kill an application
4977 if (callerUid == Process.SYSTEM_UID) {
4978 synchronized (this) {
4979 ProcessRecord app = getProcessRecordLocked(processName, uid);
4980 if (app != null) {
4981 try {
4982 app.thread.scheduleSuicide();
4983 } catch (RemoteException e) {
4984 // If the other end already died, then our work here is done.
4985 }
4986 } else {
4987 Log.w(TAG, "Process/uid not found attempting kill of "
4988 + processName + " / " + uid);
4989 }
4990 }
4991 } else {
4992 throw new SecurityException(callerUid + " cannot kill app process: " +
4993 processName);
4994 }
4995 }
4996
Dianne Hackborn03abb812010-01-04 18:43:19 -08004997 private void forceStopPackageLocked(final String packageName, int uid) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004998 forceStopPackageLocked(packageName, uid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5000 Uri.fromParts("package", packageName, null));
5001 intent.putExtra(Intent.EXTRA_UID, uid);
5002 broadcastIntentLocked(null, null, intent,
5003 null, null, 0, null, null, null,
5004 false, false, MY_PID, Process.SYSTEM_UID);
5005 }
5006
Dianne Hackborn03abb812010-01-04 18:43:19 -08005007 private final void killPackageProcessesLocked(String packageName, int uid,
5008 int minOomAdj, boolean callerWillRestart) {
5009 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005010
Dianne Hackborn03abb812010-01-04 18:43:19 -08005011 // Remove all processes this package may have touched: all with the
5012 // same UID (except for the system or root user), and all whose name
5013 // matches the package name.
5014 final String procNamePrefix = packageName + ":";
5015 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5016 final int NA = apps.size();
5017 for (int ia=0; ia<NA; ia++) {
5018 ProcessRecord app = apps.valueAt(ia);
5019 if (app.removed) {
5020 procs.add(app);
5021 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5022 || app.processName.equals(packageName)
5023 || app.processName.startsWith(procNamePrefix)) {
5024 if (app.setAdj >= minOomAdj) {
5025 app.removed = true;
5026 procs.add(app);
5027 }
5028 }
5029 }
5030 }
5031
5032 int N = procs.size();
5033 for (int i=0; i<N; i++) {
5034 removeProcessLocked(procs.get(i), callerWillRestart);
5035 }
5036 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005037
Dianne Hackborn03abb812010-01-04 18:43:19 -08005038 private final void forceStopPackageLocked(String name, int uid,
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005039 boolean callerWillRestart, boolean purgeCache) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 int i, N;
5041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 if (uid < 0) {
5043 try {
5044 uid = ActivityThread.getPackageManager().getPackageUid(name);
5045 } catch (RemoteException e) {
5046 }
5047 }
5048
Dianne Hackborn03abb812010-01-04 18:43:19 -08005049 Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
5050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5052 while (badApps.hasNext()) {
5053 SparseArray<Long> ba = badApps.next();
5054 if (ba.get(uid) != null) {
5055 badApps.remove();
5056 }
5057 }
5058
Dianne Hackborn03abb812010-01-04 18:43:19 -08005059 killPackageProcessesLocked(name, uid, -100, callerWillRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005060
5061 for (i=mHistory.size()-1; i>=0; i--) {
5062 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5063 if (r.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005064 Log.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 if (r.app != null) {
5066 r.app.removed = true;
5067 }
5068 r.app = null;
5069 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5070 }
5071 }
5072
5073 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5074 for (ServiceRecord service : mServices.values()) {
5075 if (service.packageName.equals(name)) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005076 Log.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 if (service.app != null) {
5078 service.app.removed = true;
5079 }
5080 service.app = null;
5081 services.add(service);
5082 }
5083 }
5084
5085 N = services.size();
5086 for (i=0; i<N; i++) {
5087 bringDownServiceLocked(services.get(i), true);
5088 }
5089
5090 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005091 if (purgeCache) {
5092 AttributeCache ac = AttributeCache.instance();
5093 if (ac != null) {
5094 ac.removePackage(name);
5095 }
5096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 }
5098
5099 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5100 final String name = app.processName;
5101 final int uid = app.info.uid;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005102 if (DEBUG_PROCESSES) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 TAG, "Force removing process " + app + " (" + name
5104 + "/" + uid + ")");
5105
5106 mProcessNames.remove(name, uid);
5107 boolean needRestart = false;
5108 if (app.pid > 0 && app.pid != MY_PID) {
5109 int pid = app.pid;
5110 synchronized (mPidsSelfLocked) {
5111 mPidsSelfLocked.remove(pid);
5112 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5113 }
5114 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005115 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 Process.killProcess(pid);
5117
5118 if (app.persistent) {
5119 if (!callerWillRestart) {
5120 addAppLocked(app.info);
5121 } else {
5122 needRestart = true;
5123 }
5124 }
5125 } else {
5126 mRemovedProcesses.add(app);
5127 }
5128
5129 return needRestart;
5130 }
5131
5132 private final void processStartTimedOutLocked(ProcessRecord app) {
5133 final int pid = app.pid;
5134 boolean gone = false;
5135 synchronized (mPidsSelfLocked) {
5136 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5137 if (knownApp != null && knownApp.thread == null) {
5138 mPidsSelfLocked.remove(pid);
5139 gone = true;
5140 }
5141 }
5142
5143 if (gone) {
5144 Log.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005145 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005146 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005148 // Take care of any launching providers waiting for this process.
5149 checkAppInLaunchingProvidersLocked(app, true);
5150 // Take care of any services that are waiting for the process.
5151 for (int i=0; i<mPendingServices.size(); i++) {
5152 ServiceRecord sr = mPendingServices.get(i);
5153 if (app.info.uid == sr.appInfo.uid
5154 && app.processName.equals(sr.processName)) {
5155 Log.w(TAG, "Forcing bringing down service: " + sr);
5156 mPendingServices.remove(i);
5157 i--;
5158 bringDownServiceLocked(sr, true);
5159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005161 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005162 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
5163 Log.w(TAG, "Unattached app died before backup, skipping");
5164 try {
5165 IBackupManager bm = IBackupManager.Stub.asInterface(
5166 ServiceManager.getService(Context.BACKUP_SERVICE));
5167 bm.agentDisconnected(app.info.packageName);
5168 } catch (RemoteException e) {
5169 // Can't happen; the backup manager is local
5170 }
5171 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005172 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
5173 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
5174 mPendingBroadcast = null;
5175 scheduleBroadcastsLocked();
5176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 } else {
5178 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
5179 }
5180 }
5181
5182 private final boolean attachApplicationLocked(IApplicationThread thread,
5183 int pid) {
5184
5185 // Find the application record that is being attached... either via
5186 // the pid if we are running in multiple processes, or just pull the
5187 // next app record if we are emulating process with anonymous threads.
5188 ProcessRecord app;
5189 if (pid != MY_PID && pid >= 0) {
5190 synchronized (mPidsSelfLocked) {
5191 app = mPidsSelfLocked.get(pid);
5192 }
5193 } else if (mStartingProcesses.size() > 0) {
5194 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005195 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 } else {
5197 app = null;
5198 }
5199
5200 if (app == null) {
5201 Log.w(TAG, "No pending application record for pid " + pid
5202 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005203 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 if (pid > 0 && pid != MY_PID) {
5205 Process.killProcess(pid);
5206 } else {
5207 try {
5208 thread.scheduleExit();
5209 } catch (Exception e) {
5210 // Ignore exceptions.
5211 }
5212 }
5213 return false;
5214 }
5215
5216 // If this application record is still attached to a previous
5217 // process, clean it up now.
5218 if (app.thread != null) {
5219 handleAppDiedLocked(app, true);
5220 }
5221
5222 // Tell the process all about itself.
5223
5224 if (localLOGV) Log.v(
5225 TAG, "Binding process pid " + pid + " to record " + app);
5226
5227 String processName = app.processName;
5228 try {
5229 thread.asBinder().linkToDeath(new AppDeathRecipient(
5230 app, pid, thread), 0);
5231 } catch (RemoteException e) {
5232 app.resetPackageList();
5233 startProcessLocked(app, "link fail", processName);
5234 return false;
5235 }
5236
Doug Zongker2bec3d42009-12-04 12:52:44 -08005237 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238
5239 app.thread = thread;
5240 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005241 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5242 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 app.forcingToForeground = null;
5244 app.foregroundServices = false;
5245 app.debugging = false;
5246
5247 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5248
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005249 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5250 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005252 if (!normalMode) {
5253 Log.i(TAG, "Launching preboot mode app: " + app);
5254 }
5255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 if (localLOGV) Log.v(
5257 TAG, "New app record " + app
5258 + " thread=" + thread.asBinder() + " pid=" + pid);
5259 try {
5260 int testMode = IApplicationThread.DEBUG_OFF;
5261 if (mDebugApp != null && mDebugApp.equals(processName)) {
5262 testMode = mWaitForDebugger
5263 ? IApplicationThread.DEBUG_WAIT
5264 : IApplicationThread.DEBUG_ON;
5265 app.debugging = true;
5266 if (mDebugTransient) {
5267 mDebugApp = mOrigDebugApp;
5268 mWaitForDebugger = mOrigWaitForDebugger;
5269 }
5270 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005271
Christopher Tate181fafa2009-05-14 11:12:14 -07005272 // If the app is being launched for restore or full backup, set it up specially
5273 boolean isRestrictedBackupMode = false;
5274 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5275 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5276 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5277 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005278
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005279 ensurePackageDexOpt(app.instrumentationInfo != null
5280 ? app.instrumentationInfo.packageName
5281 : app.info.packageName);
5282 if (app.instrumentationClass != null) {
5283 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005284 }
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005285 if (DEBUG_CONFIGURATION) Log.v(TAG, "Binding proc "
5286 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005287 thread.bindApplication(processName, app.instrumentationInfo != null
5288 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 app.instrumentationClass, app.instrumentationProfileFile,
5290 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005291 isRestrictedBackupMode || !normalMode,
5292 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005293 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005294 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 } catch (Exception e) {
5296 // todo: Yikes! What should we do? For now we will try to
5297 // start another process, but that could easily get us in
5298 // an infinite loop of restarting processes...
5299 Log.w(TAG, "Exception thrown during bind!", e);
5300
5301 app.resetPackageList();
5302 startProcessLocked(app, "bind fail", processName);
5303 return false;
5304 }
5305
5306 // Remove this record from the list of starting applications.
5307 mPersistentStartingProcesses.remove(app);
5308 mProcessesOnHold.remove(app);
5309
5310 boolean badApp = false;
5311 boolean didSomething = false;
5312
5313 // See if the top visible activity is waiting to run in this process...
5314 HistoryRecord hr = topRunningActivityLocked(null);
5315 if (hr != null) {
5316 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5317 && processName.equals(hr.processName)) {
5318 try {
5319 if (realStartActivityLocked(hr, app, true, true)) {
5320 didSomething = true;
5321 }
5322 } catch (Exception e) {
5323 Log.w(TAG, "Exception in new application when starting activity "
5324 + hr.intent.getComponent().flattenToShortString(), e);
5325 badApp = true;
5326 }
5327 } else {
5328 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5329 }
5330 }
5331
5332 // Find any services that should be running in this process...
5333 if (!badApp && mPendingServices.size() > 0) {
5334 ServiceRecord sr = null;
5335 try {
5336 for (int i=0; i<mPendingServices.size(); i++) {
5337 sr = mPendingServices.get(i);
5338 if (app.info.uid != sr.appInfo.uid
5339 || !processName.equals(sr.processName)) {
5340 continue;
5341 }
5342
5343 mPendingServices.remove(i);
5344 i--;
5345 realStartServiceLocked(sr, app);
5346 didSomething = true;
5347 }
5348 } catch (Exception e) {
5349 Log.w(TAG, "Exception in new application when starting service "
5350 + sr.shortName, e);
5351 badApp = true;
5352 }
5353 }
5354
5355 // Check if the next broadcast receiver is in this process...
5356 BroadcastRecord br = mPendingBroadcast;
5357 if (!badApp && br != null && br.curApp == app) {
5358 try {
5359 mPendingBroadcast = null;
5360 processCurBroadcastLocked(br, app);
5361 didSomething = true;
5362 } catch (Exception e) {
5363 Log.w(TAG, "Exception in new application when starting receiver "
5364 + br.curComponent.flattenToShortString(), e);
5365 badApp = true;
5366 logBroadcastReceiverDiscard(br);
5367 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5368 br.resultExtras, br.resultAbort, true);
5369 scheduleBroadcastsLocked();
5370 }
5371 }
5372
Christopher Tate181fafa2009-05-14 11:12:14 -07005373 // Check whether the next backup agent is in this process...
5374 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
5375 if (DEBUG_BACKUP) Log.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005376 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005377 try {
5378 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5379 } catch (Exception e) {
5380 Log.w(TAG, "Exception scheduling backup agent creation: ");
5381 e.printStackTrace();
5382 }
5383 }
5384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 if (badApp) {
5386 // todo: Also need to kill application to deal with all
5387 // kinds of exceptions.
5388 handleAppDiedLocked(app, false);
5389 return false;
5390 }
5391
5392 if (!didSomething) {
5393 updateOomAdjLocked();
5394 }
5395
5396 return true;
5397 }
5398
5399 public final void attachApplication(IApplicationThread thread) {
5400 synchronized (this) {
5401 int callingPid = Binder.getCallingPid();
5402 final long origId = Binder.clearCallingIdentity();
5403 attachApplicationLocked(thread, callingPid);
5404 Binder.restoreCallingIdentity(origId);
5405 }
5406 }
5407
Dianne Hackborne88846e2009-09-30 21:34:25 -07005408 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005410 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 Binder.restoreCallingIdentity(origId);
5412 }
5413
5414 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5415 boolean remove) {
5416 int N = mStoppingActivities.size();
5417 if (N <= 0) return null;
5418
5419 ArrayList<HistoryRecord> stops = null;
5420
5421 final boolean nowVisible = mResumedActivity != null
5422 && mResumedActivity.nowVisible
5423 && !mResumedActivity.waitingVisible;
5424 for (int i=0; i<N; i++) {
5425 HistoryRecord s = mStoppingActivities.get(i);
5426 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
5427 + nowVisible + " waitingVisible=" + s.waitingVisible
5428 + " finishing=" + s.finishing);
5429 if (s.waitingVisible && nowVisible) {
5430 mWaitingVisibleActivities.remove(s);
5431 s.waitingVisible = false;
5432 if (s.finishing) {
5433 // If this activity is finishing, it is sitting on top of
5434 // everyone else but we now know it is no longer needed...
5435 // so get rid of it. Otherwise, we need to go through the
5436 // normal flow and hide it once we determine that it is
5437 // hidden by the activities in front of it.
5438 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
5439 mWindowManager.setAppVisibility(s, false);
5440 }
5441 }
5442 if (!s.waitingVisible && remove) {
5443 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
5444 if (stops == null) {
5445 stops = new ArrayList<HistoryRecord>();
5446 }
5447 stops.add(s);
5448 mStoppingActivities.remove(i);
5449 N--;
5450 i--;
5451 }
5452 }
5453
5454 return stops;
5455 }
5456
5457 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005458 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005459 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 mWindowManager.enableScreenAfterBoot();
5461 }
5462
Dianne Hackborne88846e2009-09-30 21:34:25 -07005463 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5464 Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
5466
5467 ArrayList<HistoryRecord> stops = null;
5468 ArrayList<HistoryRecord> finishes = null;
5469 ArrayList<HistoryRecord> thumbnails = null;
5470 int NS = 0;
5471 int NF = 0;
5472 int NT = 0;
5473 IApplicationThread sendThumbnail = null;
5474 boolean booting = false;
5475 boolean enableScreen = false;
5476
5477 synchronized (this) {
5478 if (token != null) {
5479 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5480 }
5481
5482 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005483 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484 if (index >= 0) {
5485 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5486
Dianne Hackborne88846e2009-09-30 21:34:25 -07005487 // This is a hack to semi-deal with a race condition
5488 // in the client where it can be constructed with a
5489 // newer configuration from when we asked it to launch.
5490 // We'll update with whatever configuration it now says
5491 // it used to launch.
5492 if (config != null) {
5493 r.configuration = config;
5494 }
5495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 // No longer need to keep the device awake.
5497 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5498 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5499 mLaunchingActivity.release();
5500 }
5501
5502 // We are now idle. If someone is waiting for a thumbnail from
5503 // us, we can now deliver.
5504 r.idle = true;
5505 scheduleAppGcsLocked();
5506 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5507 sendThumbnail = r.app.thread;
5508 r.thumbnailNeeded = false;
5509 }
5510
5511 // If this activity is fullscreen, set up to hide those under it.
5512
5513 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
5514 ensureActivitiesVisibleLocked(null, 0);
5515
5516 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
5517 if (!mBooted && !fromTimeout) {
5518 mBooted = true;
5519 enableScreen = true;
5520 }
5521 }
5522
5523 // Atomically retrieve all of the other things to do.
5524 stops = processStoppingActivitiesLocked(true);
5525 NS = stops != null ? stops.size() : 0;
5526 if ((NF=mFinishingActivities.size()) > 0) {
5527 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5528 mFinishingActivities.clear();
5529 }
5530 if ((NT=mCancelledThumbnails.size()) > 0) {
5531 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5532 mCancelledThumbnails.clear();
5533 }
5534
5535 booting = mBooting;
5536 mBooting = false;
5537 }
5538
5539 int i;
5540
5541 // Send thumbnail if requested.
5542 if (sendThumbnail != null) {
5543 try {
5544 sendThumbnail.requestThumbnail(token);
5545 } catch (Exception e) {
5546 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5547 sendPendingThumbnail(null, token, null, null, true);
5548 }
5549 }
5550
5551 // Stop any activities that are scheduled to do so but have been
5552 // waiting for the next one to start.
5553 for (i=0; i<NS; i++) {
5554 HistoryRecord r = (HistoryRecord)stops.get(i);
5555 synchronized (this) {
5556 if (r.finishing) {
5557 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5558 } else {
5559 stopActivityLocked(r);
5560 }
5561 }
5562 }
5563
5564 // Finish any activities that are scheduled to do so but have been
5565 // waiting for the next one to start.
5566 for (i=0; i<NF; i++) {
5567 HistoryRecord r = (HistoryRecord)finishes.get(i);
5568 synchronized (this) {
5569 destroyActivityLocked(r, true);
5570 }
5571 }
5572
5573 // Report back to any thumbnail receivers.
5574 for (i=0; i<NT; i++) {
5575 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5576 sendPendingThumbnail(r, null, null, null, true);
5577 }
5578
5579 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005580 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 }
5582
5583 trimApplications();
5584 //dump();
5585 //mWindowManager.dump();
5586
5587 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 enableScreenAfterBoot();
5589 }
5590 }
5591
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005592 final void finishBooting() {
5593 // Ensure that any processes we had put on hold are now started
5594 // up.
5595 final int NP = mProcessesOnHold.size();
5596 if (NP > 0) {
5597 ArrayList<ProcessRecord> procs =
5598 new ArrayList<ProcessRecord>(mProcessesOnHold);
5599 for (int ip=0; ip<NP; ip++) {
5600 this.startProcessLocked(procs.get(ip), "on-hold", null);
5601 }
5602 }
5603 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5604 // Tell anyone interested that we are done booting!
5605 synchronized (this) {
5606 broadcastIntentLocked(null, null,
5607 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5608 null, null, 0, null, null,
5609 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5610 false, false, MY_PID, Process.SYSTEM_UID);
5611 }
5612 }
5613 }
5614
5615 final void ensureBootCompleted() {
5616 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005617 boolean enableScreen;
5618 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005619 booting = mBooting;
5620 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005621 enableScreen = !mBooted;
5622 mBooted = true;
5623 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005624
5625 if (booting) {
5626 finishBooting();
5627 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005628
5629 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005630 enableScreenAfterBoot();
5631 }
5632 }
5633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 public final void activityPaused(IBinder token, Bundle icicle) {
5635 // Refuse possible leaked file descriptors
5636 if (icicle != null && icicle.hasFileDescriptors()) {
5637 throw new IllegalArgumentException("File descriptors passed in Bundle");
5638 }
5639
5640 final long origId = Binder.clearCallingIdentity();
5641 activityPaused(token, icicle, false);
5642 Binder.restoreCallingIdentity(origId);
5643 }
5644
5645 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
5646 if (DEBUG_PAUSE) Log.v(
5647 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5648 + ", timeout=" + timeout);
5649
5650 HistoryRecord r = null;
5651
5652 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005653 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 if (index >= 0) {
5655 r = (HistoryRecord)mHistory.get(index);
5656 if (!timeout) {
5657 r.icicle = icicle;
5658 r.haveState = true;
5659 }
5660 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5661 if (mPausingActivity == r) {
5662 r.state = ActivityState.PAUSED;
5663 completePauseLocked();
5664 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005665 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 System.identityHashCode(r), r.shortComponentName,
5667 mPausingActivity != null
5668 ? mPausingActivity.shortComponentName : "(none)");
5669 }
5670 }
5671 }
5672 }
5673
5674 public final void activityStopped(IBinder token, Bitmap thumbnail,
5675 CharSequence description) {
5676 if (localLOGV) Log.v(
5677 TAG, "Activity stopped: token=" + token);
5678
5679 HistoryRecord r = null;
5680
5681 final long origId = Binder.clearCallingIdentity();
5682
5683 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005684 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 if (index >= 0) {
5686 r = (HistoryRecord)mHistory.get(index);
5687 r.thumbnail = thumbnail;
5688 r.description = description;
5689 r.stopped = true;
5690 r.state = ActivityState.STOPPED;
5691 if (!r.finishing) {
5692 if (r.configDestroy) {
5693 destroyActivityLocked(r, true);
5694 resumeTopActivityLocked(null);
5695 }
5696 }
5697 }
5698 }
5699
5700 if (r != null) {
5701 sendPendingThumbnail(r, null, null, null, false);
5702 }
5703
5704 trimApplications();
5705
5706 Binder.restoreCallingIdentity(origId);
5707 }
5708
5709 public final void activityDestroyed(IBinder token) {
5710 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
5711 synchronized (this) {
5712 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5713
Dianne Hackborn75b03852009-06-12 15:43:26 -07005714 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 if (index >= 0) {
5716 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5717 if (r.state == ActivityState.DESTROYING) {
5718 final long origId = Binder.clearCallingIdentity();
5719 removeActivityFromHistoryLocked(r);
5720 Binder.restoreCallingIdentity(origId);
5721 }
5722 }
5723 }
5724 }
5725
5726 public String getCallingPackage(IBinder token) {
5727 synchronized (this) {
5728 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005729 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 }
5731 }
5732
5733 public ComponentName getCallingActivity(IBinder token) {
5734 synchronized (this) {
5735 HistoryRecord r = getCallingRecordLocked(token);
5736 return r != null ? r.intent.getComponent() : null;
5737 }
5738 }
5739
5740 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005741 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005742 if (index >= 0) {
5743 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5744 if (r != null) {
5745 return r.resultTo;
5746 }
5747 }
5748 return null;
5749 }
5750
5751 public ComponentName getActivityClassForToken(IBinder token) {
5752 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005753 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 if (index >= 0) {
5755 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5756 return r.intent.getComponent();
5757 }
5758 return null;
5759 }
5760 }
5761
5762 public String getPackageForToken(IBinder token) {
5763 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005764 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 if (index >= 0) {
5766 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5767 return r.packageName;
5768 }
5769 return null;
5770 }
5771 }
5772
5773 public IIntentSender getIntentSender(int type,
5774 String packageName, IBinder token, String resultWho,
5775 int requestCode, Intent intent, String resolvedType, int flags) {
5776 // Refuse possible leaked file descriptors
5777 if (intent != null && intent.hasFileDescriptors() == true) {
5778 throw new IllegalArgumentException("File descriptors passed in Intent");
5779 }
5780
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005781 if (type == INTENT_SENDER_BROADCAST) {
5782 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5783 throw new IllegalArgumentException(
5784 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5785 }
5786 }
5787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 synchronized(this) {
5789 int callingUid = Binder.getCallingUid();
5790 try {
5791 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5792 Process.supportsProcesses()) {
5793 int uid = ActivityThread.getPackageManager()
5794 .getPackageUid(packageName);
5795 if (uid != Binder.getCallingUid()) {
5796 String msg = "Permission Denial: getIntentSender() from pid="
5797 + Binder.getCallingPid()
5798 + ", uid=" + Binder.getCallingUid()
5799 + ", (need uid=" + uid + ")"
5800 + " is not allowed to send as package " + packageName;
5801 Log.w(TAG, msg);
5802 throw new SecurityException(msg);
5803 }
5804 }
5805 } catch (RemoteException e) {
5806 throw new SecurityException(e);
5807 }
5808 HistoryRecord activity = null;
5809 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005810 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 if (index < 0) {
5812 return null;
5813 }
5814 activity = (HistoryRecord)mHistory.get(index);
5815 if (activity.finishing) {
5816 return null;
5817 }
5818 }
5819
5820 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5821 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5822 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5823 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5824 |PendingIntent.FLAG_UPDATE_CURRENT);
5825
5826 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5827 type, packageName, activity, resultWho,
5828 requestCode, intent, resolvedType, flags);
5829 WeakReference<PendingIntentRecord> ref;
5830 ref = mIntentSenderRecords.get(key);
5831 PendingIntentRecord rec = ref != null ? ref.get() : null;
5832 if (rec != null) {
5833 if (!cancelCurrent) {
5834 if (updateCurrent) {
5835 rec.key.requestIntent.replaceExtras(intent);
5836 }
5837 return rec;
5838 }
5839 rec.canceled = true;
5840 mIntentSenderRecords.remove(key);
5841 }
5842 if (noCreate) {
5843 return rec;
5844 }
5845 rec = new PendingIntentRecord(this, key, callingUid);
5846 mIntentSenderRecords.put(key, rec.ref);
5847 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5848 if (activity.pendingResults == null) {
5849 activity.pendingResults
5850 = new HashSet<WeakReference<PendingIntentRecord>>();
5851 }
5852 activity.pendingResults.add(rec.ref);
5853 }
5854 return rec;
5855 }
5856 }
5857
5858 public void cancelIntentSender(IIntentSender sender) {
5859 if (!(sender instanceof PendingIntentRecord)) {
5860 return;
5861 }
5862 synchronized(this) {
5863 PendingIntentRecord rec = (PendingIntentRecord)sender;
5864 try {
5865 int uid = ActivityThread.getPackageManager()
5866 .getPackageUid(rec.key.packageName);
5867 if (uid != Binder.getCallingUid()) {
5868 String msg = "Permission Denial: cancelIntentSender() from pid="
5869 + Binder.getCallingPid()
5870 + ", uid=" + Binder.getCallingUid()
5871 + " is not allowed to cancel packges "
5872 + rec.key.packageName;
5873 Log.w(TAG, msg);
5874 throw new SecurityException(msg);
5875 }
5876 } catch (RemoteException e) {
5877 throw new SecurityException(e);
5878 }
5879 cancelIntentSenderLocked(rec, true);
5880 }
5881 }
5882
5883 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5884 rec.canceled = true;
5885 mIntentSenderRecords.remove(rec.key);
5886 if (cleanActivity && rec.key.activity != null) {
5887 rec.key.activity.pendingResults.remove(rec.ref);
5888 }
5889 }
5890
5891 public String getPackageForIntentSender(IIntentSender pendingResult) {
5892 if (!(pendingResult instanceof PendingIntentRecord)) {
5893 return null;
5894 }
5895 synchronized(this) {
5896 try {
5897 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5898 return res.key.packageName;
5899 } catch (ClassCastException e) {
5900 }
5901 }
5902 return null;
5903 }
5904
5905 public void setProcessLimit(int max) {
5906 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5907 "setProcessLimit()");
5908 mProcessLimit = max;
5909 }
5910
5911 public int getProcessLimit() {
5912 return mProcessLimit;
5913 }
5914
5915 void foregroundTokenDied(ForegroundToken token) {
5916 synchronized (ActivityManagerService.this) {
5917 synchronized (mPidsSelfLocked) {
5918 ForegroundToken cur
5919 = mForegroundProcesses.get(token.pid);
5920 if (cur != token) {
5921 return;
5922 }
5923 mForegroundProcesses.remove(token.pid);
5924 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5925 if (pr == null) {
5926 return;
5927 }
5928 pr.forcingToForeground = null;
5929 pr.foregroundServices = false;
5930 }
5931 updateOomAdjLocked();
5932 }
5933 }
5934
5935 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5936 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5937 "setProcessForeground()");
5938 synchronized(this) {
5939 boolean changed = false;
5940
5941 synchronized (mPidsSelfLocked) {
5942 ProcessRecord pr = mPidsSelfLocked.get(pid);
5943 if (pr == null) {
5944 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5945 return;
5946 }
5947 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5948 if (oldToken != null) {
5949 oldToken.token.unlinkToDeath(oldToken, 0);
5950 mForegroundProcesses.remove(pid);
5951 pr.forcingToForeground = null;
5952 changed = true;
5953 }
5954 if (isForeground && token != null) {
5955 ForegroundToken newToken = new ForegroundToken() {
5956 public void binderDied() {
5957 foregroundTokenDied(this);
5958 }
5959 };
5960 newToken.pid = pid;
5961 newToken.token = token;
5962 try {
5963 token.linkToDeath(newToken, 0);
5964 mForegroundProcesses.put(pid, newToken);
5965 pr.forcingToForeground = token;
5966 changed = true;
5967 } catch (RemoteException e) {
5968 // If the process died while doing this, we will later
5969 // do the cleanup with the process death link.
5970 }
5971 }
5972 }
5973
5974 if (changed) {
5975 updateOomAdjLocked();
5976 }
5977 }
5978 }
5979
5980 // =========================================================
5981 // PERMISSIONS
5982 // =========================================================
5983
5984 static class PermissionController extends IPermissionController.Stub {
5985 ActivityManagerService mActivityManagerService;
5986 PermissionController(ActivityManagerService activityManagerService) {
5987 mActivityManagerService = activityManagerService;
5988 }
5989
5990 public boolean checkPermission(String permission, int pid, int uid) {
5991 return mActivityManagerService.checkPermission(permission, pid,
5992 uid) == PackageManager.PERMISSION_GRANTED;
5993 }
5994 }
5995
5996 /**
5997 * This can be called with or without the global lock held.
5998 */
5999 int checkComponentPermission(String permission, int pid, int uid,
6000 int reqUid) {
6001 // We might be performing an operation on behalf of an indirect binder
6002 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6003 // client identity accordingly before proceeding.
6004 Identity tlsIdentity = sCallerIdentity.get();
6005 if (tlsIdentity != null) {
6006 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
6007 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6008 uid = tlsIdentity.uid;
6009 pid = tlsIdentity.pid;
6010 }
6011
6012 // Root, system server and our own process get to do everything.
6013 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6014 !Process.supportsProcesses()) {
6015 return PackageManager.PERMISSION_GRANTED;
6016 }
6017 // If the target requires a specific UID, always fail for others.
6018 if (reqUid >= 0 && uid != reqUid) {
root0369a7c2009-03-23 15:20:47 +01006019 Log.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 return PackageManager.PERMISSION_DENIED;
6021 }
6022 if (permission == null) {
6023 return PackageManager.PERMISSION_GRANTED;
6024 }
6025 try {
6026 return ActivityThread.getPackageManager()
6027 .checkUidPermission(permission, uid);
6028 } catch (RemoteException e) {
6029 // Should never happen, but if it does... deny!
6030 Log.e(TAG, "PackageManager is dead?!?", e);
6031 }
6032 return PackageManager.PERMISSION_DENIED;
6033 }
6034
6035 /**
6036 * As the only public entry point for permissions checking, this method
6037 * can enforce the semantic that requesting a check on a null global
6038 * permission is automatically denied. (Internally a null permission
6039 * string is used when calling {@link #checkComponentPermission} in cases
6040 * when only uid-based security is needed.)
6041 *
6042 * This can be called with or without the global lock held.
6043 */
6044 public int checkPermission(String permission, int pid, int uid) {
6045 if (permission == null) {
6046 return PackageManager.PERMISSION_DENIED;
6047 }
6048 return checkComponentPermission(permission, pid, uid, -1);
6049 }
6050
6051 /**
6052 * Binder IPC calls go through the public entry point.
6053 * This can be called with or without the global lock held.
6054 */
6055 int checkCallingPermission(String permission) {
6056 return checkPermission(permission,
6057 Binder.getCallingPid(),
6058 Binder.getCallingUid());
6059 }
6060
6061 /**
6062 * This can be called with or without the global lock held.
6063 */
6064 void enforceCallingPermission(String permission, String func) {
6065 if (checkCallingPermission(permission)
6066 == PackageManager.PERMISSION_GRANTED) {
6067 return;
6068 }
6069
6070 String msg = "Permission Denial: " + func + " from pid="
6071 + Binder.getCallingPid()
6072 + ", uid=" + Binder.getCallingUid()
6073 + " requires " + permission;
6074 Log.w(TAG, msg);
6075 throw new SecurityException(msg);
6076 }
6077
6078 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6079 ProviderInfo pi, int uid, int modeFlags) {
6080 try {
6081 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6082 if ((pi.readPermission != null) &&
6083 (pm.checkUidPermission(pi.readPermission, uid)
6084 != PackageManager.PERMISSION_GRANTED)) {
6085 return false;
6086 }
6087 }
6088 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6089 if ((pi.writePermission != null) &&
6090 (pm.checkUidPermission(pi.writePermission, uid)
6091 != PackageManager.PERMISSION_GRANTED)) {
6092 return false;
6093 }
6094 }
6095 return true;
6096 } catch (RemoteException e) {
6097 return false;
6098 }
6099 }
6100
6101 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6102 int modeFlags) {
6103 // Root gets to do everything.
6104 if (uid == 0 || !Process.supportsProcesses()) {
6105 return true;
6106 }
6107 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6108 if (perms == null) return false;
6109 UriPermission perm = perms.get(uri);
6110 if (perm == null) return false;
6111 return (modeFlags&perm.modeFlags) == modeFlags;
6112 }
6113
6114 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6115 // Another redirected-binder-call permissions check as in
6116 // {@link checkComponentPermission}.
6117 Identity tlsIdentity = sCallerIdentity.get();
6118 if (tlsIdentity != null) {
6119 uid = tlsIdentity.uid;
6120 pid = tlsIdentity.pid;
6121 }
6122
6123 // Our own process gets to do everything.
6124 if (pid == MY_PID) {
6125 return PackageManager.PERMISSION_GRANTED;
6126 }
6127 synchronized(this) {
6128 return checkUriPermissionLocked(uri, uid, modeFlags)
6129 ? PackageManager.PERMISSION_GRANTED
6130 : PackageManager.PERMISSION_DENIED;
6131 }
6132 }
6133
6134 private void grantUriPermissionLocked(int callingUid,
6135 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6136 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6137 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6138 if (modeFlags == 0) {
6139 return;
6140 }
6141
6142 final IPackageManager pm = ActivityThread.getPackageManager();
6143
6144 // If this is not a content: uri, we can't do anything with it.
6145 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
6146 return;
6147 }
6148
6149 String name = uri.getAuthority();
6150 ProviderInfo pi = null;
6151 ContentProviderRecord cpr
6152 = (ContentProviderRecord)mProvidersByName.get(name);
6153 if (cpr != null) {
6154 pi = cpr.info;
6155 } else {
6156 try {
6157 pi = pm.resolveContentProvider(name,
6158 PackageManager.GET_URI_PERMISSION_PATTERNS);
6159 } catch (RemoteException ex) {
6160 }
6161 }
6162 if (pi == null) {
6163 Log.w(TAG, "No content provider found for: " + name);
6164 return;
6165 }
6166
6167 int targetUid;
6168 try {
6169 targetUid = pm.getPackageUid(targetPkg);
6170 if (targetUid < 0) {
6171 return;
6172 }
6173 } catch (RemoteException ex) {
6174 return;
6175 }
6176
6177 // First... does the target actually need this permission?
6178 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6179 // No need to grant the target this permission.
6180 return;
6181 }
6182
6183 // Second... maybe someone else has already granted the
6184 // permission?
6185 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
6186 // No need to grant the target this permission.
6187 return;
6188 }
6189
6190 // Third... is the provider allowing granting of URI permissions?
6191 if (!pi.grantUriPermissions) {
6192 throw new SecurityException("Provider " + pi.packageName
6193 + "/" + pi.name
6194 + " does not allow granting of Uri permissions (uri "
6195 + uri + ")");
6196 }
6197 if (pi.uriPermissionPatterns != null) {
6198 final int N = pi.uriPermissionPatterns.length;
6199 boolean allowed = false;
6200 for (int i=0; i<N; i++) {
6201 if (pi.uriPermissionPatterns[i] != null
6202 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6203 allowed = true;
6204 break;
6205 }
6206 }
6207 if (!allowed) {
6208 throw new SecurityException("Provider " + pi.packageName
6209 + "/" + pi.name
6210 + " does not allow granting of permission to path of Uri "
6211 + uri);
6212 }
6213 }
6214
6215 // Fourth... does the caller itself have permission to access
6216 // this uri?
6217 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6218 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6219 throw new SecurityException("Uid " + callingUid
6220 + " does not have permission to uri " + uri);
6221 }
6222 }
6223
6224 // Okay! So here we are: the caller has the assumed permission
6225 // to the uri, and the target doesn't. Let's now give this to
6226 // the target.
6227
6228 HashMap<Uri, UriPermission> targetUris
6229 = mGrantedUriPermissions.get(targetUid);
6230 if (targetUris == null) {
6231 targetUris = new HashMap<Uri, UriPermission>();
6232 mGrantedUriPermissions.put(targetUid, targetUris);
6233 }
6234
6235 UriPermission perm = targetUris.get(uri);
6236 if (perm == null) {
6237 perm = new UriPermission(targetUid, uri);
6238 targetUris.put(uri, perm);
6239
6240 }
6241 perm.modeFlags |= modeFlags;
6242 if (activity == null) {
6243 perm.globalModeFlags |= modeFlags;
6244 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6245 perm.readActivities.add(activity);
6246 if (activity.readUriPermissions == null) {
6247 activity.readUriPermissions = new HashSet<UriPermission>();
6248 }
6249 activity.readUriPermissions.add(perm);
6250 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6251 perm.writeActivities.add(activity);
6252 if (activity.writeUriPermissions == null) {
6253 activity.writeUriPermissions = new HashSet<UriPermission>();
6254 }
6255 activity.writeUriPermissions.add(perm);
6256 }
6257 }
6258
6259 private void grantUriPermissionFromIntentLocked(int callingUid,
6260 String targetPkg, Intent intent, HistoryRecord activity) {
6261 if (intent == null) {
6262 return;
6263 }
6264 Uri data = intent.getData();
6265 if (data == null) {
6266 return;
6267 }
6268 grantUriPermissionLocked(callingUid, targetPkg, data,
6269 intent.getFlags(), activity);
6270 }
6271
6272 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6273 Uri uri, int modeFlags) {
6274 synchronized(this) {
6275 final ProcessRecord r = getRecordForAppLocked(caller);
6276 if (r == null) {
6277 throw new SecurityException("Unable to find app for caller "
6278 + caller
6279 + " when granting permission to uri " + uri);
6280 }
6281 if (targetPkg == null) {
6282 Log.w(TAG, "grantUriPermission: null target");
6283 return;
6284 }
6285 if (uri == null) {
6286 Log.w(TAG, "grantUriPermission: null uri");
6287 return;
6288 }
6289
6290 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6291 null);
6292 }
6293 }
6294
6295 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6296 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6297 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6298 HashMap<Uri, UriPermission> perms
6299 = mGrantedUriPermissions.get(perm.uid);
6300 if (perms != null) {
6301 perms.remove(perm.uri);
6302 if (perms.size() == 0) {
6303 mGrantedUriPermissions.remove(perm.uid);
6304 }
6305 }
6306 }
6307 }
6308
6309 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6310 if (activity.readUriPermissions != null) {
6311 for (UriPermission perm : activity.readUriPermissions) {
6312 perm.readActivities.remove(activity);
6313 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6314 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6315 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6316 removeUriPermissionIfNeededLocked(perm);
6317 }
6318 }
6319 }
6320 if (activity.writeUriPermissions != null) {
6321 for (UriPermission perm : activity.writeUriPermissions) {
6322 perm.writeActivities.remove(activity);
6323 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6324 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6325 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6326 removeUriPermissionIfNeededLocked(perm);
6327 }
6328 }
6329 }
6330 }
6331
6332 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6333 int modeFlags) {
6334 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6335 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6336 if (modeFlags == 0) {
6337 return;
6338 }
6339
6340 final IPackageManager pm = ActivityThread.getPackageManager();
6341
6342 final String authority = uri.getAuthority();
6343 ProviderInfo pi = null;
6344 ContentProviderRecord cpr
6345 = (ContentProviderRecord)mProvidersByName.get(authority);
6346 if (cpr != null) {
6347 pi = cpr.info;
6348 } else {
6349 try {
6350 pi = pm.resolveContentProvider(authority,
6351 PackageManager.GET_URI_PERMISSION_PATTERNS);
6352 } catch (RemoteException ex) {
6353 }
6354 }
6355 if (pi == null) {
6356 Log.w(TAG, "No content provider found for: " + authority);
6357 return;
6358 }
6359
6360 // Does the caller have this permission on the URI?
6361 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6362 // Right now, if you are not the original owner of the permission,
6363 // you are not allowed to revoke it.
6364 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6365 throw new SecurityException("Uid " + callingUid
6366 + " does not have permission to uri " + uri);
6367 //}
6368 }
6369
6370 // Go through all of the permissions and remove any that match.
6371 final List<String> SEGMENTS = uri.getPathSegments();
6372 if (SEGMENTS != null) {
6373 final int NS = SEGMENTS.size();
6374 int N = mGrantedUriPermissions.size();
6375 for (int i=0; i<N; i++) {
6376 HashMap<Uri, UriPermission> perms
6377 = mGrantedUriPermissions.valueAt(i);
6378 Iterator<UriPermission> it = perms.values().iterator();
6379 toploop:
6380 while (it.hasNext()) {
6381 UriPermission perm = it.next();
6382 Uri targetUri = perm.uri;
6383 if (!authority.equals(targetUri.getAuthority())) {
6384 continue;
6385 }
6386 List<String> targetSegments = targetUri.getPathSegments();
6387 if (targetSegments == null) {
6388 continue;
6389 }
6390 if (targetSegments.size() < NS) {
6391 continue;
6392 }
6393 for (int j=0; j<NS; j++) {
6394 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6395 continue toploop;
6396 }
6397 }
6398 perm.clearModes(modeFlags);
6399 if (perm.modeFlags == 0) {
6400 it.remove();
6401 }
6402 }
6403 if (perms.size() == 0) {
6404 mGrantedUriPermissions.remove(
6405 mGrantedUriPermissions.keyAt(i));
6406 N--;
6407 i--;
6408 }
6409 }
6410 }
6411 }
6412
6413 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6414 int modeFlags) {
6415 synchronized(this) {
6416 final ProcessRecord r = getRecordForAppLocked(caller);
6417 if (r == null) {
6418 throw new SecurityException("Unable to find app for caller "
6419 + caller
6420 + " when revoking permission to uri " + uri);
6421 }
6422 if (uri == null) {
6423 Log.w(TAG, "revokeUriPermission: null uri");
6424 return;
6425 }
6426
6427 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6428 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6429 if (modeFlags == 0) {
6430 return;
6431 }
6432
6433 final IPackageManager pm = ActivityThread.getPackageManager();
6434
6435 final String authority = uri.getAuthority();
6436 ProviderInfo pi = null;
6437 ContentProviderRecord cpr
6438 = (ContentProviderRecord)mProvidersByName.get(authority);
6439 if (cpr != null) {
6440 pi = cpr.info;
6441 } else {
6442 try {
6443 pi = pm.resolveContentProvider(authority,
6444 PackageManager.GET_URI_PERMISSION_PATTERNS);
6445 } catch (RemoteException ex) {
6446 }
6447 }
6448 if (pi == null) {
6449 Log.w(TAG, "No content provider found for: " + authority);
6450 return;
6451 }
6452
6453 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6454 }
6455 }
6456
6457 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6458 synchronized (this) {
6459 ProcessRecord app =
6460 who != null ? getRecordForAppLocked(who) : null;
6461 if (app == null) return;
6462
6463 Message msg = Message.obtain();
6464 msg.what = WAIT_FOR_DEBUGGER_MSG;
6465 msg.obj = app;
6466 msg.arg1 = waiting ? 1 : 0;
6467 mHandler.sendMessage(msg);
6468 }
6469 }
6470
6471 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6472 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006473 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006474 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006475 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 }
6477
6478 // =========================================================
6479 // TASK MANAGEMENT
6480 // =========================================================
6481
6482 public List getTasks(int maxNum, int flags,
6483 IThumbnailReceiver receiver) {
6484 ArrayList list = new ArrayList();
6485
6486 PendingThumbnailsRecord pending = null;
6487 IApplicationThread topThumbnail = null;
6488 HistoryRecord topRecord = null;
6489
6490 synchronized(this) {
6491 if (localLOGV) Log.v(
6492 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6493 + ", receiver=" + receiver);
6494
6495 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6496 != PackageManager.PERMISSION_GRANTED) {
6497 if (receiver != null) {
6498 // If the caller wants to wait for pending thumbnails,
6499 // it ain't gonna get them.
6500 try {
6501 receiver.finished();
6502 } catch (RemoteException ex) {
6503 }
6504 }
6505 String msg = "Permission Denial: getTasks() from pid="
6506 + Binder.getCallingPid()
6507 + ", uid=" + Binder.getCallingUid()
6508 + " requires " + android.Manifest.permission.GET_TASKS;
6509 Log.w(TAG, msg);
6510 throw new SecurityException(msg);
6511 }
6512
6513 int pos = mHistory.size()-1;
6514 HistoryRecord next =
6515 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6516 HistoryRecord top = null;
6517 CharSequence topDescription = null;
6518 TaskRecord curTask = null;
6519 int numActivities = 0;
6520 int numRunning = 0;
6521 while (pos >= 0 && maxNum > 0) {
6522 final HistoryRecord r = next;
6523 pos--;
6524 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6525
6526 // Initialize state for next task if needed.
6527 if (top == null ||
6528 (top.state == ActivityState.INITIALIZING
6529 && top.task == r.task)) {
6530 top = r;
6531 topDescription = r.description;
6532 curTask = r.task;
6533 numActivities = numRunning = 0;
6534 }
6535
6536 // Add 'r' into the current task.
6537 numActivities++;
6538 if (r.app != null && r.app.thread != null) {
6539 numRunning++;
6540 }
6541 if (topDescription == null) {
6542 topDescription = r.description;
6543 }
6544
6545 if (localLOGV) Log.v(
6546 TAG, r.intent.getComponent().flattenToShortString()
6547 + ": task=" + r.task);
6548
6549 // If the next one is a different task, generate a new
6550 // TaskInfo entry for what we have.
6551 if (next == null || next.task != curTask) {
6552 ActivityManager.RunningTaskInfo ci
6553 = new ActivityManager.RunningTaskInfo();
6554 ci.id = curTask.taskId;
6555 ci.baseActivity = r.intent.getComponent();
6556 ci.topActivity = top.intent.getComponent();
6557 ci.thumbnail = top.thumbnail;
6558 ci.description = topDescription;
6559 ci.numActivities = numActivities;
6560 ci.numRunning = numRunning;
6561 //System.out.println(
6562 // "#" + maxNum + ": " + " descr=" + ci.description);
6563 if (ci.thumbnail == null && receiver != null) {
6564 if (localLOGV) Log.v(
6565 TAG, "State=" + top.state + "Idle=" + top.idle
6566 + " app=" + top.app
6567 + " thr=" + (top.app != null ? top.app.thread : null));
6568 if (top.state == ActivityState.RESUMED
6569 || top.state == ActivityState.PAUSING) {
6570 if (top.idle && top.app != null
6571 && top.app.thread != null) {
6572 topRecord = top;
6573 topThumbnail = top.app.thread;
6574 } else {
6575 top.thumbnailNeeded = true;
6576 }
6577 }
6578 if (pending == null) {
6579 pending = new PendingThumbnailsRecord(receiver);
6580 }
6581 pending.pendingRecords.add(top);
6582 }
6583 list.add(ci);
6584 maxNum--;
6585 top = null;
6586 }
6587 }
6588
6589 if (pending != null) {
6590 mPendingThumbnails.add(pending);
6591 }
6592 }
6593
6594 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
6595
6596 if (topThumbnail != null) {
6597 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
6598 try {
6599 topThumbnail.requestThumbnail(topRecord);
6600 } catch (Exception e) {
6601 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
6602 sendPendingThumbnail(null, topRecord, null, null, true);
6603 }
6604 }
6605
6606 if (pending == null && receiver != null) {
6607 // In this case all thumbnails were available and the client
6608 // is being asked to be told when the remaining ones come in...
6609 // which is unusually, since the top-most currently running
6610 // activity should never have a canned thumbnail! Oh well.
6611 try {
6612 receiver.finished();
6613 } catch (RemoteException ex) {
6614 }
6615 }
6616
6617 return list;
6618 }
6619
6620 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6621 int flags) {
6622 synchronized (this) {
6623 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6624 "getRecentTasks()");
6625
6626 final int N = mRecentTasks.size();
6627 ArrayList<ActivityManager.RecentTaskInfo> res
6628 = new ArrayList<ActivityManager.RecentTaskInfo>(
6629 maxNum < N ? maxNum : N);
6630 for (int i=0; i<N && maxNum > 0; i++) {
6631 TaskRecord tr = mRecentTasks.get(i);
6632 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6633 || (tr.intent == null)
6634 || ((tr.intent.getFlags()
6635 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6636 ActivityManager.RecentTaskInfo rti
6637 = new ActivityManager.RecentTaskInfo();
6638 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6639 rti.baseIntent = new Intent(
6640 tr.intent != null ? tr.intent : tr.affinityIntent);
6641 rti.origActivity = tr.origActivity;
6642 res.add(rti);
6643 maxNum--;
6644 }
6645 }
6646 return res;
6647 }
6648 }
6649
6650 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6651 int j;
6652 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6653 TaskRecord jt = startTask;
6654
6655 // First look backwards
6656 for (j=startIndex-1; j>=0; j--) {
6657 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6658 if (r.task != jt) {
6659 jt = r.task;
6660 if (affinity.equals(jt.affinity)) {
6661 return j;
6662 }
6663 }
6664 }
6665
6666 // Now look forwards
6667 final int N = mHistory.size();
6668 jt = startTask;
6669 for (j=startIndex+1; j<N; j++) {
6670 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6671 if (r.task != jt) {
6672 if (affinity.equals(jt.affinity)) {
6673 return j;
6674 }
6675 jt = r.task;
6676 }
6677 }
6678
6679 // Might it be at the top?
6680 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6681 return N-1;
6682 }
6683
6684 return -1;
6685 }
6686
6687 /**
6688 * Perform a reset of the given task, if needed as part of launching it.
6689 * Returns the new HistoryRecord at the top of the task.
6690 */
6691 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6692 HistoryRecord newActivity) {
6693 boolean forceReset = (newActivity.info.flags
6694 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6695 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6696 if ((newActivity.info.flags
6697 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6698 forceReset = true;
6699 }
6700 }
6701
6702 final TaskRecord task = taskTop.task;
6703
6704 // We are going to move through the history list so that we can look
6705 // at each activity 'target' with 'below' either the interesting
6706 // activity immediately below it in the stack or null.
6707 HistoryRecord target = null;
6708 int targetI = 0;
6709 int taskTopI = -1;
6710 int replyChainEnd = -1;
6711 int lastReparentPos = -1;
6712 for (int i=mHistory.size()-1; i>=-1; i--) {
6713 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6714
6715 if (below != null && below.finishing) {
6716 continue;
6717 }
6718 if (target == null) {
6719 target = below;
6720 targetI = i;
6721 // If we were in the middle of a reply chain before this
6722 // task, it doesn't appear like the root of the chain wants
6723 // anything interesting, so drop it.
6724 replyChainEnd = -1;
6725 continue;
6726 }
6727
6728 final int flags = target.info.flags;
6729
6730 final boolean finishOnTaskLaunch =
6731 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6732 final boolean allowTaskReparenting =
6733 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6734
6735 if (target.task == task) {
6736 // We are inside of the task being reset... we'll either
6737 // finish this activity, push it out for another task,
6738 // or leave it as-is. We only do this
6739 // for activities that are not the root of the task (since
6740 // if we finish the root, we may no longer have the task!).
6741 if (taskTopI < 0) {
6742 taskTopI = targetI;
6743 }
6744 if (below != null && below.task == task) {
6745 final boolean clearWhenTaskReset =
6746 (target.intent.getFlags()
6747 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006748 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 // If this activity is sending a reply to a previous
6750 // activity, we can't do anything with it now until
6751 // we reach the start of the reply chain.
6752 // XXX note that we are assuming the result is always
6753 // to the previous activity, which is almost always
6754 // the case but we really shouldn't count on.
6755 if (replyChainEnd < 0) {
6756 replyChainEnd = targetI;
6757 }
Ed Heyl73798232009-03-24 21:32:21 -07006758 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006759 && target.taskAffinity != null
6760 && !target.taskAffinity.equals(task.affinity)) {
6761 // If this activity has an affinity for another
6762 // task, then we need to move it out of here. We will
6763 // move it as far out of the way as possible, to the
6764 // bottom of the activity stack. This also keeps it
6765 // correctly ordered with any activities we previously
6766 // moved.
6767 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6768 if (target.taskAffinity != null
6769 && target.taskAffinity.equals(p.task.affinity)) {
6770 // If the activity currently at the bottom has the
6771 // same task affinity as the one we are moving,
6772 // then merge it into the same task.
6773 target.task = p.task;
6774 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6775 + " out to bottom task " + p.task);
6776 } else {
6777 mCurTask++;
6778 if (mCurTask <= 0) {
6779 mCurTask = 1;
6780 }
6781 target.task = new TaskRecord(mCurTask, target.info, null,
6782 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6783 target.task.affinityIntent = target.intent;
6784 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6785 + " out to new task " + target.task);
6786 }
6787 mWindowManager.setAppGroupId(target, task.taskId);
6788 if (replyChainEnd < 0) {
6789 replyChainEnd = targetI;
6790 }
6791 int dstPos = 0;
6792 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6793 p = (HistoryRecord)mHistory.get(srcPos);
6794 if (p.finishing) {
6795 continue;
6796 }
6797 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6798 + " out to target's task " + target.task);
6799 task.numActivities--;
6800 p.task = target.task;
6801 target.task.numActivities++;
6802 mHistory.remove(srcPos);
6803 mHistory.add(dstPos, p);
6804 mWindowManager.moveAppToken(dstPos, p);
6805 mWindowManager.setAppGroupId(p, p.task.taskId);
6806 dstPos++;
6807 if (VALIDATE_TOKENS) {
6808 mWindowManager.validateAppTokens(mHistory);
6809 }
6810 i++;
6811 }
6812 if (taskTop == p) {
6813 taskTop = below;
6814 }
6815 if (taskTopI == replyChainEnd) {
6816 taskTopI = -1;
6817 }
6818 replyChainEnd = -1;
6819 addRecentTask(target.task);
6820 } else if (forceReset || finishOnTaskLaunch
6821 || clearWhenTaskReset) {
6822 // If the activity should just be removed -- either
6823 // because it asks for it, or the task should be
6824 // cleared -- then finish it and anything that is
6825 // part of its reply chain.
6826 if (clearWhenTaskReset) {
6827 // In this case, we want to finish this activity
6828 // and everything above it, so be sneaky and pretend
6829 // like these are all in the reply chain.
6830 replyChainEnd = targetI+1;
6831 while (replyChainEnd < mHistory.size() &&
6832 ((HistoryRecord)mHistory.get(
6833 replyChainEnd)).task == task) {
6834 replyChainEnd++;
6835 }
6836 replyChainEnd--;
6837 } else if (replyChainEnd < 0) {
6838 replyChainEnd = targetI;
6839 }
6840 HistoryRecord p = null;
6841 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6842 p = (HistoryRecord)mHistory.get(srcPos);
6843 if (p.finishing) {
6844 continue;
6845 }
6846 if (finishActivityLocked(p, srcPos,
6847 Activity.RESULT_CANCELED, null, "reset")) {
6848 replyChainEnd--;
6849 srcPos--;
6850 }
6851 }
6852 if (taskTop == p) {
6853 taskTop = below;
6854 }
6855 if (taskTopI == replyChainEnd) {
6856 taskTopI = -1;
6857 }
6858 replyChainEnd = -1;
6859 } else {
6860 // If we were in the middle of a chain, well the
6861 // activity that started it all doesn't want anything
6862 // special, so leave it all as-is.
6863 replyChainEnd = -1;
6864 }
6865 } else {
6866 // Reached the bottom of the task -- any reply chain
6867 // should be left as-is.
6868 replyChainEnd = -1;
6869 }
6870
6871 } else if (target.resultTo != null) {
6872 // If this activity is sending a reply to a previous
6873 // activity, we can't do anything with it now until
6874 // we reach the start of the reply chain.
6875 // XXX note that we are assuming the result is always
6876 // to the previous activity, which is almost always
6877 // the case but we really shouldn't count on.
6878 if (replyChainEnd < 0) {
6879 replyChainEnd = targetI;
6880 }
6881
6882 } else if (taskTopI >= 0 && allowTaskReparenting
6883 && task.affinity != null
6884 && task.affinity.equals(target.taskAffinity)) {
6885 // We are inside of another task... if this activity has
6886 // an affinity for our task, then either remove it if we are
6887 // clearing or move it over to our task. Note that
6888 // we currently punt on the case where we are resetting a
6889 // task that is not at the top but who has activities above
6890 // with an affinity to it... this is really not a normal
6891 // case, and we will need to later pull that task to the front
6892 // and usually at that point we will do the reset and pick
6893 // up those remaining activities. (This only happens if
6894 // someone starts an activity in a new task from an activity
6895 // in a task that is not currently on top.)
6896 if (forceReset || finishOnTaskLaunch) {
6897 if (replyChainEnd < 0) {
6898 replyChainEnd = targetI;
6899 }
6900 HistoryRecord p = null;
6901 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6902 p = (HistoryRecord)mHistory.get(srcPos);
6903 if (p.finishing) {
6904 continue;
6905 }
6906 if (finishActivityLocked(p, srcPos,
6907 Activity.RESULT_CANCELED, null, "reset")) {
6908 taskTopI--;
6909 lastReparentPos--;
6910 replyChainEnd--;
6911 srcPos--;
6912 }
6913 }
6914 replyChainEnd = -1;
6915 } else {
6916 if (replyChainEnd < 0) {
6917 replyChainEnd = targetI;
6918 }
6919 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6920 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6921 if (p.finishing) {
6922 continue;
6923 }
6924 if (lastReparentPos < 0) {
6925 lastReparentPos = taskTopI;
6926 taskTop = p;
6927 } else {
6928 lastReparentPos--;
6929 }
6930 mHistory.remove(srcPos);
6931 p.task.numActivities--;
6932 p.task = task;
6933 mHistory.add(lastReparentPos, p);
6934 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6935 + " in to resetting task " + task);
6936 task.numActivities++;
6937 mWindowManager.moveAppToken(lastReparentPos, p);
6938 mWindowManager.setAppGroupId(p, p.task.taskId);
6939 if (VALIDATE_TOKENS) {
6940 mWindowManager.validateAppTokens(mHistory);
6941 }
6942 }
6943 replyChainEnd = -1;
6944
6945 // Now we've moved it in to place... but what if this is
6946 // a singleTop activity and we have put it on top of another
6947 // instance of the same activity? Then we drop the instance
6948 // below so it remains singleTop.
6949 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6950 for (int j=lastReparentPos-1; j>=0; j--) {
6951 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6952 if (p.finishing) {
6953 continue;
6954 }
6955 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6956 if (finishActivityLocked(p, j,
6957 Activity.RESULT_CANCELED, null, "replace")) {
6958 taskTopI--;
6959 lastReparentPos--;
6960 }
6961 }
6962 }
6963 }
6964 }
6965 }
6966
6967 target = below;
6968 targetI = i;
6969 }
6970
6971 return taskTop;
6972 }
6973
6974 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006975 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 */
6977 public void moveTaskToFront(int task) {
6978 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6979 "moveTaskToFront()");
6980
6981 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006982 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
6983 Binder.getCallingUid(), "Task to front")) {
6984 return;
6985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006986 final long origId = Binder.clearCallingIdentity();
6987 try {
6988 int N = mRecentTasks.size();
6989 for (int i=0; i<N; i++) {
6990 TaskRecord tr = mRecentTasks.get(i);
6991 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006992 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 return;
6994 }
6995 }
6996 for (int i=mHistory.size()-1; i>=0; i--) {
6997 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
6998 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07006999 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007000 return;
7001 }
7002 }
7003 } finally {
7004 Binder.restoreCallingIdentity(origId);
7005 }
7006 }
7007 }
7008
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007009 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007010 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
7011
7012 final int task = tr.taskId;
7013 int top = mHistory.size()-1;
7014
7015 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7016 // nothing to do!
7017 return;
7018 }
7019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 ArrayList moved = new ArrayList();
7021
7022 // Applying the affinities may have removed entries from the history,
7023 // so get the size again.
7024 top = mHistory.size()-1;
7025 int pos = top;
7026
7027 // Shift all activities with this task up to the top
7028 // of the stack, keeping them in the same internal order.
7029 while (pos >= 0) {
7030 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7031 if (localLOGV) Log.v(
7032 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7033 boolean first = true;
7034 if (r.task.taskId == task) {
7035 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
7036 mHistory.remove(pos);
7037 mHistory.add(top, r);
7038 moved.add(0, r);
7039 top--;
7040 if (first) {
7041 addRecentTask(r.task);
7042 first = false;
7043 }
7044 }
7045 pos--;
7046 }
7047
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007048 if (DEBUG_TRANSITION) Log.v(TAG,
7049 "Prepare to front transition: task=" + tr);
7050 if (reason != null &&
7051 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7052 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7053 HistoryRecord r = topRunningActivityLocked(null);
7054 if (r != null) {
7055 mNoAnimActivities.add(r);
7056 }
7057 } else {
7058 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7059 }
7060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007061 mWindowManager.moveAppTokensToTop(moved);
7062 if (VALIDATE_TOKENS) {
7063 mWindowManager.validateAppTokens(mHistory);
7064 }
7065
7066 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007067 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 }
7069
7070 private final void finishTaskMove(int task) {
7071 resumeTopActivityLocked(null);
7072 }
7073
7074 public void moveTaskToBack(int task) {
7075 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7076 "moveTaskToBack()");
7077
7078 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007079 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7080 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7081 Binder.getCallingUid(), "Task to back")) {
7082 return;
7083 }
7084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007086 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087 Binder.restoreCallingIdentity(origId);
7088 }
7089 }
7090
7091 /**
7092 * Moves an activity, and all of the other activities within the same task, to the bottom
7093 * of the history stack. The activity's order within the task is unchanged.
7094 *
7095 * @param token A reference to the activity we wish to move
7096 * @param nonRoot If false then this only works if the activity is the root
7097 * of a task; if true it will work for any activity in a task.
7098 * @return Returns true if the move completed, false if not.
7099 */
7100 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7101 synchronized(this) {
7102 final long origId = Binder.clearCallingIdentity();
7103 int taskId = getTaskForActivityLocked(token, !nonRoot);
7104 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007105 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007106 }
7107 Binder.restoreCallingIdentity(origId);
7108 }
7109 return false;
7110 }
7111
7112 /**
7113 * Worker method for rearranging history stack. Implements the function of moving all
7114 * activities for a specific task (gathering them if disjoint) into a single group at the
7115 * bottom of the stack.
7116 *
7117 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7118 * to premeptively cancel the move.
7119 *
7120 * @param task The taskId to collect and move to the bottom.
7121 * @return Returns true if the move completed, false if not.
7122 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007123 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 Log.i(TAG, "moveTaskToBack: " + task);
7125
7126 // If we have a watcher, preflight the move before committing to it. First check
7127 // for *other* available tasks, but if none are available, then try again allowing the
7128 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007129 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 HistoryRecord next = topRunningActivityLocked(null, task);
7131 if (next == null) {
7132 next = topRunningActivityLocked(null, 0);
7133 }
7134 if (next != null) {
7135 // ask watcher if this is allowed
7136 boolean moveOK = true;
7137 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007138 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007140 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007141 }
7142 if (!moveOK) {
7143 return false;
7144 }
7145 }
7146 }
7147
7148 ArrayList moved = new ArrayList();
7149
7150 if (DEBUG_TRANSITION) Log.v(TAG,
7151 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152
7153 final int N = mHistory.size();
7154 int bottom = 0;
7155 int pos = 0;
7156
7157 // Shift all activities with this task down to the bottom
7158 // of the stack, keeping them in the same internal order.
7159 while (pos < N) {
7160 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
7161 if (localLOGV) Log.v(
7162 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7163 if (r.task.taskId == task) {
7164 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
7165 mHistory.remove(pos);
7166 mHistory.add(bottom, r);
7167 moved.add(r);
7168 bottom++;
7169 }
7170 pos++;
7171 }
7172
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007173 if (reason != null &&
7174 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7175 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7176 HistoryRecord r = topRunningActivityLocked(null);
7177 if (r != null) {
7178 mNoAnimActivities.add(r);
7179 }
7180 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007181 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007183 mWindowManager.moveAppTokensToBottom(moved);
7184 if (VALIDATE_TOKENS) {
7185 mWindowManager.validateAppTokens(mHistory);
7186 }
7187
7188 finishTaskMove(task);
7189 return true;
7190 }
7191
7192 public void moveTaskBackwards(int task) {
7193 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7194 "moveTaskBackwards()");
7195
7196 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007197 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7198 Binder.getCallingUid(), "Task backwards")) {
7199 return;
7200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007201 final long origId = Binder.clearCallingIdentity();
7202 moveTaskBackwardsLocked(task);
7203 Binder.restoreCallingIdentity(origId);
7204 }
7205 }
7206
7207 private final void moveTaskBackwardsLocked(int task) {
7208 Log.e(TAG, "moveTaskBackwards not yet implemented!");
7209 }
7210
7211 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7212 synchronized(this) {
7213 return getTaskForActivityLocked(token, onlyRoot);
7214 }
7215 }
7216
7217 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7218 final int N = mHistory.size();
7219 TaskRecord lastTask = null;
7220 for (int i=0; i<N; i++) {
7221 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7222 if (r == token) {
7223 if (!onlyRoot || lastTask != r.task) {
7224 return r.task.taskId;
7225 }
7226 return -1;
7227 }
7228 lastTask = r.task;
7229 }
7230
7231 return -1;
7232 }
7233
7234 /**
7235 * Returns the top activity in any existing task matching the given
7236 * Intent. Returns null if no such task is found.
7237 */
7238 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7239 ComponentName cls = intent.getComponent();
7240 if (info.targetActivity != null) {
7241 cls = new ComponentName(info.packageName, info.targetActivity);
7242 }
7243
7244 TaskRecord cp = null;
7245
7246 final int N = mHistory.size();
7247 for (int i=(N-1); i>=0; i--) {
7248 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7249 if (!r.finishing && r.task != cp
7250 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7251 cp = r.task;
7252 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
7253 // + "/aff=" + r.task.affinity + " to new cls="
7254 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7255 if (r.task.affinity != null) {
7256 if (r.task.affinity.equals(info.taskAffinity)) {
7257 //Log.i(TAG, "Found matching affinity!");
7258 return r;
7259 }
7260 } else if (r.task.intent != null
7261 && r.task.intent.getComponent().equals(cls)) {
7262 //Log.i(TAG, "Found matching class!");
7263 //dump();
7264 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7265 return r;
7266 } else if (r.task.affinityIntent != null
7267 && r.task.affinityIntent.getComponent().equals(cls)) {
7268 //Log.i(TAG, "Found matching class!");
7269 //dump();
7270 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7271 return r;
7272 }
7273 }
7274 }
7275
7276 return null;
7277 }
7278
7279 /**
7280 * Returns the first activity (starting from the top of the stack) that
7281 * is the same as the given activity. Returns null if no such activity
7282 * is found.
7283 */
7284 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7285 ComponentName cls = intent.getComponent();
7286 if (info.targetActivity != null) {
7287 cls = new ComponentName(info.packageName, info.targetActivity);
7288 }
7289
7290 final int N = mHistory.size();
7291 for (int i=(N-1); i>=0; i--) {
7292 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7293 if (!r.finishing) {
7294 if (r.intent.getComponent().equals(cls)) {
7295 //Log.i(TAG, "Found matching class!");
7296 //dump();
7297 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
7298 return r;
7299 }
7300 }
7301 }
7302
7303 return null;
7304 }
7305
7306 public void finishOtherInstances(IBinder token, ComponentName className) {
7307 synchronized(this) {
7308 final long origId = Binder.clearCallingIdentity();
7309
7310 int N = mHistory.size();
7311 TaskRecord lastTask = null;
7312 for (int i=0; i<N; i++) {
7313 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7314 if (r.realActivity.equals(className)
7315 && r != token && lastTask != r.task) {
7316 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7317 null, "others")) {
7318 i--;
7319 N--;
7320 }
7321 }
7322 lastTask = r.task;
7323 }
7324
7325 Binder.restoreCallingIdentity(origId);
7326 }
7327 }
7328
7329 // =========================================================
7330 // THUMBNAILS
7331 // =========================================================
7332
7333 public void reportThumbnail(IBinder token,
7334 Bitmap thumbnail, CharSequence description) {
7335 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7336 final long origId = Binder.clearCallingIdentity();
7337 sendPendingThumbnail(null, token, thumbnail, description, true);
7338 Binder.restoreCallingIdentity(origId);
7339 }
7340
7341 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7342 Bitmap thumbnail, CharSequence description, boolean always) {
7343 TaskRecord task = null;
7344 ArrayList receivers = null;
7345
7346 //System.out.println("Send pending thumbnail: " + r);
7347
7348 synchronized(this) {
7349 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007350 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007351 if (index < 0) {
7352 return;
7353 }
7354 r = (HistoryRecord)mHistory.get(index);
7355 }
7356 if (thumbnail == null) {
7357 thumbnail = r.thumbnail;
7358 description = r.description;
7359 }
7360 if (thumbnail == null && !always) {
7361 // If there is no thumbnail, and this entry is not actually
7362 // going away, then abort for now and pick up the next
7363 // thumbnail we get.
7364 return;
7365 }
7366 task = r.task;
7367
7368 int N = mPendingThumbnails.size();
7369 int i=0;
7370 while (i<N) {
7371 PendingThumbnailsRecord pr =
7372 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7373 //System.out.println("Looking in " + pr.pendingRecords);
7374 if (pr.pendingRecords.remove(r)) {
7375 if (receivers == null) {
7376 receivers = new ArrayList();
7377 }
7378 receivers.add(pr);
7379 if (pr.pendingRecords.size() == 0) {
7380 pr.finished = true;
7381 mPendingThumbnails.remove(i);
7382 N--;
7383 continue;
7384 }
7385 }
7386 i++;
7387 }
7388 }
7389
7390 if (receivers != null) {
7391 final int N = receivers.size();
7392 for (int i=0; i<N; i++) {
7393 try {
7394 PendingThumbnailsRecord pr =
7395 (PendingThumbnailsRecord)receivers.get(i);
7396 pr.receiver.newThumbnail(
7397 task != null ? task.taskId : -1, thumbnail, description);
7398 if (pr.finished) {
7399 pr.receiver.finished();
7400 }
7401 } catch (Exception e) {
7402 Log.w(TAG, "Exception thrown when sending thumbnail", e);
7403 }
7404 }
7405 }
7406 }
7407
7408 // =========================================================
7409 // CONTENT PROVIDERS
7410 // =========================================================
7411
7412 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7413 List providers = null;
7414 try {
7415 providers = ActivityThread.getPackageManager().
7416 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007417 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 } catch (RemoteException ex) {
7419 }
7420 if (providers != null) {
7421 final int N = providers.size();
7422 for (int i=0; i<N; i++) {
7423 ProviderInfo cpi =
7424 (ProviderInfo)providers.get(i);
7425 ContentProviderRecord cpr =
7426 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7427 if (cpr == null) {
7428 cpr = new ContentProviderRecord(cpi, app.info);
7429 mProvidersByClass.put(cpi.name, cpr);
7430 }
7431 app.pubProviders.put(cpi.name, cpr);
7432 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007433 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 }
7435 }
7436 return providers;
7437 }
7438
7439 private final String checkContentProviderPermissionLocked(
7440 ProviderInfo cpi, ProcessRecord r, int mode) {
7441 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7442 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7443 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7444 cpi.exported ? -1 : cpi.applicationInfo.uid)
7445 == PackageManager.PERMISSION_GRANTED
7446 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7447 return null;
7448 }
7449 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7450 cpi.exported ? -1 : cpi.applicationInfo.uid)
7451 == PackageManager.PERMISSION_GRANTED) {
7452 return null;
7453 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007454
7455 PathPermission[] pps = cpi.pathPermissions;
7456 if (pps != null) {
7457 int i = pps.length;
7458 while (i > 0) {
7459 i--;
7460 PathPermission pp = pps[i];
7461 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7462 cpi.exported ? -1 : cpi.applicationInfo.uid)
7463 == PackageManager.PERMISSION_GRANTED
7464 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7465 return null;
7466 }
7467 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7468 cpi.exported ? -1 : cpi.applicationInfo.uid)
7469 == PackageManager.PERMISSION_GRANTED) {
7470 return null;
7471 }
7472 }
7473 }
7474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 String msg = "Permission Denial: opening provider " + cpi.name
7476 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7477 + ", uid=" + callingUid + ") requires "
7478 + cpi.readPermission + " or " + cpi.writePermission;
7479 Log.w(TAG, msg);
7480 return msg;
7481 }
7482
7483 private final ContentProviderHolder getContentProviderImpl(
7484 IApplicationThread caller, String name) {
7485 ContentProviderRecord cpr;
7486 ProviderInfo cpi = null;
7487
7488 synchronized(this) {
7489 ProcessRecord r = null;
7490 if (caller != null) {
7491 r = getRecordForAppLocked(caller);
7492 if (r == null) {
7493 throw new SecurityException(
7494 "Unable to find app for caller " + caller
7495 + " (pid=" + Binder.getCallingPid()
7496 + ") when getting content provider " + name);
7497 }
7498 }
7499
7500 // First check if this content provider has been published...
7501 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7502 if (cpr != null) {
7503 cpi = cpr.info;
7504 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7505 return new ContentProviderHolder(cpi,
7506 cpi.readPermission != null
7507 ? cpi.readPermission : cpi.writePermission);
7508 }
7509
7510 if (r != null && cpr.canRunHere(r)) {
7511 // This provider has been published or is in the process
7512 // of being published... but it is also allowed to run
7513 // in the caller's process, so don't make a connection
7514 // and just let the caller instantiate its own instance.
7515 if (cpr.provider != null) {
7516 // don't give caller the provider object, it needs
7517 // to make its own.
7518 cpr = new ContentProviderRecord(cpr);
7519 }
7520 return cpr;
7521 }
7522
7523 final long origId = Binder.clearCallingIdentity();
7524
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007525 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007526 // return it right away.
7527 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007528 if (DEBUG_PROVIDER) Log.v(TAG,
7529 "Adding provider requested by "
7530 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007531 + cpr.info.processName);
7532 Integer cnt = r.conProviders.get(cpr);
7533 if (cnt == null) {
7534 r.conProviders.put(cpr, new Integer(1));
7535 } else {
7536 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 cpr.clients.add(r);
7539 } else {
7540 cpr.externals++;
7541 }
7542
7543 if (cpr.app != null) {
7544 updateOomAdjLocked(cpr.app);
7545 }
7546
7547 Binder.restoreCallingIdentity(origId);
7548
7549 } else {
7550 try {
7551 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007552 resolveContentProvider(name,
7553 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 } catch (RemoteException ex) {
7555 }
7556 if (cpi == null) {
7557 return null;
7558 }
7559
7560 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7561 return new ContentProviderHolder(cpi,
7562 cpi.readPermission != null
7563 ? cpi.readPermission : cpi.writePermission);
7564 }
7565
7566 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7567 final boolean firstClass = cpr == null;
7568 if (firstClass) {
7569 try {
7570 ApplicationInfo ai =
7571 ActivityThread.getPackageManager().
7572 getApplicationInfo(
7573 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007574 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 if (ai == null) {
7576 Log.w(TAG, "No package info for content provider "
7577 + cpi.name);
7578 return null;
7579 }
7580 cpr = new ContentProviderRecord(cpi, ai);
7581 } catch (RemoteException ex) {
7582 // pm is in same process, this will never happen.
7583 }
7584 }
7585
7586 if (r != null && cpr.canRunHere(r)) {
7587 // If this is a multiprocess provider, then just return its
7588 // info and allow the caller to instantiate it. Only do
7589 // this if the provider is the same user as the caller's
7590 // process, or can run as root (so can be in any process).
7591 return cpr;
7592 }
7593
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007594 if (DEBUG_PROVIDER) {
7595 RuntimeException e = new RuntimeException("here");
7596 Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
7597 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 }
7599
7600 // This is single process, and our app is now connecting to it.
7601 // See if we are already in the process of launching this
7602 // provider.
7603 final int N = mLaunchingProviders.size();
7604 int i;
7605 for (i=0; i<N; i++) {
7606 if (mLaunchingProviders.get(i) == cpr) {
7607 break;
7608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007609 }
7610
7611 // If the provider is not already being launched, then get it
7612 // started.
7613 if (i >= N) {
7614 final long origId = Binder.clearCallingIdentity();
7615 ProcessRecord proc = startProcessLocked(cpi.processName,
7616 cpr.appInfo, false, 0, "content provider",
7617 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007618 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 if (proc == null) {
7620 Log.w(TAG, "Unable to launch app "
7621 + cpi.applicationInfo.packageName + "/"
7622 + cpi.applicationInfo.uid + " for provider "
7623 + name + ": process is bad");
7624 return null;
7625 }
7626 cpr.launchingApp = proc;
7627 mLaunchingProviders.add(cpr);
7628 Binder.restoreCallingIdentity(origId);
7629 }
7630
7631 // Make sure the provider is published (the same provider class
7632 // may be published under multiple names).
7633 if (firstClass) {
7634 mProvidersByClass.put(cpi.name, cpr);
7635 }
7636 mProvidersByName.put(name, cpr);
7637
7638 if (r != null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007639 if (DEBUG_PROVIDER) Log.v(TAG,
7640 "Adding provider requested by "
7641 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007642 + cpr.info.processName);
7643 Integer cnt = r.conProviders.get(cpr);
7644 if (cnt == null) {
7645 r.conProviders.put(cpr, new Integer(1));
7646 } else {
7647 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007649 cpr.clients.add(r);
7650 } else {
7651 cpr.externals++;
7652 }
7653 }
7654 }
7655
7656 // Wait for the provider to be published...
7657 synchronized (cpr) {
7658 while (cpr.provider == null) {
7659 if (cpr.launchingApp == null) {
7660 Log.w(TAG, "Unable to launch app "
7661 + cpi.applicationInfo.packageName + "/"
7662 + cpi.applicationInfo.uid + " for provider "
7663 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007664 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 cpi.applicationInfo.packageName,
7666 cpi.applicationInfo.uid, name);
7667 return null;
7668 }
7669 try {
7670 cpr.wait();
7671 } catch (InterruptedException ex) {
7672 }
7673 }
7674 }
7675 return cpr;
7676 }
7677
7678 public final ContentProviderHolder getContentProvider(
7679 IApplicationThread caller, String name) {
7680 if (caller == null) {
7681 String msg = "null IApplicationThread when getting content provider "
7682 + name;
7683 Log.w(TAG, msg);
7684 throw new SecurityException(msg);
7685 }
7686
7687 return getContentProviderImpl(caller, name);
7688 }
7689
7690 private ContentProviderHolder getContentProviderExternal(String name) {
7691 return getContentProviderImpl(null, name);
7692 }
7693
7694 /**
7695 * Drop a content provider from a ProcessRecord's bookkeeping
7696 * @param cpr
7697 */
7698 public void removeContentProvider(IApplicationThread caller, String name) {
7699 synchronized (this) {
7700 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7701 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007702 // remove from mProvidersByClass
7703 if (DEBUG_PROVIDER) Log.v(TAG, name +
7704 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 return;
7706 }
7707 final ProcessRecord r = getRecordForAppLocked(caller);
7708 if (r == null) {
7709 throw new SecurityException(
7710 "Unable to find app for caller " + caller +
7711 " when removing content provider " + name);
7712 }
7713 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007714 ContentProviderRecord localCpr = (ContentProviderRecord)
7715 mProvidersByClass.get(cpr.info.name);
7716 if (DEBUG_PROVIDER) Log.v(TAG, "Removing provider requested by "
7717 + r.info.processName + " from process "
7718 + localCpr.appInfo.processName);
7719 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 //should not happen. taken care of as a local provider
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007721 Log.w(TAG, "removeContentProvider called on local provider: "
7722 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 return;
7724 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007725 Integer cnt = r.conProviders.get(localCpr);
7726 if (cnt == null || cnt.intValue() <= 1) {
7727 localCpr.clients.remove(r);
7728 r.conProviders.remove(localCpr);
7729 } else {
7730 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 }
7733 updateOomAdjLocked();
7734 }
7735 }
7736
7737 private void removeContentProviderExternal(String name) {
7738 synchronized (this) {
7739 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7740 if(cpr == null) {
7741 //remove from mProvidersByClass
7742 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
7743 return;
7744 }
7745
7746 //update content provider record entry info
7747 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7748 localCpr.externals--;
7749 if (localCpr.externals < 0) {
7750 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
7751 }
7752 updateOomAdjLocked();
7753 }
7754 }
7755
7756 public final void publishContentProviders(IApplicationThread caller,
7757 List<ContentProviderHolder> providers) {
7758 if (providers == null) {
7759 return;
7760 }
7761
7762 synchronized(this) {
7763 final ProcessRecord r = getRecordForAppLocked(caller);
7764 if (r == null) {
7765 throw new SecurityException(
7766 "Unable to find app for caller " + caller
7767 + " (pid=" + Binder.getCallingPid()
7768 + ") when publishing content providers");
7769 }
7770
7771 final long origId = Binder.clearCallingIdentity();
7772
7773 final int N = providers.size();
7774 for (int i=0; i<N; i++) {
7775 ContentProviderHolder src = providers.get(i);
7776 if (src == null || src.info == null || src.provider == null) {
7777 continue;
7778 }
7779 ContentProviderRecord dst =
7780 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7781 if (dst != null) {
7782 mProvidersByClass.put(dst.info.name, dst);
7783 String names[] = dst.info.authority.split(";");
7784 for (int j = 0; j < names.length; j++) {
7785 mProvidersByName.put(names[j], dst);
7786 }
7787
7788 int NL = mLaunchingProviders.size();
7789 int j;
7790 for (j=0; j<NL; j++) {
7791 if (mLaunchingProviders.get(j) == dst) {
7792 mLaunchingProviders.remove(j);
7793 j--;
7794 NL--;
7795 }
7796 }
7797 synchronized (dst) {
7798 dst.provider = src.provider;
7799 dst.app = r;
7800 dst.notifyAll();
7801 }
7802 updateOomAdjLocked(r);
7803 }
7804 }
7805
7806 Binder.restoreCallingIdentity(origId);
7807 }
7808 }
7809
7810 public static final void installSystemProviders() {
7811 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7812 List providers = mSelf.generateApplicationProvidersLocked(app);
7813 mSystemThread.installSystemProviders(providers);
7814 }
7815
7816 // =========================================================
7817 // GLOBAL MANAGEMENT
7818 // =========================================================
7819
7820 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7821 ApplicationInfo info, String customProcess) {
7822 String proc = customProcess != null ? customProcess : info.processName;
7823 BatteryStatsImpl.Uid.Proc ps = null;
7824 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7825 synchronized (stats) {
7826 ps = stats.getProcessStatsLocked(info.uid, proc);
7827 }
7828 return new ProcessRecord(ps, thread, info, proc);
7829 }
7830
7831 final ProcessRecord addAppLocked(ApplicationInfo info) {
7832 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7833
7834 if (app == null) {
7835 app = newProcessRecordLocked(null, info, null);
7836 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007837 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 }
7839
7840 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7841 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7842 app.persistent = true;
7843 app.maxAdj = CORE_SERVER_ADJ;
7844 }
7845 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7846 mPersistentStartingProcesses.add(app);
7847 startProcessLocked(app, "added application", app.processName);
7848 }
7849
7850 return app;
7851 }
7852
7853 public void unhandledBack() {
7854 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7855 "unhandledBack()");
7856
7857 synchronized(this) {
7858 int count = mHistory.size();
Dianne Hackborn03abb812010-01-04 18:43:19 -08007859 if (DEBUG_SWITCH) Log.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 TAG, "Performing unhandledBack(): stack size = " + count);
7861 if (count > 1) {
7862 final long origId = Binder.clearCallingIdentity();
7863 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7864 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7865 Binder.restoreCallingIdentity(origId);
7866 }
7867 }
7868 }
7869
7870 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7871 String name = uri.getAuthority();
7872 ContentProviderHolder cph = getContentProviderExternal(name);
7873 ParcelFileDescriptor pfd = null;
7874 if (cph != null) {
7875 // We record the binder invoker's uid in thread-local storage before
7876 // going to the content provider to open the file. Later, in the code
7877 // that handles all permissions checks, we look for this uid and use
7878 // that rather than the Activity Manager's own uid. The effect is that
7879 // we do the check against the caller's permissions even though it looks
7880 // to the content provider like the Activity Manager itself is making
7881 // the request.
7882 sCallerIdentity.set(new Identity(
7883 Binder.getCallingPid(), Binder.getCallingUid()));
7884 try {
7885 pfd = cph.provider.openFile(uri, "r");
7886 } catch (FileNotFoundException e) {
7887 // do nothing; pfd will be returned null
7888 } finally {
7889 // Ensure that whatever happens, we clean up the identity state
7890 sCallerIdentity.remove();
7891 }
7892
7893 // We've got the fd now, so we're done with the provider.
7894 removeContentProviderExternal(name);
7895 } else {
7896 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7897 }
7898 return pfd;
7899 }
7900
7901 public void goingToSleep() {
7902 synchronized(this) {
7903 mSleeping = true;
7904 mWindowManager.setEventDispatching(false);
7905
7906 if (mResumedActivity != null) {
7907 pauseIfSleepingLocked();
7908 } else {
7909 Log.w(TAG, "goingToSleep with no resumed activity!");
7910 }
7911 }
7912 }
7913
Dianne Hackborn55280a92009-05-07 15:53:46 -07007914 public boolean shutdown(int timeout) {
7915 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7916 != PackageManager.PERMISSION_GRANTED) {
7917 throw new SecurityException("Requires permission "
7918 + android.Manifest.permission.SHUTDOWN);
7919 }
7920
7921 boolean timedout = false;
7922
7923 synchronized(this) {
7924 mShuttingDown = true;
7925 mWindowManager.setEventDispatching(false);
7926
7927 if (mResumedActivity != null) {
7928 pauseIfSleepingLocked();
7929 final long endTime = System.currentTimeMillis() + timeout;
7930 while (mResumedActivity != null || mPausingActivity != null) {
7931 long delay = endTime - System.currentTimeMillis();
7932 if (delay <= 0) {
7933 Log.w(TAG, "Activity manager shutdown timed out");
7934 timedout = true;
7935 break;
7936 }
7937 try {
7938 this.wait();
7939 } catch (InterruptedException e) {
7940 }
7941 }
7942 }
7943 }
7944
7945 mUsageStatsService.shutdown();
7946 mBatteryStatsService.shutdown();
7947
7948 return timedout;
7949 }
7950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007952 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 if (!mGoingToSleep.isHeld()) {
7954 mGoingToSleep.acquire();
7955 if (mLaunchingActivity.isHeld()) {
7956 mLaunchingActivity.release();
7957 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7958 }
7959 }
7960
7961 // If we are not currently pausing an activity, get the current
7962 // one to pause. If we are pausing one, we will just let that stuff
7963 // run and release the wake lock when all done.
7964 if (mPausingActivity == null) {
7965 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7966 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7967 startPausingLocked(false, true);
7968 }
7969 }
7970 }
7971
7972 public void wakingUp() {
7973 synchronized(this) {
7974 if (mGoingToSleep.isHeld()) {
7975 mGoingToSleep.release();
7976 }
7977 mWindowManager.setEventDispatching(true);
7978 mSleeping = false;
7979 resumeTopActivityLocked(null);
7980 }
7981 }
7982
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007983 public void stopAppSwitches() {
7984 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
7985 != PackageManager.PERMISSION_GRANTED) {
7986 throw new SecurityException("Requires permission "
7987 + android.Manifest.permission.STOP_APP_SWITCHES);
7988 }
7989
7990 synchronized(this) {
7991 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
7992 + APP_SWITCH_DELAY_TIME;
7993 mDidAppSwitch = false;
7994 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7995 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
7996 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
7997 }
7998 }
7999
8000 public void resumeAppSwitches() {
8001 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8002 != PackageManager.PERMISSION_GRANTED) {
8003 throw new SecurityException("Requires permission "
8004 + android.Manifest.permission.STOP_APP_SWITCHES);
8005 }
8006
8007 synchronized(this) {
8008 // Note that we don't execute any pending app switches... we will
8009 // let those wait until either the timeout, or the next start
8010 // activity request.
8011 mAppSwitchesAllowedTime = 0;
8012 }
8013 }
8014
8015 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8016 String name) {
8017 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8018 return true;
8019 }
8020
8021 final int perm = checkComponentPermission(
8022 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8023 callingUid, -1);
8024 if (perm == PackageManager.PERMISSION_GRANTED) {
8025 return true;
8026 }
8027
8028 Log.w(TAG, name + " request from " + callingUid + " stopped");
8029 return false;
8030 }
8031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 public void setDebugApp(String packageName, boolean waitForDebugger,
8033 boolean persistent) {
8034 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8035 "setDebugApp()");
8036
8037 // Note that this is not really thread safe if there are multiple
8038 // callers into it at the same time, but that's not a situation we
8039 // care about.
8040 if (persistent) {
8041 final ContentResolver resolver = mContext.getContentResolver();
8042 Settings.System.putString(
8043 resolver, Settings.System.DEBUG_APP,
8044 packageName);
8045 Settings.System.putInt(
8046 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8047 waitForDebugger ? 1 : 0);
8048 }
8049
8050 synchronized (this) {
8051 if (!persistent) {
8052 mOrigDebugApp = mDebugApp;
8053 mOrigWaitForDebugger = mWaitForDebugger;
8054 }
8055 mDebugApp = packageName;
8056 mWaitForDebugger = waitForDebugger;
8057 mDebugTransient = !persistent;
8058 if (packageName != null) {
8059 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008060 forceStopPackageLocked(packageName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 Binder.restoreCallingIdentity(origId);
8062 }
8063 }
8064 }
8065
8066 public void setAlwaysFinish(boolean enabled) {
8067 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8068 "setAlwaysFinish()");
8069
8070 Settings.System.putInt(
8071 mContext.getContentResolver(),
8072 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8073
8074 synchronized (this) {
8075 mAlwaysFinishActivities = enabled;
8076 }
8077 }
8078
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008079 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008081 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008083 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 }
8085 }
8086
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008087 public boolean isUserAMonkey() {
8088 // For now the fact that there is a controller implies
8089 // we have a monkey.
8090 synchronized (this) {
8091 return mController != null;
8092 }
8093 }
8094
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008095 public void registerActivityWatcher(IActivityWatcher watcher) {
8096 mWatchers.register(watcher);
8097 }
8098
8099 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8100 mWatchers.unregister(watcher);
8101 }
8102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 public final void enterSafeMode() {
8104 synchronized(this) {
8105 // It only makes sense to do this before the system is ready
8106 // and started launching other packages.
8107 if (!mSystemReady) {
8108 try {
8109 ActivityThread.getPackageManager().enterSafeMode();
8110 } catch (RemoteException e) {
8111 }
8112
8113 View v = LayoutInflater.from(mContext).inflate(
8114 com.android.internal.R.layout.safe_mode, null);
8115 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8116 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8117 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8118 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8119 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8120 lp.format = v.getBackground().getOpacity();
8121 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8122 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8123 ((WindowManager)mContext.getSystemService(
8124 Context.WINDOW_SERVICE)).addView(v, lp);
8125 }
8126 }
8127 }
8128
8129 public void noteWakeupAlarm(IIntentSender sender) {
8130 if (!(sender instanceof PendingIntentRecord)) {
8131 return;
8132 }
8133 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8134 synchronized (stats) {
8135 if (mBatteryStatsService.isOnBattery()) {
8136 mBatteryStatsService.enforceCallingPermission();
8137 PendingIntentRecord rec = (PendingIntentRecord)sender;
8138 int MY_UID = Binder.getCallingUid();
8139 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8140 BatteryStatsImpl.Uid.Pkg pkg =
8141 stats.getPackageStatsLocked(uid, rec.key.packageName);
8142 pkg.incWakeupsLocked();
8143 }
8144 }
8145 }
8146
8147 public boolean killPidsForMemory(int[] pids) {
8148 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8149 throw new SecurityException("killPidsForMemory only available to the system");
8150 }
8151
8152 // XXX Note: don't acquire main activity lock here, because the window
8153 // manager calls in with its locks held.
8154
8155 boolean killed = false;
8156 synchronized (mPidsSelfLocked) {
8157 int[] types = new int[pids.length];
8158 int worstType = 0;
8159 for (int i=0; i<pids.length; i++) {
8160 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8161 if (proc != null) {
8162 int type = proc.setAdj;
8163 types[i] = type;
8164 if (type > worstType) {
8165 worstType = type;
8166 }
8167 }
8168 }
8169
8170 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8171 // then constrain it so we will kill all hidden procs.
8172 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8173 worstType = HIDDEN_APP_MIN_ADJ;
8174 }
8175 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
8176 for (int i=0; i<pids.length; i++) {
8177 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8178 if (proc == null) {
8179 continue;
8180 }
8181 int adj = proc.setAdj;
8182 if (adj >= worstType) {
8183 Log.w(TAG, "Killing for memory: " + proc + " (adj "
8184 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008185 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 proc.processName, adj);
8187 killed = true;
8188 Process.killProcess(pids[i]);
8189 }
8190 }
8191 }
8192 return killed;
8193 }
8194
8195 public void reportPss(IApplicationThread caller, int pss) {
8196 Watchdog.PssRequestor req;
8197 String name;
8198 ProcessRecord callerApp;
8199 synchronized (this) {
8200 if (caller == null) {
8201 return;
8202 }
8203 callerApp = getRecordForAppLocked(caller);
8204 if (callerApp == null) {
8205 return;
8206 }
8207 callerApp.lastPss = pss;
8208 req = callerApp;
8209 name = callerApp.processName;
8210 }
8211 Watchdog.getInstance().reportPss(req, name, pss);
8212 if (!callerApp.persistent) {
8213 removeRequestedPss(callerApp);
8214 }
8215 }
8216
8217 public void requestPss(Runnable completeCallback) {
8218 ArrayList<ProcessRecord> procs;
8219 synchronized (this) {
8220 mRequestPssCallback = completeCallback;
8221 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008222 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8223 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 if (!proc.persistent) {
8225 mRequestPssList.add(proc);
8226 }
8227 }
8228 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8229 }
8230
8231 int oldPri = Process.getThreadPriority(Process.myTid());
8232 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8233 for (int i=procs.size()-1; i>=0; i--) {
8234 ProcessRecord proc = procs.get(i);
8235 proc.lastPss = 0;
8236 proc.requestPss();
8237 }
8238 Process.setThreadPriority(oldPri);
8239 }
8240
8241 void removeRequestedPss(ProcessRecord proc) {
8242 Runnable callback = null;
8243 synchronized (this) {
8244 if (mRequestPssList.remove(proc)) {
8245 if (mRequestPssList.size() == 0) {
8246 callback = mRequestPssCallback;
8247 mRequestPssCallback = null;
8248 }
8249 }
8250 }
8251
8252 if (callback != null) {
8253 callback.run();
8254 }
8255 }
8256
8257 public void collectPss(Watchdog.PssStats stats) {
8258 stats.mEmptyPss = 0;
8259 stats.mEmptyCount = 0;
8260 stats.mBackgroundPss = 0;
8261 stats.mBackgroundCount = 0;
8262 stats.mServicePss = 0;
8263 stats.mServiceCount = 0;
8264 stats.mVisiblePss = 0;
8265 stats.mVisibleCount = 0;
8266 stats.mForegroundPss = 0;
8267 stats.mForegroundCount = 0;
8268 stats.mNoPssCount = 0;
8269 synchronized (this) {
8270 int i;
8271 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8272 ? mProcDeaths.length : stats.mProcDeaths.length;
8273 int aggr = 0;
8274 for (i=0; i<NPD; i++) {
8275 aggr += mProcDeaths[i];
8276 stats.mProcDeaths[i] = aggr;
8277 }
8278 while (i<stats.mProcDeaths.length) {
8279 stats.mProcDeaths[i] = 0;
8280 i++;
8281 }
8282
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008283 for (i=mLruProcesses.size()-1; i>=0; i--) {
8284 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 if (proc.persistent) {
8286 continue;
8287 }
8288 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
8289 if (proc.lastPss == 0) {
8290 stats.mNoPssCount++;
8291 continue;
8292 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008293 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8294 if (proc.empty) {
8295 stats.mEmptyPss += proc.lastPss;
8296 stats.mEmptyCount++;
8297 } else {
8298 stats.mBackgroundPss += proc.lastPss;
8299 stats.mBackgroundCount++;
8300 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8302 stats.mVisiblePss += proc.lastPss;
8303 stats.mVisibleCount++;
8304 } else {
8305 stats.mForegroundPss += proc.lastPss;
8306 stats.mForegroundCount++;
8307 }
8308 }
8309 }
8310 }
8311
8312 public final void startRunning(String pkg, String cls, String action,
8313 String data) {
8314 synchronized(this) {
8315 if (mStartRunning) {
8316 return;
8317 }
8318 mStartRunning = true;
8319 mTopComponent = pkg != null && cls != null
8320 ? new ComponentName(pkg, cls) : null;
8321 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8322 mTopData = data;
8323 if (!mSystemReady) {
8324 return;
8325 }
8326 }
8327
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008328 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 }
8330
8331 private void retrieveSettings() {
8332 final ContentResolver resolver = mContext.getContentResolver();
8333 String debugApp = Settings.System.getString(
8334 resolver, Settings.System.DEBUG_APP);
8335 boolean waitForDebugger = Settings.System.getInt(
8336 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8337 boolean alwaysFinishActivities = Settings.System.getInt(
8338 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8339
8340 Configuration configuration = new Configuration();
8341 Settings.System.getConfiguration(resolver, configuration);
8342
8343 synchronized (this) {
8344 mDebugApp = mOrigDebugApp = debugApp;
8345 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8346 mAlwaysFinishActivities = alwaysFinishActivities;
8347 // This happens before any activities are started, so we can
8348 // change mConfiguration in-place.
8349 mConfiguration.updateFrom(configuration);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07008350 if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008351 }
8352 }
8353
8354 public boolean testIsSystemReady() {
8355 // no need to synchronize(this) just to read & return the value
8356 return mSystemReady;
8357 }
8358
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008359 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 // In the simulator, startRunning will never have been called, which
8361 // normally sets a few crucial variables. Do it here instead.
8362 if (!Process.supportsProcesses()) {
8363 mStartRunning = true;
8364 mTopAction = Intent.ACTION_MAIN;
8365 }
8366
8367 synchronized(this) {
8368 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008369 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 return;
8371 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008372
8373 // Check to see if there are any update receivers to run.
8374 if (!mDidUpdate) {
8375 if (mWaitingUpdate) {
8376 return;
8377 }
8378 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8379 List<ResolveInfo> ris = null;
8380 try {
8381 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8382 intent, null, 0);
8383 } catch (RemoteException e) {
8384 }
8385 if (ris != null) {
8386 for (int i=ris.size()-1; i>=0; i--) {
8387 if ((ris.get(i).activityInfo.applicationInfo.flags
8388 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8389 ris.remove(i);
8390 }
8391 }
8392 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8393 for (int i=0; i<ris.size(); i++) {
8394 ActivityInfo ai = ris.get(i).activityInfo;
8395 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8396 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008397 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008398 finisher = new IIntentReceiver.Stub() {
8399 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008400 String data, Bundle extras, boolean ordered,
8401 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008402 throws RemoteException {
8403 synchronized (ActivityManagerService.this) {
8404 mDidUpdate = true;
8405 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008406 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008407 }
8408 };
8409 }
8410 Log.i(TAG, "Sending system update to: " + intent.getComponent());
8411 broadcastIntentLocked(null, null, intent, null, finisher,
8412 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008413 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008414 mWaitingUpdate = true;
8415 }
8416 }
8417 }
8418 if (mWaitingUpdate) {
8419 return;
8420 }
8421 mDidUpdate = true;
8422 }
8423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008424 mSystemReady = true;
8425 if (!mStartRunning) {
8426 return;
8427 }
8428 }
8429
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008430 ArrayList<ProcessRecord> procsToKill = null;
8431 synchronized(mPidsSelfLocked) {
8432 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8433 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8434 if (!isAllowedWhileBooting(proc.info)){
8435 if (procsToKill == null) {
8436 procsToKill = new ArrayList<ProcessRecord>();
8437 }
8438 procsToKill.add(proc);
8439 }
8440 }
8441 }
8442
8443 if (procsToKill != null) {
8444 synchronized(this) {
8445 for (int i=procsToKill.size()-1; i>=0; i--) {
8446 ProcessRecord proc = procsToKill.get(i);
8447 Log.i(TAG, "Removing system update proc: " + proc);
8448 removeProcessLocked(proc, true);
8449 }
8450 }
8451 }
8452
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008453 Log.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008454 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 SystemClock.uptimeMillis());
8456
8457 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008458 // Make sure we have no pre-ready processes sitting around.
8459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8461 ResolveInfo ri = mContext.getPackageManager()
8462 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008463 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464 CharSequence errorMsg = null;
8465 if (ri != null) {
8466 ActivityInfo ai = ri.activityInfo;
8467 ApplicationInfo app = ai.applicationInfo;
8468 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8469 mTopAction = Intent.ACTION_FACTORY_TEST;
8470 mTopData = null;
8471 mTopComponent = new ComponentName(app.packageName,
8472 ai.name);
8473 } else {
8474 errorMsg = mContext.getResources().getText(
8475 com.android.internal.R.string.factorytest_not_system);
8476 }
8477 } else {
8478 errorMsg = mContext.getResources().getText(
8479 com.android.internal.R.string.factorytest_no_action);
8480 }
8481 if (errorMsg != null) {
8482 mTopAction = null;
8483 mTopData = null;
8484 mTopComponent = null;
8485 Message msg = Message.obtain();
8486 msg.what = SHOW_FACTORY_ERROR_MSG;
8487 msg.getData().putCharSequence("msg", errorMsg);
8488 mHandler.sendMessage(msg);
8489 }
8490 }
8491 }
8492
8493 retrieveSettings();
8494
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008495 if (goingCallback != null) goingCallback.run();
8496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497 synchronized (this) {
8498 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8499 try {
8500 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008501 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 if (apps != null) {
8503 int N = apps.size();
8504 int i;
8505 for (i=0; i<N; i++) {
8506 ApplicationInfo info
8507 = (ApplicationInfo)apps.get(i);
8508 if (info != null &&
8509 !info.packageName.equals("android")) {
8510 addAppLocked(info);
8511 }
8512 }
8513 }
8514 } catch (RemoteException ex) {
8515 // pm is in same process, this will never happen.
8516 }
8517 }
8518
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008519 // Start up initial activity.
8520 mBooting = true;
8521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 try {
8523 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8524 Message msg = Message.obtain();
8525 msg.what = SHOW_UID_ERROR_MSG;
8526 mHandler.sendMessage(msg);
8527 }
8528 } catch (RemoteException e) {
8529 }
8530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 resumeTopActivityLocked(null);
8532 }
8533 }
8534
Dan Egnorb7f03672009-12-09 16:22:32 -08008535 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008536 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008538 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008539 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 startAppProblemLocked(app);
8541 app.stopFreezingAllLocked();
8542 return handleAppCrashLocked(app);
8543 }
8544
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008545 private ComponentName getErrorReportReceiver(ProcessRecord app) {
Doug Zongker43866e02010-01-07 12:09:54 -08008546 // check if error reporting is enabled in secure settings
8547 int enabled = Settings.Secure.getInt(mContext.getContentResolver(),
8548 Settings.Secure.SEND_ACTION_APP_ERROR, 0);
Jacek Surazskia2339432009-09-18 15:01:26 +02008549 if (enabled == 0) {
8550 return null;
8551 }
8552
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008553 IPackageManager pm = ActivityThread.getPackageManager();
Jacek Surazski82a73df2009-06-17 14:33:18 +02008554
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008555 try {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008556 // look for receiver in the installer package
8557 String candidate = pm.getInstallerPackageName(app.info.packageName);
8558 ComponentName result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8559 if (result != null) {
8560 return result;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008561 }
8562
Jacek Surazski82a73df2009-06-17 14:33:18 +02008563 // if the error app is on the system image, look for system apps
8564 // error receiver
8565 if ((app.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8566 candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
8567 result = getErrorReportReceiver(pm, app.info.packageName, candidate);
8568 if (result != null) {
8569 return result;
8570 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008571 }
8572
Jacek Surazski82a73df2009-06-17 14:33:18 +02008573 // if there is a default receiver, try that
8574 candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
8575 return getErrorReportReceiver(pm, app.info.packageName, candidate);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008576 } catch (RemoteException e) {
Jacek Surazski82a73df2009-06-17 14:33:18 +02008577 // should not happen
8578 Log.e(TAG, "error talking to PackageManager", e);
8579 return null;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008580 }
Jacek Surazski82a73df2009-06-17 14:33:18 +02008581 }
8582
8583 /**
8584 * Return activity in receiverPackage that handles ACTION_APP_ERROR.
8585 *
8586 * @param pm PackageManager isntance
8587 * @param errorPackage package which caused the error
8588 * @param receiverPackage candidate package to receive the error
8589 * @return activity component within receiverPackage which handles
8590 * ACTION_APP_ERROR, or null if not found
8591 */
8592 private ComponentName getErrorReportReceiver(IPackageManager pm, String errorPackage,
8593 String receiverPackage) throws RemoteException {
8594 if (receiverPackage == null || receiverPackage.length() == 0) {
8595 return null;
8596 }
8597
8598 // break the loop if it's the error report receiver package that crashed
8599 if (receiverPackage.equals(errorPackage)) {
8600 return null;
8601 }
8602
8603 Intent intent = new Intent(Intent.ACTION_APP_ERROR);
8604 intent.setPackage(receiverPackage);
8605 ResolveInfo info = pm.resolveIntent(intent, null, 0);
8606 if (info == null || info.activityInfo == null) {
8607 return null;
8608 }
8609 return new ComponentName(receiverPackage, info.activityInfo.name);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008610 }
8611
Dan Egnorb7f03672009-12-09 16:22:32 -08008612 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008613 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008615 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008616 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8617 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008618 startAppProblemLocked(app);
8619 app.stopFreezingAllLocked();
8620 }
8621
8622 /**
8623 * Generate a process error record, suitable for attachment to a ProcessRecord.
8624 *
8625 * @param app The ProcessRecord in which the error occurred.
8626 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8627 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008628 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 * @param shortMsg Short message describing the crash.
8630 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008631 * @param stackTrace Full crash stack trace, may be null.
8632 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 * @return Returns a fully-formed AppErrorStateInfo record.
8634 */
8635 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008636 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 report.condition = condition;
8640 report.processName = app.processName;
8641 report.pid = app.pid;
8642 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008643 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 report.shortMsg = shortMsg;
8645 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008646 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647
8648 return report;
8649 }
8650
Dan Egnor42471dd2010-01-07 17:25:22 -08008651 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 synchronized (this) {
8653 app.crashing = false;
8654 app.crashingReport = null;
8655 app.notResponding = false;
8656 app.notRespondingReport = null;
8657 if (app.anrDialog == fromDialog) {
8658 app.anrDialog = null;
8659 }
8660 if (app.waitDialog == fromDialog) {
8661 app.waitDialog = null;
8662 }
8663 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008664 handleAppCrashLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008665 Log.i(ActivityManagerService.TAG, "Killing process "
8666 + app.processName
8667 + " (pid=" + app.pid + ") at user's request");
8668 Process.killProcess(app.pid);
8669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 }
8671 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008672
Dan Egnorb7f03672009-12-09 16:22:32 -08008673 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008674 long now = SystemClock.uptimeMillis();
8675
8676 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8677 app.info.uid);
8678 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8679 // This process loses!
8680 Log.w(TAG, "Process " + app.info.processName
8681 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008682 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 app.info.processName, app.info.uid);
8684 killServicesLocked(app, false);
8685 for (int i=mHistory.size()-1; i>=0; i--) {
8686 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8687 if (r.app == app) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08008688 Log.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 + r.intent.getComponent().flattenToShortString());
8690 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8691 }
8692 }
8693 if (!app.persistent) {
8694 // We don't want to start this process again until the user
8695 // explicitly does so... but for persistent process, we really
8696 // need to keep it running. If a persistent process is actually
8697 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008698 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 app.info.processName);
8700 mBadProcesses.put(app.info.processName, app.info.uid, now);
8701 app.bad = true;
8702 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8703 app.removed = true;
8704 removeProcessLocked(app, false);
8705 return false;
8706 }
8707 }
8708
8709 // Bump up the crash count of any services currently running in the proc.
8710 if (app.services.size() != 0) {
8711 // Any services running in the application need to be placed
8712 // back in the pending list.
8713 Iterator it = app.services.iterator();
8714 while (it.hasNext()) {
8715 ServiceRecord sr = (ServiceRecord)it.next();
8716 sr.crashCount++;
8717 }
8718 }
8719
8720 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8721 return true;
8722 }
8723
8724 void startAppProblemLocked(ProcessRecord app) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008725 app.errorReportReceiver = getErrorReportReceiver(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 skipCurrentReceiverLocked(app);
8727 }
8728
8729 void skipCurrentReceiverLocked(ProcessRecord app) {
8730 boolean reschedule = false;
8731 BroadcastRecord r = app.curReceiver;
8732 if (r != null) {
8733 // The current broadcast is waiting for this app's receiver
8734 // to be finished. Looks like that's not going to happen, so
8735 // let the broadcast continue.
8736 logBroadcastReceiverDiscard(r);
8737 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8738 r.resultExtras, r.resultAbort, true);
8739 reschedule = true;
8740 }
8741 r = mPendingBroadcast;
8742 if (r != null && r.curApp == app) {
8743 if (DEBUG_BROADCAST) Log.v(TAG,
8744 "skip & discard pending app " + r);
8745 logBroadcastReceiverDiscard(r);
8746 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8747 r.resultExtras, r.resultAbort, true);
8748 reschedule = true;
8749 }
8750 if (reschedule) {
8751 scheduleBroadcastsLocked();
8752 }
8753 }
8754
Dan Egnor60d87622009-12-16 16:32:58 -08008755 /**
8756 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8757 * The application process will exit immediately after this call returns.
8758 * @param app object of the crashing app, null for the system server
8759 * @param crashInfo describing the exception
8760 */
8761 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8762 ProcessRecord r = findAppProcess(app);
8763
8764 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8765 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008766 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008767 crashInfo.exceptionClassName,
8768 crashInfo.exceptionMessage,
8769 crashInfo.throwFileName,
8770 crashInfo.throwLineNumber);
8771
Dan Egnor42471dd2010-01-07 17:25:22 -08008772 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008773
8774 crashApplication(r, crashInfo);
8775 }
8776
8777 /**
8778 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8779 * @param app object of the crashing app, null for the system server
8780 * @param tag reported by the caller
8781 * @param crashInfo describing the context of the error
8782 * @return true if the process should exit immediately (WTF is fatal)
8783 */
8784 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008785 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008786 ProcessRecord r = findAppProcess(app);
8787
8788 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8789 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008790 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008791 tag, crashInfo.exceptionMessage);
8792
Dan Egnor42471dd2010-01-07 17:25:22 -08008793 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008794
Doug Zongker43866e02010-01-07 12:09:54 -08008795 if (Settings.Secure.getInt(mContext.getContentResolver(),
8796 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008797 crashApplication(r, crashInfo);
8798 return true;
8799 } else {
8800 return false;
8801 }
8802 }
8803
8804 /**
8805 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8806 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8807 */
8808 private ProcessRecord findAppProcess(IBinder app) {
8809 if (app == null) {
8810 return null;
8811 }
8812
8813 synchronized (this) {
8814 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8815 final int NA = apps.size();
8816 for (int ia=0; ia<NA; ia++) {
8817 ProcessRecord p = apps.valueAt(ia);
8818 if (p.thread != null && p.thread.asBinder() == app) {
8819 return p;
8820 }
8821 }
8822 }
8823
8824 Log.w(TAG, "Can't find mystery application: " + app);
8825 return null;
8826 }
8827 }
8828
8829 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008830 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008831 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008832 * @param process which caused the error, null means the system server
8833 * @param activity which triggered the error, null if unknown
8834 * @param parent activity related to the error, null if unknown
8835 * @param subject line related to the error, null if absent
8836 * @param report in long form describing the error, null if absent
8837 * @param logFile to include in the report, null if none
8838 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008839 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008840 private void addErrorToDropBox(String eventType,
8841 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8842 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008843 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008844 String dropboxTag;
8845 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008846 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008847 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008848 dropboxTag = "system_app_" + eventType;
8849 } else {
8850 dropboxTag = "data_app_" + eventType;
8851 }
8852
8853 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8854 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8855 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008856 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008857 sb.append("Process: system_server\n");
8858 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008859 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008860 }
8861 if (process != null) {
8862 int flags = process.info.flags;
8863 IPackageManager pm = ActivityThread.getPackageManager();
8864 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8865 for (String pkg : process.pkgList) {
8866 sb.append("Package: ").append(pkg);
8867 try {
8868 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8869 if (pi != null) {
8870 sb.append(" v").append(pi.versionCode);
8871 if (pi.versionName != null) {
8872 sb.append(" (").append(pi.versionName).append(")");
8873 }
8874 }
8875 } catch (RemoteException e) {
8876 Log.e(TAG, "Error getting package info: " + pkg, e);
8877 }
8878 sb.append("\n");
8879 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008880 }
8881 if (activity != null) {
8882 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
8883 }
8884 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
8885 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
8886 }
8887 if (parent != null && parent != activity) {
8888 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
8889 }
8890 if (subject != null) {
8891 sb.append("Subject: ").append(subject).append("\n");
8892 }
8893 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
8894 sb.append("\n");
8895 if (report != null) {
8896 sb.append(report);
8897 }
8898 if (logFile != null) {
8899 try {
8900 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
8901 } catch (IOException e) {
8902 Log.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08008903 }
8904 }
Dan Egnor60d87622009-12-16 16:32:58 -08008905 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008906 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08008907 }
8908 dbox.addText(dropboxTag, sb.toString());
8909 }
8910 }
8911
8912 /**
8913 * Bring up the "unexpected error" dialog box for a crashing app.
8914 * Deal with edge cases (intercepts from instrumented applications,
8915 * ActivityController, error intent receivers, that sort of thing).
8916 * @param r the application crashing
8917 * @param crashInfo describing the failure
8918 */
8919 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008920 long timeMillis = System.currentTimeMillis();
8921 String shortMsg = crashInfo.exceptionClassName;
8922 String longMsg = crashInfo.exceptionMessage;
8923 String stackTrace = crashInfo.stackTrace;
8924 if (shortMsg != null && longMsg != null) {
8925 longMsg = shortMsg + ": " + longMsg;
8926 } else if (shortMsg != null) {
8927 longMsg = shortMsg;
8928 }
8929
Dan Egnor60d87622009-12-16 16:32:58 -08008930 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008932 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 try {
8934 String name = r != null ? r.processName : null;
8935 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08008936 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08008937 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938 Log.w(TAG, "Force-killing crashed app " + name
8939 + " at watcher's request");
8940 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08008941 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 }
8943 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008944 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008945 }
8946 }
8947
8948 final long origId = Binder.clearCallingIdentity();
8949
8950 // If this process is running instrumentation, finish it.
8951 if (r != null && r.instrumentationClass != null) {
8952 Log.w(TAG, "Error in app " + r.processName
8953 + " running instrumentation " + r.instrumentationClass + ":");
8954 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
8955 if (longMsg != null) Log.w(TAG, " " + longMsg);
8956 Bundle info = new Bundle();
8957 info.putString("shortMsg", shortMsg);
8958 info.putString("longMsg", longMsg);
8959 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
8960 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008961 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 }
8963
Dan Egnor60d87622009-12-16 16:32:58 -08008964 // If we can't identify the process or it's already exceeded its crash quota,
8965 // quit right away without showing a crash dialog.
8966 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08008968 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008969 }
8970
8971 Message msg = Message.obtain();
8972 msg.what = SHOW_ERROR_MSG;
8973 HashMap data = new HashMap();
8974 data.put("result", result);
8975 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 msg.obj = data;
8977 mHandler.sendMessage(msg);
8978
8979 Binder.restoreCallingIdentity(origId);
8980 }
8981
8982 int res = result.get();
8983
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008984 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 synchronized (this) {
8986 if (r != null) {
8987 mProcessCrashTimes.put(r.info.processName, r.info.uid,
8988 SystemClock.uptimeMillis());
8989 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008990 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08008991 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02008992 }
8993 }
8994
8995 if (appErrorIntent != null) {
8996 try {
8997 mContext.startActivity(appErrorIntent);
8998 } catch (ActivityNotFoundException e) {
8999 Log.w(TAG, "bug report receiver dissappeared", e);
9000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009003
9004 Intent createAppErrorIntentLocked(ProcessRecord r,
9005 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9006 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009007 if (report == null) {
9008 return null;
9009 }
9010 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9011 result.setComponent(r.errorReportReceiver);
9012 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9013 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9014 return result;
9015 }
9016
Dan Egnorb7f03672009-12-09 16:22:32 -08009017 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9018 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009019 if (r.errorReportReceiver == null) {
9020 return null;
9021 }
9022
9023 if (!r.crashing && !r.notResponding) {
9024 return null;
9025 }
9026
Dan Egnorb7f03672009-12-09 16:22:32 -08009027 ApplicationErrorReport report = new ApplicationErrorReport();
9028 report.packageName = r.info.packageName;
9029 report.installerPackageName = r.errorReportReceiver.getPackageName();
9030 report.processName = r.processName;
9031 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009032 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009033
Dan Egnorb7f03672009-12-09 16:22:32 -08009034 if (r.crashing) {
9035 report.type = ApplicationErrorReport.TYPE_CRASH;
9036 report.crashInfo = crashInfo;
9037 } else if (r.notResponding) {
9038 report.type = ApplicationErrorReport.TYPE_ANR;
9039 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009040
Dan Egnorb7f03672009-12-09 16:22:32 -08009041 report.anrInfo.activity = r.notRespondingReport.tag;
9042 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9043 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009044 }
9045
Dan Egnorb7f03672009-12-09 16:22:32 -08009046 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009047 }
9048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9050 // assume our apps are happy - lazy create the list
9051 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9052
9053 synchronized (this) {
9054
9055 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009056 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9057 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9059 // This one's in trouble, so we'll generate a report for it
9060 // crashes are higher priority (in case there's a crash *and* an anr)
9061 ActivityManager.ProcessErrorStateInfo report = null;
9062 if (app.crashing) {
9063 report = app.crashingReport;
9064 } else if (app.notResponding) {
9065 report = app.notRespondingReport;
9066 }
9067
9068 if (report != null) {
9069 if (errList == null) {
9070 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9071 }
9072 errList.add(report);
9073 } else {
9074 Log.w(TAG, "Missing app error report, app = " + app.processName +
9075 " crashing = " + app.crashing +
9076 " notResponding = " + app.notResponding);
9077 }
9078 }
9079 }
9080 }
9081
9082 return errList;
9083 }
9084
9085 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9086 // Lazy instantiation of list
9087 List<ActivityManager.RunningAppProcessInfo> runList = null;
9088 synchronized (this) {
9089 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009090 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9091 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9093 // Generate process state info for running application
9094 ActivityManager.RunningAppProcessInfo currApp =
9095 new ActivityManager.RunningAppProcessInfo(app.processName,
9096 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009097 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009099 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9101 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9102 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009103 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9104 } else if (adj >= HOME_APP_ADJ) {
9105 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9106 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 } else if (adj >= SECONDARY_SERVER_ADJ) {
9108 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9109 } else if (adj >= VISIBLE_APP_ADJ) {
9110 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9111 } else {
9112 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9113 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009114 currApp.importanceReasonCode = app.adjTypeCode;
9115 if (app.adjSource instanceof ProcessRecord) {
9116 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9117 } else if (app.adjSource instanceof HistoryRecord) {
9118 HistoryRecord r = (HistoryRecord)app.adjSource;
9119 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9120 }
9121 if (app.adjTarget instanceof ComponentName) {
9122 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
9125 // + " lru=" + currApp.lru);
9126 if (runList == null) {
9127 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9128 }
9129 runList.add(currApp);
9130 }
9131 }
9132 }
9133 return runList;
9134 }
9135
9136 @Override
9137 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009138 if (checkCallingPermission(android.Manifest.permission.DUMP)
9139 != PackageManager.PERMISSION_GRANTED) {
9140 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9141 + Binder.getCallingPid()
9142 + ", uid=" + Binder.getCallingUid()
9143 + " without permission "
9144 + android.Manifest.permission.DUMP);
9145 return;
9146 }
9147
9148 boolean dumpAll = false;
9149
9150 int opti = 0;
9151 while (opti < args.length) {
9152 String opt = args[opti];
9153 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9154 break;
9155 }
9156 opti++;
9157 if ("-a".equals(opt)) {
9158 dumpAll = true;
9159 } else if ("-h".equals(opt)) {
9160 pw.println("Activity manager dump options:");
9161 pw.println(" [-a] [h- [cmd] ...");
9162 pw.println(" cmd may be one of:");
9163 pw.println(" activities: activity stack state");
9164 pw.println(" broadcasts: broadcast state");
9165 pw.println(" intents: pending intent state");
9166 pw.println(" processes: process state");
9167 pw.println(" providers: content provider state");
9168 pw.println(" services: service state");
9169 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009171 } else {
9172 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009174 }
9175
9176 // Is the caller requesting to dump a particular piece of data?
9177 if (opti < args.length) {
9178 String cmd = args[opti];
9179 opti++;
9180 if ("activities".equals(cmd) || "a".equals(cmd)) {
9181 synchronized (this) {
9182 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009184 return;
9185 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9186 synchronized (this) {
9187 dumpBroadcastsLocked(fd, pw, args, opti, true);
9188 }
9189 return;
9190 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9191 synchronized (this) {
9192 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9193 }
9194 return;
9195 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9196 synchronized (this) {
9197 dumpProcessesLocked(fd, pw, args, opti, true);
9198 }
9199 return;
9200 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9201 synchronized (this) {
9202 dumpProvidersLocked(fd, pw, args, opti, true);
9203 }
9204 return;
9205 } else if ("service".equals(cmd)) {
9206 dumpService(fd, pw, args, opti, true);
9207 return;
9208 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9209 synchronized (this) {
9210 dumpServicesLocked(fd, pw, args, opti, true);
9211 }
9212 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009214 }
9215
9216 // No piece of data specified, dump everything.
9217 synchronized (this) {
9218 boolean needSep;
9219 if (dumpAll) {
9220 pw.println("Providers in Current Activity Manager State:");
9221 }
9222 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9223 if (needSep) {
9224 pw.println(" ");
9225 }
9226 if (dumpAll) {
9227 pw.println("-------------------------------------------------------------------------------");
9228 pw.println("Broadcasts in Current Activity Manager State:");
9229 }
9230 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9231 if (needSep) {
9232 pw.println(" ");
9233 }
9234 if (dumpAll) {
9235 pw.println("-------------------------------------------------------------------------------");
9236 pw.println("Services in Current Activity Manager State:");
9237 }
9238 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9239 if (needSep) {
9240 pw.println(" ");
9241 }
9242 if (dumpAll) {
9243 pw.println("-------------------------------------------------------------------------------");
9244 pw.println("PendingIntents in Current Activity Manager State:");
9245 }
9246 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9247 if (needSep) {
9248 pw.println(" ");
9249 }
9250 if (dumpAll) {
9251 pw.println("-------------------------------------------------------------------------------");
9252 pw.println("Activities in Current Activity Manager State:");
9253 }
9254 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9255 if (needSep) {
9256 pw.println(" ");
9257 }
9258 if (dumpAll) {
9259 pw.println("-------------------------------------------------------------------------------");
9260 pw.println("Processes in Current Activity Manager State:");
9261 }
9262 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9263 }
9264 }
9265
9266 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9267 int opti, boolean dumpAll, boolean needHeader) {
9268 if (needHeader) {
9269 pw.println(" Activity stack:");
9270 }
9271 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9272 pw.println(" ");
9273 pw.println(" Running activities (most recent first):");
9274 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9275 if (mWaitingVisibleActivities.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 for another to become visible:");
9278 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9279 }
9280 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009282 pw.println(" Activities waiting to stop:");
9283 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9284 }
9285 if (mFinishingActivities.size() > 0) {
9286 pw.println(" ");
9287 pw.println(" Activities waiting to finish:");
9288 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009291 pw.println(" ");
9292 pw.println(" mPausingActivity: " + mPausingActivity);
9293 pw.println(" mResumedActivity: " + mResumedActivity);
9294 pw.println(" mFocusedActivity: " + mFocusedActivity);
9295 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009297 if (dumpAll && mRecentTasks.size() > 0) {
9298 pw.println(" ");
9299 pw.println("Recent tasks in Current Activity Manager State:");
9300
9301 final int N = mRecentTasks.size();
9302 for (int i=0; i<N; i++) {
9303 TaskRecord tr = mRecentTasks.get(i);
9304 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9305 pw.println(tr);
9306 mRecentTasks.get(i).dump(pw, " ");
9307 }
9308 }
9309
9310 pw.println(" ");
9311 pw.println(" mCurTask: " + mCurTask);
9312
9313 return true;
9314 }
9315
9316 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9317 int opti, boolean dumpAll) {
9318 boolean needSep = false;
9319 int numPers = 0;
9320
9321 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009322 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9323 final int NA = procs.size();
9324 for (int ia=0; ia<NA; ia++) {
9325 if (!needSep) {
9326 pw.println(" All known processes:");
9327 needSep = true;
9328 }
9329 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009330 pw.print(r.persistent ? " *PERS*" : " *APP*");
9331 pw.print(" UID "); pw.print(procs.keyAt(ia));
9332 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 r.dump(pw, " ");
9334 if (r.persistent) {
9335 numPers++;
9336 }
9337 }
9338 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009339 }
9340
9341 if (mLruProcesses.size() > 0) {
9342 if (needSep) pw.println(" ");
9343 needSep = true;
9344 pw.println(" Running processes (most recent first):");
9345 dumpProcessList(pw, this, mLruProcesses, " ",
9346 "App ", "PERS", true);
9347 needSep = true;
9348 }
9349
9350 synchronized (mPidsSelfLocked) {
9351 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009352 if (needSep) pw.println(" ");
9353 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009354 pw.println(" PID mappings:");
9355 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9356 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9357 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 }
9359 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009360 }
9361
9362 if (mForegroundProcesses.size() > 0) {
9363 if (needSep) pw.println(" ");
9364 needSep = true;
9365 pw.println(" Foreground Processes:");
9366 for (int i=0; i<mForegroundProcesses.size(); i++) {
9367 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9368 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009370 }
9371
9372 if (mPersistentStartingProcesses.size() > 0) {
9373 if (needSep) pw.println(" ");
9374 needSep = true;
9375 pw.println(" Persisent processes that are starting:");
9376 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9377 "Starting Norm", "Restarting PERS", false);
9378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009380 if (mStartingProcesses.size() > 0) {
9381 if (needSep) pw.println(" ");
9382 needSep = true;
9383 pw.println(" Processes that are starting:");
9384 dumpProcessList(pw, this, mStartingProcesses, " ",
9385 "Starting Norm", "Starting PERS", false);
9386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009388 if (mRemovedProcesses.size() > 0) {
9389 if (needSep) pw.println(" ");
9390 needSep = true;
9391 pw.println(" Processes that are being removed:");
9392 dumpProcessList(pw, this, mRemovedProcesses, " ",
9393 "Removed Norm", "Removed PERS", false);
9394 }
9395
9396 if (mProcessesOnHold.size() > 0) {
9397 if (needSep) pw.println(" ");
9398 needSep = true;
9399 pw.println(" Processes that are on old until the system is ready:");
9400 dumpProcessList(pw, this, mProcessesOnHold, " ",
9401 "OnHold Norm", "OnHold PERS", false);
9402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009404 if (mProcessesToGc.size() > 0) {
9405 if (needSep) pw.println(" ");
9406 needSep = true;
9407 pw.println(" Processes that are waiting to GC:");
9408 long now = SystemClock.uptimeMillis();
9409 for (int i=0; i<mProcessesToGc.size(); i++) {
9410 ProcessRecord proc = mProcessesToGc.get(i);
9411 pw.print(" Process "); pw.println(proc);
9412 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9413 pw.print(", last gced=");
9414 pw.print(now-proc.lastRequestedGc);
9415 pw.print(" ms ago, last lowMem=");
9416 pw.print(now-proc.lastLowMemory);
9417 pw.println(" ms ago");
9418
9419 }
9420 }
9421
9422 if (mProcessCrashTimes.getMap().size() > 0) {
9423 if (needSep) pw.println(" ");
9424 needSep = true;
9425 pw.println(" Time since processes crashed:");
9426 long now = SystemClock.uptimeMillis();
9427 for (Map.Entry<String, SparseArray<Long>> procs
9428 : mProcessCrashTimes.getMap().entrySet()) {
9429 SparseArray<Long> uids = procs.getValue();
9430 final int N = uids.size();
9431 for (int i=0; i<N; i++) {
9432 pw.print(" Process "); pw.print(procs.getKey());
9433 pw.print(" uid "); pw.print(uids.keyAt(i));
9434 pw.print(": last crashed ");
9435 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009436 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009437 }
9438 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009440
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009441 if (mBadProcesses.getMap().size() > 0) {
9442 if (needSep) pw.println(" ");
9443 needSep = true;
9444 pw.println(" Bad processes:");
9445 for (Map.Entry<String, SparseArray<Long>> procs
9446 : mBadProcesses.getMap().entrySet()) {
9447 SparseArray<Long> uids = procs.getValue();
9448 final int N = uids.size();
9449 for (int i=0; i<N; i++) {
9450 pw.print(" Bad process "); pw.print(procs.getKey());
9451 pw.print(" uid "); pw.print(uids.keyAt(i));
9452 pw.print(": crashed at time ");
9453 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 }
9455 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009457
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009458 pw.println(" ");
9459 pw.println(" mHomeProcess: " + mHomeProcess);
9460 pw.println(" mConfiguration: " + mConfiguration);
9461 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9462 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9463 || mOrigWaitForDebugger) {
9464 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9465 + " mDebugTransient=" + mDebugTransient
9466 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9467 }
9468 if (mAlwaysFinishActivities || mController != null) {
9469 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9470 + " mController=" + mController);
9471 }
9472 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009474 pw.println(" mStartRunning=" + mStartRunning
9475 + " mSystemReady=" + mSystemReady
9476 + " mBooting=" + mBooting
9477 + " mBooted=" + mBooted
9478 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 pw.println(" mGoingToSleep=" + mGoingToSleep);
9480 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009482
9483 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 }
9485
9486 /**
9487 * There are three ways to call this:
9488 * - no service specified: dump all the services
9489 * - a flattened component name that matched an existing service was specified as the
9490 * first arg: dump that one service
9491 * - the first arg isn't the flattened component name of an existing service:
9492 * dump all services whose component contains the first arg as a substring
9493 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009494 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9495 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009496 String[] newArgs;
9497 String componentNameString;
9498 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009499 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500 componentNameString = null;
9501 newArgs = EMPTY_STRING_ARRAY;
9502 r = null;
9503 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009504 componentNameString = args[opti];
9505 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9507 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009508 newArgs = new String[args.length - opti];
9509 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009510 }
9511
9512 if (r != null) {
9513 dumpService(fd, pw, r, newArgs);
9514 } else {
9515 for (ServiceRecord r1 : mServices.values()) {
9516 if (componentNameString == null
9517 || r1.name.flattenToString().contains(componentNameString)) {
9518 dumpService(fd, pw, r1, newArgs);
9519 }
9520 }
9521 }
9522 }
9523
9524 /**
9525 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9526 * there is a thread associated with the service.
9527 */
9528 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9529 pw.println(" Service " + r.name.flattenToString());
9530 if (r.app != null && r.app.thread != null) {
9531 try {
9532 // flush anything that is already in the PrintWriter since the thread is going
9533 // to write to the file descriptor directly
9534 pw.flush();
9535 r.app.thread.dumpService(fd, r, args);
9536 pw.print("\n");
9537 } catch (RemoteException e) {
9538 pw.println("got a RemoteException while dumping the service");
9539 }
9540 }
9541 }
9542
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009543 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9544 int opti, boolean dumpAll) {
9545 boolean needSep = false;
9546
9547 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009548 if (mRegisteredReceivers.size() > 0) {
9549 pw.println(" ");
9550 pw.println(" Registered Receivers:");
9551 Iterator it = mRegisteredReceivers.values().iterator();
9552 while (it.hasNext()) {
9553 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009554 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555 r.dump(pw, " ");
9556 }
9557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 pw.println(" ");
9560 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009561 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009562 needSep = true;
9563 }
9564
9565 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9566 || mPendingBroadcast != null) {
9567 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009569 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009571 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9572 pw.println(" Broadcast #" + i + ":");
9573 mParallelBroadcasts.get(i).dump(pw, " ");
9574 }
9575 if (mOrderedBroadcasts.size() > 0) {
9576 pw.println(" ");
9577 pw.println(" Active serialized broadcasts:");
9578 }
9579 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9580 pw.println(" Serialized Broadcast #" + i + ":");
9581 mOrderedBroadcasts.get(i).dump(pw, " ");
9582 }
9583 pw.println(" ");
9584 pw.println(" Pending broadcast:");
9585 if (mPendingBroadcast != null) {
9586 mPendingBroadcast.dump(pw, " ");
9587 } else {
9588 pw.println(" (null)");
9589 }
9590 needSep = true;
9591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009593 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009594 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009595 pw.println(" Historical broadcasts:");
9596 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9597 BroadcastRecord r = mBroadcastHistory[i];
9598 if (r == null) {
9599 break;
9600 }
9601 pw.println(" Historical Broadcast #" + i + ":");
9602 r.dump(pw, " ");
9603 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009604 needSep = true;
9605 }
9606
9607 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009608 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009609 pw.println(" Sticky broadcasts:");
9610 StringBuilder sb = new StringBuilder(128);
9611 for (Map.Entry<String, ArrayList<Intent>> ent
9612 : mStickyBroadcasts.entrySet()) {
9613 pw.print(" * Sticky action "); pw.print(ent.getKey());
9614 pw.println(":");
9615 ArrayList<Intent> intents = ent.getValue();
9616 final int N = intents.size();
9617 for (int i=0; i<N; i++) {
9618 sb.setLength(0);
9619 sb.append(" Intent: ");
9620 intents.get(i).toShortString(sb, true, false);
9621 pw.println(sb.toString());
9622 Bundle bundle = intents.get(i).getExtras();
9623 if (bundle != null) {
9624 pw.print(" ");
9625 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 }
9627 }
9628 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009629 needSep = true;
9630 }
9631
9632 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009634 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 pw.println(" mHandler:");
9636 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009637 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009639
9640 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641 }
9642
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009643 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9644 int opti, boolean dumpAll) {
9645 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009647 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009648 if (mServices.size() > 0) {
9649 pw.println(" Active services:");
9650 Iterator<ServiceRecord> it = mServices.values().iterator();
9651 while (it.hasNext()) {
9652 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009653 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654 r.dump(pw, " ");
9655 }
9656 needSep = true;
9657 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009660 if (mPendingServices.size() > 0) {
9661 if (needSep) pw.println(" ");
9662 pw.println(" Pending services:");
9663 for (int i=0; i<mPendingServices.size(); i++) {
9664 ServiceRecord r = mPendingServices.get(i);
9665 pw.print(" * Pending "); pw.println(r);
9666 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009668 needSep = true;
9669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009671 if (mRestartingServices.size() > 0) {
9672 if (needSep) pw.println(" ");
9673 pw.println(" Restarting services:");
9674 for (int i=0; i<mRestartingServices.size(); i++) {
9675 ServiceRecord r = mRestartingServices.get(i);
9676 pw.print(" * Restarting "); pw.println(r);
9677 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009679 needSep = true;
9680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009682 if (mStoppingServices.size() > 0) {
9683 if (needSep) pw.println(" ");
9684 pw.println(" Stopping services:");
9685 for (int i=0; i<mStoppingServices.size(); i++) {
9686 ServiceRecord r = mStoppingServices.get(i);
9687 pw.print(" * Stopping "); pw.println(r);
9688 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009690 needSep = true;
9691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009693 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009694 if (mServiceConnections.size() > 0) {
9695 if (needSep) pw.println(" ");
9696 pw.println(" Connection bindings to services:");
9697 Iterator<ConnectionRecord> it
9698 = mServiceConnections.values().iterator();
9699 while (it.hasNext()) {
9700 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009701 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 r.dump(pw, " ");
9703 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009704 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 }
9706 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009707
9708 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709 }
9710
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009711 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9712 int opti, boolean dumpAll) {
9713 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009714
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009715 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 if (mProvidersByClass.size() > 0) {
9717 if (needSep) pw.println(" ");
9718 pw.println(" Published content providers (by class):");
9719 Iterator it = mProvidersByClass.entrySet().iterator();
9720 while (it.hasNext()) {
9721 Map.Entry e = (Map.Entry)it.next();
9722 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009723 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009724 r.dump(pw, " ");
9725 }
9726 needSep = true;
9727 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009728
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009729 if (mProvidersByName.size() > 0) {
9730 pw.println(" ");
9731 pw.println(" Authority to provider mappings:");
9732 Iterator it = mProvidersByName.entrySet().iterator();
9733 while (it.hasNext()) {
9734 Map.Entry e = (Map.Entry)it.next();
9735 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9736 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9737 pw.println(r);
9738 }
9739 needSep = true;
9740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009742
9743 if (mLaunchingProviders.size() > 0) {
9744 if (needSep) pw.println(" ");
9745 pw.println(" Launching content providers:");
9746 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9747 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9748 pw.println(mLaunchingProviders.get(i));
9749 }
9750 needSep = true;
9751 }
9752
9753 if (mGrantedUriPermissions.size() > 0) {
9754 pw.println();
9755 pw.println("Granted Uri Permissions:");
9756 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9757 int uid = mGrantedUriPermissions.keyAt(i);
9758 HashMap<Uri, UriPermission> perms
9759 = mGrantedUriPermissions.valueAt(i);
9760 pw.print(" * UID "); pw.print(uid);
9761 pw.println(" holds:");
9762 for (UriPermission perm : perms.values()) {
9763 pw.print(" "); pw.println(perm);
9764 perm.dump(pw, " ");
9765 }
9766 }
9767 needSep = true;
9768 }
9769
9770 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009771 }
9772
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009773 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9774 int opti, boolean dumpAll) {
9775 boolean needSep = false;
9776
9777 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 if (this.mIntentSenderRecords.size() > 0) {
9779 Iterator<WeakReference<PendingIntentRecord>> it
9780 = mIntentSenderRecords.values().iterator();
9781 while (it.hasNext()) {
9782 WeakReference<PendingIntentRecord> ref = it.next();
9783 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009784 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009786 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009787 rec.dump(pw, " ");
9788 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009789 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790 }
9791 }
9792 }
9793 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009794
9795 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 }
9797
9798 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009799 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009800 TaskRecord lastTask = null;
9801 for (int i=list.size()-1; i>=0; i--) {
9802 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009803 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009804 if (lastTask != r.task) {
9805 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009806 pw.print(prefix);
9807 pw.print(full ? "* " : " ");
9808 pw.println(lastTask);
9809 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009810 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009813 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9814 pw.print(" #"); pw.print(i); pw.print(": ");
9815 pw.println(r);
9816 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009817 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 }
9820 }
9821
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009822 private static String buildOomTag(String prefix, String space, int val, int base) {
9823 if (val == base) {
9824 if (space == null) return prefix;
9825 return prefix + " ";
9826 }
9827 return prefix + "+" + Integer.toString(val-base);
9828 }
9829
9830 private static final int dumpProcessList(PrintWriter pw,
9831 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 String prefix, String normalLabel, String persistentLabel,
9833 boolean inclOomAdj) {
9834 int numPers = 0;
9835 for (int i=list.size()-1; i>=0; i--) {
9836 ProcessRecord r = (ProcessRecord)list.get(i);
9837 if (false) {
9838 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9839 + " #" + i + ":");
9840 r.dump(pw, prefix + " ");
9841 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009842 String oomAdj;
9843 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009844 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009845 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009846 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9847 } else if (r.setAdj >= HOME_APP_ADJ) {
9848 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9849 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9850 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9851 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9852 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9853 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9854 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9855 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9856 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009857 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009858 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009859 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009860 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009861 } else {
9862 oomAdj = Integer.toString(r.setAdj);
9863 }
9864 String schedGroup;
9865 switch (r.setSchedGroup) {
9866 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9867 schedGroup = "B";
9868 break;
9869 case Process.THREAD_GROUP_DEFAULT:
9870 schedGroup = "F";
9871 break;
9872 default:
9873 schedGroup = Integer.toString(r.setSchedGroup);
9874 break;
9875 }
9876 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009878 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009879 if (r.adjSource != null || r.adjTarget != null) {
9880 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009881 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 } else {
9884 pw.println(String.format("%s%s #%2d: %s",
9885 prefix, (r.persistent ? persistentLabel : normalLabel),
9886 i, r.toString()));
9887 }
9888 if (r.persistent) {
9889 numPers++;
9890 }
9891 }
9892 return numPers;
9893 }
9894
9895 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
9896 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009897 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 long uptime = SystemClock.uptimeMillis();
9899 long realtime = SystemClock.elapsedRealtime();
9900
9901 if (isCheckinRequest) {
9902 // short checkin version
9903 pw.println(uptime + "," + realtime);
9904 pw.flush();
9905 } else {
9906 pw.println("Applications Memory Usage (kB):");
9907 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9908 }
9909 for (int i = list.size() - 1 ; i >= 0 ; i--) {
9910 ProcessRecord r = (ProcessRecord)list.get(i);
9911 if (r.thread != null) {
9912 if (!isCheckinRequest) {
9913 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9914 pw.flush();
9915 }
9916 try {
9917 r.thread.asBinder().dump(fd, args);
9918 } catch (RemoteException e) {
9919 if (!isCheckinRequest) {
9920 pw.println("Got RemoteException!");
9921 pw.flush();
9922 }
9923 }
9924 }
9925 }
9926 }
9927
9928 /**
9929 * Searches array of arguments for the specified string
9930 * @param args array of argument strings
9931 * @param value value to search for
9932 * @return true if the value is contained in the array
9933 */
9934 private static boolean scanArgs(String[] args, String value) {
9935 if (args != null) {
9936 for (String arg : args) {
9937 if (value.equals(arg)) {
9938 return true;
9939 }
9940 }
9941 }
9942 return false;
9943 }
9944
Dianne Hackborn75b03852009-06-12 15:43:26 -07009945 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 int count = mHistory.size();
9947
9948 // convert the token to an entry in the history.
9949 HistoryRecord r = null;
9950 int index = -1;
9951 for (int i=count-1; i>=0; i--) {
9952 Object o = mHistory.get(i);
9953 if (o == token) {
9954 r = (HistoryRecord)o;
9955 index = i;
9956 break;
9957 }
9958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009959
9960 return index;
9961 }
9962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 private final void killServicesLocked(ProcessRecord app,
9964 boolean allowRestart) {
9965 // Report disconnected services.
9966 if (false) {
9967 // XXX we are letting the client link to the service for
9968 // death notifications.
9969 if (app.services.size() > 0) {
9970 Iterator it = app.services.iterator();
9971 while (it.hasNext()) {
9972 ServiceRecord r = (ServiceRecord)it.next();
9973 if (r.connections.size() > 0) {
9974 Iterator<ConnectionRecord> jt
9975 = r.connections.values().iterator();
9976 while (jt.hasNext()) {
9977 ConnectionRecord c = jt.next();
9978 if (c.binding.client != app) {
9979 try {
9980 //c.conn.connected(r.className, null);
9981 } catch (Exception e) {
9982 // todo: this should be asynchronous!
9983 Log.w(TAG, "Exception thrown disconnected servce "
9984 + r.shortName
9985 + " from app " + app.processName, e);
9986 }
9987 }
9988 }
9989 }
9990 }
9991 }
9992 }
9993
9994 // Clean up any connections this application has to other services.
9995 if (app.connections.size() > 0) {
9996 Iterator<ConnectionRecord> it = app.connections.iterator();
9997 while (it.hasNext()) {
9998 ConnectionRecord r = it.next();
9999 removeConnectionLocked(r, app, null);
10000 }
10001 }
10002 app.connections.clear();
10003
10004 if (app.services.size() != 0) {
10005 // Any services running in the application need to be placed
10006 // back in the pending list.
10007 Iterator it = app.services.iterator();
10008 while (it.hasNext()) {
10009 ServiceRecord sr = (ServiceRecord)it.next();
10010 synchronized (sr.stats.getBatteryStats()) {
10011 sr.stats.stopLaunchedLocked();
10012 }
10013 sr.app = null;
10014 sr.executeNesting = 0;
10015 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010016
10017 boolean hasClients = sr.bindings.size() > 0;
10018 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 Iterator<IntentBindRecord> bindings
10020 = sr.bindings.values().iterator();
10021 while (bindings.hasNext()) {
10022 IntentBindRecord b = bindings.next();
10023 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
10024 + ": shouldUnbind=" + b.hasBound);
10025 b.binder = null;
10026 b.requested = b.received = b.hasBound = false;
10027 }
10028 }
10029
10030 if (sr.crashCount >= 2) {
10031 Log.w(TAG, "Service crashed " + sr.crashCount
10032 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010033 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 sr.crashCount, sr.shortName, app.pid);
10035 bringDownServiceLocked(sr, true);
10036 } else if (!allowRestart) {
10037 bringDownServiceLocked(sr, true);
10038 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010039 boolean canceled = scheduleServiceRestartLocked(sr, true);
10040
10041 // Should the service remain running? Note that in the
10042 // extreme case of so many attempts to deliver a command
10043 // that it failed, that we also will stop it here.
10044 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10045 if (sr.pendingStarts.size() == 0) {
10046 sr.startRequested = false;
10047 if (!hasClients) {
10048 // Whoops, no reason to restart!
10049 bringDownServiceLocked(sr, true);
10050 }
10051 }
10052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 }
10054 }
10055
10056 if (!allowRestart) {
10057 app.services.clear();
10058 }
10059 }
10060
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010061 // Make sure we have no more records on the stopping list.
10062 int i = mStoppingServices.size();
10063 while (i > 0) {
10064 i--;
10065 ServiceRecord sr = mStoppingServices.get(i);
10066 if (sr.app == app) {
10067 mStoppingServices.remove(i);
10068 }
10069 }
10070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 app.executingServices.clear();
10072 }
10073
10074 private final void removeDyingProviderLocked(ProcessRecord proc,
10075 ContentProviderRecord cpr) {
10076 synchronized (cpr) {
10077 cpr.launchingApp = null;
10078 cpr.notifyAll();
10079 }
10080
10081 mProvidersByClass.remove(cpr.info.name);
10082 String names[] = cpr.info.authority.split(";");
10083 for (int j = 0; j < names.length; j++) {
10084 mProvidersByName.remove(names[j]);
10085 }
10086
10087 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10088 while (cit.hasNext()) {
10089 ProcessRecord capp = cit.next();
10090 if (!capp.persistent && capp.thread != null
10091 && capp.pid != 0
10092 && capp.pid != MY_PID) {
10093 Log.i(TAG, "Killing app " + capp.processName
10094 + " (pid " + capp.pid
10095 + ") because provider " + cpr.info.name
10096 + " is in dying process " + proc.processName);
10097 Process.killProcess(capp.pid);
10098 }
10099 }
10100
10101 mLaunchingProviders.remove(cpr);
10102 }
10103
10104 /**
10105 * Main code for cleaning up a process when it has gone away. This is
10106 * called both as a result of the process dying, or directly when stopping
10107 * a process when running in single process mode.
10108 */
10109 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10110 boolean restarting, int index) {
10111 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010112 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113 }
10114
Dianne Hackborn36124872009-10-08 16:22:03 -070010115 mProcessesToGc.remove(app);
10116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 // Dismiss any open dialogs.
10118 if (app.crashDialog != null) {
10119 app.crashDialog.dismiss();
10120 app.crashDialog = null;
10121 }
10122 if (app.anrDialog != null) {
10123 app.anrDialog.dismiss();
10124 app.anrDialog = null;
10125 }
10126 if (app.waitDialog != null) {
10127 app.waitDialog.dismiss();
10128 app.waitDialog = null;
10129 }
10130
10131 app.crashing = false;
10132 app.notResponding = false;
10133
10134 app.resetPackageList();
10135 app.thread = null;
10136 app.forcingToForeground = null;
10137 app.foregroundServices = false;
10138
10139 killServicesLocked(app, true);
10140
10141 boolean restart = false;
10142
10143 int NL = mLaunchingProviders.size();
10144
10145 // Remove published content providers.
10146 if (!app.pubProviders.isEmpty()) {
10147 Iterator it = app.pubProviders.values().iterator();
10148 while (it.hasNext()) {
10149 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10150 cpr.provider = null;
10151 cpr.app = null;
10152
10153 // See if someone is waiting for this provider... in which
10154 // case we don't remove it, but just let it restart.
10155 int i = 0;
10156 if (!app.bad) {
10157 for (; i<NL; i++) {
10158 if (mLaunchingProviders.get(i) == cpr) {
10159 restart = true;
10160 break;
10161 }
10162 }
10163 } else {
10164 i = NL;
10165 }
10166
10167 if (i >= NL) {
10168 removeDyingProviderLocked(app, cpr);
10169 NL = mLaunchingProviders.size();
10170 }
10171 }
10172 app.pubProviders.clear();
10173 }
10174
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010175 // Take care of any launching providers waiting for this process.
10176 if (checkAppInLaunchingProvidersLocked(app, false)) {
10177 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010180 // Unregister from connected content providers.
10181 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010182 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010183 while (it.hasNext()) {
10184 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10185 cpr.clients.remove(app);
10186 }
10187 app.conProviders.clear();
10188 }
10189
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010190 // At this point there may be remaining entries in mLaunchingProviders
10191 // where we were the only one waiting, so they are no longer of use.
10192 // Look for these and clean up if found.
10193 // XXX Commented out for now. Trying to figure out a way to reproduce
10194 // the actual situation to identify what is actually going on.
10195 if (false) {
10196 for (int i=0; i<NL; i++) {
10197 ContentProviderRecord cpr = (ContentProviderRecord)
10198 mLaunchingProviders.get(i);
10199 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10200 synchronized (cpr) {
10201 cpr.launchingApp = null;
10202 cpr.notifyAll();
10203 }
10204 }
10205 }
10206 }
10207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010208 skipCurrentReceiverLocked(app);
10209
10210 // Unregister any receivers.
10211 if (app.receivers.size() > 0) {
10212 Iterator<ReceiverList> it = app.receivers.iterator();
10213 while (it.hasNext()) {
10214 removeReceiverLocked(it.next());
10215 }
10216 app.receivers.clear();
10217 }
10218
Christopher Tate181fafa2009-05-14 11:12:14 -070010219 // If the app is undergoing backup, tell the backup manager about it
10220 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
10221 if (DEBUG_BACKUP) Log.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
10222 try {
10223 IBackupManager bm = IBackupManager.Stub.asInterface(
10224 ServiceManager.getService(Context.BACKUP_SERVICE));
10225 bm.agentDisconnected(app.info.packageName);
10226 } catch (RemoteException e) {
10227 // can't happen; backup manager is local
10228 }
10229 }
10230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 // If the caller is restarting this app, then leave it in its
10232 // current lists and let the caller take care of it.
10233 if (restarting) {
10234 return;
10235 }
10236
10237 if (!app.persistent) {
10238 if (DEBUG_PROCESSES) Log.v(TAG,
10239 "Removing non-persistent process during cleanup: " + app);
10240 mProcessNames.remove(app.processName, app.info.uid);
10241 } else if (!app.removed) {
10242 // This app is persistent, so we need to keep its record around.
10243 // If it is not already on the pending app list, add it there
10244 // and start a new process for it.
10245 app.thread = null;
10246 app.forcingToForeground = null;
10247 app.foregroundServices = false;
10248 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10249 mPersistentStartingProcesses.add(app);
10250 restart = true;
10251 }
10252 }
10253 mProcessesOnHold.remove(app);
10254
The Android Open Source Project4df24232009-03-05 14:34:35 -080010255 if (app == mHomeProcess) {
10256 mHomeProcess = null;
10257 }
10258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 if (restart) {
10260 // We have components that still need to be running in the
10261 // process, so re-launch it.
10262 mProcessNames.put(app.processName, app.info.uid, app);
10263 startProcessLocked(app, "restart", app.processName);
10264 } else if (app.pid > 0 && app.pid != MY_PID) {
10265 // Goodbye!
10266 synchronized (mPidsSelfLocked) {
10267 mPidsSelfLocked.remove(app.pid);
10268 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10269 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010270 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 }
10272 }
10273
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010274 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10275 // Look through the content providers we are waiting to have launched,
10276 // and if any run in this process then either schedule a restart of
10277 // the process or kill the client waiting for it if this process has
10278 // gone bad.
10279 int NL = mLaunchingProviders.size();
10280 boolean restart = false;
10281 for (int i=0; i<NL; i++) {
10282 ContentProviderRecord cpr = (ContentProviderRecord)
10283 mLaunchingProviders.get(i);
10284 if (cpr.launchingApp == app) {
10285 if (!alwaysBad && !app.bad) {
10286 restart = true;
10287 } else {
10288 removeDyingProviderLocked(app, cpr);
10289 NL = mLaunchingProviders.size();
10290 }
10291 }
10292 }
10293 return restart;
10294 }
10295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 // =========================================================
10297 // SERVICES
10298 // =========================================================
10299
10300 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10301 ActivityManager.RunningServiceInfo info =
10302 new ActivityManager.RunningServiceInfo();
10303 info.service = r.name;
10304 if (r.app != null) {
10305 info.pid = r.app.pid;
10306 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010307 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010308 info.process = r.processName;
10309 info.foreground = r.isForeground;
10310 info.activeSince = r.createTime;
10311 info.started = r.startRequested;
10312 info.clientCount = r.connections.size();
10313 info.crashCount = r.crashCount;
10314 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010315 if (r.isForeground) {
10316 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10317 }
10318 if (r.startRequested) {
10319 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10320 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010321 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010322 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10323 }
10324 if (r.app != null && r.app.persistent) {
10325 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10326 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010327 for (ConnectionRecord conn : r.connections.values()) {
10328 if (conn.clientLabel != 0) {
10329 info.clientPackage = conn.binding.client.info.packageName;
10330 info.clientLabel = conn.clientLabel;
10331 break;
10332 }
10333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 return info;
10335 }
10336
10337 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10338 int flags) {
10339 synchronized (this) {
10340 ArrayList<ActivityManager.RunningServiceInfo> res
10341 = new ArrayList<ActivityManager.RunningServiceInfo>();
10342
10343 if (mServices.size() > 0) {
10344 Iterator<ServiceRecord> it = mServices.values().iterator();
10345 while (it.hasNext() && res.size() < maxNum) {
10346 res.add(makeRunningServiceInfoLocked(it.next()));
10347 }
10348 }
10349
10350 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10351 ServiceRecord r = mRestartingServices.get(i);
10352 ActivityManager.RunningServiceInfo info =
10353 makeRunningServiceInfoLocked(r);
10354 info.restarting = r.nextRestartTime;
10355 res.add(info);
10356 }
10357
10358 return res;
10359 }
10360 }
10361
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010362 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10363 synchronized (this) {
10364 ServiceRecord r = mServices.get(name);
10365 if (r != null) {
10366 for (ConnectionRecord conn : r.connections.values()) {
10367 if (conn.clientIntent != null) {
10368 return conn.clientIntent;
10369 }
10370 }
10371 }
10372 }
10373 return null;
10374 }
10375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010376 private final ServiceRecord findServiceLocked(ComponentName name,
10377 IBinder token) {
10378 ServiceRecord r = mServices.get(name);
10379 return r == token ? r : null;
10380 }
10381
10382 private final class ServiceLookupResult {
10383 final ServiceRecord record;
10384 final String permission;
10385
10386 ServiceLookupResult(ServiceRecord _record, String _permission) {
10387 record = _record;
10388 permission = _permission;
10389 }
10390 };
10391
10392 private ServiceLookupResult findServiceLocked(Intent service,
10393 String resolvedType) {
10394 ServiceRecord r = null;
10395 if (service.getComponent() != null) {
10396 r = mServices.get(service.getComponent());
10397 }
10398 if (r == null) {
10399 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10400 r = mServicesByIntent.get(filter);
10401 }
10402
10403 if (r == null) {
10404 try {
10405 ResolveInfo rInfo =
10406 ActivityThread.getPackageManager().resolveService(
10407 service, resolvedType, 0);
10408 ServiceInfo sInfo =
10409 rInfo != null ? rInfo.serviceInfo : null;
10410 if (sInfo == null) {
10411 return null;
10412 }
10413
10414 ComponentName name = new ComponentName(
10415 sInfo.applicationInfo.packageName, sInfo.name);
10416 r = mServices.get(name);
10417 } catch (RemoteException ex) {
10418 // pm is in same process, this will never happen.
10419 }
10420 }
10421 if (r != null) {
10422 int callingPid = Binder.getCallingPid();
10423 int callingUid = Binder.getCallingUid();
10424 if (checkComponentPermission(r.permission,
10425 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10426 != PackageManager.PERMISSION_GRANTED) {
10427 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10428 + " from pid=" + callingPid
10429 + ", uid=" + callingUid
10430 + " requires " + r.permission);
10431 return new ServiceLookupResult(null, r.permission);
10432 }
10433 return new ServiceLookupResult(r, null);
10434 }
10435 return null;
10436 }
10437
10438 private class ServiceRestarter implements Runnable {
10439 private ServiceRecord mService;
10440
10441 void setService(ServiceRecord service) {
10442 mService = service;
10443 }
10444
10445 public void run() {
10446 synchronized(ActivityManagerService.this) {
10447 performServiceRestartLocked(mService);
10448 }
10449 }
10450 }
10451
10452 private ServiceLookupResult retrieveServiceLocked(Intent service,
10453 String resolvedType, int callingPid, int callingUid) {
10454 ServiceRecord r = null;
10455 if (service.getComponent() != null) {
10456 r = mServices.get(service.getComponent());
10457 }
10458 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10459 r = mServicesByIntent.get(filter);
10460 if (r == null) {
10461 try {
10462 ResolveInfo rInfo =
10463 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010464 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010465 ServiceInfo sInfo =
10466 rInfo != null ? rInfo.serviceInfo : null;
10467 if (sInfo == null) {
10468 Log.w(TAG, "Unable to start service " + service +
10469 ": not found");
10470 return null;
10471 }
10472
10473 ComponentName name = new ComponentName(
10474 sInfo.applicationInfo.packageName, sInfo.name);
10475 r = mServices.get(name);
10476 if (r == null) {
10477 filter = new Intent.FilterComparison(service.cloneFilter());
10478 ServiceRestarter res = new ServiceRestarter();
10479 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10480 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10481 synchronized (stats) {
10482 ss = stats.getServiceStatsLocked(
10483 sInfo.applicationInfo.uid, sInfo.packageName,
10484 sInfo.name);
10485 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010486 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487 res.setService(r);
10488 mServices.put(name, r);
10489 mServicesByIntent.put(filter, r);
10490
10491 // Make sure this component isn't in the pending list.
10492 int N = mPendingServices.size();
10493 for (int i=0; i<N; i++) {
10494 ServiceRecord pr = mPendingServices.get(i);
10495 if (pr.name.equals(name)) {
10496 mPendingServices.remove(i);
10497 i--;
10498 N--;
10499 }
10500 }
10501 }
10502 } catch (RemoteException ex) {
10503 // pm is in same process, this will never happen.
10504 }
10505 }
10506 if (r != null) {
10507 if (checkComponentPermission(r.permission,
10508 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10509 != PackageManager.PERMISSION_GRANTED) {
10510 Log.w(TAG, "Permission Denial: Accessing service " + r.name
10511 + " from pid=" + Binder.getCallingPid()
10512 + ", uid=" + Binder.getCallingUid()
10513 + " requires " + r.permission);
10514 return new ServiceLookupResult(null, r.permission);
10515 }
10516 return new ServiceLookupResult(r, null);
10517 }
10518 return null;
10519 }
10520
10521 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10522 long now = SystemClock.uptimeMillis();
10523 if (r.executeNesting == 0 && r.app != null) {
10524 if (r.app.executingServices.size() == 0) {
10525 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10526 msg.obj = r.app;
10527 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10528 }
10529 r.app.executingServices.add(r);
10530 }
10531 r.executeNesting++;
10532 r.executingStart = now;
10533 }
10534
10535 private final void sendServiceArgsLocked(ServiceRecord r,
10536 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010537 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538 if (N == 0) {
10539 return;
10540 }
10541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010542 int i = 0;
10543 while (i < N) {
10544 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010545 ServiceRecord.StartItem si = r.pendingStarts.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010547 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010548 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010549 // If somehow we got a dummy start at the front, then
10550 // just drop it here.
10551 i++;
10552 continue;
10553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010554 bumpServiceExecutingLocked(r);
10555 if (!oomAdjusted) {
10556 oomAdjusted = true;
10557 updateOomAdjLocked(r.app);
10558 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010559 int flags = 0;
10560 if (si.deliveryCount > 0) {
10561 flags |= Service.START_FLAG_RETRY;
10562 }
10563 if (si.doneExecutingCount > 0) {
10564 flags |= Service.START_FLAG_REDELIVERY;
10565 }
10566 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10567 si.deliveredTime = SystemClock.uptimeMillis();
10568 r.deliveredStarts.add(si);
10569 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010571 } catch (RemoteException e) {
10572 // Remote process gone... we'll let the normal cleanup take
10573 // care of this.
10574 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 } catch (Exception e) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010576 Log.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010577 break;
10578 }
10579 }
10580 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010581 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010582 } else {
10583 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010585 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 }
10587 }
10588 }
10589
10590 private final boolean requestServiceBindingLocked(ServiceRecord r,
10591 IntentBindRecord i, boolean rebind) {
10592 if (r.app == null || r.app.thread == null) {
10593 // If service is not currently running, can't yet bind.
10594 return false;
10595 }
10596 if ((!i.requested || rebind) && i.apps.size() > 0) {
10597 try {
10598 bumpServiceExecutingLocked(r);
10599 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
10600 + ": shouldUnbind=" + i.hasBound);
10601 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10602 if (!rebind) {
10603 i.requested = true;
10604 }
10605 i.hasBound = true;
10606 i.doRebind = false;
10607 } catch (RemoteException e) {
10608 return false;
10609 }
10610 }
10611 return true;
10612 }
10613
10614 private final void requestServiceBindingsLocked(ServiceRecord r) {
10615 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10616 while (bindings.hasNext()) {
10617 IntentBindRecord i = bindings.next();
10618 if (!requestServiceBindingLocked(r, i, false)) {
10619 break;
10620 }
10621 }
10622 }
10623
10624 private final void realStartServiceLocked(ServiceRecord r,
10625 ProcessRecord app) throws RemoteException {
10626 if (app.thread == null) {
10627 throw new RemoteException();
10628 }
10629
10630 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010631 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632
10633 app.services.add(r);
10634 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010635 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636
10637 boolean created = false;
10638 try {
10639 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
10640 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010641 mStringBuilder.setLength(0);
10642 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010643 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010644 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010645 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 synchronized (r.stats.getBatteryStats()) {
10647 r.stats.startLaunchedLocked();
10648 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010649 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010650 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010651 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 created = true;
10653 } finally {
10654 if (!created) {
10655 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010656 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010657 }
10658 }
10659
10660 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010661
10662 // If the service is in the started state, and there are no
10663 // pending arguments, then fake up one so its onStartCommand() will
10664 // be called.
10665 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10666 r.lastStartId++;
10667 if (r.lastStartId < 1) {
10668 r.lastStartId = 1;
10669 }
10670 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10671 }
10672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 sendServiceArgsLocked(r, true);
10674 }
10675
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010676 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10677 boolean allowCancel) {
10678 boolean canceled = false;
10679
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010680 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010681 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010682 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010683
10684 // Any delivered but not yet finished starts should be put back
10685 // on the pending list.
10686 final int N = r.deliveredStarts.size();
10687 if (N > 0) {
10688 for (int i=N-1; i>=0; i--) {
10689 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10690 if (si.intent == null) {
10691 // We'll generate this again if needed.
10692 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10693 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10694 r.pendingStarts.add(0, si);
10695 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10696 dur *= 2;
10697 if (minDuration < dur) minDuration = dur;
10698 if (resetTime < dur) resetTime = dur;
10699 } else {
10700 Log.w(TAG, "Canceling start item " + si.intent + " in service "
10701 + r.name);
10702 canceled = true;
10703 }
10704 }
10705 r.deliveredStarts.clear();
10706 }
10707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010708 r.totalRestartCount++;
10709 if (r.restartDelay == 0) {
10710 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010711 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 } else {
10713 // If it has been a "reasonably long time" since the service
10714 // was started, then reset our restart duration back to
10715 // the beginning, so we don't infinitely increase the duration
10716 // on a service that just occasionally gets killed (which is
10717 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010718 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010720 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010722 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010723 if (r.restartDelay < minDuration) {
10724 r.restartDelay = minDuration;
10725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 }
10727 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010728
10729 r.nextRestartTime = now + r.restartDelay;
10730
10731 // Make sure that we don't end up restarting a bunch of services
10732 // all at the same time.
10733 boolean repeat;
10734 do {
10735 repeat = false;
10736 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10737 ServiceRecord r2 = mRestartingServices.get(i);
10738 if (r2 != r && r.nextRestartTime
10739 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10740 && r.nextRestartTime
10741 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10742 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10743 r.restartDelay = r.nextRestartTime - now;
10744 repeat = true;
10745 break;
10746 }
10747 }
10748 } while (repeat);
10749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750 if (!mRestartingServices.contains(r)) {
10751 mRestartingServices.add(r);
10752 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010753
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010754 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010757 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
10759 Log.w(TAG, "Scheduling restart of crashed service "
10760 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010761 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 r.shortName, r.restartDelay);
10763
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010764 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 }
10766
10767 final void performServiceRestartLocked(ServiceRecord r) {
10768 if (!mRestartingServices.contains(r)) {
10769 return;
10770 }
10771 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10772 }
10773
10774 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10775 if (r.restartDelay == 0) {
10776 return false;
10777 }
10778 r.resetRestartCounter();
10779 mRestartingServices.remove(r);
10780 mHandler.removeCallbacks(r.restarter);
10781 return true;
10782 }
10783
10784 private final boolean bringUpServiceLocked(ServiceRecord r,
10785 int intentFlags, boolean whileRestarting) {
10786 //Log.i(TAG, "Bring up service:");
10787 //r.dump(" ");
10788
Dianne Hackborn36124872009-10-08 16:22:03 -070010789 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010790 sendServiceArgsLocked(r, false);
10791 return true;
10792 }
10793
10794 if (!whileRestarting && r.restartDelay > 0) {
10795 // If waiting for a restart, then do nothing.
10796 return true;
10797 }
10798
10799 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
10800 + " " + r.intent);
10801
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010802 // We are now bringing the service up, so no longer in the
10803 // restarting state.
10804 mRestartingServices.remove(r);
10805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 final String appName = r.processName;
10807 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10808 if (app != null && app.thread != null) {
10809 try {
10810 realStartServiceLocked(r, app);
10811 return true;
10812 } catch (RemoteException e) {
10813 Log.w(TAG, "Exception when starting service " + r.shortName, e);
10814 }
10815
10816 // If a dead object exception was thrown -- fall through to
10817 // restart the application.
10818 }
10819
Dianne Hackborn36124872009-10-08 16:22:03 -070010820 // Not running -- get it started, and enqueue this service record
10821 // to be executed when the app comes up.
10822 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10823 "service", r.name, false) == null) {
10824 Log.w(TAG, "Unable to launch app "
10825 + r.appInfo.packageName + "/"
10826 + r.appInfo.uid + " for service "
10827 + r.intent.getIntent() + ": process is bad");
10828 bringDownServiceLocked(r, true);
10829 return false;
10830 }
10831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 mPendingServices.add(r);
10834 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 return true;
10837 }
10838
10839 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
10840 //Log.i(TAG, "Bring down service:");
10841 //r.dump(" ");
10842
10843 // Does it still need to run?
10844 if (!force && r.startRequested) {
10845 return;
10846 }
10847 if (r.connections.size() > 0) {
10848 if (!force) {
10849 // XXX should probably keep a count of the number of auto-create
10850 // connections directly in the service.
10851 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10852 while (it.hasNext()) {
10853 ConnectionRecord cr = it.next();
10854 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10855 return;
10856 }
10857 }
10858 }
10859
10860 // Report to all of the connections that the service is no longer
10861 // available.
10862 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10863 while (it.hasNext()) {
10864 ConnectionRecord c = it.next();
10865 try {
10866 // todo: shouldn't be a synchronous call!
10867 c.conn.connected(r.name, null);
10868 } catch (Exception e) {
10869 Log.w(TAG, "Failure disconnecting service " + r.name +
10870 " to connection " + c.conn.asBinder() +
10871 " (in " + c.binding.client.processName + ")", e);
10872 }
10873 }
10874 }
10875
10876 // Tell the service that it has been unbound.
10877 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10878 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10879 while (it.hasNext()) {
10880 IntentBindRecord ibr = it.next();
10881 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
10882 + ": hasBound=" + ibr.hasBound);
10883 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10884 try {
10885 bumpServiceExecutingLocked(r);
10886 updateOomAdjLocked(r.app);
10887 ibr.hasBound = false;
10888 r.app.thread.scheduleUnbindService(r,
10889 ibr.intent.getIntent());
10890 } catch (Exception e) {
10891 Log.w(TAG, "Exception when unbinding service "
10892 + r.shortName, e);
10893 serviceDoneExecutingLocked(r, true);
10894 }
10895 }
10896 }
10897 }
10898
10899 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
10900 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010901 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010902 System.identityHashCode(r), r.shortName,
10903 (r.app != null) ? r.app.pid : -1);
10904
10905 mServices.remove(r.name);
10906 mServicesByIntent.remove(r.intent);
10907 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
10908 r.totalRestartCount = 0;
10909 unscheduleServiceRestartLocked(r);
10910
10911 // Also make sure it is not on the pending list.
10912 int N = mPendingServices.size();
10913 for (int i=0; i<N; i++) {
10914 if (mPendingServices.get(i) == r) {
10915 mPendingServices.remove(i);
10916 if (DEBUG_SERVICE) Log.v(
10917 TAG, "Removed pending service: " + r.shortName);
10918 i--;
10919 N--;
10920 }
10921 }
10922
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010923 r.cancelNotification();
10924 r.isForeground = false;
10925 r.foregroundId = 0;
10926 r.foregroundNoti = null;
10927
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010928 // Clear start entries.
10929 r.deliveredStarts.clear();
10930 r.pendingStarts.clear();
10931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 if (r.app != null) {
10933 synchronized (r.stats.getBatteryStats()) {
10934 r.stats.stopLaunchedLocked();
10935 }
10936 r.app.services.remove(r);
10937 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 try {
Dianne Hackborna1e989b2009-09-01 19:54:29 -070010939 if (DEBUG_SERVICE) Log.v(TAG,
10940 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 bumpServiceExecutingLocked(r);
10942 mStoppingServices.add(r);
10943 updateOomAdjLocked(r.app);
10944 r.app.thread.scheduleStopService(r);
10945 } catch (Exception e) {
10946 Log.w(TAG, "Exception when stopping service "
10947 + r.shortName, e);
10948 serviceDoneExecutingLocked(r, true);
10949 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010950 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 } else {
10952 if (DEBUG_SERVICE) Log.v(
10953 TAG, "Removed service that has no process: " + r.shortName);
10954 }
10955 } else {
10956 if (DEBUG_SERVICE) Log.v(
10957 TAG, "Removed service that is not running: " + r.shortName);
10958 }
10959 }
10960
10961 ComponentName startServiceLocked(IApplicationThread caller,
10962 Intent service, String resolvedType,
10963 int callingPid, int callingUid) {
10964 synchronized(this) {
10965 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
10966 + " type=" + resolvedType + " args=" + service.getExtras());
10967
10968 if (caller != null) {
10969 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10970 if (callerApp == null) {
10971 throw new SecurityException(
10972 "Unable to find app for caller " + caller
10973 + " (pid=" + Binder.getCallingPid()
10974 + ") when starting service " + service);
10975 }
10976 }
10977
10978 ServiceLookupResult res =
10979 retrieveServiceLocked(service, resolvedType,
10980 callingPid, callingUid);
10981 if (res == null) {
10982 return null;
10983 }
10984 if (res.record == null) {
10985 return new ComponentName("!", res.permission != null
10986 ? res.permission : "private to package");
10987 }
10988 ServiceRecord r = res.record;
10989 if (unscheduleServiceRestartLocked(r)) {
10990 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
10991 + r.shortName);
10992 }
10993 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010994 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 r.lastStartId++;
10996 if (r.lastStartId < 1) {
10997 r.lastStartId = 1;
10998 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010999 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011000 r.lastActivity = SystemClock.uptimeMillis();
11001 synchronized (r.stats.getBatteryStats()) {
11002 r.stats.startRunningLocked();
11003 }
11004 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11005 return new ComponentName("!", "Service process is bad");
11006 }
11007 return r.name;
11008 }
11009 }
11010
11011 public ComponentName startService(IApplicationThread caller, Intent service,
11012 String resolvedType) {
11013 // Refuse possible leaked file descriptors
11014 if (service != null && service.hasFileDescriptors() == true) {
11015 throw new IllegalArgumentException("File descriptors passed in Intent");
11016 }
11017
11018 synchronized(this) {
11019 final int callingPid = Binder.getCallingPid();
11020 final int callingUid = Binder.getCallingUid();
11021 final long origId = Binder.clearCallingIdentity();
11022 ComponentName res = startServiceLocked(caller, service,
11023 resolvedType, callingPid, callingUid);
11024 Binder.restoreCallingIdentity(origId);
11025 return res;
11026 }
11027 }
11028
11029 ComponentName startServiceInPackage(int uid,
11030 Intent service, String resolvedType) {
11031 synchronized(this) {
11032 final long origId = Binder.clearCallingIdentity();
11033 ComponentName res = startServiceLocked(null, service,
11034 resolvedType, -1, uid);
11035 Binder.restoreCallingIdentity(origId);
11036 return res;
11037 }
11038 }
11039
11040 public int stopService(IApplicationThread caller, Intent service,
11041 String resolvedType) {
11042 // Refuse possible leaked file descriptors
11043 if (service != null && service.hasFileDescriptors() == true) {
11044 throw new IllegalArgumentException("File descriptors passed in Intent");
11045 }
11046
11047 synchronized(this) {
11048 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
11049 + " type=" + resolvedType);
11050
11051 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11052 if (caller != null && callerApp == null) {
11053 throw new SecurityException(
11054 "Unable to find app for caller " + caller
11055 + " (pid=" + Binder.getCallingPid()
11056 + ") when stopping service " + service);
11057 }
11058
11059 // If this service is active, make sure it is stopped.
11060 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11061 if (r != null) {
11062 if (r.record != null) {
11063 synchronized (r.record.stats.getBatteryStats()) {
11064 r.record.stats.stopRunningLocked();
11065 }
11066 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011067 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068 final long origId = Binder.clearCallingIdentity();
11069 bringDownServiceLocked(r.record, false);
11070 Binder.restoreCallingIdentity(origId);
11071 return 1;
11072 }
11073 return -1;
11074 }
11075 }
11076
11077 return 0;
11078 }
11079
11080 public IBinder peekService(Intent service, String resolvedType) {
11081 // Refuse possible leaked file descriptors
11082 if (service != null && service.hasFileDescriptors() == true) {
11083 throw new IllegalArgumentException("File descriptors passed in Intent");
11084 }
11085
11086 IBinder ret = null;
11087
11088 synchronized(this) {
11089 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11090
11091 if (r != null) {
11092 // r.record is null if findServiceLocked() failed the caller permission check
11093 if (r.record == null) {
11094 throw new SecurityException(
11095 "Permission Denial: Accessing service " + r.record.name
11096 + " from pid=" + Binder.getCallingPid()
11097 + ", uid=" + Binder.getCallingUid()
11098 + " requires " + r.permission);
11099 }
11100 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11101 if (ib != null) {
11102 ret = ib.binder;
11103 }
11104 }
11105 }
11106
11107 return ret;
11108 }
11109
11110 public boolean stopServiceToken(ComponentName className, IBinder token,
11111 int startId) {
11112 synchronized(this) {
11113 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
11114 + " " + token + " startId=" + startId);
11115 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011116 if (r != null) {
11117 if (startId >= 0) {
11118 // Asked to only stop if done with all work. Note that
11119 // to avoid leaks, we will take this as dropping all
11120 // start items up to and including this one.
11121 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11122 if (si != null) {
11123 while (r.deliveredStarts.size() > 0) {
11124 if (r.deliveredStarts.remove(0) == si) {
11125 break;
11126 }
11127 }
11128 }
11129
11130 if (r.lastStartId != startId) {
11131 return false;
11132 }
11133
11134 if (r.deliveredStarts.size() > 0) {
11135 Log.w(TAG, "stopServiceToken startId " + startId
11136 + " is last, but have " + r.deliveredStarts.size()
11137 + " remaining args");
11138 }
11139 }
11140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 synchronized (r.stats.getBatteryStats()) {
11142 r.stats.stopRunningLocked();
11143 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011144 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 }
11146 final long origId = Binder.clearCallingIdentity();
11147 bringDownServiceLocked(r, false);
11148 Binder.restoreCallingIdentity(origId);
11149 return true;
11150 }
11151 }
11152 return false;
11153 }
11154
11155 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011156 int id, Notification notification, boolean removeNotification) {
11157 final long origId = Binder.clearCallingIdentity();
11158 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 synchronized(this) {
11160 ServiceRecord r = findServiceLocked(className, token);
11161 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011162 if (id != 0) {
11163 if (notification == null) {
11164 throw new IllegalArgumentException("null notification");
11165 }
11166 if (r.foregroundId != id) {
11167 r.cancelNotification();
11168 r.foregroundId = id;
11169 }
11170 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11171 r.foregroundNoti = notification;
11172 r.isForeground = true;
11173 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011174 if (r.app != null) {
11175 updateServiceForegroundLocked(r.app, true);
11176 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011177 } else {
11178 if (r.isForeground) {
11179 r.isForeground = false;
11180 if (r.app != null) {
11181 updateServiceForegroundLocked(r.app, true);
11182 }
11183 }
11184 if (removeNotification) {
11185 r.cancelNotification();
11186 r.foregroundId = 0;
11187 r.foregroundNoti = null;
11188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 }
11190 }
11191 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011192 } finally {
11193 Binder.restoreCallingIdentity(origId);
11194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011195 }
11196
11197 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11198 boolean anyForeground = false;
11199 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11200 if (sr.isForeground) {
11201 anyForeground = true;
11202 break;
11203 }
11204 }
11205 if (anyForeground != proc.foregroundServices) {
11206 proc.foregroundServices = anyForeground;
11207 if (oomAdj) {
11208 updateOomAdjLocked();
11209 }
11210 }
11211 }
11212
11213 public int bindService(IApplicationThread caller, IBinder token,
11214 Intent service, String resolvedType,
11215 IServiceConnection connection, int flags) {
11216 // Refuse possible leaked file descriptors
11217 if (service != null && service.hasFileDescriptors() == true) {
11218 throw new IllegalArgumentException("File descriptors passed in Intent");
11219 }
11220
11221 synchronized(this) {
11222 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
11223 + " type=" + resolvedType + " conn=" + connection.asBinder()
11224 + " flags=0x" + Integer.toHexString(flags));
11225 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11226 if (callerApp == null) {
11227 throw new SecurityException(
11228 "Unable to find app for caller " + caller
11229 + " (pid=" + Binder.getCallingPid()
11230 + ") when binding service " + service);
11231 }
11232
11233 HistoryRecord activity = null;
11234 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011235 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 if (aindex < 0) {
11237 Log.w(TAG, "Binding with unknown activity: " + token);
11238 return 0;
11239 }
11240 activity = (HistoryRecord)mHistory.get(aindex);
11241 }
11242
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011243 int clientLabel = 0;
11244 PendingIntent clientIntent = null;
11245
11246 if (callerApp.info.uid == Process.SYSTEM_UID) {
11247 // Hacky kind of thing -- allow system stuff to tell us
11248 // what they are, so we can report this elsewhere for
11249 // others to know why certain services are running.
11250 try {
11251 clientIntent = (PendingIntent)service.getParcelableExtra(
11252 Intent.EXTRA_CLIENT_INTENT);
11253 } catch (RuntimeException e) {
11254 }
11255 if (clientIntent != null) {
11256 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11257 if (clientLabel != 0) {
11258 // There are no useful extras in the intent, trash them.
11259 // System code calling with this stuff just needs to know
11260 // this will happen.
11261 service = service.cloneFilter();
11262 }
11263 }
11264 }
11265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 ServiceLookupResult res =
11267 retrieveServiceLocked(service, resolvedType,
11268 Binder.getCallingPid(), Binder.getCallingUid());
11269 if (res == null) {
11270 return 0;
11271 }
11272 if (res.record == null) {
11273 return -1;
11274 }
11275 ServiceRecord s = res.record;
11276
11277 final long origId = Binder.clearCallingIdentity();
11278
11279 if (unscheduleServiceRestartLocked(s)) {
11280 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
11281 + s.shortName);
11282 }
11283
11284 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11285 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011286 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287
11288 IBinder binder = connection.asBinder();
11289 s.connections.put(binder, c);
11290 b.connections.add(c);
11291 if (activity != null) {
11292 if (activity.connections == null) {
11293 activity.connections = new HashSet<ConnectionRecord>();
11294 }
11295 activity.connections.add(c);
11296 }
11297 b.client.connections.add(c);
11298 mServiceConnections.put(binder, c);
11299
11300 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11301 s.lastActivity = SystemClock.uptimeMillis();
11302 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11303 return 0;
11304 }
11305 }
11306
11307 if (s.app != null) {
11308 // This could have made the service more important.
11309 updateOomAdjLocked(s.app);
11310 }
11311
11312 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
11313 + ": received=" + b.intent.received
11314 + " apps=" + b.intent.apps.size()
11315 + " doRebind=" + b.intent.doRebind);
11316
11317 if (s.app != null && b.intent.received) {
11318 // Service is already running, so we can immediately
11319 // publish the connection.
11320 try {
11321 c.conn.connected(s.name, b.intent.binder);
11322 } catch (Exception e) {
11323 Log.w(TAG, "Failure sending service " + s.shortName
11324 + " to connection " + c.conn.asBinder()
11325 + " (in " + c.binding.client.processName + ")", e);
11326 }
11327
11328 // If this is the first app connected back to this binding,
11329 // and the service had previously asked to be told when
11330 // rebound, then do so.
11331 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11332 requestServiceBindingLocked(s, b.intent, true);
11333 }
11334 } else if (!b.intent.requested) {
11335 requestServiceBindingLocked(s, b.intent, false);
11336 }
11337
11338 Binder.restoreCallingIdentity(origId);
11339 }
11340
11341 return 1;
11342 }
11343
11344 private void removeConnectionLocked(
11345 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11346 IBinder binder = c.conn.asBinder();
11347 AppBindRecord b = c.binding;
11348 ServiceRecord s = b.service;
11349 s.connections.remove(binder);
11350 b.connections.remove(c);
11351 if (c.activity != null && c.activity != skipAct) {
11352 if (c.activity.connections != null) {
11353 c.activity.connections.remove(c);
11354 }
11355 }
11356 if (b.client != skipApp) {
11357 b.client.connections.remove(c);
11358 }
11359 mServiceConnections.remove(binder);
11360
11361 if (b.connections.size() == 0) {
11362 b.intent.apps.remove(b.client);
11363 }
11364
11365 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
11366 + ": shouldUnbind=" + b.intent.hasBound);
11367 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11368 && b.intent.hasBound) {
11369 try {
11370 bumpServiceExecutingLocked(s);
11371 updateOomAdjLocked(s.app);
11372 b.intent.hasBound = false;
11373 // Assume the client doesn't want to know about a rebind;
11374 // we will deal with that later if it asks for one.
11375 b.intent.doRebind = false;
11376 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11377 } catch (Exception e) {
11378 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
11379 serviceDoneExecutingLocked(s, true);
11380 }
11381 }
11382
11383 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11384 bringDownServiceLocked(s, false);
11385 }
11386 }
11387
11388 public boolean unbindService(IServiceConnection connection) {
11389 synchronized (this) {
11390 IBinder binder = connection.asBinder();
11391 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
11392 ConnectionRecord r = mServiceConnections.get(binder);
11393 if (r == null) {
11394 Log.w(TAG, "Unbind failed: could not find connection for "
11395 + connection.asBinder());
11396 return false;
11397 }
11398
11399 final long origId = Binder.clearCallingIdentity();
11400
11401 removeConnectionLocked(r, null, null);
11402
11403 if (r.binding.service.app != null) {
11404 // This could have made the service less important.
11405 updateOomAdjLocked(r.binding.service.app);
11406 }
11407
11408 Binder.restoreCallingIdentity(origId);
11409 }
11410
11411 return true;
11412 }
11413
11414 public void publishService(IBinder token, Intent intent, IBinder service) {
11415 // Refuse possible leaked file descriptors
11416 if (intent != null && intent.hasFileDescriptors() == true) {
11417 throw new IllegalArgumentException("File descriptors passed in Intent");
11418 }
11419
11420 synchronized(this) {
11421 if (!(token instanceof ServiceRecord)) {
11422 throw new IllegalArgumentException("Invalid service token");
11423 }
11424 ServiceRecord r = (ServiceRecord)token;
11425
11426 final long origId = Binder.clearCallingIdentity();
11427
11428 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
11429 + " " + intent + ": " + service);
11430 if (r != null) {
11431 Intent.FilterComparison filter
11432 = new Intent.FilterComparison(intent);
11433 IntentBindRecord b = r.bindings.get(filter);
11434 if (b != null && !b.received) {
11435 b.binder = service;
11436 b.requested = true;
11437 b.received = true;
11438 if (r.connections.size() > 0) {
11439 Iterator<ConnectionRecord> it
11440 = r.connections.values().iterator();
11441 while (it.hasNext()) {
11442 ConnectionRecord c = it.next();
11443 if (!filter.equals(c.binding.intent.intent)) {
11444 if (DEBUG_SERVICE) Log.v(
11445 TAG, "Not publishing to: " + c);
11446 if (DEBUG_SERVICE) Log.v(
11447 TAG, "Bound intent: " + c.binding.intent.intent);
11448 if (DEBUG_SERVICE) Log.v(
11449 TAG, "Published intent: " + intent);
11450 continue;
11451 }
11452 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
11453 try {
11454 c.conn.connected(r.name, service);
11455 } catch (Exception e) {
11456 Log.w(TAG, "Failure sending service " + r.name +
11457 " to connection " + c.conn.asBinder() +
11458 " (in " + c.binding.client.processName + ")", e);
11459 }
11460 }
11461 }
11462 }
11463
11464 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11465
11466 Binder.restoreCallingIdentity(origId);
11467 }
11468 }
11469 }
11470
11471 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11472 // Refuse possible leaked file descriptors
11473 if (intent != null && intent.hasFileDescriptors() == true) {
11474 throw new IllegalArgumentException("File descriptors passed in Intent");
11475 }
11476
11477 synchronized(this) {
11478 if (!(token instanceof ServiceRecord)) {
11479 throw new IllegalArgumentException("Invalid service token");
11480 }
11481 ServiceRecord r = (ServiceRecord)token;
11482
11483 final long origId = Binder.clearCallingIdentity();
11484
11485 if (r != null) {
11486 Intent.FilterComparison filter
11487 = new Intent.FilterComparison(intent);
11488 IntentBindRecord b = r.bindings.get(filter);
11489 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
11490 + " at " + b + ": apps="
11491 + (b != null ? b.apps.size() : 0));
11492 if (b != null) {
11493 if (b.apps.size() > 0) {
11494 // Applications have already bound since the last
11495 // unbind, so just rebind right here.
11496 requestServiceBindingLocked(r, b, true);
11497 } else {
11498 // Note to tell the service the next time there is
11499 // a new client.
11500 b.doRebind = true;
11501 }
11502 }
11503
11504 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11505
11506 Binder.restoreCallingIdentity(origId);
11507 }
11508 }
11509 }
11510
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011511 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 synchronized(this) {
11513 if (!(token instanceof ServiceRecord)) {
11514 throw new IllegalArgumentException("Invalid service token");
11515 }
11516 ServiceRecord r = (ServiceRecord)token;
11517 boolean inStopping = mStoppingServices.contains(token);
11518 if (r != null) {
11519 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
11520 + ": nesting=" + r.executeNesting
11521 + ", inStopping=" + inStopping);
11522 if (r != token) {
11523 Log.w(TAG, "Done executing service " + r.name
11524 + " with incorrect token: given " + token
11525 + ", expected " + r);
11526 return;
11527 }
11528
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011529 if (type == 1) {
11530 // This is a call from a service start... take care of
11531 // book-keeping.
11532 r.callStart = true;
11533 switch (res) {
11534 case Service.START_STICKY_COMPATIBILITY:
11535 case Service.START_STICKY: {
11536 // We are done with the associated start arguments.
11537 r.findDeliveredStart(startId, true);
11538 // Don't stop if killed.
11539 r.stopIfKilled = false;
11540 break;
11541 }
11542 case Service.START_NOT_STICKY: {
11543 // We are done with the associated start arguments.
11544 r.findDeliveredStart(startId, true);
11545 if (r.lastStartId == startId) {
11546 // There is no more work, and this service
11547 // doesn't want to hang around if killed.
11548 r.stopIfKilled = true;
11549 }
11550 break;
11551 }
11552 case Service.START_REDELIVER_INTENT: {
11553 // We'll keep this item until they explicitly
11554 // call stop for it, but keep track of the fact
11555 // that it was delivered.
11556 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11557 if (si != null) {
11558 si.deliveryCount = 0;
11559 si.doneExecutingCount++;
11560 // Don't stop if killed.
11561 r.stopIfKilled = true;
11562 }
11563 break;
11564 }
11565 default:
11566 throw new IllegalArgumentException(
11567 "Unknown service start result: " + res);
11568 }
11569 if (res == Service.START_STICKY_COMPATIBILITY) {
11570 r.callStart = false;
11571 }
11572 }
11573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 final long origId = Binder.clearCallingIdentity();
11575 serviceDoneExecutingLocked(r, inStopping);
11576 Binder.restoreCallingIdentity(origId);
11577 } else {
11578 Log.w(TAG, "Done executing unknown service " + r.name
11579 + " with token " + token);
11580 }
11581 }
11582 }
11583
11584 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11585 r.executeNesting--;
11586 if (r.executeNesting <= 0 && r.app != null) {
11587 r.app.executingServices.remove(r);
11588 if (r.app.executingServices.size() == 0) {
11589 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11590 }
11591 if (inStopping) {
11592 mStoppingServices.remove(r);
11593 }
11594 updateOomAdjLocked(r.app);
11595 }
11596 }
11597
11598 void serviceTimeout(ProcessRecord proc) {
11599 synchronized(this) {
11600 if (proc.executingServices.size() == 0 || proc.thread == null) {
11601 return;
11602 }
11603 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11604 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11605 ServiceRecord timeout = null;
11606 long nextTime = 0;
11607 while (it.hasNext()) {
11608 ServiceRecord sr = it.next();
11609 if (sr.executingStart < maxTime) {
11610 timeout = sr;
11611 break;
11612 }
11613 if (sr.executingStart > nextTime) {
11614 nextTime = sr.executingStart;
11615 }
11616 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011617 if (timeout != null && mLruProcesses.contains(proc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011618 Log.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011619 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 } else {
11621 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11622 msg.obj = proc;
11623 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11624 }
11625 }
11626 }
11627
11628 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011629 // BACKUP AND RESTORE
11630 // =========================================================
11631
11632 // Cause the target app to be launched if necessary and its backup agent
11633 // instantiated. The backup agent will invoke backupAgentCreated() on the
11634 // activity manager to announce its creation.
11635 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
11636 if (DEBUG_BACKUP) Log.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
11637 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11638
11639 synchronized(this) {
11640 // !!! TODO: currently no check here that we're already bound
11641 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11642 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11643 synchronized (stats) {
11644 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11645 }
11646
11647 BackupRecord r = new BackupRecord(ss, app, backupMode);
11648 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11649 // startProcessLocked() returns existing proc's record if it's already running
11650 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011651 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011652 if (proc == null) {
11653 Log.e(TAG, "Unable to start backup agent process " + r);
11654 return false;
11655 }
11656
11657 r.app = proc;
11658 mBackupTarget = r;
11659 mBackupAppName = app.packageName;
11660
Christopher Tate6fa95972009-06-05 18:43:55 -070011661 // Try not to kill the process during backup
11662 updateOomAdjLocked(proc);
11663
Christopher Tate181fafa2009-05-14 11:12:14 -070011664 // If the process is already attached, schedule the creation of the backup agent now.
11665 // If it is not yet live, this will be done when it attaches to the framework.
11666 if (proc.thread != null) {
11667 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc already running: " + proc);
11668 try {
11669 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11670 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011671 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011672 }
11673 } else {
11674 if (DEBUG_BACKUP) Log.v(TAG, "Agent proc not running, waiting for attach");
11675 }
11676 // Invariants: at this point, the target app process exists and the application
11677 // is either already running or in the process of coming up. mBackupTarget and
11678 // mBackupAppName describe the app, so that when it binds back to the AM we
11679 // know that it's scheduled for a backup-agent operation.
11680 }
11681
11682 return true;
11683 }
11684
11685 // A backup agent has just come up
11686 public void backupAgentCreated(String agentPackageName, IBinder agent) {
11687 if (DEBUG_BACKUP) Log.v(TAG, "backupAgentCreated: " + agentPackageName
11688 + " = " + agent);
11689
11690 synchronized(this) {
11691 if (!agentPackageName.equals(mBackupAppName)) {
11692 Log.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
11693 return;
11694 }
11695
Christopher Tate043dadc2009-06-02 16:11:00 -070011696 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011697 try {
11698 IBackupManager bm = IBackupManager.Stub.asInterface(
11699 ServiceManager.getService(Context.BACKUP_SERVICE));
11700 bm.agentConnected(agentPackageName, agent);
11701 } catch (RemoteException e) {
11702 // can't happen; the backup manager service is local
11703 } catch (Exception e) {
11704 Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11705 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011706 } finally {
11707 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011708 }
11709 }
11710 }
11711
11712 // done with this agent
11713 public void unbindBackupAgent(ApplicationInfo appInfo) {
11714 if (DEBUG_BACKUP) Log.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011715 if (appInfo == null) {
11716 Log.w(TAG, "unbind backup agent for null app");
11717 return;
11718 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011719
11720 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011721 if (mBackupAppName == null) {
11722 Log.w(TAG, "Unbinding backup agent with no active backup");
11723 return;
11724 }
11725
Christopher Tate181fafa2009-05-14 11:12:14 -070011726 if (!mBackupAppName.equals(appInfo.packageName)) {
11727 Log.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
11728 return;
11729 }
11730
Christopher Tate6fa95972009-06-05 18:43:55 -070011731 ProcessRecord proc = mBackupTarget.app;
11732 mBackupTarget = null;
11733 mBackupAppName = null;
11734
11735 // Not backing this app up any more; reset its OOM adjustment
11736 updateOomAdjLocked(proc);
11737
Christopher Tatec7b31e32009-06-10 15:49:30 -070011738 // If the app crashed during backup, 'thread' will be null here
11739 if (proc.thread != null) {
11740 try {
11741 proc.thread.scheduleDestroyBackupAgent(appInfo);
11742 } catch (Exception e) {
11743 Log.e(TAG, "Exception when unbinding backup agent:");
11744 e.printStackTrace();
11745 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011746 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011747 }
11748 }
11749 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 // BROADCASTS
11751 // =========================================================
11752
11753 private final List getStickies(String action, IntentFilter filter,
11754 List cur) {
11755 final ContentResolver resolver = mContext.getContentResolver();
11756 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11757 if (list == null) {
11758 return cur;
11759 }
11760 int N = list.size();
11761 for (int i=0; i<N; i++) {
11762 Intent intent = list.get(i);
11763 if (filter.match(resolver, intent, true, TAG) >= 0) {
11764 if (cur == null) {
11765 cur = new ArrayList<Intent>();
11766 }
11767 cur.add(intent);
11768 }
11769 }
11770 return cur;
11771 }
11772
11773 private final void scheduleBroadcastsLocked() {
11774 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
11775 + mBroadcastsScheduled);
11776
11777 if (mBroadcastsScheduled) {
11778 return;
11779 }
11780 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11781 mBroadcastsScheduled = true;
11782 }
11783
11784 public Intent registerReceiver(IApplicationThread caller,
11785 IIntentReceiver receiver, IntentFilter filter, String permission) {
11786 synchronized(this) {
11787 ProcessRecord callerApp = null;
11788 if (caller != null) {
11789 callerApp = getRecordForAppLocked(caller);
11790 if (callerApp == null) {
11791 throw new SecurityException(
11792 "Unable to find app for caller " + caller
11793 + " (pid=" + Binder.getCallingPid()
11794 + ") when registering receiver " + receiver);
11795 }
11796 }
11797
11798 List allSticky = null;
11799
11800 // Look for any matching sticky broadcasts...
11801 Iterator actions = filter.actionsIterator();
11802 if (actions != null) {
11803 while (actions.hasNext()) {
11804 String action = (String)actions.next();
11805 allSticky = getStickies(action, filter, allSticky);
11806 }
11807 } else {
11808 allSticky = getStickies(null, filter, allSticky);
11809 }
11810
11811 // The first sticky in the list is returned directly back to
11812 // the client.
11813 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11814
11815 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
11816 + ": " + sticky);
11817
11818 if (receiver == null) {
11819 return sticky;
11820 }
11821
11822 ReceiverList rl
11823 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11824 if (rl == null) {
11825 rl = new ReceiverList(this, callerApp,
11826 Binder.getCallingPid(),
11827 Binder.getCallingUid(), receiver);
11828 if (rl.app != null) {
11829 rl.app.receivers.add(rl);
11830 } else {
11831 try {
11832 receiver.asBinder().linkToDeath(rl, 0);
11833 } catch (RemoteException e) {
11834 return sticky;
11835 }
11836 rl.linkedToDeath = true;
11837 }
11838 mRegisteredReceivers.put(receiver.asBinder(), rl);
11839 }
11840 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11841 rl.add(bf);
11842 if (!bf.debugCheck()) {
11843 Log.w(TAG, "==> For Dynamic broadast");
11844 }
11845 mReceiverResolver.addFilter(bf);
11846
11847 // Enqueue broadcasts for all existing stickies that match
11848 // this filter.
11849 if (allSticky != null) {
11850 ArrayList receivers = new ArrayList();
11851 receivers.add(bf);
11852
11853 int N = allSticky.size();
11854 for (int i=0; i<N; i++) {
11855 Intent intent = (Intent)allSticky.get(i);
11856 BroadcastRecord r = new BroadcastRecord(intent, null,
11857 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011858 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 if (mParallelBroadcasts.size() == 0) {
11860 scheduleBroadcastsLocked();
11861 }
11862 mParallelBroadcasts.add(r);
11863 }
11864 }
11865
11866 return sticky;
11867 }
11868 }
11869
11870 public void unregisterReceiver(IIntentReceiver receiver) {
11871 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
11872
11873 boolean doNext = false;
11874
11875 synchronized(this) {
11876 ReceiverList rl
11877 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11878 if (rl != null) {
11879 if (rl.curBroadcast != null) {
11880 BroadcastRecord r = rl.curBroadcast;
11881 doNext = finishReceiverLocked(
11882 receiver.asBinder(), r.resultCode, r.resultData,
11883 r.resultExtras, r.resultAbort, true);
11884 }
11885
11886 if (rl.app != null) {
11887 rl.app.receivers.remove(rl);
11888 }
11889 removeReceiverLocked(rl);
11890 if (rl.linkedToDeath) {
11891 rl.linkedToDeath = false;
11892 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11893 }
11894 }
11895 }
11896
11897 if (!doNext) {
11898 return;
11899 }
11900
11901 final long origId = Binder.clearCallingIdentity();
11902 processNextBroadcast(false);
11903 trimApplications();
11904 Binder.restoreCallingIdentity(origId);
11905 }
11906
11907 void removeReceiverLocked(ReceiverList rl) {
11908 mRegisteredReceivers.remove(rl.receiver.asBinder());
11909 int N = rl.size();
11910 for (int i=0; i<N; i++) {
11911 mReceiverResolver.removeFilter(rl.get(i));
11912 }
11913 }
11914
11915 private final int broadcastIntentLocked(ProcessRecord callerApp,
11916 String callerPackage, Intent intent, String resolvedType,
11917 IIntentReceiver resultTo, int resultCode, String resultData,
11918 Bundle map, String requiredPermission,
11919 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11920 intent = new Intent(intent);
11921
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011922 if (DEBUG_BROADCAST_LIGHT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11924 + " ordered=" + ordered);
11925 if ((resultTo != null) && !ordered) {
11926 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
11927 }
11928
11929 // Handle special intents: if this broadcast is from the package
11930 // manager about a package being removed, we need to remove all of
11931 // its activities from the history stack.
11932 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
11933 intent.getAction());
11934 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11935 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011936 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011937 || uidRemoved) {
11938 if (checkComponentPermission(
11939 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
11940 callingPid, callingUid, -1)
11941 == PackageManager.PERMISSION_GRANTED) {
11942 if (uidRemoved) {
11943 final Bundle intentExtras = intent.getExtras();
11944 final int uid = intentExtras != null
11945 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11946 if (uid >= 0) {
11947 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11948 synchronized (bs) {
11949 bs.removeUidStatsLocked(uid);
11950 }
11951 }
11952 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011953 // If resources are unvailble just force stop all
11954 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011955 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011956 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11957 if (list != null && (list.length > 0)) {
11958 for (String pkg : list) {
11959 forceStopPackageLocked(pkg, -1, false, true);
11960 }
11961 }
11962 } else {
11963 Uri data = intent.getData();
11964 String ssp;
11965 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11966 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11967 forceStopPackageLocked(ssp,
11968 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011970 }
11971 }
11972 }
11973 } else {
11974 String msg = "Permission Denial: " + intent.getAction()
11975 + " broadcast from " + callerPackage + " (pid=" + callingPid
11976 + ", uid=" + callingUid + ")"
11977 + " requires "
11978 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
11979 Log.w(TAG, msg);
11980 throw new SecurityException(msg);
11981 }
11982 }
11983
11984 /*
11985 * If this is the time zone changed action, queue up a message that will reset the timezone
11986 * of all currently running processes. This message will get queued up before the broadcast
11987 * happens.
11988 */
11989 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11990 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11991 }
11992
Dianne Hackborn854060af2009-07-09 18:14:31 -070011993 /*
11994 * Prevent non-system code (defined here to be non-persistent
11995 * processes) from sending protected broadcasts.
11996 */
11997 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11998 || callingUid == Process.SHELL_UID || callingUid == 0) {
11999 // Always okay.
12000 } else if (callerApp == null || !callerApp.persistent) {
12001 try {
12002 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12003 intent.getAction())) {
12004 String msg = "Permission Denial: not allowed to send broadcast "
12005 + intent.getAction() + " from pid="
12006 + callingPid + ", uid=" + callingUid;
12007 Log.w(TAG, msg);
12008 throw new SecurityException(msg);
12009 }
12010 } catch (RemoteException e) {
12011 Log.w(TAG, "Remote exception", e);
12012 return BROADCAST_SUCCESS;
12013 }
12014 }
12015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012016 // Add to the sticky list if requested.
12017 if (sticky) {
12018 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12019 callingPid, callingUid)
12020 != PackageManager.PERMISSION_GRANTED) {
12021 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12022 + callingPid + ", uid=" + callingUid
12023 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12024 Log.w(TAG, msg);
12025 throw new SecurityException(msg);
12026 }
12027 if (requiredPermission != null) {
12028 Log.w(TAG, "Can't broadcast sticky intent " + intent
12029 + " and enforce permission " + requiredPermission);
12030 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12031 }
12032 if (intent.getComponent() != null) {
12033 throw new SecurityException(
12034 "Sticky broadcasts can't target a specific component");
12035 }
12036 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12037 if (list == null) {
12038 list = new ArrayList<Intent>();
12039 mStickyBroadcasts.put(intent.getAction(), list);
12040 }
12041 int N = list.size();
12042 int i;
12043 for (i=0; i<N; i++) {
12044 if (intent.filterEquals(list.get(i))) {
12045 // This sticky already exists, replace it.
12046 list.set(i, new Intent(intent));
12047 break;
12048 }
12049 }
12050 if (i >= N) {
12051 list.add(new Intent(intent));
12052 }
12053 }
12054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 // Figure out who all will receive this broadcast.
12056 List receivers = null;
12057 List<BroadcastFilter> registeredReceivers = null;
12058 try {
12059 if (intent.getComponent() != null) {
12060 // Broadcast is going to one specific receiver class...
12061 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012062 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 if (ai != null) {
12064 receivers = new ArrayList();
12065 ResolveInfo ri = new ResolveInfo();
12066 ri.activityInfo = ai;
12067 receivers.add(ri);
12068 }
12069 } else {
12070 // Need to resolve the intent to interested receivers...
12071 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12072 == 0) {
12073 receivers =
12074 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012075 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 }
Mihai Preda074edef2009-05-18 17:13:31 +020012077 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012078 }
12079 } catch (RemoteException ex) {
12080 // pm is in same process, this will never happen.
12081 }
12082
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012083 final boolean replacePending =
12084 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12085
12086 if (DEBUG_BROADCAST) Log.v(TAG, "Enqueing broadcast: " + intent.getAction()
12087 + " replacePending=" + replacePending);
12088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12090 if (!ordered && NR > 0) {
12091 // If we are not serializing this broadcast, then send the
12092 // registered receivers separately so they don't wait for the
12093 // components to be launched.
12094 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12095 callerPackage, callingPid, callingUid, requiredPermission,
12096 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012097 ordered, sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012098 if (DEBUG_BROADCAST) Log.v(
12099 TAG, "Enqueueing parallel broadcast " + r
12100 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012101 boolean replaced = false;
12102 if (replacePending) {
12103 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12104 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
12105 if (DEBUG_BROADCAST) Log.v(TAG,
12106 "***** DROPPING PARALLEL: " + intent);
12107 mParallelBroadcasts.set(i, r);
12108 replaced = true;
12109 break;
12110 }
12111 }
12112 }
12113 if (!replaced) {
12114 mParallelBroadcasts.add(r);
12115 scheduleBroadcastsLocked();
12116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012117 registeredReceivers = null;
12118 NR = 0;
12119 }
12120
12121 // Merge into one list.
12122 int ir = 0;
12123 if (receivers != null) {
12124 // A special case for PACKAGE_ADDED: do not allow the package
12125 // being added to see this broadcast. This prevents them from
12126 // using this as a back door to get run as soon as they are
12127 // installed. Maybe in the future we want to have a special install
12128 // broadcast or such for apps, but we'd like to deliberately make
12129 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012130 String skipPackages[] = null;
12131 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12132 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12133 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12134 Uri data = intent.getData();
12135 if (data != null) {
12136 String pkgName = data.getSchemeSpecificPart();
12137 if (pkgName != null) {
12138 skipPackages = new String[] { pkgName };
12139 }
12140 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012141 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012142 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012143 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012144 if (skipPackages != null && (skipPackages.length > 0)) {
12145 for (String skipPackage : skipPackages) {
12146 if (skipPackage != null) {
12147 int NT = receivers.size();
12148 for (int it=0; it<NT; it++) {
12149 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12150 if (curt.activityInfo.packageName.equals(skipPackage)) {
12151 receivers.remove(it);
12152 it--;
12153 NT--;
12154 }
12155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012156 }
12157 }
12158 }
12159
12160 int NT = receivers != null ? receivers.size() : 0;
12161 int it = 0;
12162 ResolveInfo curt = null;
12163 BroadcastFilter curr = null;
12164 while (it < NT && ir < NR) {
12165 if (curt == null) {
12166 curt = (ResolveInfo)receivers.get(it);
12167 }
12168 if (curr == null) {
12169 curr = registeredReceivers.get(ir);
12170 }
12171 if (curr.getPriority() >= curt.priority) {
12172 // Insert this broadcast record into the final list.
12173 receivers.add(it, curr);
12174 ir++;
12175 curr = null;
12176 it++;
12177 NT++;
12178 } else {
12179 // Skip to the next ResolveInfo in the final list.
12180 it++;
12181 curt = null;
12182 }
12183 }
12184 }
12185 while (ir < NR) {
12186 if (receivers == null) {
12187 receivers = new ArrayList();
12188 }
12189 receivers.add(registeredReceivers.get(ir));
12190 ir++;
12191 }
12192
12193 if ((receivers != null && receivers.size() > 0)
12194 || resultTo != null) {
12195 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12196 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012197 receivers, resultTo, resultCode, resultData, map, ordered,
12198 sticky, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 if (DEBUG_BROADCAST) Log.v(
12200 TAG, "Enqueueing ordered broadcast " + r
12201 + ": prev had " + mOrderedBroadcasts.size());
12202 if (DEBUG_BROADCAST) {
12203 int seq = r.intent.getIntExtra("seq", -1);
12204 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
12205 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012206 boolean replaced = false;
12207 if (replacePending) {
12208 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12209 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
12210 if (DEBUG_BROADCAST) Log.v(TAG,
12211 "***** DROPPING ORDERED: " + intent);
12212 mOrderedBroadcasts.set(i, r);
12213 replaced = true;
12214 break;
12215 }
12216 }
12217 }
12218 if (!replaced) {
12219 mOrderedBroadcasts.add(r);
12220 scheduleBroadcastsLocked();
12221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012222 }
12223
12224 return BROADCAST_SUCCESS;
12225 }
12226
12227 public final int broadcastIntent(IApplicationThread caller,
12228 Intent intent, String resolvedType, IIntentReceiver resultTo,
12229 int resultCode, String resultData, Bundle map,
12230 String requiredPermission, boolean serialized, boolean sticky) {
12231 // Refuse possible leaked file descriptors
12232 if (intent != null && intent.hasFileDescriptors() == true) {
12233 throw new IllegalArgumentException("File descriptors passed in Intent");
12234 }
12235
12236 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012237 int flags = intent.getFlags();
12238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239 if (!mSystemReady) {
12240 // if the caller really truly claims to know what they're doing, go
12241 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12243 intent = new Intent(intent);
12244 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12245 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
12246 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12247 + " before boot completion");
12248 throw new IllegalStateException("Cannot broadcast before boot completed");
12249 }
12250 }
12251
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012252 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12253 throw new IllegalArgumentException(
12254 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12255 }
12256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012257 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12258 final int callingPid = Binder.getCallingPid();
12259 final int callingUid = Binder.getCallingUid();
12260 final long origId = Binder.clearCallingIdentity();
12261 int res = broadcastIntentLocked(callerApp,
12262 callerApp != null ? callerApp.info.packageName : null,
12263 intent, resolvedType, resultTo,
12264 resultCode, resultData, map, requiredPermission, serialized,
12265 sticky, callingPid, callingUid);
12266 Binder.restoreCallingIdentity(origId);
12267 return res;
12268 }
12269 }
12270
12271 int broadcastIntentInPackage(String packageName, int uid,
12272 Intent intent, String resolvedType, IIntentReceiver resultTo,
12273 int resultCode, String resultData, Bundle map,
12274 String requiredPermission, boolean serialized, boolean sticky) {
12275 synchronized(this) {
12276 final long origId = Binder.clearCallingIdentity();
12277 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12278 resultTo, resultCode, resultData, map, requiredPermission,
12279 serialized, sticky, -1, uid);
12280 Binder.restoreCallingIdentity(origId);
12281 return res;
12282 }
12283 }
12284
12285 public final void unbroadcastIntent(IApplicationThread caller,
12286 Intent intent) {
12287 // Refuse possible leaked file descriptors
12288 if (intent != null && intent.hasFileDescriptors() == true) {
12289 throw new IllegalArgumentException("File descriptors passed in Intent");
12290 }
12291
12292 synchronized(this) {
12293 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12294 != PackageManager.PERMISSION_GRANTED) {
12295 String msg = "Permission Denial: unbroadcastIntent() from pid="
12296 + Binder.getCallingPid()
12297 + ", uid=" + Binder.getCallingUid()
12298 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
12299 Log.w(TAG, msg);
12300 throw new SecurityException(msg);
12301 }
12302 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12303 if (list != null) {
12304 int N = list.size();
12305 int i;
12306 for (i=0; i<N; i++) {
12307 if (intent.filterEquals(list.get(i))) {
12308 list.remove(i);
12309 break;
12310 }
12311 }
12312 }
12313 }
12314 }
12315
12316 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12317 String resultData, Bundle resultExtras, boolean resultAbort,
12318 boolean explicit) {
12319 if (mOrderedBroadcasts.size() == 0) {
12320 if (explicit) {
12321 Log.w(TAG, "finishReceiver called but no pending broadcasts");
12322 }
12323 return false;
12324 }
12325 BroadcastRecord r = mOrderedBroadcasts.get(0);
12326 if (r.receiver == null) {
12327 if (explicit) {
12328 Log.w(TAG, "finishReceiver called but none active");
12329 }
12330 return false;
12331 }
12332 if (r.receiver != receiver) {
12333 Log.w(TAG, "finishReceiver called but active receiver is different");
12334 return false;
12335 }
12336 int state = r.state;
12337 r.state = r.IDLE;
12338 if (state == r.IDLE) {
12339 if (explicit) {
12340 Log.w(TAG, "finishReceiver called but state is IDLE");
12341 }
12342 }
12343 r.receiver = null;
12344 r.intent.setComponent(null);
12345 if (r.curApp != null) {
12346 r.curApp.curReceiver = null;
12347 }
12348 if (r.curFilter != null) {
12349 r.curFilter.receiverList.curBroadcast = null;
12350 }
12351 r.curFilter = null;
12352 r.curApp = null;
12353 r.curComponent = null;
12354 r.curReceiver = null;
12355 mPendingBroadcast = null;
12356
12357 r.resultCode = resultCode;
12358 r.resultData = resultData;
12359 r.resultExtras = resultExtras;
12360 r.resultAbort = resultAbort;
12361
12362 // We will process the next receiver right now if this is finishing
12363 // an app receiver (which is always asynchronous) or after we have
12364 // come back from calling a receiver.
12365 return state == BroadcastRecord.APP_RECEIVE
12366 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12367 }
12368
12369 public void finishReceiver(IBinder who, int resultCode, String resultData,
12370 Bundle resultExtras, boolean resultAbort) {
12371 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
12372
12373 // Refuse possible leaked file descriptors
12374 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12375 throw new IllegalArgumentException("File descriptors passed in Bundle");
12376 }
12377
12378 boolean doNext;
12379
12380 final long origId = Binder.clearCallingIdentity();
12381
12382 synchronized(this) {
12383 doNext = finishReceiverLocked(
12384 who, resultCode, resultData, resultExtras, resultAbort, true);
12385 }
12386
12387 if (doNext) {
12388 processNextBroadcast(false);
12389 }
12390 trimApplications();
12391
12392 Binder.restoreCallingIdentity(origId);
12393 }
12394
12395 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12396 if (r.nextReceiver > 0) {
12397 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12398 if (curReceiver instanceof BroadcastFilter) {
12399 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012400 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401 System.identityHashCode(r),
12402 r.intent.getAction(),
12403 r.nextReceiver - 1,
12404 System.identityHashCode(bf));
12405 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012406 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012407 System.identityHashCode(r),
12408 r.intent.getAction(),
12409 r.nextReceiver - 1,
12410 ((ResolveInfo)curReceiver).toString());
12411 }
12412 } else {
12413 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
12414 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012415 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012416 System.identityHashCode(r),
12417 r.intent.getAction(),
12418 r.nextReceiver,
12419 "NONE");
12420 }
12421 }
12422
12423 private final void broadcastTimeout() {
12424 synchronized (this) {
12425 if (mOrderedBroadcasts.size() == 0) {
12426 return;
12427 }
12428 long now = SystemClock.uptimeMillis();
12429 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012430 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012431 if (DEBUG_BROADCAST) Log.v(TAG,
12432 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012433 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012434 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012435 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436 return;
12437 }
12438
12439 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012440 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441 r.anrCount++;
12442
12443 // Current receiver has passed its expiration date.
12444 if (r.nextReceiver <= 0) {
12445 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12446 return;
12447 }
12448
12449 ProcessRecord app = null;
12450
12451 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12452 Log.w(TAG, "Receiver during timeout: " + curReceiver);
12453 logBroadcastReceiverDiscard(r);
12454 if (curReceiver instanceof BroadcastFilter) {
12455 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12456 if (bf.receiverList.pid != 0
12457 && bf.receiverList.pid != MY_PID) {
12458 synchronized (this.mPidsSelfLocked) {
12459 app = this.mPidsSelfLocked.get(
12460 bf.receiverList.pid);
12461 }
12462 }
12463 } else {
12464 app = r.curApp;
12465 }
12466
12467 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012468 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 }
12470
12471 if (mPendingBroadcast == r) {
12472 mPendingBroadcast = null;
12473 }
12474
12475 // Move on to the next receiver.
12476 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12477 r.resultExtras, r.resultAbort, true);
12478 scheduleBroadcastsLocked();
12479 }
12480 }
12481
12482 private final void processCurBroadcastLocked(BroadcastRecord r,
12483 ProcessRecord app) throws RemoteException {
12484 if (app.thread == null) {
12485 throw new RemoteException();
12486 }
12487 r.receiver = app.thread.asBinder();
12488 r.curApp = app;
12489 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012490 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012491
12492 // Tell the application to launch this receiver.
12493 r.intent.setComponent(r.curComponent);
12494
12495 boolean started = false;
12496 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012497 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 "Delivering to component " + r.curComponent
12499 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012500 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012501 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12502 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12503 started = true;
12504 } finally {
12505 if (!started) {
12506 r.receiver = null;
12507 r.curApp = null;
12508 app.curReceiver = null;
12509 }
12510 }
12511
12512 }
12513
12514 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012515 Intent intent, int resultCode, String data, Bundle extras,
12516 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012517 if (app != null && app.thread != null) {
12518 // If we have an app thread, do the call through that so it is
12519 // correctly ordered with other one-way calls.
12520 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012521 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012523 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012524 }
12525 }
12526
12527 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12528 BroadcastFilter filter, boolean ordered) {
12529 boolean skip = false;
12530 if (filter.requiredPermission != null) {
12531 int perm = checkComponentPermission(filter.requiredPermission,
12532 r.callingPid, r.callingUid, -1);
12533 if (perm != PackageManager.PERMISSION_GRANTED) {
12534 Log.w(TAG, "Permission Denial: broadcasting "
12535 + r.intent.toString()
12536 + " from " + r.callerPackage + " (pid="
12537 + r.callingPid + ", uid=" + r.callingUid + ")"
12538 + " requires " + filter.requiredPermission
12539 + " due to registered receiver " + filter);
12540 skip = true;
12541 }
12542 }
12543 if (r.requiredPermission != null) {
12544 int perm = checkComponentPermission(r.requiredPermission,
12545 filter.receiverList.pid, filter.receiverList.uid, -1);
12546 if (perm != PackageManager.PERMISSION_GRANTED) {
12547 Log.w(TAG, "Permission Denial: receiving "
12548 + r.intent.toString()
12549 + " to " + filter.receiverList.app
12550 + " (pid=" + filter.receiverList.pid
12551 + ", uid=" + filter.receiverList.uid + ")"
12552 + " requires " + r.requiredPermission
12553 + " due to sender " + r.callerPackage
12554 + " (uid " + r.callingUid + ")");
12555 skip = true;
12556 }
12557 }
12558
12559 if (!skip) {
12560 // If this is not being sent as an ordered broadcast, then we
12561 // don't want to touch the fields that keep track of the current
12562 // state of ordered broadcasts.
12563 if (ordered) {
12564 r.receiver = filter.receiverList.receiver.asBinder();
12565 r.curFilter = filter;
12566 filter.receiverList.curBroadcast = r;
12567 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012568 if (filter.receiverList.app != null) {
12569 // Bump hosting application to no longer be in background
12570 // scheduling class. Note that we can't do that if there
12571 // isn't an app... but we can only be in that case for
12572 // things that directly call the IActivityManager API, which
12573 // are already core system stuff so don't matter for this.
12574 r.curApp = filter.receiverList.app;
12575 filter.receiverList.app.curReceiver = r;
12576 updateOomAdjLocked();
12577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 }
12579 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012580 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012581 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012582 Log.i(TAG, "Delivering to " + filter.receiverList.app
12583 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012584 }
12585 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12586 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012587 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 if (ordered) {
12589 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12590 }
12591 } catch (RemoteException e) {
12592 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
12593 if (ordered) {
12594 r.receiver = null;
12595 r.curFilter = null;
12596 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012597 if (filter.receiverList.app != null) {
12598 filter.receiverList.app.curReceiver = null;
12599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 }
12601 }
12602 }
12603 }
12604
Dianne Hackborn12527f92009-11-11 17:39:50 -080012605 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12606 if (r.callingUid < 0) {
12607 // This was from a registerReceiver() call; ignore it.
12608 return;
12609 }
12610 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12611 MAX_BROADCAST_HISTORY-1);
12612 r.finishTime = SystemClock.uptimeMillis();
12613 mBroadcastHistory[0] = r;
12614 }
12615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012616 private final void processNextBroadcast(boolean fromMsg) {
12617 synchronized(this) {
12618 BroadcastRecord r;
12619
12620 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
12621 + mParallelBroadcasts.size() + " broadcasts, "
12622 + mOrderedBroadcasts.size() + " serialized broadcasts");
12623
12624 updateCpuStats();
12625
12626 if (fromMsg) {
12627 mBroadcastsScheduled = false;
12628 }
12629
12630 // First, deliver any non-serialized broadcasts right away.
12631 while (mParallelBroadcasts.size() > 0) {
12632 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012633 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 final int N = r.receivers.size();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012635 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing parallel broadcast "
12636 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012637 for (int i=0; i<N; i++) {
12638 Object target = r.receivers.get(i);
12639 if (DEBUG_BROADCAST) Log.v(TAG,
12640 "Delivering non-serialized to registered "
12641 + target + ": " + r);
12642 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12643 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012644 addBroadcastToHistoryLocked(r);
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012645 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Done with parallel broadcast "
12646 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012647 }
12648
12649 // Now take care of the next serialized one...
12650
12651 // If we are waiting for a process to come up to handle the next
12652 // broadcast, then do nothing at this point. Just in case, we
12653 // check that the process we're waiting for still exists.
12654 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012655 if (DEBUG_BROADCAST_LIGHT) {
12656 Log.v(TAG, "processNextBroadcast: waiting for "
12657 + mPendingBroadcast.curApp);
12658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012659
12660 boolean isDead;
12661 synchronized (mPidsSelfLocked) {
12662 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12663 }
12664 if (!isDead) {
12665 // It's still alive, so keep waiting
12666 return;
12667 } else {
12668 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
12669 + " died before responding to broadcast");
12670 mPendingBroadcast = null;
12671 }
12672 }
12673
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012674 boolean looped = false;
12675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676 do {
12677 if (mOrderedBroadcasts.size() == 0) {
12678 // No more broadcasts pending, so all done!
12679 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012680 if (looped) {
12681 // If we had finished the last ordered broadcast, then
12682 // make sure all processes have correct oom and sched
12683 // adjustments.
12684 updateOomAdjLocked();
12685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012686 return;
12687 }
12688 r = mOrderedBroadcasts.get(0);
12689 boolean forceReceive = false;
12690
12691 // Ensure that even if something goes awry with the timeout
12692 // detection, we catch "hung" broadcasts here, discard them,
12693 // and continue to make progress.
12694 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12695 long now = SystemClock.uptimeMillis();
12696 if (r.dispatchTime > 0) {
12697 if ((numReceivers > 0) &&
12698 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
12699 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
12700 + " now=" + now
12701 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012702 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012703 + " intent=" + r.intent
12704 + " numReceivers=" + numReceivers
12705 + " nextReceiver=" + r.nextReceiver
12706 + " state=" + r.state);
12707 broadcastTimeout(); // forcibly finish this broadcast
12708 forceReceive = true;
12709 r.state = BroadcastRecord.IDLE;
12710 }
12711 }
12712
12713 if (r.state != BroadcastRecord.IDLE) {
12714 if (DEBUG_BROADCAST) Log.d(TAG,
12715 "processNextBroadcast() called when not idle (state="
12716 + r.state + ")");
12717 return;
12718 }
12719
12720 if (r.receivers == null || r.nextReceiver >= numReceivers
12721 || r.resultAbort || forceReceive) {
12722 // No more receivers for this broadcast! Send the final
12723 // result if requested...
12724 if (r.resultTo != null) {
12725 try {
12726 if (DEBUG_BROADCAST) {
12727 int seq = r.intent.getIntExtra("seq", -1);
12728 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
12729 + " seq=" + seq + " app=" + r.callerApp);
12730 }
12731 performReceive(r.callerApp, r.resultTo,
12732 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012733 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012734 } catch (RemoteException e) {
12735 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
12736 }
12737 }
12738
12739 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
12740 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12741
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012742 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Finished with ordered broadcast "
12743 + r);
12744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012746 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012747 mOrderedBroadcasts.remove(0);
12748 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012749 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012750 continue;
12751 }
12752 } while (r == null);
12753
12754 // Get the next receiver...
12755 int recIdx = r.nextReceiver++;
12756
12757 // Keep track of when this receiver started, and make sure there
12758 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012759 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012760 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012761 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012762
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012763 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing ordered broadcast "
12764 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 if (DEBUG_BROADCAST) Log.v(TAG,
12766 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012767 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012768 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012769 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 }
12771
12772 Object nextReceiver = r.receivers.get(recIdx);
12773 if (nextReceiver instanceof BroadcastFilter) {
12774 // Simple case: this is a registered receiver who gets
12775 // a direct call.
12776 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
12777 if (DEBUG_BROADCAST) Log.v(TAG,
12778 "Delivering serialized to registered "
12779 + filter + ": " + r);
12780 deliverToRegisteredReceiver(r, filter, r.ordered);
12781 if (r.receiver == null || !r.ordered) {
12782 // The receiver has already finished, so schedule to
12783 // process the next one.
12784 r.state = BroadcastRecord.IDLE;
12785 scheduleBroadcastsLocked();
12786 }
12787 return;
12788 }
12789
12790 // Hard case: need to instantiate the receiver, possibly
12791 // starting its application process to host it.
12792
12793 ResolveInfo info =
12794 (ResolveInfo)nextReceiver;
12795
12796 boolean skip = false;
12797 int perm = checkComponentPermission(info.activityInfo.permission,
12798 r.callingPid, r.callingUid,
12799 info.activityInfo.exported
12800 ? -1 : info.activityInfo.applicationInfo.uid);
12801 if (perm != PackageManager.PERMISSION_GRANTED) {
12802 Log.w(TAG, "Permission Denial: broadcasting "
12803 + r.intent.toString()
12804 + " from " + r.callerPackage + " (pid=" + r.callingPid
12805 + ", uid=" + r.callingUid + ")"
12806 + " requires " + info.activityInfo.permission
12807 + " due to receiver " + info.activityInfo.packageName
12808 + "/" + info.activityInfo.name);
12809 skip = true;
12810 }
12811 if (r.callingUid != Process.SYSTEM_UID &&
12812 r.requiredPermission != null) {
12813 try {
12814 perm = ActivityThread.getPackageManager().
12815 checkPermission(r.requiredPermission,
12816 info.activityInfo.applicationInfo.packageName);
12817 } catch (RemoteException e) {
12818 perm = PackageManager.PERMISSION_DENIED;
12819 }
12820 if (perm != PackageManager.PERMISSION_GRANTED) {
12821 Log.w(TAG, "Permission Denial: receiving "
12822 + r.intent + " to "
12823 + info.activityInfo.applicationInfo.packageName
12824 + " requires " + r.requiredPermission
12825 + " due to sender " + r.callerPackage
12826 + " (uid " + r.callingUid + ")");
12827 skip = true;
12828 }
12829 }
12830 if (r.curApp != null && r.curApp.crashing) {
12831 // If the target process is crashing, just skip it.
12832 skip = true;
12833 }
12834
12835 if (skip) {
12836 r.receiver = null;
12837 r.curFilter = null;
12838 r.state = BroadcastRecord.IDLE;
12839 scheduleBroadcastsLocked();
12840 return;
12841 }
12842
12843 r.state = BroadcastRecord.APP_RECEIVE;
12844 String targetProcess = info.activityInfo.processName;
12845 r.curComponent = new ComponentName(
12846 info.activityInfo.applicationInfo.packageName,
12847 info.activityInfo.name);
12848 r.curReceiver = info.activityInfo;
12849
12850 // Is this receiver's application already running?
12851 ProcessRecord app = getProcessRecordLocked(targetProcess,
12852 info.activityInfo.applicationInfo.uid);
12853 if (app != null && app.thread != null) {
12854 try {
12855 processCurBroadcastLocked(r, app);
12856 return;
12857 } catch (RemoteException e) {
12858 Log.w(TAG, "Exception when sending broadcast to "
12859 + r.curComponent, e);
12860 }
12861
12862 // If a dead object exception was thrown -- fall through to
12863 // restart the application.
12864 }
12865
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012866 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012867 if ((r.curApp=startProcessLocked(targetProcess,
12868 info.activityInfo.applicationInfo, true,
12869 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012870 "broadcast", r.curComponent,
12871 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12872 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 // Ah, this recipient is unavailable. Finish it if necessary,
12874 // and mark the broadcast record as ready for the next.
12875 Log.w(TAG, "Unable to launch app "
12876 + info.activityInfo.applicationInfo.packageName + "/"
12877 + info.activityInfo.applicationInfo.uid + " for broadcast "
12878 + r.intent + ": process is bad");
12879 logBroadcastReceiverDiscard(r);
12880 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12881 r.resultExtras, r.resultAbort, true);
12882 scheduleBroadcastsLocked();
12883 r.state = BroadcastRecord.IDLE;
12884 return;
12885 }
12886
12887 mPendingBroadcast = r;
12888 }
12889 }
12890
12891 // =========================================================
12892 // INSTRUMENTATION
12893 // =========================================================
12894
12895 public boolean startInstrumentation(ComponentName className,
12896 String profileFile, int flags, Bundle arguments,
12897 IInstrumentationWatcher watcher) {
12898 // Refuse possible leaked file descriptors
12899 if (arguments != null && arguments.hasFileDescriptors()) {
12900 throw new IllegalArgumentException("File descriptors passed in Bundle");
12901 }
12902
12903 synchronized(this) {
12904 InstrumentationInfo ii = null;
12905 ApplicationInfo ai = null;
12906 try {
12907 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012908 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012909 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012910 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012911 } catch (PackageManager.NameNotFoundException e) {
12912 }
12913 if (ii == null) {
12914 reportStartInstrumentationFailure(watcher, className,
12915 "Unable to find instrumentation info for: " + className);
12916 return false;
12917 }
12918 if (ai == null) {
12919 reportStartInstrumentationFailure(watcher, className,
12920 "Unable to find instrumentation target package: " + ii.targetPackage);
12921 return false;
12922 }
12923
12924 int match = mContext.getPackageManager().checkSignatures(
12925 ii.targetPackage, ii.packageName);
12926 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12927 String msg = "Permission Denial: starting instrumentation "
12928 + className + " from pid="
12929 + Binder.getCallingPid()
12930 + ", uid=" + Binder.getCallingPid()
12931 + " not allowed because package " + ii.packageName
12932 + " does not have a signature matching the target "
12933 + ii.targetPackage;
12934 reportStartInstrumentationFailure(watcher, className, msg);
12935 throw new SecurityException(msg);
12936 }
12937
12938 final long origId = Binder.clearCallingIdentity();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012939 forceStopPackageLocked(ii.targetPackage, -1, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012940 ProcessRecord app = addAppLocked(ai);
12941 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012942 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 app.instrumentationProfileFile = profileFile;
12944 app.instrumentationArguments = arguments;
12945 app.instrumentationWatcher = watcher;
12946 app.instrumentationResultClass = className;
12947 Binder.restoreCallingIdentity(origId);
12948 }
12949
12950 return true;
12951 }
12952
12953 /**
12954 * Report errors that occur while attempting to start Instrumentation. Always writes the
12955 * error to the logs, but if somebody is watching, send the report there too. This enables
12956 * the "am" command to report errors with more information.
12957 *
12958 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12959 * @param cn The component name of the instrumentation.
12960 * @param report The error report.
12961 */
12962 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12963 ComponentName cn, String report) {
12964 Log.w(TAG, report);
12965 try {
12966 if (watcher != null) {
12967 Bundle results = new Bundle();
12968 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12969 results.putString("Error", report);
12970 watcher.instrumentationStatus(cn, -1, results);
12971 }
12972 } catch (RemoteException e) {
12973 Log.w(TAG, e);
12974 }
12975 }
12976
12977 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12978 if (app.instrumentationWatcher != null) {
12979 try {
12980 // NOTE: IInstrumentationWatcher *must* be oneway here
12981 app.instrumentationWatcher.instrumentationFinished(
12982 app.instrumentationClass,
12983 resultCode,
12984 results);
12985 } catch (RemoteException e) {
12986 }
12987 }
12988 app.instrumentationWatcher = null;
12989 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012990 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012991 app.instrumentationProfileFile = null;
12992 app.instrumentationArguments = null;
12993
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012994 forceStopPackageLocked(app.processName, -1, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012995 }
12996
12997 public void finishInstrumentation(IApplicationThread target,
12998 int resultCode, Bundle results) {
12999 // Refuse possible leaked file descriptors
13000 if (results != null && results.hasFileDescriptors()) {
13001 throw new IllegalArgumentException("File descriptors passed in Intent");
13002 }
13003
13004 synchronized(this) {
13005 ProcessRecord app = getRecordForAppLocked(target);
13006 if (app == null) {
13007 Log.w(TAG, "finishInstrumentation: no app for " + target);
13008 return;
13009 }
13010 final long origId = Binder.clearCallingIdentity();
13011 finishInstrumentationLocked(app, resultCode, results);
13012 Binder.restoreCallingIdentity(origId);
13013 }
13014 }
13015
13016 // =========================================================
13017 // CONFIGURATION
13018 // =========================================================
13019
13020 public ConfigurationInfo getDeviceConfigurationInfo() {
13021 ConfigurationInfo config = new ConfigurationInfo();
13022 synchronized (this) {
13023 config.reqTouchScreen = mConfiguration.touchscreen;
13024 config.reqKeyboardType = mConfiguration.keyboard;
13025 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013026 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13027 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013028 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13029 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013030 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13031 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013032 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13033 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013034 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013035 }
13036 return config;
13037 }
13038
13039 public Configuration getConfiguration() {
13040 Configuration ci;
13041 synchronized(this) {
13042 ci = new Configuration(mConfiguration);
13043 }
13044 return ci;
13045 }
13046
13047 public void updateConfiguration(Configuration values) {
13048 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13049 "updateConfiguration()");
13050
13051 synchronized(this) {
13052 if (values == null && mWindowManager != null) {
13053 // sentinel: fetch the current configuration from the window manager
13054 values = mWindowManager.computeNewConfiguration();
13055 }
13056
13057 final long origId = Binder.clearCallingIdentity();
13058 updateConfigurationLocked(values, null);
13059 Binder.restoreCallingIdentity(origId);
13060 }
13061 }
13062
13063 /**
13064 * Do either or both things: (1) change the current configuration, and (2)
13065 * make sure the given activity is running with the (now) current
13066 * configuration. Returns true if the activity has been left running, or
13067 * false if <var>starting</var> is being destroyed to match the new
13068 * configuration.
13069 */
13070 public boolean updateConfigurationLocked(Configuration values,
13071 HistoryRecord starting) {
13072 int changes = 0;
13073
13074 boolean kept = true;
13075
13076 if (values != null) {
13077 Configuration newConfig = new Configuration(mConfiguration);
13078 changes = newConfig.updateFrom(values);
13079 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013080 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013081 Log.i(TAG, "Updating configuration to: " + values);
13082 }
13083
Doug Zongker2bec3d42009-12-04 12:52:44 -080013084 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013085
13086 if (values.locale != null) {
13087 saveLocaleLocked(values.locale,
13088 !values.locale.equals(mConfiguration.locale),
13089 values.userSetLocale);
13090 }
13091
13092 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
13148 return kept;
13149 }
13150
13151 private final boolean relaunchActivityLocked(HistoryRecord r,
13152 int changes, boolean andResume) {
13153 List<ResultInfo> results = null;
13154 List<Intent> newIntents = null;
13155 if (andResume) {
13156 results = r.results;
13157 newIntents = r.newIntents;
13158 }
13159 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
13160 + " with results=" + results + " newIntents=" + newIntents
13161 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013162 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13163 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013164 r.task.taskId, r.shortComponentName);
13165
13166 r.startFreezingScreenLocked(r.app, 0);
13167
13168 try {
13169 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
13170 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013171 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013172 // Note: don't need to call pauseIfSleepingLocked() here, because
13173 // the caller will only pass in 'andResume' if this activity is
13174 // currently resumed, which implies we aren't sleeping.
13175 } catch (RemoteException e) {
13176 return false;
13177 }
13178
13179 if (andResume) {
13180 r.results = null;
13181 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013182 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 }
13184
13185 return true;
13186 }
13187
13188 /**
13189 * Make sure the given activity matches the current configuration. Returns
13190 * false if the activity had to be destroyed. Returns true if the
13191 * configuration is the same, or the activity will remain running as-is
13192 * for whatever reason. Ensures the HistoryRecord is updated with the
13193 * correct configuration and all other bookkeeping is handled.
13194 */
13195 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13196 int globalChanges) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013197 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13198 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199
13200 // Short circuit: if the two configurations are the exact same
13201 // object (the common case), then there is nothing to do.
13202 Configuration newConfig = mConfiguration;
13203 if (r.configuration == newConfig) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013204 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13205 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 return true;
13207 }
13208
13209 // We don't worry about activities that are finishing.
13210 if (r.finishing) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013211 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013212 "Configuration doesn't matter in finishing " + r);
13213 r.stopFreezingScreenLocked(false);
13214 return true;
13215 }
13216
13217 // Okay we now are going to make this activity have the new config.
13218 // But then we need to figure out how it needs to deal with that.
13219 Configuration oldConfig = r.configuration;
13220 r.configuration = newConfig;
13221
13222 // If the activity isn't currently running, just leave the new
13223 // configuration and it will pick that up next time it starts.
13224 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013225 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013226 "Configuration doesn't matter not running " + r);
13227 r.stopFreezingScreenLocked(false);
13228 return true;
13229 }
13230
13231 // If the activity isn't persistent, there is a chance we will
13232 // need to restart it.
13233 if (!r.persistent) {
13234
13235 // Figure out what has changed between the two configurations.
13236 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013237 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
13238 Log.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013239 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013240 + Integer.toHexString(r.info.configChanges)
13241 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 }
13243 if ((changes&(~r.info.configChanges)) != 0) {
13244 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13245 r.configChangeFlags |= changes;
13246 r.startFreezingScreenLocked(r.app, globalChanges);
13247 if (r.app == null || r.app.thread == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013248 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13249 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013250 destroyActivityLocked(r, true);
13251 } else if (r.state == ActivityState.PAUSING) {
13252 // A little annoying: we are waiting for this activity to
13253 // finish pausing. Let's not do anything now, but just
13254 // flag that it needs to be restarted when done pausing.
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013255 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13256 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013257 r.configDestroy = true;
13258 return true;
13259 } else if (r.state == ActivityState.RESUMED) {
13260 // Try to optimize this case: the configuration is changing
13261 // and we need to restart the top, resumed activity.
13262 // Instead of doing the normal handshaking, just say
13263 // "restart!".
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013264 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13265 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013266 relaunchActivityLocked(r, r.configChangeFlags, true);
13267 r.configChangeFlags = 0;
13268 } else {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013269 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Log.v(TAG,
13270 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013271 relaunchActivityLocked(r, r.configChangeFlags, false);
13272 r.configChangeFlags = 0;
13273 }
13274
13275 // All done... tell the caller we weren't able to keep this
13276 // activity around.
13277 return false;
13278 }
13279 }
13280
13281 // Default case: the activity can handle this new configuration, so
13282 // hand it over. Note that we don't need to give it the new
13283 // configuration, since we always send configuration changes to all
13284 // process when they happen so it can just use whatever configuration
13285 // it last got.
13286 if (r.app != null && r.app.thread != null) {
13287 try {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013288 if (DEBUG_CONFIGURATION) Log.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013289 r.app.thread.scheduleActivityConfigurationChanged(r);
13290 } catch (RemoteException e) {
13291 // If process died, whatever.
13292 }
13293 }
13294 r.stopFreezingScreenLocked(false);
13295
13296 return true;
13297 }
13298
13299 /**
13300 * Save the locale. You must be inside a synchronized (this) block.
13301 */
13302 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13303 if(isDiff) {
13304 SystemProperties.set("user.language", l.getLanguage());
13305 SystemProperties.set("user.region", l.getCountry());
13306 }
13307
13308 if(isPersist) {
13309 SystemProperties.set("persist.sys.language", l.getLanguage());
13310 SystemProperties.set("persist.sys.country", l.getCountry());
13311 SystemProperties.set("persist.sys.localevar", l.getVariant());
13312 }
13313 }
13314
13315 // =========================================================
13316 // LIFETIME MANAGEMENT
13317 // =========================================================
13318
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013319 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13320 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013321 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013322 // This adjustment has already been computed. If we are calling
13323 // from the top, we may have already computed our adjustment with
13324 // an earlier hidden adjustment that isn't really for us... if
13325 // so, use the new hidden adjustment.
13326 if (!recursed && app.hidden) {
13327 app.curAdj = hiddenAdj;
13328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329 return app.curAdj;
13330 }
13331
13332 if (app.thread == null) {
13333 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013334 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013335 return (app.curAdj=EMPTY_APP_ADJ);
13336 }
13337
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013338 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13339 // The max adjustment doesn't allow this app to be anything
13340 // below foreground, so it is not worth doing work for it.
13341 app.adjType = "fixed";
13342 app.adjSeq = mAdjSeq;
13343 app.curRawAdj = app.maxAdj;
13344 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13345 return (app.curAdj=app.maxAdj);
13346 }
13347
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013348 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013349 app.adjSource = null;
13350 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013351 app.empty = false;
13352 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013353
The Android Open Source Project4df24232009-03-05 14:34:35 -080013354 // Determine the importance of the process, starting with most
13355 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013356 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013357 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013359 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 // The last app on the list is the foreground app.
13361 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013362 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013363 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013364 } else if (app.instrumentationClass != null) {
13365 // Don't want to kill running instrumentation.
13366 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013367 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013368 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013369 } else if (app.persistentActivities > 0) {
13370 // Special persistent activities... shouldn't be used these days.
13371 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013372 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013373 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013374 } else if (app.curReceiver != null ||
13375 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13376 // An app that is currently receiving a broadcast also
13377 // counts as being in the foreground.
13378 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013379 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013380 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 } else if (app.executingServices.size() > 0) {
13382 // An app that is currently executing a service callback also
13383 // counts as being in the foreground.
13384 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013385 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013386 app.adjType = "exec-service";
13387 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013388 // The user is aware of this app, so make it visible.
13389 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013390 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013391 app.adjType = "foreground-service";
13392 } else if (app.forcingToForeground != null) {
13393 // The user is aware of this app, so make it visible.
13394 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013395 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013396 app.adjType = "force-foreground";
13397 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013398 } else if (app == mHomeProcess) {
13399 // This process is hosting what we currently consider to be the
13400 // home app, so we don't want to let it go into the background.
13401 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013402 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013403 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404 } else if ((N=app.activities.size()) != 0) {
13405 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013406 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013408 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013409 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013410 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013411 for (int j=0; j<N; j++) {
13412 if (((HistoryRecord)app.activities.get(j)).visible) {
13413 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013414 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013416 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013417 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 break;
13419 }
13420 }
13421 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013422 // A very not-needed process. If this is lower in the lru list,
13423 // we will push it in to the empty bucket.
13424 app.hidden = true;
13425 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013426 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013427 adj = hiddenAdj;
13428 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013429 }
13430
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013431 //Log.i(TAG, "OOM " + app + ": initial adj=" + adj);
13432
The Android Open Source Project4df24232009-03-05 14:34:35 -080013433 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013434 // there are applications dependent on our services or providers, but
13435 // this gives us a baseline and makes sure we don't get into an
13436 // infinite recursion.
13437 app.adjSeq = mAdjSeq;
13438 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013439
Christopher Tate6fa95972009-06-05 18:43:55 -070013440 if (mBackupTarget != null && app == mBackupTarget.app) {
13441 // If possible we want to avoid killing apps while they're being backed up
13442 if (adj > BACKUP_APP_ADJ) {
13443 if (DEBUG_BACKUP) Log.v(TAG, "oom BACKUP_APP_ADJ for " + app);
13444 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013445 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013446 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013447 }
13448 }
13449
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013450 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13451 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013452 final long now = SystemClock.uptimeMillis();
13453 // This process is more important if the top activity is
13454 // bound to the service.
13455 Iterator jt = app.services.iterator();
13456 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13457 ServiceRecord s = (ServiceRecord)jt.next();
13458 if (s.startRequested) {
13459 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13460 // This service has seen some activity within
13461 // recent memory, so we will keep its process ahead
13462 // of the background processes.
13463 if (adj > SECONDARY_SERVER_ADJ) {
13464 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013465 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013466 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013467 }
13468 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013469 // If we have let the service slide into the background
13470 // state, still have some text describing what it is doing
13471 // even though the service no longer has an impact.
13472 if (adj > SECONDARY_SERVER_ADJ) {
13473 app.adjType = "started-bg-services";
13474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013475 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013476 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13477 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013478 Iterator<ConnectionRecord> kt
13479 = s.connections.values().iterator();
13480 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13481 // XXX should compute this based on the max of
13482 // all connected clients.
13483 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013484 if (cr.binding.client == app) {
13485 // Binding to ourself is not interesting.
13486 continue;
13487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013488 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13489 ProcessRecord client = cr.binding.client;
13490 int myHiddenAdj = hiddenAdj;
13491 if (myHiddenAdj > client.hiddenAdj) {
13492 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13493 myHiddenAdj = client.hiddenAdj;
13494 } else {
13495 myHiddenAdj = VISIBLE_APP_ADJ;
13496 }
13497 }
13498 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013499 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013500 if (adj > clientAdj) {
13501 adj = clientAdj > VISIBLE_APP_ADJ
13502 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013503 if (!client.hidden) {
13504 app.hidden = false;
13505 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013506 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013507 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13508 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013509 app.adjSource = cr.binding.client;
13510 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013511 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013512 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13513 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13514 schedGroup = Process.THREAD_GROUP_DEFAULT;
13515 }
13516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013517 }
13518 HistoryRecord a = cr.activity;
13519 //if (a != null) {
13520 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
13521 //}
13522 if (a != null && adj > FOREGROUND_APP_ADJ &&
13523 (a.state == ActivityState.RESUMED
13524 || a.state == ActivityState.PAUSING)) {
13525 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013526 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013527 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013528 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013529 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13530 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013531 app.adjSource = a;
13532 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013533 }
13534 }
13535 }
13536 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013537
13538 // Finally, f this process has active services running in it, we
13539 // would like to avoid killing it unless it would prevent the current
13540 // application from running. By default we put the process in
13541 // with the rest of the background processes; as we scan through
13542 // its services we may bump it up from there.
13543 if (adj > hiddenAdj) {
13544 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013545 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013546 app.adjType = "bg-services";
13547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013548 }
13549
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013550 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13551 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013552 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013553 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13554 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013555 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13556 if (cpr.clients.size() != 0) {
13557 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13558 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13559 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013560 if (client == app) {
13561 // Being our own client is not interesting.
13562 continue;
13563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564 int myHiddenAdj = hiddenAdj;
13565 if (myHiddenAdj > client.hiddenAdj) {
13566 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13567 myHiddenAdj = client.hiddenAdj;
13568 } else {
13569 myHiddenAdj = FOREGROUND_APP_ADJ;
13570 }
13571 }
13572 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013573 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013574 if (adj > clientAdj) {
13575 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013576 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013577 if (!client.hidden) {
13578 app.hidden = false;
13579 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013580 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013581 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13582 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013583 app.adjSource = client;
13584 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013585 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013586 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13587 schedGroup = Process.THREAD_GROUP_DEFAULT;
13588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013589 }
13590 }
13591 // If the provider has external (non-framework) process
13592 // dependencies, ensure that its adjustment is at least
13593 // FOREGROUND_APP_ADJ.
13594 if (cpr.externals != 0) {
13595 if (adj > FOREGROUND_APP_ADJ) {
13596 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013597 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013598 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013599 app.adjType = "provider";
13600 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013601 }
13602 }
13603 }
13604 }
13605
13606 app.curRawAdj = adj;
13607
13608 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
13609 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13610 if (adj > app.maxAdj) {
13611 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013612 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13613 schedGroup = Process.THREAD_GROUP_DEFAULT;
13614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013615 }
13616
13617 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013618 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 return adj;
13621 }
13622
13623 /**
13624 * Ask a given process to GC right now.
13625 */
13626 final void performAppGcLocked(ProcessRecord app) {
13627 try {
13628 app.lastRequestedGc = SystemClock.uptimeMillis();
13629 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013630 if (app.reportLowMemory) {
13631 app.reportLowMemory = false;
13632 app.thread.scheduleLowMemory();
13633 } else {
13634 app.thread.processInBackground();
13635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013636 }
13637 } catch (Exception e) {
13638 // whatever.
13639 }
13640 }
13641
13642 /**
13643 * Returns true if things are idle enough to perform GCs.
13644 */
13645 private final boolean canGcNow() {
13646 return mParallelBroadcasts.size() == 0
13647 && mOrderedBroadcasts.size() == 0
13648 && (mSleeping || (mResumedActivity != null &&
13649 mResumedActivity.idle));
13650 }
13651
13652 /**
13653 * Perform GCs on all processes that are waiting for it, but only
13654 * if things are idle.
13655 */
13656 final void performAppGcsLocked() {
13657 final int N = mProcessesToGc.size();
13658 if (N <= 0) {
13659 return;
13660 }
13661 if (canGcNow()) {
13662 while (mProcessesToGc.size() > 0) {
13663 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013664 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13665 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13666 <= SystemClock.uptimeMillis()) {
13667 // To avoid spamming the system, we will GC processes one
13668 // at a time, waiting a few seconds between each.
13669 performAppGcLocked(proc);
13670 scheduleAppGcsLocked();
13671 return;
13672 } else {
13673 // It hasn't been long enough since we last GCed this
13674 // process... put it in the list to wait for its time.
13675 addProcessToGcListLocked(proc);
13676 break;
13677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013678 }
13679 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013680
13681 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 }
13683 }
13684
13685 /**
13686 * If all looks good, perform GCs on all processes waiting for them.
13687 */
13688 final void performAppGcsIfAppropriateLocked() {
13689 if (canGcNow()) {
13690 performAppGcsLocked();
13691 return;
13692 }
13693 // Still not idle, wait some more.
13694 scheduleAppGcsLocked();
13695 }
13696
13697 /**
13698 * Schedule the execution of all pending app GCs.
13699 */
13700 final void scheduleAppGcsLocked() {
13701 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013702
13703 if (mProcessesToGc.size() > 0) {
13704 // Schedule a GC for the time to the next process.
13705 ProcessRecord proc = mProcessesToGc.get(0);
13706 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13707
13708 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13709 long now = SystemClock.uptimeMillis();
13710 if (when < (now+GC_TIMEOUT)) {
13711 when = now + GC_TIMEOUT;
13712 }
13713 mHandler.sendMessageAtTime(msg, when);
13714 }
13715 }
13716
13717 /**
13718 * Add a process to the array of processes waiting to be GCed. Keeps the
13719 * list in sorted order by the last GC time. The process can't already be
13720 * on the list.
13721 */
13722 final void addProcessToGcListLocked(ProcessRecord proc) {
13723 boolean added = false;
13724 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13725 if (mProcessesToGc.get(i).lastRequestedGc <
13726 proc.lastRequestedGc) {
13727 added = true;
13728 mProcessesToGc.add(i+1, proc);
13729 break;
13730 }
13731 }
13732 if (!added) {
13733 mProcessesToGc.add(0, proc);
13734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013735 }
13736
13737 /**
13738 * Set up to ask a process to GC itself. This will either do it
13739 * immediately, or put it on the list of processes to gc the next
13740 * time things are idle.
13741 */
13742 final void scheduleAppGcLocked(ProcessRecord app) {
13743 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013744 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013745 return;
13746 }
13747 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013748 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013749 scheduleAppGcsLocked();
13750 }
13751 }
13752
13753 private final boolean updateOomAdjLocked(
13754 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13755 app.hiddenAdj = hiddenAdj;
13756
13757 if (app.thread == null) {
13758 return true;
13759 }
13760
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013761 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013763 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013764 if (app.curRawAdj != app.setRawAdj) {
13765 if (app.curRawAdj > FOREGROUND_APP_ADJ
13766 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13767 // If this app is transitioning from foreground to
13768 // non-foreground, have it do a gc.
13769 scheduleAppGcLocked(app);
13770 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13771 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13772 // Likewise do a gc when an app is moving in to the
13773 // background (such as a service stopping).
13774 scheduleAppGcLocked(app);
13775 }
13776 app.setRawAdj = app.curRawAdj;
13777 }
13778 if (adj != app.setAdj) {
13779 if (Process.setOomAdj(app.pid, adj)) {
13780 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
13781 TAG, "Set app " + app.processName +
13782 " oom adj to " + adj);
13783 app.setAdj = adj;
13784 } else {
13785 return false;
13786 }
13787 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013788 if (app.setSchedGroup != app.curSchedGroup) {
13789 app.setSchedGroup = app.curSchedGroup;
13790 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG,
13791 "Setting process group of " + app.processName
13792 + " to " + app.curSchedGroup);
13793 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013794 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013795 try {
13796 Process.setProcessGroup(app.pid, app.curSchedGroup);
13797 } catch (Exception e) {
13798 Log.w(TAG, "Failed setting process group of " + app.pid
13799 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013800 e.printStackTrace();
13801 } finally {
13802 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013803 }
13804 }
13805 if (false) {
13806 if (app.thread != null) {
13807 try {
13808 app.thread.setSchedulingGroup(app.curSchedGroup);
13809 } catch (RemoteException e) {
13810 }
13811 }
13812 }
13813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013814 }
13815
13816 return true;
13817 }
13818
13819 private final HistoryRecord resumedAppLocked() {
13820 HistoryRecord resumedActivity = mResumedActivity;
13821 if (resumedActivity == null || resumedActivity.app == null) {
13822 resumedActivity = mPausingActivity;
13823 if (resumedActivity == null || resumedActivity.app == null) {
13824 resumedActivity = topRunningActivityLocked(null);
13825 }
13826 }
13827 return resumedActivity;
13828 }
13829
13830 private final boolean updateOomAdjLocked(ProcessRecord app) {
13831 final HistoryRecord TOP_ACT = resumedAppLocked();
13832 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13833 int curAdj = app.curAdj;
13834 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13835 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13836
13837 mAdjSeq++;
13838
13839 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13840 if (res) {
13841 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13842 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13843 if (nowHidden != wasHidden) {
13844 // Changed to/from hidden state, so apps after it in the LRU
13845 // list may also be changed.
13846 updateOomAdjLocked();
13847 }
13848 }
13849 return res;
13850 }
13851
13852 private final boolean updateOomAdjLocked() {
13853 boolean didOomAdj = true;
13854 final HistoryRecord TOP_ACT = resumedAppLocked();
13855 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13856
13857 if (false) {
13858 RuntimeException e = new RuntimeException();
13859 e.fillInStackTrace();
13860 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
13861 }
13862
13863 mAdjSeq++;
13864
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013865 // Let's determine how many processes we have running vs.
13866 // how many slots we have for background processes; we may want
13867 // to put multiple processes in a slot of there are enough of
13868 // them.
13869 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13870 int factor = (mLruProcesses.size()-4)/numSlots;
13871 if (factor < 1) factor = 1;
13872 int step = 0;
13873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 // First try updating the OOM adjustment for each of the
13875 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013876 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013877 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13878 while (i > 0) {
13879 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013880 ProcessRecord app = mLruProcesses.get(i);
13881 //Log.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013882 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013883 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013884 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013885 step++;
13886 if (step >= factor) {
13887 step = 0;
13888 curHiddenAdj++;
13889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013890 }
13891 } else {
13892 didOomAdj = false;
13893 }
13894 }
13895
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013896 // If we return false, we will fall back on killing processes to
13897 // have a fixed limit. Do this if a limit has been requested; else
13898 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013899 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13900 }
13901
13902 private final void trimApplications() {
13903 synchronized (this) {
13904 int i;
13905
13906 // First remove any unused application processes whose package
13907 // has been removed.
13908 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13909 final ProcessRecord app = mRemovedProcesses.get(i);
13910 if (app.activities.size() == 0
13911 && app.curReceiver == null && app.services.size() == 0) {
13912 Log.i(
13913 TAG, "Exiting empty application process "
13914 + app.processName + " ("
13915 + (app.thread != null ? app.thread.asBinder() : null)
13916 + ")\n");
13917 if (app.pid > 0 && app.pid != MY_PID) {
13918 Process.killProcess(app.pid);
13919 } else {
13920 try {
13921 app.thread.scheduleExit();
13922 } catch (Exception e) {
13923 // Ignore exceptions.
13924 }
13925 }
13926 cleanUpApplicationRecordLocked(app, false, -1);
13927 mRemovedProcesses.remove(i);
13928
13929 if (app.persistent) {
13930 if (app.persistent) {
13931 addAppLocked(app.info);
13932 }
13933 }
13934 }
13935 }
13936
13937 // Now try updating the OOM adjustment for each of the
13938 // application processes based on their current state.
13939 // If the setOomAdj() API is not supported, then go with our
13940 // back-up plan...
13941 if (!updateOomAdjLocked()) {
13942
13943 // Count how many processes are running services.
13944 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013945 for (i=mLruProcesses.size()-1; i>=0; i--) {
13946 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013947
13948 if (app.persistent || app.services.size() != 0
13949 || app.curReceiver != null
13950 || app.persistentActivities > 0) {
13951 // Don't count processes holding services against our
13952 // maximum process count.
13953 if (localLOGV) Log.v(
13954 TAG, "Not trimming app " + app + " with services: "
13955 + app.services);
13956 numServiceProcs++;
13957 }
13958 }
13959
13960 int curMaxProcs = mProcessLimit;
13961 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13962 if (mAlwaysFinishActivities) {
13963 curMaxProcs = 1;
13964 }
13965 curMaxProcs += numServiceProcs;
13966
13967 // Quit as many processes as we can to get down to the desired
13968 // process count. First remove any processes that no longer
13969 // have activites running in them.
13970 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013971 i<mLruProcesses.size()
13972 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013973 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013974 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013975 // Quit an application only if it is not currently
13976 // running any activities.
13977 if (!app.persistent && app.activities.size() == 0
13978 && app.curReceiver == null && app.services.size() == 0) {
13979 Log.i(
13980 TAG, "Exiting empty application process "
13981 + app.processName + " ("
13982 + (app.thread != null ? app.thread.asBinder() : null)
13983 + ")\n");
13984 if (app.pid > 0 && app.pid != MY_PID) {
13985 Process.killProcess(app.pid);
13986 } else {
13987 try {
13988 app.thread.scheduleExit();
13989 } catch (Exception e) {
13990 // Ignore exceptions.
13991 }
13992 }
13993 // todo: For now we assume the application is not buggy
13994 // or evil, and will quit as a result of our request.
13995 // Eventually we need to drive this off of the death
13996 // notification, and kill the process if it takes too long.
13997 cleanUpApplicationRecordLocked(app, false, i);
13998 i--;
13999 }
14000 }
14001
14002 // If we still have too many processes, now from the least
14003 // recently used process we start finishing activities.
14004 if (Config.LOGV) Log.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014005 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014006 " of " + curMaxProcs + " processes");
14007 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014008 i<mLruProcesses.size()
14009 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014010 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014011 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014012 // Quit the application only if we have a state saved for
14013 // all of its activities.
14014 boolean canQuit = !app.persistent && app.curReceiver == null
14015 && app.services.size() == 0
14016 && app.persistentActivities == 0;
14017 int NUMA = app.activities.size();
14018 int j;
14019 if (Config.LOGV) Log.v(
14020 TAG, "Looking to quit " + app.processName);
14021 for (j=0; j<NUMA && canQuit; j++) {
14022 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14023 if (Config.LOGV) Log.v(
14024 TAG, " " + r.intent.getComponent().flattenToShortString()
14025 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14026 canQuit = (r.haveState || !r.stateNotNeeded)
14027 && !r.visible && r.stopped;
14028 }
14029 if (canQuit) {
14030 // Finish all of the activities, and then the app itself.
14031 for (j=0; j<NUMA; j++) {
14032 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14033 if (!r.finishing) {
14034 destroyActivityLocked(r, false);
14035 }
14036 r.resultTo = null;
14037 }
14038 Log.i(TAG, "Exiting application process "
14039 + app.processName + " ("
14040 + (app.thread != null ? app.thread.asBinder() : null)
14041 + ")\n");
14042 if (app.pid > 0 && app.pid != MY_PID) {
14043 Process.killProcess(app.pid);
14044 } else {
14045 try {
14046 app.thread.scheduleExit();
14047 } catch (Exception e) {
14048 // Ignore exceptions.
14049 }
14050 }
14051 // todo: For now we assume the application is not buggy
14052 // or evil, and will quit as a result of our request.
14053 // Eventually we need to drive this off of the death
14054 // notification, and kill the process if it takes too long.
14055 cleanUpApplicationRecordLocked(app, false, i);
14056 i--;
14057 //dump();
14058 }
14059 }
14060
14061 }
14062
14063 int curMaxActivities = MAX_ACTIVITIES;
14064 if (mAlwaysFinishActivities) {
14065 curMaxActivities = 1;
14066 }
14067
14068 // Finally, if there are too many activities now running, try to
14069 // finish as many as we can to get back down to the limit.
14070 for ( i=0;
14071 i<mLRUActivities.size()
14072 && mLRUActivities.size() > curMaxActivities;
14073 i++) {
14074 final HistoryRecord r
14075 = (HistoryRecord)mLRUActivities.get(i);
14076
14077 // We can finish this one if we have its icicle saved and
14078 // it is not persistent.
14079 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14080 && r.stopped && !r.persistent && !r.finishing) {
14081 final int origSize = mLRUActivities.size();
14082 destroyActivityLocked(r, true);
14083
14084 // This will remove it from the LRU list, so keep
14085 // our index at the same value. Note that this check to
14086 // see if the size changes is just paranoia -- if
14087 // something unexpected happens, we don't want to end up
14088 // in an infinite loop.
14089 if (origSize > mLRUActivities.size()) {
14090 i--;
14091 }
14092 }
14093 }
14094 }
14095 }
14096
14097 /** This method sends the specified signal to each of the persistent apps */
14098 public void signalPersistentProcesses(int sig) throws RemoteException {
14099 if (sig != Process.SIGNAL_USR1) {
14100 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14101 }
14102
14103 synchronized (this) {
14104 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14105 != PackageManager.PERMISSION_GRANTED) {
14106 throw new SecurityException("Requires permission "
14107 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14108 }
14109
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014110 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14111 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014112 if (r.thread != null && r.persistent) {
14113 Process.sendSignal(r.pid, sig);
14114 }
14115 }
14116 }
14117 }
14118
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014119 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014120 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014121
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014122 try {
14123 synchronized (this) {
14124 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14125 // its own permission.
14126 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14127 != PackageManager.PERMISSION_GRANTED) {
14128 throw new SecurityException("Requires permission "
14129 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014130 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014131
14132 if (start && fd == null) {
14133 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014134 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014135
14136 ProcessRecord proc = null;
14137 try {
14138 int pid = Integer.parseInt(process);
14139 synchronized (mPidsSelfLocked) {
14140 proc = mPidsSelfLocked.get(pid);
14141 }
14142 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014143 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014144
14145 if (proc == null) {
14146 HashMap<String, SparseArray<ProcessRecord>> all
14147 = mProcessNames.getMap();
14148 SparseArray<ProcessRecord> procs = all.get(process);
14149 if (procs != null && procs.size() > 0) {
14150 proc = procs.valueAt(0);
14151 }
14152 }
14153
14154 if (proc == null || proc.thread == null) {
14155 throw new IllegalArgumentException("Unknown process: " + process);
14156 }
14157
14158 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14159 if (isSecure) {
14160 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14161 throw new SecurityException("Process not debuggable: " + proc);
14162 }
14163 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014164
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014165 proc.thread.profilerControl(start, path, fd);
14166 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014167 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014168 }
14169 } catch (RemoteException e) {
14170 throw new IllegalStateException("Process disappeared");
14171 } finally {
14172 if (fd != null) {
14173 try {
14174 fd.close();
14175 } catch (IOException e) {
14176 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014177 }
14178 }
14179 }
14180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014181 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14182 public void monitor() {
14183 synchronized (this) { }
14184 }
14185}