blob: b6f323dd0a6b93b2ddeb2592bb9d974743ead899 [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;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080038import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.IActivityWatcher;
40import android.app.IApplicationThread;
41import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IServiceConnection;
43import android.app.IThumbnailReceiver;
44import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070045import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.PendingIntent;
47import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070048import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080049import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.ContentResolver;
54import android.content.Context;
55import android.content.Intent;
56import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057import android.content.IIntentReceiver;
58import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070059import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.ActivityInfo;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.ConfigurationInfo;
63import android.content.pm.IPackageDataObserver;
64import android.content.pm.IPackageManager;
65import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080066import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070068import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.ProviderInfo;
70import android.content.pm.ResolveInfo;
71import android.content.pm.ServiceInfo;
72import android.content.res.Configuration;
73import android.graphics.Bitmap;
74import android.net.Uri;
75import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080076import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080077import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070078import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080079import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPermissionController;
86import android.os.Looper;
87import android.os.Message;
88import android.os.Parcel;
89import android.os.ParcelFileDescriptor;
90import android.os.PowerManager;
91import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070092import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.RemoteException;
94import android.os.ServiceManager;
95import android.os.SystemClock;
96import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Config;
99import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800101import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.PrintWriterPrinter;
103import android.util.SparseArray;
104import android.view.Gravity;
105import android.view.LayoutInflater;
106import android.view.View;
107import android.view.WindowManager;
108import android.view.WindowManagerPolicy;
109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.File;
111import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800114import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.PrintWriter;
116import java.lang.IllegalStateException;
117import java.lang.ref.WeakReference;
118import java.util.ArrayList;
119import java.util.HashMap;
120import java.util.HashSet;
121import java.util.Iterator;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700125import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
127public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
128 static final String TAG = "ActivityManager";
129 static final boolean DEBUG = false;
130 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
131 static final boolean DEBUG_SWITCH = localLOGV || false;
132 static final boolean DEBUG_TASKS = localLOGV || false;
133 static final boolean DEBUG_PAUSE = localLOGV || false;
134 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
135 static final boolean DEBUG_TRANSITION = localLOGV || false;
136 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700137 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 static final boolean DEBUG_SERVICE = localLOGV || false;
139 static final boolean DEBUG_VISBILITY = localLOGV || false;
140 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700141 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800142 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700144 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700145 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700146 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final boolean VALIDATE_TOKENS = false;
148 static final boolean SHOW_ACTIVITY_START_TIME = true;
149
150 // Control over CPU and battery monitoring.
151 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
152 static final boolean MONITOR_CPU_USAGE = true;
153 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
154 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
155 static final boolean MONITOR_THREAD_CPU_USAGE = false;
156
Dianne Hackborn1655be42009-05-08 14:29:01 -0700157 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700158 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 private static final String SYSTEM_SECURE = "ro.secure";
161
162 // This is the maximum number of application processes we would like
163 // to have running. Due to the asynchronous nature of things, we can
164 // temporarily go beyond this limit.
165 static final int MAX_PROCESSES = 2;
166
167 // Set to false to leave processes running indefinitely, relying on
168 // the kernel killing them as resources are required.
169 static final boolean ENFORCE_PROCESS_LIMIT = false;
170
171 // This is the maximum number of activities that we would like to have
172 // running at a given time.
173 static final int MAX_ACTIVITIES = 20;
174
175 // Maximum number of recent tasks that we can remember.
176 static final int MAX_RECENT_TASKS = 20;
177
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700178 // Amount of time after a call to stopAppSwitches() during which we will
179 // prevent further untrusted switches from happening.
180 static final long APP_SWITCH_DELAY_TIME = 5*1000;
181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 // How long until we reset a task when the user returns to it. Currently
183 // 30 minutes.
184 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
185
186 // Set to true to disable the icon that is shown while a new activity
187 // is being started.
188 static final boolean SHOW_APP_STARTING_ICON = true;
189
190 // How long we wait until giving up on the last activity to pause. This
191 // is short because it directly impacts the responsiveness of starting the
192 // next activity.
193 static final int PAUSE_TIMEOUT = 500;
194
195 /**
196 * How long we can hold the launch wake lock before giving up.
197 */
198 static final int LAUNCH_TIMEOUT = 10*1000;
199
200 // How long we wait for a launched process to attach to the activity manager
201 // before we decide it's never going to come up for real.
202 static final int PROC_START_TIMEOUT = 10*1000;
203
204 // How long we wait until giving up on the last activity telling us it
205 // is idle.
206 static final int IDLE_TIMEOUT = 10*1000;
207
208 // How long to wait after going idle before forcing apps to GC.
209 static final int GC_TIMEOUT = 5*1000;
210
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700211 // The minimum amount of time between successive GC requests for a process.
212 static final int GC_MIN_INTERVAL = 60*1000;
213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 // How long we wait until giving up on an activity telling us it has
215 // finished destroying itself.
216 static final int DESTROY_TIMEOUT = 10*1000;
217
218 // How long we allow a receiver to run before giving up on it.
219 static final int BROADCAST_TIMEOUT = 10*1000;
220
221 // How long we wait for a service to finish executing.
222 static final int SERVICE_TIMEOUT = 20*1000;
223
224 // How long a service needs to be running until restarting its process
225 // is no longer considered to be a relaunch of the service.
226 static final int SERVICE_RESTART_DURATION = 5*1000;
227
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700228 // How long a service needs to be running until it will start back at
229 // SERVICE_RESTART_DURATION after being killed.
230 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
231
232 // Multiplying factor to increase restart duration time by, for each time
233 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
234 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
235
236 // The minimum amount of time between restarting services that we allow.
237 // That is, when multiple services are restarting, we won't allow each
238 // to restart less than this amount of time from the last one.
239 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 // Maximum amount of time for there to be no activity on a service before
242 // we consider it non-essential and allow its process to go on the
243 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700244 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245
246 // How long we wait until we timeout on key dispatching.
247 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
248
249 // The minimum time we allow between crashes, for us to consider this
250 // application to be bad and stop and its services and reject broadcasts.
251 static final int MIN_CRASH_INTERVAL = 60*1000;
252
253 // How long we wait until we timeout on key dispatching during instrumentation.
254 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
255
256 // OOM adjustments for processes in various states:
257
258 // This is a process without anything currently running in it. Definitely
259 // the first to go! Value set in system/rootdir/init.rc on startup.
260 // This value is initalized in the constructor, careful when refering to
261 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800262 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263
264 // This is a process only hosting activities that are not visible,
265 // so it can be killed without any disruption. Value set in
266 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 static int HIDDEN_APP_MIN_ADJ;
269
The Android Open Source Project4df24232009-03-05 14:34:35 -0800270 // This is a process holding the home application -- we want to try
271 // avoiding killing it, even if it would normally be in the background,
272 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800273 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800274
Christopher Tate6fa95972009-06-05 18:43:55 -0700275 // This is a process currently hosting a backup operation. Killing it
276 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800277 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 // This is a process holding a secondary server -- killing it will not
280 // have much of an impact as far as the user is concerned. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is a process only hosting activities that are visible to the
285 // user, so we'd prefer they don't disappear. Value set in
286 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // This is the process running the current foreground app. We'd really
290 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800291 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
293 // This is a process running a core server, such as telephony. Definitely
294 // don't want to kill it, but doing so is not completely fatal.
295 static final int CORE_SERVER_ADJ = -12;
296
297 // The system process runs at the default adjustment.
298 static final int SYSTEM_ADJ = -16;
299
300 // Memory pages are 4K.
301 static final int PAGE_SIZE = 4*1024;
302
303 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800304 static final int EMPTY_APP_MEM;
305 static final int HIDDEN_APP_MEM;
306 static final int HOME_APP_MEM;
307 static final int BACKUP_APP_MEM;
308 static final int SECONDARY_SERVER_MEM;
309 static final int VISIBLE_APP_MEM;
310 static final int FOREGROUND_APP_MEM;
311
312 // The minimum number of hidden apps we want to be able to keep around,
313 // without empty apps being able to push them out of memory.
314 static final int MIN_HIDDEN_APPS = 2;
315
316 // We put empty content processes after any hidden processes that have
317 // been idle for less than 30 seconds.
318 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
319
320 // We put empty content processes after any hidden processes that have
321 // been idle for less than 60 seconds.
322 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
323
324 static {
325 // These values are set in system/rootdir/init.rc on startup.
326 FOREGROUND_APP_ADJ =
327 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
328 VISIBLE_APP_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
330 SECONDARY_SERVER_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
332 BACKUP_APP_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
334 HOME_APP_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
336 HIDDEN_APP_MIN_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
338 EMPTY_APP_ADJ =
339 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
340 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
341 FOREGROUND_APP_MEM =
342 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
343 VISIBLE_APP_MEM =
344 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
345 SECONDARY_SERVER_MEM =
346 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
347 BACKUP_APP_MEM =
348 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
349 HOME_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
351 HIDDEN_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
353 EMPTY_APP_MEM =
354 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
Dan Egnor42471dd2010-01-07 17:25:22 -0800357 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358
359 static final String[] EMPTY_STRING_ARRAY = new String[0];
360
361 enum ActivityState {
362 INITIALIZING,
363 RESUMED,
364 PAUSING,
365 PAUSED,
366 STOPPING,
367 STOPPED,
368 FINISHING,
369 DESTROYING,
370 DESTROYED
371 }
372
373 /**
374 * The back history of all previous (and possibly still
375 * running) activities. It contains HistoryRecord objects.
376 */
377 final ArrayList mHistory = new ArrayList();
378
379 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700380 * Description of a request to start a new activity, which has been held
381 * due to app switches being disabled.
382 */
383 class PendingActivityLaunch {
384 HistoryRecord r;
385 HistoryRecord sourceRecord;
386 Uri[] grantedUriPermissions;
387 int grantedMode;
388 boolean onlyIfNeeded;
389 }
390
391 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
392 = new ArrayList<PendingActivityLaunch>();
393
394 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800395 * List of people waiting to find out about the next launched activity.
396 */
397 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
398 = new ArrayList<IActivityManager.WaitResult>();
399
400 /**
401 * List of people waiting to find out about the next visible activity.
402 */
403 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
404 = new ArrayList<IActivityManager.WaitResult>();
405
406 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 * List of all active broadcasts that are to be executed immediately
408 * (without waiting for another broadcast to finish). Currently this only
409 * contains broadcasts to registered receivers, to avoid spinning up
410 * a bunch of processes to execute IntentReceiver components.
411 */
412 final ArrayList<BroadcastRecord> mParallelBroadcasts
413 = new ArrayList<BroadcastRecord>();
414
415 /**
416 * List of all active broadcasts that are to be executed one at a time.
417 * The object at the top of the list is the currently activity broadcasts;
418 * those after it are waiting for the top to finish..
419 */
420 final ArrayList<BroadcastRecord> mOrderedBroadcasts
421 = new ArrayList<BroadcastRecord>();
422
423 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800424 * Historical data of past broadcasts, for debugging.
425 */
426 static final int MAX_BROADCAST_HISTORY = 100;
427 final BroadcastRecord[] mBroadcastHistory
428 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
429
430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * Set when we current have a BROADCAST_INTENT_MSG in flight.
432 */
433 boolean mBroadcastsScheduled = false;
434
435 /**
436 * Set to indicate whether to issue an onUserLeaving callback when a
437 * newly launched activity is being brought in front of us.
438 */
439 boolean mUserLeaving = false;
440
441 /**
442 * When we are in the process of pausing an activity, before starting the
443 * next one, this variable holds the activity that is currently being paused.
444 */
445 HistoryRecord mPausingActivity = null;
446
447 /**
448 * Current activity that is resumed, or null if there is none.
449 */
450 HistoryRecord mResumedActivity = null;
451
452 /**
453 * Activity we have told the window manager to have key focus.
454 */
455 HistoryRecord mFocusedActivity = null;
456
457 /**
458 * This is the last activity that we put into the paused state. This is
459 * used to determine if we need to do an activity transition while sleeping,
460 * when we normally hold the top activity paused.
461 */
462 HistoryRecord mLastPausedActivity = null;
463
464 /**
465 * List of activities that are waiting for a new activity
466 * to become visible before completing whatever operation they are
467 * supposed to do.
468 */
469 final ArrayList mWaitingVisibleActivities = new ArrayList();
470
471 /**
472 * List of activities that are ready to be stopped, but waiting
473 * for the next activity to settle down before doing so. It contains
474 * HistoryRecord objects.
475 */
476 final ArrayList<HistoryRecord> mStoppingActivities
477 = new ArrayList<HistoryRecord>();
478
479 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700480 * Animations that for the current transition have requested not to
481 * be considered for the transition animation.
482 */
483 final ArrayList<HistoryRecord> mNoAnimActivities
484 = new ArrayList<HistoryRecord>();
485
486 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 * List of intents that were used to start the most recent tasks.
488 */
489 final ArrayList<TaskRecord> mRecentTasks
490 = new ArrayList<TaskRecord>();
491
492 /**
493 * List of activities that are ready to be finished, but waiting
494 * for the previous activity to settle down before doing so. It contains
495 * HistoryRecord objects.
496 */
497 final ArrayList mFinishingActivities = new ArrayList();
498
499 /**
500 * All of the applications we currently have running organized by name.
501 * The keys are strings of the application package name (as
502 * returned by the package manager), and the keys are ApplicationRecord
503 * objects.
504 */
505 final ProcessMap<ProcessRecord> mProcessNames
506 = new ProcessMap<ProcessRecord>();
507
508 /**
509 * The last time that various processes have crashed.
510 */
511 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
512
513 /**
514 * Set of applications that we consider to be bad, and will reject
515 * incoming broadcasts from (which the user has no control over).
516 * Processes are added to this set when they have crashed twice within
517 * a minimum amount of time; they are removed from it when they are
518 * later restarted (hopefully due to some user action). The value is the
519 * time it was added to the list.
520 */
521 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
522
523 /**
524 * All of the processes we currently have running organized by pid.
525 * The keys are the pid running the application.
526 *
527 * <p>NOTE: This object is protected by its own lock, NOT the global
528 * activity manager lock!
529 */
530 final SparseArray<ProcessRecord> mPidsSelfLocked
531 = new SparseArray<ProcessRecord>();
532
533 /**
534 * All of the processes that have been forced to be foreground. The key
535 * is the pid of the caller who requested it (we hold a death
536 * link on it).
537 */
538 abstract class ForegroundToken implements IBinder.DeathRecipient {
539 int pid;
540 IBinder token;
541 }
542 final SparseArray<ForegroundToken> mForegroundProcesses
543 = new SparseArray<ForegroundToken>();
544
545 /**
546 * List of records for processes that someone had tried to start before the
547 * system was ready. We don't start them at that point, but ensure they
548 * are started by the time booting is complete.
549 */
550 final ArrayList<ProcessRecord> mProcessesOnHold
551 = new ArrayList<ProcessRecord>();
552
553 /**
554 * List of records for processes that we have started and are waiting
555 * for them to call back. This is really only needed when running in
556 * single processes mode, in which case we do not have a unique pid for
557 * each process.
558 */
559 final ArrayList<ProcessRecord> mStartingProcesses
560 = new ArrayList<ProcessRecord>();
561
562 /**
563 * List of persistent applications that are in the process
564 * of being started.
565 */
566 final ArrayList<ProcessRecord> mPersistentStartingProcesses
567 = new ArrayList<ProcessRecord>();
568
569 /**
570 * Processes that are being forcibly torn down.
571 */
572 final ArrayList<ProcessRecord> mRemovedProcesses
573 = new ArrayList<ProcessRecord>();
574
575 /**
576 * List of running applications, sorted by recent usage.
577 * The first entry in the list is the least recently used.
578 * It contains ApplicationRecord objects. This list does NOT include
579 * any persistent application records (since we never want to exit them).
580 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800581 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 = new ArrayList<ProcessRecord>();
583
584 /**
585 * List of processes that should gc as soon as things are idle.
586 */
587 final ArrayList<ProcessRecord> mProcessesToGc
588 = new ArrayList<ProcessRecord>();
589
590 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800591 * This is the process holding what we currently consider to be
592 * the "home" activity.
593 */
594 private ProcessRecord mHomeProcess;
595
596 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 * List of running activities, sorted by recent usage.
598 * The first entry in the list is the least recently used.
599 * It contains HistoryRecord objects.
600 */
601 private final ArrayList mLRUActivities = new ArrayList();
602
603 /**
604 * Set of PendingResultRecord objects that are currently active.
605 */
606 final HashSet mPendingResultRecords = new HashSet();
607
608 /**
609 * Set of IntentSenderRecord objects that are currently active.
610 */
611 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
612 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
613
614 /**
615 * Intent broadcast that we have tried to start, but are
616 * waiting for its application's process to be created. We only
617 * need one (instead of a list) because we always process broadcasts
618 * one at a time, so no others can be started while waiting for this
619 * one.
620 */
621 BroadcastRecord mPendingBroadcast = null;
622
623 /**
624 * Keeps track of all IIntentReceivers that have been registered for
625 * broadcasts. Hash keys are the receiver IBinder, hash value is
626 * a ReceiverList.
627 */
628 final HashMap mRegisteredReceivers = new HashMap();
629
630 /**
631 * Resolver for broadcast intents to registered receivers.
632 * Holds BroadcastFilter (subclass of IntentFilter).
633 */
634 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
635 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
636 @Override
637 protected boolean allowFilterResult(
638 BroadcastFilter filter, List<BroadcastFilter> dest) {
639 IBinder target = filter.receiverList.receiver.asBinder();
640 for (int i=dest.size()-1; i>=0; i--) {
641 if (dest.get(i).receiverList.receiver.asBinder() == target) {
642 return false;
643 }
644 }
645 return true;
646 }
647 };
648
649 /**
650 * State of all active sticky broadcasts. Keys are the action of the
651 * sticky Intent, values are an ArrayList of all broadcasted intents with
652 * that action (which should usually be one).
653 */
654 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
655 new HashMap<String, ArrayList<Intent>>();
656
657 /**
658 * All currently running services.
659 */
660 final HashMap<ComponentName, ServiceRecord> mServices =
661 new HashMap<ComponentName, ServiceRecord>();
662
663 /**
664 * All currently running services indexed by the Intent used to start them.
665 */
666 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
667 new HashMap<Intent.FilterComparison, ServiceRecord>();
668
669 /**
670 * All currently bound service connections. Keys are the IBinder of
671 * the client's IServiceConnection.
672 */
673 final HashMap<IBinder, ConnectionRecord> mServiceConnections
674 = new HashMap<IBinder, ConnectionRecord>();
675
676 /**
677 * List of services that we have been asked to start,
678 * but haven't yet been able to. It is used to hold start requests
679 * while waiting for their corresponding application thread to get
680 * going.
681 */
682 final ArrayList<ServiceRecord> mPendingServices
683 = new ArrayList<ServiceRecord>();
684
685 /**
686 * List of services that are scheduled to restart following a crash.
687 */
688 final ArrayList<ServiceRecord> mRestartingServices
689 = new ArrayList<ServiceRecord>();
690
691 /**
692 * List of services that are in the process of being stopped.
693 */
694 final ArrayList<ServiceRecord> mStoppingServices
695 = new ArrayList<ServiceRecord>();
696
697 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700698 * Backup/restore process management
699 */
700 String mBackupAppName = null;
701 BackupRecord mBackupTarget = null;
702
703 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 * List of PendingThumbnailsRecord objects of clients who are still
705 * waiting to receive all of the thumbnails for a task.
706 */
707 final ArrayList mPendingThumbnails = new ArrayList();
708
709 /**
710 * List of HistoryRecord objects that have been finished and must
711 * still report back to a pending thumbnail receiver.
712 */
713 final ArrayList mCancelledThumbnails = new ArrayList();
714
715 /**
716 * All of the currently running global content providers. Keys are a
717 * string containing the provider name and values are a
718 * ContentProviderRecord object containing the data about it. Note
719 * that a single provider may be published under multiple names, so
720 * there may be multiple entries here for a single one in mProvidersByClass.
721 */
722 final HashMap mProvidersByName = new HashMap();
723
724 /**
725 * All of the currently running global content providers. Keys are a
726 * string containing the provider's implementation class and values are a
727 * ContentProviderRecord object containing the data about it.
728 */
729 final HashMap mProvidersByClass = new HashMap();
730
731 /**
732 * List of content providers who have clients waiting for them. The
733 * application is currently being launched and the provider will be
734 * removed from this list once it is published.
735 */
736 final ArrayList mLaunchingProviders = new ArrayList();
737
738 /**
739 * Global set of specific Uri permissions that have been granted.
740 */
741 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
742 = new SparseArray<HashMap<Uri, UriPermission>>();
743
744 /**
745 * Thread-local storage used to carry caller permissions over through
746 * indirect content-provider access.
747 * @see #ActivityManagerService.openContentUri()
748 */
749 private class Identity {
750 public int pid;
751 public int uid;
752
753 Identity(int _pid, int _uid) {
754 pid = _pid;
755 uid = _uid;
756 }
757 }
758 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
759
760 /**
761 * All information we have collected about the runtime performance of
762 * any user id that can impact battery performance.
763 */
764 final BatteryStatsService mBatteryStatsService;
765
766 /**
767 * information about component usage
768 */
769 final UsageStatsService mUsageStatsService;
770
771 /**
772 * Current configuration information. HistoryRecord objects are given
773 * a reference to this object to indicate which configuration they are
774 * currently running in, so this object must be kept immutable.
775 */
776 Configuration mConfiguration = new Configuration();
777
778 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800779 * Current sequencing integer of the configuration, for skipping old
780 * configurations.
781 */
782 int mConfigurationSeq = 0;
783
784 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700785 * Set when we know we are going to be calling updateConfiguration()
786 * soon, so want to skip intermediate config checks.
787 */
788 boolean mConfigWillChange;
789
790 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700791 * Hardware-reported OpenGLES version.
792 */
793 final int GL_ES_VERSION;
794
795 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 * List of initialization arguments to pass to all processes when binding applications to them.
797 * For example, references to the commonly used services.
798 */
799 HashMap<String, IBinder> mAppBindArgs;
800
801 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700802 * Temporary to avoid allocations. Protected by main lock.
803 */
804 final StringBuilder mStringBuilder = new StringBuilder(256);
805
806 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 * Used to control how we initialize the service.
808 */
809 boolean mStartRunning = false;
810 ComponentName mTopComponent;
811 String mTopAction;
812 String mTopData;
813 boolean mSystemReady = false;
814 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700815 boolean mWaitingUpdate = false;
816 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817
818 Context mContext;
819
820 int mFactoryTest;
821
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700822 boolean mCheckedForSetup;
823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700825 * The time at which we will allow normal application switches again,
826 * after a call to {@link #stopAppSwitches()}.
827 */
828 long mAppSwitchesAllowedTime;
829
830 /**
831 * This is set to true after the first switch after mAppSwitchesAllowedTime
832 * is set; any switches after that will clear the time.
833 */
834 boolean mDidAppSwitch;
835
836 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 * Set while we are wanting to sleep, to prevent any
838 * activities from being started/resumed.
839 */
840 boolean mSleeping = false;
841
842 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700843 * Set if we are shutting down the system, similar to sleeping.
844 */
845 boolean mShuttingDown = false;
846
847 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 * Set when the system is going to sleep, until we have
849 * successfully paused the current activity and released our wake lock.
850 * At that point the system is allowed to actually sleep.
851 */
852 PowerManager.WakeLock mGoingToSleep;
853
854 /**
855 * We don't want to allow the device to go to sleep while in the process
856 * of launching an activity. This is primarily to allow alarm intent
857 * receivers to launch an activity and get that to run before the device
858 * goes back to sleep.
859 */
860 PowerManager.WakeLock mLaunchingActivity;
861
862 /**
863 * Task identifier that activities are currently being started
864 * in. Incremented each time a new task is created.
865 * todo: Replace this with a TokenSpace class that generates non-repeating
866 * integers that won't wrap.
867 */
868 int mCurTask = 1;
869
870 /**
871 * Current sequence id for oom_adj computation traversal.
872 */
873 int mAdjSeq = 0;
874
875 /**
876 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
877 * is set, indicating the user wants processes started in such a way
878 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
879 * running in each process (thus no pre-initialized process, etc).
880 */
881 boolean mSimpleProcessManagement = false;
882
883 /**
884 * System monitoring: number of processes that died since the last
885 * N procs were started.
886 */
887 int[] mProcDeaths = new int[20];
888
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700889 /**
890 * This is set if we had to do a delayed dexopt of an app before launching
891 * it, to increasing the ANR timeouts in that case.
892 */
893 boolean mDidDexOpt;
894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 String mDebugApp = null;
896 boolean mWaitForDebugger = false;
897 boolean mDebugTransient = false;
898 String mOrigDebugApp = null;
899 boolean mOrigWaitForDebugger = false;
900 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700901 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700903 final RemoteCallbackList<IActivityWatcher> mWatchers
904 = new RemoteCallbackList<IActivityWatcher>();
905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 /**
907 * Callback of last caller to {@link #requestPss}.
908 */
909 Runnable mRequestPssCallback;
910
911 /**
912 * Remaining processes for which we are waiting results from the last
913 * call to {@link #requestPss}.
914 */
915 final ArrayList<ProcessRecord> mRequestPssList
916 = new ArrayList<ProcessRecord>();
917
918 /**
919 * Runtime statistics collection thread. This object's lock is used to
920 * protect all related state.
921 */
922 final Thread mProcessStatsThread;
923
924 /**
925 * Used to collect process stats when showing not responding dialog.
926 * Protected by mProcessStatsThread.
927 */
928 final ProcessStats mProcessStats = new ProcessStats(
929 MONITOR_THREAD_CPU_USAGE);
930 long mLastCpuTime = 0;
931 long mLastWriteTime = 0;
932
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700933 long mInitialStartTime = 0;
934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 /**
936 * Set to true after the system has finished booting.
937 */
938 boolean mBooted = false;
939
940 int mProcessLimit = 0;
941
942 WindowManagerService mWindowManager;
943
944 static ActivityManagerService mSelf;
945 static ActivityThread mSystemThread;
946
947 private final class AppDeathRecipient implements IBinder.DeathRecipient {
948 final ProcessRecord mApp;
949 final int mPid;
950 final IApplicationThread mAppThread;
951
952 AppDeathRecipient(ProcessRecord app, int pid,
953 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800954 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 TAG, "New death recipient " + this
956 + " for thread " + thread.asBinder());
957 mApp = app;
958 mPid = pid;
959 mAppThread = thread;
960 }
961
962 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800963 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 TAG, "Death received in " + this
965 + " for thread " + mAppThread.asBinder());
966 removeRequestedPss(mApp);
967 synchronized(ActivityManagerService.this) {
968 appDiedLocked(mApp, mPid, mAppThread);
969 }
970 }
971 }
972
973 static final int SHOW_ERROR_MSG = 1;
974 static final int SHOW_NOT_RESPONDING_MSG = 2;
975 static final int SHOW_FACTORY_ERROR_MSG = 3;
976 static final int UPDATE_CONFIGURATION_MSG = 4;
977 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
978 static final int WAIT_FOR_DEBUGGER_MSG = 6;
979 static final int BROADCAST_INTENT_MSG = 7;
980 static final int BROADCAST_TIMEOUT_MSG = 8;
981 static final int PAUSE_TIMEOUT_MSG = 9;
982 static final int IDLE_TIMEOUT_MSG = 10;
983 static final int IDLE_NOW_MSG = 11;
984 static final int SERVICE_TIMEOUT_MSG = 12;
985 static final int UPDATE_TIME_ZONE = 13;
986 static final int SHOW_UID_ERROR_MSG = 14;
987 static final int IM_FEELING_LUCKY_MSG = 15;
988 static final int LAUNCH_TIMEOUT_MSG = 16;
989 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 static final int RESUME_TOP_ACTIVITY_MSG = 19;
991 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700992 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700993 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800994 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995
996 AlertDialog mUidAlert;
997
998 final Handler mHandler = new Handler() {
999 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001000 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 //}
1002
1003 public void handleMessage(Message msg) {
1004 switch (msg.what) {
1005 case SHOW_ERROR_MSG: {
1006 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 synchronized (ActivityManagerService.this) {
1008 ProcessRecord proc = (ProcessRecord)data.get("app");
1009 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001010 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 return;
1012 }
1013 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001014 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001015 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 d.show();
1017 proc.crashDialog = d;
1018 } else {
1019 // The device is asleep, so just pretend that the user
1020 // saw a crash dialog and hit "force quit".
1021 res.set(0);
1022 }
1023 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001024
1025 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 } break;
1027 case SHOW_NOT_RESPONDING_MSG: {
1028 synchronized (ActivityManagerService.this) {
1029 HashMap data = (HashMap) msg.obj;
1030 ProcessRecord proc = (ProcessRecord)data.get("app");
1031 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001032 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 return;
1034 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001035
1036 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1037 null, null, 0, null, null, null,
1038 false, false, MY_PID, Process.SYSTEM_UID);
1039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1041 mContext, proc, (HistoryRecord)data.get("activity"));
1042 d.show();
1043 proc.anrDialog = d;
1044 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001045
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001046 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 } break;
1048 case SHOW_FACTORY_ERROR_MSG: {
1049 Dialog d = new FactoryErrorDialog(
1050 mContext, msg.getData().getCharSequence("msg"));
1051 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001052 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 } break;
1054 case UPDATE_CONFIGURATION_MSG: {
1055 final ContentResolver resolver = mContext.getContentResolver();
1056 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1057 } break;
1058 case GC_BACKGROUND_PROCESSES_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 performAppGcsIfAppropriateLocked();
1061 }
1062 } break;
1063 case WAIT_FOR_DEBUGGER_MSG: {
1064 synchronized (ActivityManagerService.this) {
1065 ProcessRecord app = (ProcessRecord)msg.obj;
1066 if (msg.arg1 != 0) {
1067 if (!app.waitedForDebugger) {
1068 Dialog d = new AppWaitingForDebuggerDialog(
1069 ActivityManagerService.this,
1070 mContext, app);
1071 app.waitDialog = d;
1072 app.waitedForDebugger = true;
1073 d.show();
1074 }
1075 } else {
1076 if (app.waitDialog != null) {
1077 app.waitDialog.dismiss();
1078 app.waitDialog = null;
1079 }
1080 }
1081 }
1082 } break;
1083 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001084 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 TAG, "Received BROADCAST_INTENT_MSG");
1086 processNextBroadcast(true);
1087 } break;
1088 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001089 if (mDidDexOpt) {
1090 mDidDexOpt = false;
1091 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1092 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1093 return;
1094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 broadcastTimeout();
1096 } break;
1097 case PAUSE_TIMEOUT_MSG: {
1098 IBinder token = (IBinder)msg.obj;
1099 // We don't at this point know if the activity is fullscreen,
1100 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001101 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 activityPaused(token, null, true);
1103 } break;
1104 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001105 if (mDidDexOpt) {
1106 mDidDexOpt = false;
1107 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1108 nmsg.obj = msg.obj;
1109 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1110 return;
1111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 // We don't at this point know if the activity is fullscreen,
1113 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001114 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001115 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001116 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 } break;
1118 case DESTROY_TIMEOUT_MSG: {
1119 IBinder token = (IBinder)msg.obj;
1120 // We don't at this point know if the activity is fullscreen,
1121 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001122 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 activityDestroyed(token);
1124 } break;
1125 case IDLE_NOW_MSG: {
1126 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001127 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 } break;
1129 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001130 if (mDidDexOpt) {
1131 mDidDexOpt = false;
1132 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1133 nmsg.obj = msg.obj;
1134 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1135 return;
1136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 serviceTimeout((ProcessRecord)msg.obj);
1138 } break;
1139 case UPDATE_TIME_ZONE: {
1140 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001141 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1142 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 if (r.thread != null) {
1144 try {
1145 r.thread.updateTimeZone();
1146 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001147 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 }
1149 }
1150 }
1151 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001152 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 case SHOW_UID_ERROR_MSG: {
1154 // XXX This is a temporary dialog, no need to localize.
1155 AlertDialog d = new BaseErrorDialog(mContext);
1156 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1157 d.setCancelable(false);
1158 d.setTitle("System UIDs Inconsistent");
1159 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1160 d.setButton("I'm Feeling Lucky",
1161 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1162 mUidAlert = d;
1163 d.show();
1164 } break;
1165 case IM_FEELING_LUCKY_MSG: {
1166 if (mUidAlert != null) {
1167 mUidAlert.dismiss();
1168 mUidAlert = null;
1169 }
1170 } break;
1171 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001172 if (mDidDexOpt) {
1173 mDidDexOpt = false;
1174 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1175 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1176 return;
1177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 synchronized (ActivityManagerService.this) {
1179 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001180 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 mLaunchingActivity.release();
1182 }
1183 }
1184 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 case RESUME_TOP_ACTIVITY_MSG: {
1186 synchronized (ActivityManagerService.this) {
1187 resumeTopActivityLocked(null);
1188 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001189 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001191 if (mDidDexOpt) {
1192 mDidDexOpt = false;
1193 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1194 nmsg.obj = msg.obj;
1195 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1196 return;
1197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 ProcessRecord app = (ProcessRecord)msg.obj;
1199 synchronized (ActivityManagerService.this) {
1200 processStartTimedOutLocked(app);
1201 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001202 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001203 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1204 synchronized (ActivityManagerService.this) {
1205 doPendingActivityLaunchesLocked(true);
1206 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001207 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001208 case KILL_APPLICATION_MSG: {
1209 synchronized (ActivityManagerService.this) {
1210 int uid = msg.arg1;
1211 boolean restart = (msg.arg2 == 1);
1212 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001213 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001214 }
1215 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001216 case FINALIZE_PENDING_INTENT_MSG: {
1217 ((PendingIntentRecord)msg.obj).completeFinalize();
1218 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 }
1220 }
1221 };
1222
1223 public static void setSystemProcess() {
1224 try {
1225 ActivityManagerService m = mSelf;
1226
1227 ServiceManager.addService("activity", m);
1228 ServiceManager.addService("meminfo", new MemBinder(m));
1229 if (MONITOR_CPU_USAGE) {
1230 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 ServiceManager.addService("permission", new PermissionController(m));
1233
1234 ApplicationInfo info =
1235 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001236 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001237 mSystemThread.installSystemApplicationInfo(info);
1238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 synchronized (mSelf) {
1240 ProcessRecord app = mSelf.newProcessRecordLocked(
1241 mSystemThread.getApplicationThread(), info,
1242 info.processName);
1243 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001244 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 app.maxAdj = SYSTEM_ADJ;
1246 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1247 synchronized (mSelf.mPidsSelfLocked) {
1248 mSelf.mPidsSelfLocked.put(app.pid, app);
1249 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001250 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 }
1252 } catch (PackageManager.NameNotFoundException e) {
1253 throw new RuntimeException(
1254 "Unable to find android system package", e);
1255 }
1256 }
1257
1258 public void setWindowManager(WindowManagerService wm) {
1259 mWindowManager = wm;
1260 }
1261
1262 public static final Context main(int factoryTest) {
1263 AThread thr = new AThread();
1264 thr.start();
1265
1266 synchronized (thr) {
1267 while (thr.mService == null) {
1268 try {
1269 thr.wait();
1270 } catch (InterruptedException e) {
1271 }
1272 }
1273 }
1274
1275 ActivityManagerService m = thr.mService;
1276 mSelf = m;
1277 ActivityThread at = ActivityThread.systemMain();
1278 mSystemThread = at;
1279 Context context = at.getSystemContext();
1280 m.mContext = context;
1281 m.mFactoryTest = factoryTest;
1282 PowerManager pm =
1283 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1284 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1285 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1286 m.mLaunchingActivity.setReferenceCounted(false);
1287
1288 m.mBatteryStatsService.publish(context);
1289 m.mUsageStatsService.publish(context);
1290
1291 synchronized (thr) {
1292 thr.mReady = true;
1293 thr.notifyAll();
1294 }
1295
1296 m.startRunning(null, null, null, null);
1297
1298 return context;
1299 }
1300
1301 public static ActivityManagerService self() {
1302 return mSelf;
1303 }
1304
1305 static class AThread extends Thread {
1306 ActivityManagerService mService;
1307 boolean mReady = false;
1308
1309 public AThread() {
1310 super("ActivityManager");
1311 }
1312
1313 public void run() {
1314 Looper.prepare();
1315
1316 android.os.Process.setThreadPriority(
1317 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1318
1319 ActivityManagerService m = new ActivityManagerService();
1320
1321 synchronized (this) {
1322 mService = m;
1323 notifyAll();
1324 }
1325
1326 synchronized (this) {
1327 while (!mReady) {
1328 try {
1329 wait();
1330 } catch (InterruptedException e) {
1331 }
1332 }
1333 }
1334
1335 Looper.loop();
1336 }
1337 }
1338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 static class MemBinder extends Binder {
1340 ActivityManagerService mActivityManagerService;
1341 MemBinder(ActivityManagerService activityManagerService) {
1342 mActivityManagerService = activityManagerService;
1343 }
1344
1345 @Override
1346 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1347 ActivityManagerService service = mActivityManagerService;
1348 ArrayList<ProcessRecord> procs;
1349 synchronized (mActivityManagerService) {
1350 if (args != null && args.length > 0
1351 && args[0].charAt(0) != '-') {
1352 procs = new ArrayList<ProcessRecord>();
1353 int pid = -1;
1354 try {
1355 pid = Integer.parseInt(args[0]);
1356 } catch (NumberFormatException e) {
1357
1358 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001359 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1360 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 if (proc.pid == pid) {
1362 procs.add(proc);
1363 } else if (proc.processName.equals(args[0])) {
1364 procs.add(proc);
1365 }
1366 }
1367 if (procs.size() <= 0) {
1368 pw.println("No process found for: " + args[0]);
1369 return;
1370 }
1371 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001372 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374 }
1375 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1376 }
1377 }
1378
1379 static class CpuBinder extends Binder {
1380 ActivityManagerService mActivityManagerService;
1381 CpuBinder(ActivityManagerService activityManagerService) {
1382 mActivityManagerService = activityManagerService;
1383 }
1384
1385 @Override
1386 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1387 synchronized (mActivityManagerService.mProcessStatsThread) {
1388 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1389 }
1390 }
1391 }
1392
1393 private ActivityManagerService() {
1394 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1395 if (v != null && Integer.getInteger(v) != 0) {
1396 mSimpleProcessManagement = true;
1397 }
1398 v = System.getenv("ANDROID_DEBUG_APP");
1399 if (v != null) {
1400 mSimpleProcessManagement = true;
1401 }
1402
Joe Onorato8a9b2202010-02-26 18:56:32 -08001403 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 File dataDir = Environment.getDataDirectory();
1406 File systemDir = new File(dataDir, "system");
1407 systemDir.mkdirs();
1408 mBatteryStatsService = new BatteryStatsService(new File(
1409 systemDir, "batterystats.bin").toString());
1410 mBatteryStatsService.getActiveStatistics().readLocked();
1411 mBatteryStatsService.getActiveStatistics().writeLocked();
1412
1413 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001414 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415
Jack Palevichb90d28c2009-07-22 15:35:24 -07001416 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1417 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1418
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001419 mConfiguration.setToDefaults();
1420 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 mProcessStats.init();
1422
1423 // Add ourself to the Watchdog monitors.
1424 Watchdog.getInstance().addMonitor(this);
1425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 mProcessStatsThread = new Thread("ProcessStats") {
1427 public void run() {
1428 while (true) {
1429 try {
1430 try {
1431 synchronized(this) {
1432 final long now = SystemClock.uptimeMillis();
1433 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1434 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001435 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 // + ", write delay=" + nextWriteDelay);
1437 if (nextWriteDelay < nextCpuDelay) {
1438 nextCpuDelay = nextWriteDelay;
1439 }
1440 if (nextCpuDelay > 0) {
1441 this.wait(nextCpuDelay);
1442 }
1443 }
1444 } catch (InterruptedException e) {
1445 }
1446
1447 updateCpuStatsNow();
1448 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001449 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 }
1451 }
1452 }
1453 };
1454 mProcessStatsThread.start();
1455 }
1456
1457 @Override
1458 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1459 throws RemoteException {
1460 try {
1461 return super.onTransact(code, data, reply, flags);
1462 } catch (RuntimeException e) {
1463 // The activity manager only throws security exceptions, so let's
1464 // log all others.
1465 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001466 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
1468 throw e;
1469 }
1470 }
1471
1472 void updateCpuStats() {
1473 synchronized (mProcessStatsThread) {
1474 final long now = SystemClock.uptimeMillis();
1475 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1476 mProcessStatsThread.notify();
1477 }
1478 }
1479 }
1480
1481 void updateCpuStatsNow() {
1482 synchronized (mProcessStatsThread) {
1483 final long now = SystemClock.uptimeMillis();
1484 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 if (MONITOR_CPU_USAGE &&
1487 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1488 mLastCpuTime = now;
1489 haveNewCpuStats = true;
1490 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001491 //Slog.i(TAG, mProcessStats.printCurrentState());
1492 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 // + mProcessStats.getTotalCpuPercent() + "%");
1494
Joe Onorato8a9b2202010-02-26 18:56:32 -08001495 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 if ("true".equals(SystemProperties.get("events.cpu"))) {
1497 int user = mProcessStats.getLastUserTime();
1498 int system = mProcessStats.getLastSystemTime();
1499 int iowait = mProcessStats.getLastIoWaitTime();
1500 int irq = mProcessStats.getLastIrqTime();
1501 int softIrq = mProcessStats.getLastSoftIrqTime();
1502 int idle = mProcessStats.getLastIdleTime();
1503
1504 int total = user + system + iowait + irq + softIrq + idle;
1505 if (total == 0) total = 1;
1506
Doug Zongker2bec3d42009-12-04 12:52:44 -08001507 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 ((user+system+iowait+irq+softIrq) * 100) / total,
1509 (user * 100) / total,
1510 (system * 100) / total,
1511 (iowait * 100) / total,
1512 (irq * 100) / total,
1513 (softIrq * 100) / total);
1514 }
1515 }
1516
Amith Yamasanie43530a2009-08-21 13:11:37 -07001517 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001518 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001519 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 synchronized(mPidsSelfLocked) {
1521 if (haveNewCpuStats) {
1522 if (mBatteryStatsService.isOnBattery()) {
1523 final int N = mProcessStats.countWorkingStats();
1524 for (int i=0; i<N; i++) {
1525 ProcessStats.Stats st
1526 = mProcessStats.getWorkingStats(i);
1527 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1528 if (pr != null) {
1529 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1530 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001531 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001532 } else {
1533 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001534 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001535 if (ps != null) {
1536 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001537 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540 }
1541 }
1542 }
1543 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1546 mLastWriteTime = now;
1547 mBatteryStatsService.getActiveStatistics().writeLocked();
1548 }
1549 }
1550 }
1551 }
1552
1553 /**
1554 * Initialize the application bind args. These are passed to each
1555 * process when the bindApplication() IPC is sent to the process. They're
1556 * lazily setup to make sure the services are running when they're asked for.
1557 */
1558 private HashMap<String, IBinder> getCommonServicesLocked() {
1559 if (mAppBindArgs == null) {
1560 mAppBindArgs = new HashMap<String, IBinder>();
1561
1562 // Setup the application init args
1563 mAppBindArgs.put("package", ServiceManager.getService("package"));
1564 mAppBindArgs.put("window", ServiceManager.getService("window"));
1565 mAppBindArgs.put(Context.ALARM_SERVICE,
1566 ServiceManager.getService(Context.ALARM_SERVICE));
1567 }
1568 return mAppBindArgs;
1569 }
1570
1571 private final void setFocusedActivityLocked(HistoryRecord r) {
1572 if (mFocusedActivity != r) {
1573 mFocusedActivity = r;
1574 mWindowManager.setFocusedApp(r, true);
1575 }
1576 }
1577
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001578 private final void updateLruProcessLocked(ProcessRecord app,
1579 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001581 int lrui = mLruProcesses.indexOf(app);
1582 if (lrui >= 0) mLruProcesses.remove(lrui);
1583
1584 int i = mLruProcesses.size()-1;
1585 int skipTop = 0;
1586
1587 // compute the new weight for this process.
1588 if (updateActivityTime) {
1589 app.lastActivityTime = SystemClock.uptimeMillis();
1590 }
1591 if (app.activities.size() > 0) {
1592 // If this process has activities, we more strongly want to keep
1593 // it around.
1594 app.lruWeight = app.lastActivityTime;
1595 } else if (app.pubProviders.size() > 0) {
1596 // If this process contains content providers, we want to keep
1597 // it a little more strongly.
1598 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1599 // Also don't let it kick out the first few "real" hidden processes.
1600 skipTop = MIN_HIDDEN_APPS;
1601 } else {
1602 // If this process doesn't have activities, we less strongly
1603 // want to keep it around, and generally want to avoid getting
1604 // in front of any very recently used activities.
1605 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1606 // Also don't let it kick out the first few "real" hidden processes.
1607 skipTop = MIN_HIDDEN_APPS;
1608 }
1609 while (i >= 0) {
1610 ProcessRecord p = mLruProcesses.get(i);
1611 // If this app shouldn't be in front of the first N background
1612 // apps, then skip over that many that are currently hidden.
1613 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1614 skipTop--;
1615 }
1616 if (p.lruWeight <= app.lruWeight){
1617 mLruProcesses.add(i+1, app);
1618 break;
1619 }
1620 i--;
1621 }
1622 if (i < 0) {
1623 mLruProcesses.add(0, app);
1624 }
1625
Joe Onorato8a9b2202010-02-26 18:56:32 -08001626 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 if (oomAdj) {
1628 updateOomAdjLocked();
1629 }
1630 }
1631
1632 private final boolean updateLRUListLocked(HistoryRecord r) {
1633 final boolean hadit = mLRUActivities.remove(r);
1634 mLRUActivities.add(r);
1635 return hadit;
1636 }
1637
1638 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1639 int i = mHistory.size()-1;
1640 while (i >= 0) {
1641 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1642 if (!r.finishing && r != notTop) {
1643 return r;
1644 }
1645 i--;
1646 }
1647 return null;
1648 }
1649
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001650 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1651 int i = mHistory.size()-1;
1652 while (i >= 0) {
1653 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1654 if (!r.finishing && !r.delayedResume && r != notTop) {
1655 return r;
1656 }
1657 i--;
1658 }
1659 return null;
1660 }
1661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 /**
1663 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001664 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 *
1666 * @param token If non-null, any history records matching this token will be skipped.
1667 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1668 *
1669 * @return Returns the HistoryRecord of the next activity on the stack.
1670 */
1671 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1672 int i = mHistory.size()-1;
1673 while (i >= 0) {
1674 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1675 // Note: the taskId check depends on real taskId fields being non-zero
1676 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1677 return r;
1678 }
1679 i--;
1680 }
1681 return null;
1682 }
1683
1684 private final ProcessRecord getProcessRecordLocked(
1685 String processName, int uid) {
1686 if (uid == Process.SYSTEM_UID) {
1687 // The system gets to run in any process. If there are multiple
1688 // processes with the same uid, just pick the first (this
1689 // should never happen).
1690 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1691 processName);
1692 return procs != null ? procs.valueAt(0) : null;
1693 }
1694 ProcessRecord proc = mProcessNames.get(processName, uid);
1695 return proc;
1696 }
1697
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001698 private void ensurePackageDexOpt(String packageName) {
1699 IPackageManager pm = ActivityThread.getPackageManager();
1700 try {
1701 if (pm.performDexOpt(packageName)) {
1702 mDidDexOpt = true;
1703 }
1704 } catch (RemoteException e) {
1705 }
1706 }
1707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 private boolean isNextTransitionForward() {
1709 int transit = mWindowManager.getPendingAppTransition();
1710 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1711 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1712 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1713 }
1714
1715 private final boolean realStartActivityLocked(HistoryRecord r,
1716 ProcessRecord app, boolean andResume, boolean checkConfig)
1717 throws RemoteException {
1718
1719 r.startFreezingScreenLocked(app, 0);
1720 mWindowManager.setAppVisibility(r, true);
1721
1722 // Have the window manager re-evaluate the orientation of
1723 // the screen based on the new activity order. Note that
1724 // as a result of this, it can call back into the activity
1725 // manager with a new orientation. We don't care about that,
1726 // because the activity is not currently running so we are
1727 // just restarting it anyway.
1728 if (checkConfig) {
1729 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001730 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 r.mayFreezeScreenLocked(app) ? r : null);
1732 updateConfigurationLocked(config, r);
1733 }
1734
1735 r.app = app;
1736
Joe Onorato8a9b2202010-02-26 18:56:32 -08001737 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738
1739 int idx = app.activities.indexOf(r);
1740 if (idx < 0) {
1741 app.activities.add(r);
1742 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001743 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744
1745 try {
1746 if (app.thread == null) {
1747 throw new RemoteException();
1748 }
1749 List<ResultInfo> results = null;
1750 List<Intent> newIntents = null;
1751 if (andResume) {
1752 results = r.results;
1753 newIntents = r.newIntents;
1754 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001755 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 + " icicle=" + r.icicle
1757 + " with results=" + results + " newIntents=" + newIntents
1758 + " andResume=" + andResume);
1759 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001760 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 System.identityHashCode(r),
1762 r.task.taskId, r.shortComponentName);
1763 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001764 if (r.isHomeActivity) {
1765 mHomeProcess = app;
1766 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001767 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001769 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 r.info, r.icicle, results, newIntents, !andResume,
1771 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 } catch (RemoteException e) {
1773 if (r.launchFailed) {
1774 // This is the second time we failed -- finish activity
1775 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001776 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 + r.intent.getComponent().flattenToShortString()
1778 + ", giving up", e);
1779 appDiedLocked(app, app.pid, app.thread);
1780 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1781 "2nd-crash");
1782 return false;
1783 }
1784
1785 // This is the first time we failed -- restart process and
1786 // retry.
1787 app.activities.remove(r);
1788 throw e;
1789 }
1790
1791 r.launchFailed = false;
1792 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001793 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 + " being launched, but already in LRU list");
1795 }
1796
1797 if (andResume) {
1798 // As part of the process of launching, ActivityThread also performs
1799 // a resume.
1800 r.state = ActivityState.RESUMED;
1801 r.icicle = null;
1802 r.haveState = false;
1803 r.stopped = false;
1804 mResumedActivity = r;
1805 r.task.touchActiveTime();
1806 completeResumeLocked(r);
1807 pauseIfSleepingLocked();
1808 } else {
1809 // This activity is not starting in the resumed state... which
1810 // should look like we asked it to pause+stop (but remain visible),
1811 // and it has done so and reported back the current icicle and
1812 // other state.
1813 r.state = ActivityState.STOPPED;
1814 r.stopped = true;
1815 }
1816
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001817 // Launch the new version setup screen if needed. We do this -after-
1818 // launching the initial activity (that is, home), so that it can have
1819 // a chance to initialize itself while in the background, making the
1820 // switch back to it faster and look better.
1821 startSetupActivityLocked();
1822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 return true;
1824 }
1825
1826 private final void startSpecificActivityLocked(HistoryRecord r,
1827 boolean andResume, boolean checkConfig) {
1828 // Is this activity's application already running?
1829 ProcessRecord app = getProcessRecordLocked(r.processName,
1830 r.info.applicationInfo.uid);
1831
1832 if (r.startTime == 0) {
1833 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001834 if (mInitialStartTime == 0) {
1835 mInitialStartTime = r.startTime;
1836 }
1837 } else if (mInitialStartTime == 0) {
1838 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 }
1840
1841 if (app != null && app.thread != null) {
1842 try {
1843 realStartActivityLocked(r, app, andResume, checkConfig);
1844 return;
1845 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001846 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 + r.intent.getComponent().flattenToShortString(), e);
1848 }
1849
1850 // If a dead object exception was thrown -- fall through to
1851 // restart the application.
1852 }
1853
1854 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001855 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857
1858 private final ProcessRecord startProcessLocked(String processName,
1859 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001860 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1862 // We don't have to do anything more if:
1863 // (1) There is an existing application record; and
1864 // (2) The caller doesn't think it is dead, OR there is no thread
1865 // object attached to it so we know it couldn't have crashed; and
1866 // (3) There is a pid assigned to it, so it is either starting or
1867 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001868 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 + " app=" + app + " knownToBeDead=" + knownToBeDead
1870 + " thread=" + (app != null ? app.thread : null)
1871 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001872 if (app != null && app.pid > 0) {
1873 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001874 // We already have the app running, or are waiting for it to
1875 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001876 return app;
1877 } else {
1878 // An application record is attached to a previous process,
1879 // clean it up now.
1880 handleAppDiedLocked(app, true);
1881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001882 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 String hostingNameStr = hostingName != null
1885 ? hostingName.flattenToShortString() : null;
1886
1887 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1888 // If we are in the background, then check to see if this process
1889 // is bad. If so, we will just silently fail.
1890 if (mBadProcesses.get(info.processName, info.uid) != null) {
1891 return null;
1892 }
1893 } else {
1894 // When the user is explicitly starting a process, then clear its
1895 // crash count so that we won't make it bad until they see at
1896 // least one crash dialog again, and make the process good again
1897 // if it had been bad.
1898 mProcessCrashTimes.remove(info.processName, info.uid);
1899 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001900 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 info.processName);
1902 mBadProcesses.remove(info.processName, info.uid);
1903 if (app != null) {
1904 app.bad = false;
1905 }
1906 }
1907 }
1908
1909 if (app == null) {
1910 app = newProcessRecordLocked(null, info, processName);
1911 mProcessNames.put(processName, info.uid, app);
1912 } else {
1913 // If this is a new package in the process, add the package to the list
1914 app.addPackage(info.packageName);
1915 }
1916
1917 // If the system is not ready yet, then hold off on starting this
1918 // process until it is.
1919 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001920 && !isAllowedWhileBooting(info)
1921 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 if (!mProcessesOnHold.contains(app)) {
1923 mProcessesOnHold.add(app);
1924 }
1925 return app;
1926 }
1927
1928 startProcessLocked(app, hostingType, hostingNameStr);
1929 return (app.pid != 0) ? app : null;
1930 }
1931
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001932 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1933 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1934 }
1935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 private final void startProcessLocked(ProcessRecord app,
1937 String hostingType, String hostingNameStr) {
1938 if (app.pid > 0 && app.pid != MY_PID) {
1939 synchronized (mPidsSelfLocked) {
1940 mPidsSelfLocked.remove(app.pid);
1941 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1942 }
1943 app.pid = 0;
1944 }
1945
1946 mProcessesOnHold.remove(app);
1947
1948 updateCpuStats();
1949
1950 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1951 mProcDeaths[0] = 0;
1952
1953 try {
1954 int uid = app.info.uid;
1955 int[] gids = null;
1956 try {
1957 gids = mContext.getPackageManager().getPackageGids(
1958 app.info.packageName);
1959 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001960 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 }
1962 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1963 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1964 && mTopComponent != null
1965 && app.processName.equals(mTopComponent.getPackageName())) {
1966 uid = 0;
1967 }
1968 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1969 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1970 uid = 0;
1971 }
1972 }
1973 int debugFlags = 0;
1974 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1975 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1976 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001977 // Run the app in safe mode if its manifest requests so or the
1978 // system is booted in safe mode.
1979 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1980 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001981 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1984 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1985 }
1986 if ("1".equals(SystemProperties.get("debug.assert"))) {
1987 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1988 }
1989 int pid = Process.start("android.app.ActivityThread",
1990 mSimpleProcessManagement ? app.processName : null, uid, uid,
1991 gids, debugFlags, null);
1992 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1993 synchronized (bs) {
1994 if (bs.isOnBattery()) {
1995 app.batteryStats.incStartsLocked();
1996 }
1997 }
1998
Doug Zongker2bec3d42009-12-04 12:52:44 -08001999 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 app.processName, hostingType,
2001 hostingNameStr != null ? hostingNameStr : "");
2002
2003 if (app.persistent) {
2004 Watchdog.getInstance().processStarted(app, app.processName, pid);
2005 }
2006
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002007 StringBuilder buf = mStringBuilder;
2008 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 buf.append("Start proc ");
2010 buf.append(app.processName);
2011 buf.append(" for ");
2012 buf.append(hostingType);
2013 if (hostingNameStr != null) {
2014 buf.append(" ");
2015 buf.append(hostingNameStr);
2016 }
2017 buf.append(": pid=");
2018 buf.append(pid);
2019 buf.append(" uid=");
2020 buf.append(uid);
2021 buf.append(" gids={");
2022 if (gids != null) {
2023 for (int gi=0; gi<gids.length; gi++) {
2024 if (gi != 0) buf.append(", ");
2025 buf.append(gids[gi]);
2026
2027 }
2028 }
2029 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002030 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 if (pid == 0 || pid == MY_PID) {
2032 // Processes are being emulated with threads.
2033 app.pid = MY_PID;
2034 app.removed = false;
2035 mStartingProcesses.add(app);
2036 } else if (pid > 0) {
2037 app.pid = pid;
2038 app.removed = false;
2039 synchronized (mPidsSelfLocked) {
2040 this.mPidsSelfLocked.put(pid, app);
2041 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2042 msg.obj = app;
2043 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2044 }
2045 } else {
2046 app.pid = 0;
2047 RuntimeException e = new RuntimeException(
2048 "Failure starting process " + app.processName
2049 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002050 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 }
2052 } catch (RuntimeException e) {
2053 // XXX do better error recovery.
2054 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002055 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 }
2057 }
2058
2059 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2060 if (mPausingActivity != null) {
2061 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002062 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 + mPausingActivity, e);
2064 }
2065 HistoryRecord prev = mResumedActivity;
2066 if (prev == null) {
2067 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002068 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 resumeTopActivityLocked(null);
2070 return;
2071 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002072 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 mResumedActivity = null;
2074 mPausingActivity = prev;
2075 mLastPausedActivity = prev;
2076 prev.state = ActivityState.PAUSING;
2077 prev.task.touchActiveTime();
2078
2079 updateCpuStats();
2080
2081 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002082 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002084 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 System.identityHashCode(prev),
2086 prev.shortComponentName);
2087 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2088 prev.configChangeFlags);
2089 updateUsageStats(prev, false);
2090 } catch (Exception e) {
2091 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002092 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 mPausingActivity = null;
2094 mLastPausedActivity = null;
2095 }
2096 } else {
2097 mPausingActivity = null;
2098 mLastPausedActivity = null;
2099 }
2100
2101 // If we are not going to sleep, we want to ensure the device is
2102 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002103 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 mLaunchingActivity.acquire();
2105 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2106 // To be safe, don't allow the wake lock to be held for too long.
2107 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2108 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2109 }
2110 }
2111
2112
2113 if (mPausingActivity != null) {
2114 // Have the window manager pause its key dispatching until the new
2115 // activity has started. If we're pausing the activity just because
2116 // the screen is being turned off and the UI is sleeping, don't interrupt
2117 // key dispatch; the same activity will pick it up again on wakeup.
2118 if (!uiSleeping) {
2119 prev.pauseKeyDispatchingLocked();
2120 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002121 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 }
2123
2124 // Schedule a pause timeout in case the app doesn't respond.
2125 // We don't give it much time because this directly impacts the
2126 // responsiveness seen by the user.
2127 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2128 msg.obj = prev;
2129 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002130 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 } else {
2132 // This activity failed to schedule the
2133 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002134 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 resumeTopActivityLocked(null);
2136 }
2137 }
2138
2139 private final void completePauseLocked() {
2140 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002141 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142
2143 if (prev != null) {
2144 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002145 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2147 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002148 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 if (prev.waitingVisible) {
2150 prev.waitingVisible = false;
2151 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002152 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 TAG, "Complete pause, no longer waiting: " + prev);
2154 }
2155 if (prev.configDestroy) {
2156 // The previous is being paused because the configuration
2157 // is changing, which means it is actually stopping...
2158 // To juggle the fact that we are also starting a new
2159 // instance right now, we need to first completely stop
2160 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002161 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 destroyActivityLocked(prev, true);
2163 } else {
2164 mStoppingActivities.add(prev);
2165 if (mStoppingActivities.size() > 3) {
2166 // If we already have a few activities waiting to stop,
2167 // then give up on things going idle and start clearing
2168 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002169 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 Message msg = Message.obtain();
2171 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2172 mHandler.sendMessage(msg);
2173 }
2174 }
2175 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002176 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 prev = null;
2178 }
2179 mPausingActivity = null;
2180 }
2181
Dianne Hackborn55280a92009-05-07 15:53:46 -07002182 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 resumeTopActivityLocked(prev);
2184 } else {
2185 if (mGoingToSleep.isHeld()) {
2186 mGoingToSleep.release();
2187 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002188 if (mShuttingDown) {
2189 notifyAll();
2190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 }
2192
2193 if (prev != null) {
2194 prev.resumeKeyDispatchingLocked();
2195 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002196
2197 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2198 long diff = 0;
2199 synchronized (mProcessStatsThread) {
2200 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2201 }
2202 if (diff > 0) {
2203 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2204 synchronized (bsi) {
2205 BatteryStatsImpl.Uid.Proc ps =
2206 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2207 prev.info.packageName);
2208 if (ps != null) {
2209 ps.addForegroundTimeLocked(diff);
2210 }
2211 }
2212 }
2213 }
2214 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 }
2216
2217 /**
2218 * Once we know that we have asked an application to put an activity in
2219 * the resumed state (either by launching it or explicitly telling it),
2220 * this function updates the rest of our state to match that fact.
2221 */
2222 private final void completeResumeLocked(HistoryRecord next) {
2223 next.idle = false;
2224 next.results = null;
2225 next.newIntents = null;
2226
2227 // schedule an idle timeout in case the app doesn't do it for us.
2228 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2229 msg.obj = next;
2230 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2231
2232 if (false) {
2233 // The activity was never told to pause, so just keep
2234 // things going as-is. To maintain our own state,
2235 // we need to emulate it coming back and saying it is
2236 // idle.
2237 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2238 msg.obj = next;
2239 mHandler.sendMessage(msg);
2240 }
2241
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002242 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 next.thumbnail = null;
2245 setFocusedActivityLocked(next);
2246 next.resumeKeyDispatchingLocked();
2247 ensureActivitiesVisibleLocked(null, 0);
2248 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002249 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002250
2251 // Mark the point when the activity is resuming
2252 // TODO: To be more accurate, the mark should be before the onCreate,
2253 // not after the onResume. But for subsequent starts, onResume is fine.
2254 if (next.app != null) {
2255 synchronized (mProcessStatsThread) {
2256 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2257 }
2258 } else {
2259 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 }
2262
2263 /**
2264 * Make sure that all activities that need to be visible (that is, they
2265 * currently can be seen by the user) actually are.
2266 */
2267 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2268 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002269 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 TAG, "ensureActivitiesVisible behind " + top
2271 + " configChanges=0x" + Integer.toHexString(configChanges));
2272
2273 // If the top activity is not fullscreen, then we need to
2274 // make sure any activities under it are now visible.
2275 final int count = mHistory.size();
2276 int i = count-1;
2277 while (mHistory.get(i) != top) {
2278 i--;
2279 }
2280 HistoryRecord r;
2281 boolean behindFullscreen = false;
2282 for (; i>=0; i--) {
2283 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002284 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 TAG, "Make visible? " + r + " finishing=" + r.finishing
2286 + " state=" + r.state);
2287 if (r.finishing) {
2288 continue;
2289 }
2290
2291 final boolean doThisProcess = onlyThisProcess == null
2292 || onlyThisProcess.equals(r.processName);
2293
2294 // First: if this is not the current activity being started, make
2295 // sure it matches the current configuration.
2296 if (r != starting && doThisProcess) {
2297 ensureActivityConfigurationLocked(r, 0);
2298 }
2299
2300 if (r.app == null || r.app.thread == null) {
2301 if (onlyThisProcess == null
2302 || onlyThisProcess.equals(r.processName)) {
2303 // This activity needs to be visible, but isn't even
2304 // running... get it started, but don't resume it
2305 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002306 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 TAG, "Start and freeze screen for " + r);
2308 if (r != starting) {
2309 r.startFreezingScreenLocked(r.app, configChanges);
2310 }
2311 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002312 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 TAG, "Starting and making visible: " + r);
2314 mWindowManager.setAppVisibility(r, true);
2315 }
2316 if (r != starting) {
2317 startSpecificActivityLocked(r, false, false);
2318 }
2319 }
2320
2321 } else if (r.visible) {
2322 // If this activity is already visible, then there is nothing
2323 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002324 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 TAG, "Skipping: already visible at " + r);
2326 r.stopFreezingScreenLocked(false);
2327
2328 } else if (onlyThisProcess == null) {
2329 // This activity is not currently visible, but is running.
2330 // Tell it to become visible.
2331 r.visible = true;
2332 if (r.state != ActivityState.RESUMED && r != starting) {
2333 // If this activity is paused, tell it
2334 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002335 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002336 TAG, "Making visible and scheduling visibility: " + r);
2337 try {
2338 mWindowManager.setAppVisibility(r, true);
2339 r.app.thread.scheduleWindowVisibility(r, true);
2340 r.stopFreezingScreenLocked(false);
2341 } catch (Exception e) {
2342 // Just skip on any failure; we'll make it
2343 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002344 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 + r.intent.getComponent(), e);
2346 }
2347 }
2348 }
2349
2350 // Aggregate current change flags.
2351 configChanges |= r.configChangeFlags;
2352
2353 if (r.fullscreen) {
2354 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002355 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 TAG, "Stopping: fullscreen at " + r);
2357 behindFullscreen = true;
2358 i--;
2359 break;
2360 }
2361 }
2362
2363 // Now for any activities that aren't visible to the user, make
2364 // sure they no longer are keeping the screen frozen.
2365 while (i >= 0) {
2366 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002367 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2369 + " state=" + r.state
2370 + " behindFullscreen=" + behindFullscreen);
2371 if (!r.finishing) {
2372 if (behindFullscreen) {
2373 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002374 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 TAG, "Making invisible: " + r);
2376 r.visible = false;
2377 try {
2378 mWindowManager.setAppVisibility(r, false);
2379 if ((r.state == ActivityState.STOPPING
2380 || r.state == ActivityState.STOPPED)
2381 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002382 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 TAG, "Scheduling invisibility: " + r);
2384 r.app.thread.scheduleWindowVisibility(r, false);
2385 }
2386 } catch (Exception e) {
2387 // Just skip on any failure; we'll make it
2388 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002389 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 + r.intent.getComponent(), e);
2391 }
2392 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002393 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 TAG, "Already invisible: " + r);
2395 }
2396 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002397 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 TAG, "Now behindFullscreen: " + r);
2399 behindFullscreen = true;
2400 }
2401 }
2402 i--;
2403 }
2404 }
2405
2406 /**
2407 * Version of ensureActivitiesVisible that can easily be called anywhere.
2408 */
2409 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2410 int configChanges) {
2411 HistoryRecord r = topRunningActivityLocked(null);
2412 if (r != null) {
2413 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2414 }
2415 }
2416
2417 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2418 if (resumed) {
2419 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2420 } else {
2421 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2422 }
2423 }
2424
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002425 private boolean startHomeActivityLocked() {
2426 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2427 && mTopAction == null) {
2428 // We are running in factory test mode, but unable to find
2429 // the factory test app, so just sit around displaying the
2430 // error message and don't try to start anything.
2431 return false;
2432 }
2433 Intent intent = new Intent(
2434 mTopAction,
2435 mTopData != null ? Uri.parse(mTopData) : null);
2436 intent.setComponent(mTopComponent);
2437 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2438 intent.addCategory(Intent.CATEGORY_HOME);
2439 }
2440 ActivityInfo aInfo =
2441 intent.resolveActivityInfo(mContext.getPackageManager(),
2442 STOCK_PM_FLAGS);
2443 if (aInfo != null) {
2444 intent.setComponent(new ComponentName(
2445 aInfo.applicationInfo.packageName, aInfo.name));
2446 // Don't do this if the home app is currently being
2447 // instrumented.
2448 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2449 aInfo.applicationInfo.uid);
2450 if (app == null || app.instrumentationClass == null) {
2451 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2452 startActivityLocked(null, intent, null, null, 0, aInfo,
2453 null, null, 0, 0, 0, false, false);
2454 }
2455 }
2456
2457
2458 return true;
2459 }
2460
2461 /**
2462 * Starts the "new version setup screen" if appropriate.
2463 */
2464 private void startSetupActivityLocked() {
2465 // Only do this once per boot.
2466 if (mCheckedForSetup) {
2467 return;
2468 }
2469
2470 // We will show this screen if the current one is a different
2471 // version than the last one shown, and we are not running in
2472 // low-level factory test mode.
2473 final ContentResolver resolver = mContext.getContentResolver();
2474 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2475 Settings.Secure.getInt(resolver,
2476 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2477 mCheckedForSetup = true;
2478
2479 // See if we should be showing the platform update setup UI.
2480 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2481 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2482 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2483
2484 // We don't allow third party apps to replace this.
2485 ResolveInfo ri = null;
2486 for (int i=0; ris != null && i<ris.size(); i++) {
2487 if ((ris.get(i).activityInfo.applicationInfo.flags
2488 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2489 ri = ris.get(i);
2490 break;
2491 }
2492 }
2493
2494 if (ri != null) {
2495 String vers = ri.activityInfo.metaData != null
2496 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2497 : null;
2498 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2499 vers = ri.activityInfo.applicationInfo.metaData.getString(
2500 Intent.METADATA_SETUP_VERSION);
2501 }
2502 String lastVers = Settings.Secure.getString(
2503 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2504 if (vers != null && !vers.equals(lastVers)) {
2505 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2506 intent.setComponent(new ComponentName(
2507 ri.activityInfo.packageName, ri.activityInfo.name));
2508 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2509 null, null, 0, 0, 0, false, false);
2510 }
2511 }
2512 }
2513 }
2514
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002515 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002516 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002517
2518 final int identHash = System.identityHashCode(r);
2519 updateUsageStats(r, true);
2520
2521 int i = mWatchers.beginBroadcast();
2522 while (i > 0) {
2523 i--;
2524 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2525 if (w != null) {
2526 try {
2527 w.activityResuming(identHash);
2528 } catch (RemoteException e) {
2529 }
2530 }
2531 }
2532 mWatchers.finishBroadcast();
2533 }
2534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 /**
2536 * Ensure that the top activity in the stack is resumed.
2537 *
2538 * @param prev The previously resumed activity, for when in the process
2539 * of pausing; can be null to call from elsewhere.
2540 *
2541 * @return Returns true if something is being resumed, or false if
2542 * nothing happened.
2543 */
2544 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2545 // Find the first activity that is not finishing.
2546 HistoryRecord next = topRunningActivityLocked(null);
2547
2548 // Remember how we'll process this pause/resume situation, and ensure
2549 // that the state is reset however we wind up proceeding.
2550 final boolean userLeaving = mUserLeaving;
2551 mUserLeaving = false;
2552
2553 if (next == null) {
2554 // There are no more activities! Let's just start up the
2555 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002556 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
2558
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002559 next.delayedResume = false;
2560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 // If the top activity is the resumed one, nothing to do.
2562 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2563 // Make sure we have executed any pending transitions, since there
2564 // should be nothing left to do at this point.
2565 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002566 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 return false;
2568 }
2569
2570 // If we are sleeping, and there is no resumed activity, and the top
2571 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002572 if ((mSleeping || mShuttingDown)
2573 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 // Make sure we have executed any pending transitions, since there
2575 // should be nothing left to do at this point.
2576 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002577 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 return false;
2579 }
2580
2581 // The activity may be waiting for stop, but that is no longer
2582 // appropriate for it.
2583 mStoppingActivities.remove(next);
2584 mWaitingVisibleActivities.remove(next);
2585
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587
2588 // If we are currently pausing an activity, then don't do anything
2589 // until that is done.
2590 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002591 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002592 return false;
2593 }
2594
2595 // We need to start pausing the current activity so the top one
2596 // can be resumed...
2597 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002598 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 startPausingLocked(userLeaving, false);
2600 return true;
2601 }
2602
2603 if (prev != null && prev != next) {
2604 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2605 prev.waitingVisible = true;
2606 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002607 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 TAG, "Resuming top, waiting visible to hide: " + prev);
2609 } else {
2610 // The next activity is already visible, so hide the previous
2611 // activity's windows right now so we can show the new one ASAP.
2612 // We only do this if the previous is finishing, which should mean
2613 // it is on top of the one being resumed so hiding it quickly
2614 // is good. Otherwise, we want to do the normal route of allowing
2615 // the resumed activity to be shown so we can decide if the
2616 // previous should actually be hidden depending on whether the
2617 // new one is found to be full-screen or not.
2618 if (prev.finishing) {
2619 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002620 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 + prev + ", waitingVisible="
2622 + (prev != null ? prev.waitingVisible : null)
2623 + ", nowVisible=" + next.nowVisible);
2624 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002625 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 + prev + ", waitingVisible="
2627 + (prev != null ? prev.waitingVisible : null)
2628 + ", nowVisible=" + next.nowVisible);
2629 }
2630 }
2631 }
2632
2633 // We are starting up the next activity, so tell the window manager
2634 // that the previous one will be hidden soon. This way it can know
2635 // to ignore it when computing the desired screen orientation.
2636 if (prev != null) {
2637 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002638 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002640 if (mNoAnimActivities.contains(prev)) {
2641 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2642 } else {
2643 mWindowManager.prepareAppTransition(prev.task == next.task
2644 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2645 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 mWindowManager.setAppWillBeHidden(prev);
2648 mWindowManager.setAppVisibility(prev, false);
2649 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002650 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002652 if (mNoAnimActivities.contains(next)) {
2653 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2654 } else {
2655 mWindowManager.prepareAppTransition(prev.task == next.task
2656 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2657 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 }
2660 if (false) {
2661 mWindowManager.setAppWillBeHidden(prev);
2662 mWindowManager.setAppVisibility(prev, false);
2663 }
2664 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002665 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002667 if (mNoAnimActivities.contains(next)) {
2668 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2669 } else {
2670 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 }
2673
2674 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002675 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676
2677 // This activity is now becoming visible.
2678 mWindowManager.setAppVisibility(next, true);
2679
2680 HistoryRecord lastResumedActivity = mResumedActivity;
2681 ActivityState lastState = next.state;
2682
2683 updateCpuStats();
2684
2685 next.state = ActivityState.RESUMED;
2686 mResumedActivity = next;
2687 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002688 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 updateLRUListLocked(next);
2690
2691 // Have the window manager re-evaluate the orientation of
2692 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002693 boolean updated;
2694 synchronized (this) {
2695 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2696 mConfiguration,
2697 next.mayFreezeScreenLocked(next.app) ? next : null);
2698 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002699 next.frozenBeforeDestroy = true;
2700 }
2701 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002703 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 // The configuration update wasn't able to keep the existing
2705 // instance of the activity, and instead started a new one.
2706 // We should be all done, but let's just make sure our activity
2707 // is still at the top and schedule another run if something
2708 // weird happened.
2709 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002710 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 "Activity config changed during resume: " + next
2712 + ", new next: " + nextNext);
2713 if (nextNext != next) {
2714 // Do over!
2715 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2716 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002717 setFocusedActivityLocked(next);
2718 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002720 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 return true;
2722 }
2723
2724 try {
2725 // Deliver all pending results.
2726 ArrayList a = next.results;
2727 if (a != null) {
2728 final int N = a.size();
2729 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002730 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 TAG, "Delivering results to " + next
2732 + ": " + a);
2733 next.app.thread.scheduleSendResult(next, a);
2734 }
2735 }
2736
2737 if (next.newIntents != null) {
2738 next.app.thread.scheduleNewIntent(next.newIntents, next);
2739 }
2740
Doug Zongker2bec3d42009-12-04 12:52:44 -08002741 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 System.identityHashCode(next),
2743 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744
2745 next.app.thread.scheduleResumeActivity(next,
2746 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 pauseIfSleepingLocked();
2749
2750 } catch (Exception e) {
2751 // Whoops, need to restart this activity!
2752 next.state = lastState;
2753 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002754 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 if (!next.hasBeenLaunched) {
2756 next.hasBeenLaunched = true;
2757 } else {
2758 if (SHOW_APP_STARTING_ICON) {
2759 mWindowManager.setAppStartingWindow(
2760 next, next.packageName, next.theme,
2761 next.nonLocalizedLabel,
2762 next.labelRes, next.icon, null, true);
2763 }
2764 }
2765 startSpecificActivityLocked(next, true, false);
2766 return true;
2767 }
2768
2769 // From this point on, if something goes wrong there is no way
2770 // to recover the activity.
2771 try {
2772 next.visible = true;
2773 completeResumeLocked(next);
2774 } catch (Exception e) {
2775 // If any exception gets thrown, toss away this
2776 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002777 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2779 "resume-exception");
2780 return true;
2781 }
2782
2783 // Didn't need to use the icicle, and it is now out of date.
2784 next.icicle = null;
2785 next.haveState = false;
2786 next.stopped = false;
2787
2788 } else {
2789 // Whoops, need to restart this activity!
2790 if (!next.hasBeenLaunched) {
2791 next.hasBeenLaunched = true;
2792 } else {
2793 if (SHOW_APP_STARTING_ICON) {
2794 mWindowManager.setAppStartingWindow(
2795 next, next.packageName, next.theme,
2796 next.nonLocalizedLabel,
2797 next.labelRes, next.icon, null, true);
2798 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002799 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002800 }
2801 startSpecificActivityLocked(next, true, true);
2802 }
2803
2804 return true;
2805 }
2806
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002807 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2808 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 final int NH = mHistory.size();
2810
2811 int addPos = -1;
2812
2813 if (!newTask) {
2814 // If starting in an existing task, find where that is...
2815 HistoryRecord next = null;
2816 boolean startIt = true;
2817 for (int i = NH-1; i >= 0; i--) {
2818 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2819 if (p.finishing) {
2820 continue;
2821 }
2822 if (p.task == r.task) {
2823 // Here it is! Now, if this is not yet visible to the
2824 // user, then just add it without starting; it will
2825 // get started when the user navigates back to it.
2826 addPos = i+1;
2827 if (!startIt) {
2828 mHistory.add(addPos, r);
2829 r.inHistory = true;
2830 r.task.numActivities++;
2831 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2832 r.info.screenOrientation, r.fullscreen);
2833 if (VALIDATE_TOKENS) {
2834 mWindowManager.validateAppTokens(mHistory);
2835 }
2836 return;
2837 }
2838 break;
2839 }
2840 if (p.fullscreen) {
2841 startIt = false;
2842 }
2843 next = p;
2844 }
2845 }
2846
2847 // Place a new activity at top of stack, so it is next to interact
2848 // with the user.
2849 if (addPos < 0) {
2850 addPos = mHistory.size();
2851 }
2852
2853 // If we are not placing the new activity frontmost, we do not want
2854 // to deliver the onUserLeaving callback to the actual frontmost
2855 // activity
2856 if (addPos < NH) {
2857 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002858 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
2860
2861 // Slot the activity into the history stack and proceed
2862 mHistory.add(addPos, r);
2863 r.inHistory = true;
2864 r.frontOfTask = newTask;
2865 r.task.numActivities++;
2866 if (NH > 0) {
2867 // We want to show the starting preview window if we are
2868 // switching to a new task, or the next activity's process is
2869 // not currently running.
2870 boolean showStartingIcon = newTask;
2871 ProcessRecord proc = r.app;
2872 if (proc == null) {
2873 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2874 }
2875 if (proc == null || proc.thread == null) {
2876 showStartingIcon = true;
2877 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002878 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002880 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2881 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2882 mNoAnimActivities.add(r);
2883 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2884 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2885 mNoAnimActivities.remove(r);
2886 } else {
2887 mWindowManager.prepareAppTransition(newTask
2888 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2889 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2890 mNoAnimActivities.remove(r);
2891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 mWindowManager.addAppToken(
2893 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2894 boolean doShow = true;
2895 if (newTask) {
2896 // Even though this activity is starting fresh, we still need
2897 // to reset it to make sure we apply affinities to move any
2898 // existing activities from other tasks in to it.
2899 // If the caller has requested that the target task be
2900 // reset, then do so.
2901 if ((r.intent.getFlags()
2902 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2903 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002904 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 }
2906 }
2907 if (SHOW_APP_STARTING_ICON && doShow) {
2908 // Figure out if we are transitioning from another activity that is
2909 // "has the same starting icon" as the next one. This allows the
2910 // window manager to keep the previous window it had previously
2911 // created, if it still had one.
2912 HistoryRecord prev = mResumedActivity;
2913 if (prev != null) {
2914 // We don't want to reuse the previous starting preview if:
2915 // (1) The current activity is in a different task.
2916 if (prev.task != r.task) prev = null;
2917 // (2) The current activity is already displayed.
2918 else if (prev.nowVisible) prev = null;
2919 }
2920 mWindowManager.setAppStartingWindow(
2921 r, r.packageName, r.theme, r.nonLocalizedLabel,
2922 r.labelRes, r.icon, prev, showStartingIcon);
2923 }
2924 } else {
2925 // If this is the first activity, don't do any fancy animations,
2926 // because there is nothing for it to animate on top of.
2927 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2928 r.info.screenOrientation, r.fullscreen);
2929 }
2930 if (VALIDATE_TOKENS) {
2931 mWindowManager.validateAppTokens(mHistory);
2932 }
2933
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002934 if (doResume) {
2935 resumeTopActivityLocked(null);
2936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 }
2938
2939 /**
2940 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002941 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2942 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 * an instance of that activity in the stack and, if found, finish all
2944 * activities on top of it and return the instance.
2945 *
2946 * @param newR Description of the new activity being started.
2947 * @return Returns the old activity that should be continue to be used,
2948 * or null if none was found.
2949 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002950 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002951 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002953
2954 // First find the requested task.
2955 while (i > 0) {
2956 i--;
2957 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2958 if (r.task.taskId == taskId) {
2959 i++;
2960 break;
2961 }
2962 }
2963
2964 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 while (i > 0) {
2966 i--;
2967 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2968 if (r.finishing) {
2969 continue;
2970 }
2971 if (r.task.taskId != taskId) {
2972 return null;
2973 }
2974 if (r.realActivity.equals(newR.realActivity)) {
2975 // Here it is! Now finish everything in front...
2976 HistoryRecord ret = r;
2977 if (doClear) {
2978 while (i < (mHistory.size()-1)) {
2979 i++;
2980 r = (HistoryRecord)mHistory.get(i);
2981 if (r.finishing) {
2982 continue;
2983 }
2984 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2985 null, "clear")) {
2986 i--;
2987 }
2988 }
2989 }
2990
2991 // Finally, if this is a normal launch mode (that is, not
2992 // expecting onNewIntent()), then we will finish the current
2993 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002994 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2995 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002997 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07002999 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003000 null, "clear");
3001 }
3002 return null;
3003 }
3004 }
3005
3006 return ret;
3007 }
3008 }
3009
3010 return null;
3011 }
3012
3013 /**
3014 * Find the activity in the history stack within the given task. Returns
3015 * the index within the history at which it's found, or < 0 if not found.
3016 */
3017 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3018 int i = mHistory.size();
3019 while (i > 0) {
3020 i--;
3021 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3022 if (candidate.task.taskId != task) {
3023 break;
3024 }
3025 if (candidate.realActivity.equals(r.realActivity)) {
3026 return i;
3027 }
3028 }
3029
3030 return -1;
3031 }
3032
3033 /**
3034 * Reorder the history stack so that the activity at the given index is
3035 * brought to the front.
3036 */
3037 private final HistoryRecord moveActivityToFrontLocked(int where) {
3038 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3039 int top = mHistory.size();
3040 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3041 mHistory.add(top, newTop);
3042 oldTop.frontOfTask = false;
3043 newTop.frontOfTask = true;
3044 return newTop;
3045 }
3046
3047 /**
3048 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3049 * method will be called at the proper time.
3050 */
3051 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3052 boolean sent = false;
3053 if (r.state == ActivityState.RESUMED
3054 && r.app != null && r.app.thread != null) {
3055 try {
3056 ArrayList<Intent> ar = new ArrayList<Intent>();
3057 ar.add(new Intent(intent));
3058 r.app.thread.scheduleNewIntent(ar, r);
3059 sent = true;
3060 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003061 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 }
3063 }
3064 if (!sent) {
3065 r.addNewIntentLocked(new Intent(intent));
3066 }
3067 }
3068
3069 private final void logStartActivity(int tag, HistoryRecord r,
3070 TaskRecord task) {
3071 EventLog.writeEvent(tag,
3072 System.identityHashCode(r), task.taskId,
3073 r.shortComponentName, r.intent.getAction(),
3074 r.intent.getType(), r.intent.getDataString(),
3075 r.intent.getFlags());
3076 }
3077
3078 private final int startActivityLocked(IApplicationThread caller,
3079 Intent intent, String resolvedType,
3080 Uri[] grantedUriPermissions,
3081 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3082 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003083 int callingPid, int callingUid, boolean onlyIfNeeded,
3084 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003085 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086
3087 HistoryRecord sourceRecord = null;
3088 HistoryRecord resultRecord = null;
3089 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003090 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003091 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3093 if (index >= 0) {
3094 sourceRecord = (HistoryRecord)mHistory.get(index);
3095 if (requestCode >= 0 && !sourceRecord.finishing) {
3096 resultRecord = sourceRecord;
3097 }
3098 }
3099 }
3100
3101 int launchFlags = intent.getFlags();
3102
3103 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3104 && sourceRecord != null) {
3105 // Transfer the result target from the source activity to the new
3106 // one being started, including any failures.
3107 if (requestCode >= 0) {
3108 return START_FORWARD_AND_REQUEST_CONFLICT;
3109 }
3110 resultRecord = sourceRecord.resultTo;
3111 resultWho = sourceRecord.resultWho;
3112 requestCode = sourceRecord.requestCode;
3113 sourceRecord.resultTo = null;
3114 if (resultRecord != null) {
3115 resultRecord.removeResultsLocked(
3116 sourceRecord, resultWho, requestCode);
3117 }
3118 }
3119
3120 int err = START_SUCCESS;
3121
3122 if (intent.getComponent() == null) {
3123 // We couldn't find a class that can handle the given Intent.
3124 // That's the end of that!
3125 err = START_INTENT_NOT_RESOLVED;
3126 }
3127
3128 if (err == START_SUCCESS && aInfo == null) {
3129 // We couldn't find the specific class specified in the Intent.
3130 // Also the end of the line.
3131 err = START_CLASS_NOT_FOUND;
3132 }
3133
3134 ProcessRecord callerApp = null;
3135 if (err == START_SUCCESS && caller != null) {
3136 callerApp = getRecordForAppLocked(caller);
3137 if (callerApp != null) {
3138 callingPid = callerApp.pid;
3139 callingUid = callerApp.info.uid;
3140 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003141 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 + " (pid=" + callingPid + ") when starting: "
3143 + intent.toString());
3144 err = START_PERMISSION_DENIED;
3145 }
3146 }
3147
3148 if (err != START_SUCCESS) {
3149 if (resultRecord != null) {
3150 sendActivityResultLocked(-1,
3151 resultRecord, resultWho, requestCode,
3152 Activity.RESULT_CANCELED, null);
3153 }
3154 return err;
3155 }
3156
3157 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3158 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3159 if (perm != PackageManager.PERMISSION_GRANTED) {
3160 if (resultRecord != null) {
3161 sendActivityResultLocked(-1,
3162 resultRecord, resultWho, requestCode,
3163 Activity.RESULT_CANCELED, null);
3164 }
3165 String msg = "Permission Denial: starting " + intent.toString()
3166 + " from " + callerApp + " (pid=" + callingPid
3167 + ", uid=" + callingUid + ")"
3168 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003169 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 throw new SecurityException(msg);
3171 }
3172
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003173 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 boolean abort = false;
3175 try {
3176 // The Intent we give to the watcher has the extra data
3177 // stripped off, since it can contain private information.
3178 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003179 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 aInfo.applicationInfo.packageName);
3181 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003182 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 }
3184
3185 if (abort) {
3186 if (resultRecord != null) {
3187 sendActivityResultLocked(-1,
3188 resultRecord, resultWho, requestCode,
3189 Activity.RESULT_CANCELED, null);
3190 }
3191 // We pretend to the caller that it was really started, but
3192 // they will just get a cancel result.
3193 return START_SUCCESS;
3194 }
3195 }
3196
3197 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3198 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003199 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003201 if (mResumedActivity == null
3202 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3203 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3204 PendingActivityLaunch pal = new PendingActivityLaunch();
3205 pal.r = r;
3206 pal.sourceRecord = sourceRecord;
3207 pal.grantedUriPermissions = grantedUriPermissions;
3208 pal.grantedMode = grantedMode;
3209 pal.onlyIfNeeded = onlyIfNeeded;
3210 mPendingActivityLaunches.add(pal);
3211 return START_SWITCHES_CANCELED;
3212 }
3213 }
3214
3215 if (mDidAppSwitch) {
3216 // This is the second allowed switch since we stopped switches,
3217 // so now just generally allow switches. Use case: user presses
3218 // home (switches disabled, switch to home, mDidAppSwitch now true);
3219 // user taps a home icon (coming from home so allowed, we hit here
3220 // and now allow anyone to switch again).
3221 mAppSwitchesAllowedTime = 0;
3222 } else {
3223 mDidAppSwitch = true;
3224 }
3225
3226 doPendingActivityLaunchesLocked(false);
3227
3228 return startActivityUncheckedLocked(r, sourceRecord,
3229 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3230 }
3231
3232 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3233 final int N = mPendingActivityLaunches.size();
3234 if (N <= 0) {
3235 return;
3236 }
3237 for (int i=0; i<N; i++) {
3238 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3239 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3240 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3241 doResume && i == (N-1));
3242 }
3243 mPendingActivityLaunches.clear();
3244 }
3245
3246 private final int startActivityUncheckedLocked(HistoryRecord r,
3247 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3248 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3249 final Intent intent = r.intent;
3250 final int callingUid = r.launchedFromUid;
3251
3252 int launchFlags = intent.getFlags();
3253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254 // We'll invoke onUserLeaving before onPause only if the launching
3255 // activity did not explicitly state that this is an automated launch.
3256 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003257 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 "startActivity() => mUserLeaving=" + mUserLeaving);
3259
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003260 // If the caller has asked not to resume at this point, we make note
3261 // of this in the record so that we can skip it when trying to find
3262 // the top running activity.
3263 if (!doResume) {
3264 r.delayedResume = true;
3265 }
3266
3267 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3268 != 0 ? r : null;
3269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 // If the onlyIfNeeded flag is set, then we can do this if the activity
3271 // being launched is the same as the one making the call... or, as
3272 // a special case, if we do not know the caller then we count the
3273 // current top activity as the caller.
3274 if (onlyIfNeeded) {
3275 HistoryRecord checkedCaller = sourceRecord;
3276 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003277 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 }
3279 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3280 // Caller is not the same as launcher, so always needed.
3281 onlyIfNeeded = false;
3282 }
3283 }
3284
3285 if (grantedUriPermissions != null && callingUid > 0) {
3286 for (int i=0; i<grantedUriPermissions.length; i++) {
3287 grantUriPermissionLocked(callingUid, r.packageName,
3288 grantedUriPermissions[i], grantedMode, r);
3289 }
3290 }
3291
3292 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3293 intent, r);
3294
3295 if (sourceRecord == null) {
3296 // This activity is not being started from another... in this
3297 // case we -always- start a new task.
3298 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003299 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 + intent);
3301 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3302 }
3303 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3304 // The original activity who is starting us is running as a single
3305 // instance... this new activity it is starting must go on its
3306 // own task.
3307 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3308 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3309 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3310 // The activity being started is a single instance... it always
3311 // gets launched into its own task.
3312 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3313 }
3314
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003315 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 // For whatever reason this activity is being launched into a new
3317 // task... yet the caller has requested a result back. Well, that
3318 // is pretty messed up, so instead immediately send back a cancel
3319 // and let the new task continue launched as normal without a
3320 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003321 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003323 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 Activity.RESULT_CANCELED, null);
3325 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 }
3327
3328 boolean addingToTask = false;
3329 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3330 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3331 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3332 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3333 // If bring to front is requested, and no result is requested, and
3334 // we can find a task that was started with this same
3335 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003336 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 // See if there is a task to bring to the front. If this is
3338 // a SINGLE_INSTANCE activity, there can be one and only one
3339 // instance of it in the history, and it is always in its own
3340 // unique task, so we do a special search.
3341 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3342 ? findTaskLocked(intent, r.info)
3343 : findActivityLocked(intent, r.info);
3344 if (taskTop != null) {
3345 if (taskTop.task.intent == null) {
3346 // This task was started because of movement of
3347 // the activity based on affinity... now that we
3348 // are actually launching it, we can assign the
3349 // base intent.
3350 taskTop.task.setIntent(intent, r.info);
3351 }
3352 // If the target task is not in the front, then we need
3353 // to bring it to the front... except... well, with
3354 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3355 // to have the same behavior as if a new instance was
3356 // being started, which means not bringing it to the front
3357 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003358 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 if (curTop.task != taskTop.task) {
3360 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3361 boolean callerAtFront = sourceRecord == null
3362 || curTop.task == sourceRecord.task;
3363 if (callerAtFront) {
3364 // We really do want to push this one into the
3365 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003366 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 }
3368 }
3369 // If the caller has requested that the target task be
3370 // reset, then do so.
3371 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3372 taskTop = resetTaskIfNeededLocked(taskTop, r);
3373 }
3374 if (onlyIfNeeded) {
3375 // We don't need to start a new activity, and
3376 // the client said not to do anything if that
3377 // is the case, so this is it! And for paranoia, make
3378 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003379 if (doResume) {
3380 resumeTopActivityLocked(null);
3381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 return START_RETURN_INTENT_TO_CALLER;
3383 }
3384 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3385 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3386 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3387 // In this situation we want to remove all activities
3388 // from the task up to the one being started. In most
3389 // cases this means we are resetting the task to its
3390 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003391 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003392 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 if (top != null) {
3394 if (top.frontOfTask) {
3395 // Activity aliases may mean we use different
3396 // intents for the top activity, so make sure
3397 // the task now has the identity of the new
3398 // intent.
3399 top.task.setIntent(r.intent, r.info);
3400 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003401 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 deliverNewIntentLocked(top, r.intent);
3403 } else {
3404 // A special case: we need to
3405 // start the activity because it is not currently
3406 // running, and the caller has asked to clear the
3407 // current task to have this activity at the top.
3408 addingToTask = true;
3409 // Now pretend like this activity is being started
3410 // by the top of its task, so it is put in the
3411 // right place.
3412 sourceRecord = taskTop;
3413 }
3414 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3415 // In this case the top activity on the task is the
3416 // same as the one being launched, so we take that
3417 // as a request to bring the task to the foreground.
3418 // If the top activity in the task is the root
3419 // activity, deliver this new intent to it if it
3420 // desires.
3421 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3422 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003423 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 if (taskTop.frontOfTask) {
3425 taskTop.task.setIntent(r.intent, r.info);
3426 }
3427 deliverNewIntentLocked(taskTop, r.intent);
3428 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3429 // In this case we are launching the root activity
3430 // of the task, but with a different intent. We
3431 // should start a new instance on top.
3432 addingToTask = true;
3433 sourceRecord = taskTop;
3434 }
3435 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3436 // In this case an activity is being launched in to an
3437 // existing task, without resetting that task. This
3438 // is typically the situation of launching an activity
3439 // from a notification or shortcut. We want to place
3440 // the new activity on top of the current task.
3441 addingToTask = true;
3442 sourceRecord = taskTop;
3443 } else if (!taskTop.task.rootWasReset) {
3444 // In this case we are launching in to an existing task
3445 // that has not yet been started from its front door.
3446 // The current task has been brought to the front.
3447 // Ideally, we'd probably like to place this new task
3448 // at the bottom of its stack, but that's a little hard
3449 // to do with the current organization of the code so
3450 // for now we'll just drop it.
3451 taskTop.task.setIntent(r.intent, r.info);
3452 }
3453 if (!addingToTask) {
3454 // We didn't do anything... but it was needed (a.k.a., client
3455 // don't use that intent!) And for paranoia, make
3456 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003457 if (doResume) {
3458 resumeTopActivityLocked(null);
3459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 return START_TASK_TO_FRONT;
3461 }
3462 }
3463 }
3464 }
3465
3466 //String uri = r.intent.toURI();
3467 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003468 //Slog.i(TAG, "Given intent: " + r.intent);
3469 //Slog.i(TAG, "URI is: " + uri);
3470 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471
3472 if (r.packageName != null) {
3473 // If the activity being launched is the same as the one currently
3474 // at the top, then we need to check if it should only be launched
3475 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003476 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3477 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 if (top.realActivity.equals(r.realActivity)) {
3479 if (top.app != null && top.app.thread != null) {
3480 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3481 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3482 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003483 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 // For paranoia, make sure we have correctly
3485 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003486 if (doResume) {
3487 resumeTopActivityLocked(null);
3488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003489 if (onlyIfNeeded) {
3490 // We don't need to start a new activity, and
3491 // the client said not to do anything if that
3492 // is the case, so this is it!
3493 return START_RETURN_INTENT_TO_CALLER;
3494 }
3495 deliverNewIntentLocked(top, r.intent);
3496 return START_DELIVERED_TO_TOP;
3497 }
3498 }
3499 }
3500 }
3501
3502 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003503 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003505 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 Activity.RESULT_CANCELED, null);
3507 }
3508 return START_CLASS_NOT_FOUND;
3509 }
3510
3511 boolean newTask = false;
3512
3513 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003514 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3516 // todo: should do better management of integers.
3517 mCurTask++;
3518 if (mCurTask <= 0) {
3519 mCurTask = 1;
3520 }
3521 r.task = new TaskRecord(mCurTask, r.info, intent,
3522 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003523 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 + " in new task " + r.task);
3525 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003526 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527
3528 } else if (sourceRecord != null) {
3529 if (!addingToTask &&
3530 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3531 // In this case, we are adding the activity to an existing
3532 // task, but the caller has asked to clear that task if the
3533 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003534 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003535 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003537 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 deliverNewIntentLocked(top, r.intent);
3539 // For paranoia, make sure we have correctly
3540 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003541 if (doResume) {
3542 resumeTopActivityLocked(null);
3543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 return START_DELIVERED_TO_TOP;
3545 }
3546 } else if (!addingToTask &&
3547 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3548 // In this case, we are launching an activity in our own task
3549 // that may already be running somewhere in the history, and
3550 // we want to shuffle it to the front of the stack if so.
3551 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3552 if (where >= 0) {
3553 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003554 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003556 if (doResume) {
3557 resumeTopActivityLocked(null);
3558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 return START_DELIVERED_TO_TOP;
3560 }
3561 }
3562 // An existing activity is starting this new activity, so we want
3563 // to keep the new one in the same task as the one that is starting
3564 // it.
3565 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003566 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 + " in existing task " + r.task);
3568
3569 } else {
3570 // This not being started from an existing activity, and not part
3571 // of a new task... just put it in the top task, though these days
3572 // this case should never happen.
3573 final int N = mHistory.size();
3574 HistoryRecord prev =
3575 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3576 r.task = prev != null
3577 ? prev.task
3578 : new TaskRecord(mCurTask, r.info, intent,
3579 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003580 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 + " in new guessed " + r.task);
3582 }
3583 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003584 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003586 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003587 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 return START_SUCCESS;
3589 }
3590
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003591 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3592 long thisTime, long totalTime) {
3593 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3594 WaitResult w = mWaitingActivityLaunched.get(i);
3595 w.timeout = timeout;
3596 if (r != null) {
3597 w.who = new ComponentName(r.info.packageName, r.info.name);
3598 }
3599 w.thisTime = thisTime;
3600 w.totalTime = totalTime;
3601 }
3602 notify();
3603 }
3604
3605 void reportActivityVisibleLocked(HistoryRecord r) {
3606 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3607 WaitResult w = mWaitingActivityVisible.get(i);
3608 w.timeout = false;
3609 if (r != null) {
3610 w.who = new ComponentName(r.info.packageName, r.info.name);
3611 }
3612 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3613 w.thisTime = w.totalTime;
3614 }
3615 notify();
3616 }
3617
3618 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3620 int grantedMode, IBinder resultTo,
3621 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003622 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 // Refuse possible leaked file descriptors
3624 if (intent != null && intent.hasFileDescriptors()) {
3625 throw new IllegalArgumentException("File descriptors passed in Intent");
3626 }
3627
The Android Open Source Project4df24232009-03-05 14:34:35 -08003628 final boolean componentSpecified = intent.getComponent() != null;
3629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 // Don't modify the client's object!
3631 intent = new Intent(intent);
3632
3633 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 ActivityInfo aInfo;
3635 try {
3636 ResolveInfo rInfo =
3637 ActivityThread.getPackageManager().resolveIntent(
3638 intent, resolvedType,
3639 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003640 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 aInfo = rInfo != null ? rInfo.activityInfo : null;
3642 } catch (RemoteException e) {
3643 aInfo = null;
3644 }
3645
3646 if (aInfo != null) {
3647 // Store the found target back into the intent, because now that
3648 // we have it we never want to do this again. For example, if the
3649 // user navigates back to this point in the history, we should
3650 // always restart the exact same activity.
3651 intent.setComponent(new ComponentName(
3652 aInfo.applicationInfo.packageName, aInfo.name));
3653
3654 // Don't debug things in the system process
3655 if (debug) {
3656 if (!aInfo.processName.equals("system")) {
3657 setDebugApp(aInfo.processName, true, false);
3658 }
3659 }
3660 }
3661
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003662 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003663 int callingPid;
3664 int callingUid;
3665 if (caller == null) {
3666 callingPid = Binder.getCallingPid();
3667 callingUid = Binder.getCallingUid();
3668 } else {
3669 callingPid = callingUid = -1;
3670 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003671
3672 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003673 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3674 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678 int res = startActivityLocked(caller, intent, resolvedType,
3679 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003680 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003681 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003682
Dianne Hackborne2522462010-03-29 18:41:30 -07003683 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003684 // If the caller also wants to switch to a new configuration,
3685 // do so now. This allows a clean switch, as we are waiting
3686 // for the current activity to pause (so we will not destroy
3687 // it), and have not yet started the next activity.
3688 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3689 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003690 mConfigWillChange = false;
3691 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3692 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003693 updateConfigurationLocked(config, null);
3694 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003697
3698 if (outResult != null) {
3699 outResult.result = res;
3700 if (res == IActivityManager.START_SUCCESS) {
3701 mWaitingActivityLaunched.add(outResult);
3702 do {
3703 try {
3704 wait();
3705 } catch (InterruptedException e) {
3706 }
3707 } while (!outResult.timeout && outResult.who == null);
3708 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3709 HistoryRecord r = this.topRunningActivityLocked(null);
3710 if (r.nowVisible) {
3711 outResult.timeout = false;
3712 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3713 outResult.totalTime = 0;
3714 outResult.thisTime = 0;
3715 } else {
3716 outResult.thisTime = SystemClock.uptimeMillis();
3717 mWaitingActivityVisible.add(outResult);
3718 do {
3719 try {
3720 wait();
3721 } catch (InterruptedException e) {
3722 }
3723 } while (!outResult.timeout && outResult.who == null);
3724 }
3725 }
3726 }
3727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 return res;
3729 }
3730 }
3731
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003732 public final int startActivity(IApplicationThread caller,
3733 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3734 int grantedMode, IBinder resultTo,
3735 String resultWho, int requestCode, boolean onlyIfNeeded,
3736 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003737 return startActivityMayWait(caller, intent, resolvedType,
3738 grantedUriPermissions, grantedMode, resultTo, resultWho,
3739 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003740 }
3741
3742 public final WaitResult startActivityAndWait(IApplicationThread caller,
3743 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3744 int grantedMode, IBinder resultTo,
3745 String resultWho, int requestCode, boolean onlyIfNeeded,
3746 boolean debug) {
3747 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003748 startActivityMayWait(caller, intent, resolvedType,
3749 grantedUriPermissions, grantedMode, resultTo, resultWho,
3750 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003751 return res;
3752 }
3753
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003754 public final int startActivityWithConfig(IApplicationThread caller,
3755 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3756 int grantedMode, IBinder resultTo,
3757 String resultWho, int requestCode, boolean onlyIfNeeded,
3758 boolean debug, Configuration config) {
3759 return startActivityMayWait(caller, intent, resolvedType,
3760 grantedUriPermissions, grantedMode, resultTo, resultWho,
3761 requestCode, onlyIfNeeded, debug, null, config);
3762 }
3763
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003764 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003765 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003766 IBinder resultTo, String resultWho, int requestCode,
3767 int flagsMask, int flagsValues) {
3768 // Refuse possible leaked file descriptors
3769 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3770 throw new IllegalArgumentException("File descriptors passed in Intent");
3771 }
3772
3773 IIntentSender sender = intent.getTarget();
3774 if (!(sender instanceof PendingIntentRecord)) {
3775 throw new IllegalArgumentException("Bad PendingIntent object");
3776 }
3777
3778 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003779
3780 synchronized (this) {
3781 // If this is coming from the currently resumed activity, it is
3782 // effectively saying that app switches are allowed at this point.
3783 if (mResumedActivity != null
3784 && mResumedActivity.info.applicationInfo.uid ==
3785 Binder.getCallingUid()) {
3786 mAppSwitchesAllowedTime = 0;
3787 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003788 }
3789
3790 return pir.sendInner(0, fillInIntent, resolvedType,
3791 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3792 }
3793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 public boolean startNextMatchingActivity(IBinder callingActivity,
3795 Intent intent) {
3796 // Refuse possible leaked file descriptors
3797 if (intent != null && intent.hasFileDescriptors() == true) {
3798 throw new IllegalArgumentException("File descriptors passed in Intent");
3799 }
3800
3801 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003802 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 if (index < 0) {
3804 return false;
3805 }
3806 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3807 if (r.app == null || r.app.thread == null) {
3808 // The caller is not running... d'oh!
3809 return false;
3810 }
3811 intent = new Intent(intent);
3812 // The caller is not allowed to change the data.
3813 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3814 // And we are resetting to find the next component...
3815 intent.setComponent(null);
3816
3817 ActivityInfo aInfo = null;
3818 try {
3819 List<ResolveInfo> resolves =
3820 ActivityThread.getPackageManager().queryIntentActivities(
3821 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003822 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823
3824 // Look for the original activity in the list...
3825 final int N = resolves != null ? resolves.size() : 0;
3826 for (int i=0; i<N; i++) {
3827 ResolveInfo rInfo = resolves.get(i);
3828 if (rInfo.activityInfo.packageName.equals(r.packageName)
3829 && rInfo.activityInfo.name.equals(r.info.name)) {
3830 // We found the current one... the next matching is
3831 // after it.
3832 i++;
3833 if (i<N) {
3834 aInfo = resolves.get(i).activityInfo;
3835 }
3836 break;
3837 }
3838 }
3839 } catch (RemoteException e) {
3840 }
3841
3842 if (aInfo == null) {
3843 // Nobody who is next!
3844 return false;
3845 }
3846
3847 intent.setComponent(new ComponentName(
3848 aInfo.applicationInfo.packageName, aInfo.name));
3849 intent.setFlags(intent.getFlags()&~(
3850 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3851 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3852 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3853 Intent.FLAG_ACTIVITY_NEW_TASK));
3854
3855 // Okay now we need to start the new activity, replacing the
3856 // currently running activity. This is a little tricky because
3857 // we want to start the new one as if the current one is finished,
3858 // but not finish the current one first so that there is no flicker.
3859 // And thus...
3860 final boolean wasFinishing = r.finishing;
3861 r.finishing = true;
3862
3863 // Propagate reply information over to the new activity.
3864 final HistoryRecord resultTo = r.resultTo;
3865 final String resultWho = r.resultWho;
3866 final int requestCode = r.requestCode;
3867 r.resultTo = null;
3868 if (resultTo != null) {
3869 resultTo.removeResultsLocked(r, resultWho, requestCode);
3870 }
3871
3872 final long origId = Binder.clearCallingIdentity();
3873 // XXX we are not dealing with propagating grantedUriPermissions...
3874 // those are not yet exposed to user code, so there is no need.
3875 int res = startActivityLocked(r.app.thread, intent,
3876 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003877 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 Binder.restoreCallingIdentity(origId);
3879
3880 r.finishing = wasFinishing;
3881 if (res != START_SUCCESS) {
3882 return false;
3883 }
3884 return true;
3885 }
3886 }
3887
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003888 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 Intent intent, String resolvedType, IBinder resultTo,
3890 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003891
3892 // This is so super not safe, that only the system (or okay root)
3893 // can do it.
3894 final int callingUid = Binder.getCallingUid();
3895 if (callingUid != 0 && callingUid != Process.myUid()) {
3896 throw new SecurityException(
3897 "startActivityInPackage only available to the system");
3898 }
3899
The Android Open Source Project4df24232009-03-05 14:34:35 -08003900 final boolean componentSpecified = intent.getComponent() != null;
3901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003902 // Don't modify the client's object!
3903 intent = new Intent(intent);
3904
3905 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 ActivityInfo aInfo;
3907 try {
3908 ResolveInfo rInfo =
3909 ActivityThread.getPackageManager().resolveIntent(
3910 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003911 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 aInfo = rInfo != null ? rInfo.activityInfo : null;
3913 } catch (RemoteException e) {
3914 aInfo = null;
3915 }
3916
3917 if (aInfo != null) {
3918 // Store the found target back into the intent, because now that
3919 // we have it we never want to do this again. For example, if the
3920 // user navigates back to this point in the history, we should
3921 // always restart the exact same activity.
3922 intent.setComponent(new ComponentName(
3923 aInfo.applicationInfo.packageName, aInfo.name));
3924 }
3925
3926 synchronized(this) {
3927 return startActivityLocked(null, intent, resolvedType,
3928 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003929 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 }
3931 }
3932
Josh Bartel7f208742010-02-25 11:01:44 -06003933 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 // Remove any existing entries that are the same kind of task.
3935 int N = mRecentTasks.size();
3936 for (int i=0; i<N; i++) {
3937 TaskRecord tr = mRecentTasks.get(i);
3938 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3939 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3940 mRecentTasks.remove(i);
3941 i--;
3942 N--;
3943 if (task.intent == null) {
3944 // If the new recent task we are adding is not fully
3945 // specified, then replace it with the existing recent task.
3946 task = tr;
3947 }
3948 }
3949 }
3950 if (N >= MAX_RECENT_TASKS) {
3951 mRecentTasks.remove(N-1);
3952 }
3953 mRecentTasks.add(0, task);
3954 }
3955
3956 public void setRequestedOrientation(IBinder token,
3957 int requestedOrientation) {
3958 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003959 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 if (index < 0) {
3961 return;
3962 }
3963 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3964 final long origId = Binder.clearCallingIdentity();
3965 mWindowManager.setAppOrientation(r, requestedOrientation);
3966 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003967 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 r.mayFreezeScreenLocked(r.app) ? r : null);
3969 if (config != null) {
3970 r.frozenBeforeDestroy = true;
3971 if (!updateConfigurationLocked(config, r)) {
3972 resumeTopActivityLocked(null);
3973 }
3974 }
3975 Binder.restoreCallingIdentity(origId);
3976 }
3977 }
3978
3979 public int getRequestedOrientation(IBinder token) {
3980 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003981 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 if (index < 0) {
3983 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3984 }
3985 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3986 return mWindowManager.getAppOrientation(r);
3987 }
3988 }
3989
3990 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003991 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3993 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3994 if (!r.finishing) {
3995 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3996 "no-history");
3997 }
3998 } else if (r.app != null && r.app.thread != null) {
3999 if (mFocusedActivity == r) {
4000 setFocusedActivityLocked(topRunningActivityLocked(null));
4001 }
4002 r.resumeKeyDispatchingLocked();
4003 try {
4004 r.stopped = false;
4005 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004006 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 TAG, "Stopping visible=" + r.visible + " for " + r);
4008 if (!r.visible) {
4009 mWindowManager.setAppVisibility(r, false);
4010 }
4011 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4012 } catch (Exception e) {
4013 // Maybe just ignore exceptions here... if the process
4014 // has crashed, our death notification will clean things
4015 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004016 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 // Just in case, assume it to be stopped.
4018 r.stopped = true;
4019 r.state = ActivityState.STOPPED;
4020 if (r.configDestroy) {
4021 destroyActivityLocked(r, true);
4022 }
4023 }
4024 }
4025 }
4026
4027 /**
4028 * @return Returns true if the activity is being finished, false if for
4029 * some reason it is being left as-is.
4030 */
4031 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4032 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004033 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 TAG, "Finishing activity: token=" + token
4035 + ", result=" + resultCode + ", data=" + resultData);
4036
Dianne Hackborn75b03852009-06-12 15:43:26 -07004037 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 if (index < 0) {
4039 return false;
4040 }
4041 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4042
4043 // Is this the last activity left?
4044 boolean lastActivity = true;
4045 for (int i=mHistory.size()-1; i>=0; i--) {
4046 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4047 if (!p.finishing && p != r) {
4048 lastActivity = false;
4049 break;
4050 }
4051 }
4052
4053 // If this is the last activity, but it is the home activity, then
4054 // just don't finish it.
4055 if (lastActivity) {
4056 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4057 return false;
4058 }
4059 }
4060
4061 finishActivityLocked(r, index, resultCode, resultData, reason);
4062 return true;
4063 }
4064
4065 /**
4066 * @return Returns true if this activity has been removed from the history
4067 * list, or false if it is still in the list and will be removed later.
4068 */
4069 private final boolean finishActivityLocked(HistoryRecord r, int index,
4070 int resultCode, Intent resultData, String reason) {
4071 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004072 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 return false;
4074 }
4075
4076 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004077 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 System.identityHashCode(r),
4079 r.task.taskId, r.shortComponentName, reason);
4080 r.task.numActivities--;
4081 if (r.frontOfTask && index < (mHistory.size()-1)) {
4082 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4083 if (next.task == r.task) {
4084 next.frontOfTask = true;
4085 }
4086 }
4087
4088 r.pauseKeyDispatchingLocked();
4089 if (mFocusedActivity == r) {
4090 setFocusedActivityLocked(topRunningActivityLocked(null));
4091 }
4092
4093 // send the result
4094 HistoryRecord resultTo = r.resultTo;
4095 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004096 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004097 + " who=" + r.resultWho + " req=" + r.requestCode
4098 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 if (r.info.applicationInfo.uid > 0) {
4100 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4101 r.packageName, resultData, r);
4102 }
4103 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4104 resultData);
4105 r.resultTo = null;
4106 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004107 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108
4109 // Make sure this HistoryRecord is not holding on to other resources,
4110 // because clients have remote IPC references to this object so we
4111 // can't assume that will go away and want to avoid circular IPC refs.
4112 r.results = null;
4113 r.pendingResults = null;
4114 r.newIntents = null;
4115 r.icicle = null;
4116
4117 if (mPendingThumbnails.size() > 0) {
4118 // There are clients waiting to receive thumbnails so, in case
4119 // this is an activity that someone is waiting for, add it
4120 // to the pending list so we can correctly update the clients.
4121 mCancelledThumbnails.add(r);
4122 }
4123
4124 if (mResumedActivity == r) {
4125 boolean endTask = index <= 0
4126 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004127 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 "Prepare close transition: finishing " + r);
4129 mWindowManager.prepareAppTransition(endTask
4130 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4131 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4132
4133 // Tell window manager to prepare for this one to be removed.
4134 mWindowManager.setAppVisibility(r, false);
4135
4136 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004137 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4138 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139 startPausingLocked(false, false);
4140 }
4141
4142 } else if (r.state != ActivityState.PAUSING) {
4143 // If the activity is PAUSING, we will complete the finish once
4144 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004145 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 return finishCurrentActivityLocked(r, index,
4147 FINISH_AFTER_PAUSE) == null;
4148 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004149 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 }
4151
4152 return false;
4153 }
4154
4155 private static final int FINISH_IMMEDIATELY = 0;
4156 private static final int FINISH_AFTER_PAUSE = 1;
4157 private static final int FINISH_AFTER_VISIBLE = 2;
4158
4159 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4160 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004161 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 if (index < 0) {
4163 return null;
4164 }
4165
4166 return finishCurrentActivityLocked(r, index, mode);
4167 }
4168
4169 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4170 int index, int mode) {
4171 // First things first: if this activity is currently visible,
4172 // and the resumed activity is not yet visible, then hold off on
4173 // finishing until the resumed one becomes visible.
4174 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4175 if (!mStoppingActivities.contains(r)) {
4176 mStoppingActivities.add(r);
4177 if (mStoppingActivities.size() > 3) {
4178 // If we already have a few activities waiting to stop,
4179 // then give up on things going idle and start clearing
4180 // them out.
4181 Message msg = Message.obtain();
4182 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4183 mHandler.sendMessage(msg);
4184 }
4185 }
4186 r.state = ActivityState.STOPPING;
4187 updateOomAdjLocked();
4188 return r;
4189 }
4190
4191 // make sure the record is cleaned out of other places.
4192 mStoppingActivities.remove(r);
4193 mWaitingVisibleActivities.remove(r);
4194 if (mResumedActivity == r) {
4195 mResumedActivity = null;
4196 }
4197 final ActivityState prevState = r.state;
4198 r.state = ActivityState.FINISHING;
4199
4200 if (mode == FINISH_IMMEDIATELY
4201 || prevState == ActivityState.STOPPED
4202 || prevState == ActivityState.INITIALIZING) {
4203 // If this activity is already stopped, we can just finish
4204 // it right now.
4205 return destroyActivityLocked(r, true) ? null : r;
4206 } else {
4207 // Need to go through the full pause cycle to get this
4208 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004209 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004210 mFinishingActivities.add(r);
4211 resumeTopActivityLocked(null);
4212 }
4213 return r;
4214 }
4215
4216 /**
4217 * This is the internal entry point for handling Activity.finish().
4218 *
4219 * @param token The Binder token referencing the Activity we want to finish.
4220 * @param resultCode Result code, if any, from this Activity.
4221 * @param resultData Result data (Intent), if any, from this Activity.
4222 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004223 * @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 -08004224 */
4225 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4226 // Refuse possible leaked file descriptors
4227 if (resultData != null && resultData.hasFileDescriptors() == true) {
4228 throw new IllegalArgumentException("File descriptors passed in Intent");
4229 }
4230
4231 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004232 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 // Find the first activity that is not finishing.
4234 HistoryRecord next = topRunningActivityLocked(token, 0);
4235 if (next != null) {
4236 // ask watcher if this is allowed
4237 boolean resumeOK = true;
4238 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004239 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004241 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 }
4243
4244 if (!resumeOK) {
4245 return false;
4246 }
4247 }
4248 }
4249 final long origId = Binder.clearCallingIdentity();
4250 boolean res = requestFinishActivityLocked(token, resultCode,
4251 resultData, "app-request");
4252 Binder.restoreCallingIdentity(origId);
4253 return res;
4254 }
4255 }
4256
4257 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4258 String resultWho, int requestCode, int resultCode, Intent data) {
4259
4260 if (callingUid > 0) {
4261 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4262 data, r);
4263 }
4264
Joe Onorato8a9b2202010-02-26 18:56:32 -08004265 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004266 + " : who=" + resultWho + " req=" + requestCode
4267 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4269 try {
4270 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4271 list.add(new ResultInfo(resultWho, requestCode,
4272 resultCode, data));
4273 r.app.thread.scheduleSendResult(r, list);
4274 return;
4275 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004276 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 }
4278 }
4279
4280 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4281 }
4282
4283 public final void finishSubActivity(IBinder token, String resultWho,
4284 int requestCode) {
4285 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004286 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 if (index < 0) {
4288 return;
4289 }
4290 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4291
4292 final long origId = Binder.clearCallingIdentity();
4293
4294 int i;
4295 for (i=mHistory.size()-1; i>=0; i--) {
4296 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4297 if (r.resultTo == self && r.requestCode == requestCode) {
4298 if ((r.resultWho == null && resultWho == null) ||
4299 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4300 finishActivityLocked(r, i,
4301 Activity.RESULT_CANCELED, null, "request-sub");
4302 }
4303 }
4304 }
4305
4306 Binder.restoreCallingIdentity(origId);
4307 }
4308 }
4309
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004310 public boolean willActivityBeVisible(IBinder token) {
4311 synchronized(this) {
4312 int i;
4313 for (i=mHistory.size()-1; i>=0; i--) {
4314 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4315 if (r == token) {
4316 return true;
4317 }
4318 if (r.fullscreen && !r.finishing) {
4319 return false;
4320 }
4321 }
4322 return true;
4323 }
4324 }
4325
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004326 public void overridePendingTransition(IBinder token, String packageName,
4327 int enterAnim, int exitAnim) {
4328 synchronized(this) {
4329 int index = indexOfTokenLocked(token);
4330 if (index < 0) {
4331 return;
4332 }
4333 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4334
4335 final long origId = Binder.clearCallingIdentity();
4336
4337 if (self.state == ActivityState.RESUMED
4338 || self.state == ActivityState.PAUSING) {
4339 mWindowManager.overridePendingAppTransition(packageName,
4340 enterAnim, exitAnim);
4341 }
4342
4343 Binder.restoreCallingIdentity(origId);
4344 }
4345 }
4346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 /**
4348 * Perform clean-up of service connections in an activity record.
4349 */
4350 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4351 // Throw away any services that have been bound by this activity.
4352 if (r.connections != null) {
4353 Iterator<ConnectionRecord> it = r.connections.iterator();
4354 while (it.hasNext()) {
4355 ConnectionRecord c = it.next();
4356 removeConnectionLocked(c, null, r);
4357 }
4358 r.connections = null;
4359 }
4360 }
4361
4362 /**
4363 * Perform the common clean-up of an activity record. This is called both
4364 * as part of destroyActivityLocked() (when destroying the client-side
4365 * representation) and cleaning things up as a result of its hosting
4366 * processing going away, in which case there is no remaining client-side
4367 * state to destroy so only the cleanup here is needed.
4368 */
4369 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4370 if (mResumedActivity == r) {
4371 mResumedActivity = null;
4372 }
4373 if (mFocusedActivity == r) {
4374 mFocusedActivity = null;
4375 }
4376
4377 r.configDestroy = false;
4378 r.frozenBeforeDestroy = false;
4379
4380 // Make sure this record is no longer in the pending finishes list.
4381 // This could happen, for example, if we are trimming activities
4382 // down to the max limit while they are still waiting to finish.
4383 mFinishingActivities.remove(r);
4384 mWaitingVisibleActivities.remove(r);
4385
4386 // Remove any pending results.
4387 if (r.finishing && r.pendingResults != null) {
4388 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4389 PendingIntentRecord rec = apr.get();
4390 if (rec != null) {
4391 cancelIntentSenderLocked(rec, false);
4392 }
4393 }
4394 r.pendingResults = null;
4395 }
4396
4397 if (cleanServices) {
4398 cleanUpActivityServicesLocked(r);
4399 }
4400
4401 if (mPendingThumbnails.size() > 0) {
4402 // There are clients waiting to receive thumbnails so, in case
4403 // this is an activity that someone is waiting for, add it
4404 // to the pending list so we can correctly update the clients.
4405 mCancelledThumbnails.add(r);
4406 }
4407
4408 // Get rid of any pending idle timeouts.
4409 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4410 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4411 }
4412
4413 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4414 if (r.state != ActivityState.DESTROYED) {
4415 mHistory.remove(r);
4416 r.inHistory = false;
4417 r.state = ActivityState.DESTROYED;
4418 mWindowManager.removeAppToken(r);
4419 if (VALIDATE_TOKENS) {
4420 mWindowManager.validateAppTokens(mHistory);
4421 }
4422 cleanUpActivityServicesLocked(r);
4423 removeActivityUriPermissionsLocked(r);
4424 }
4425 }
4426
4427 /**
4428 * Destroy the current CLIENT SIDE instance of an activity. This may be
4429 * called both when actually finishing an activity, or when performing
4430 * a configuration switch where we destroy the current client-side object
4431 * but then create a new client-side object for this same HistoryRecord.
4432 */
4433 private final boolean destroyActivityLocked(HistoryRecord r,
4434 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004435 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 TAG, "Removing activity: token=" + r
4437 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004438 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 System.identityHashCode(r),
4440 r.task.taskId, r.shortComponentName);
4441
4442 boolean removedFromHistory = false;
4443
4444 cleanUpActivityLocked(r, false);
4445
Dianne Hackborn03abb812010-01-04 18:43:19 -08004446 final boolean hadApp = r.app != null;
4447
4448 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004449 if (removeFromApp) {
4450 int idx = r.app.activities.indexOf(r);
4451 if (idx >= 0) {
4452 r.app.activities.remove(idx);
4453 }
4454 if (r.persistent) {
4455 decPersistentCountLocked(r.app);
4456 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004457 if (r.app.activities.size() == 0) {
4458 // No longer have activities, so update location in
4459 // LRU list.
4460 updateLruProcessLocked(r.app, true, false);
4461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 }
4463
4464 boolean skipDestroy = false;
4465
4466 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004467 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4469 r.configChangeFlags);
4470 } catch (Exception e) {
4471 // We can just ignore exceptions here... if the process
4472 // has crashed, our death notification will clean things
4473 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004474 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 if (r.finishing) {
4476 removeActivityFromHistoryLocked(r);
4477 removedFromHistory = true;
4478 skipDestroy = true;
4479 }
4480 }
4481
4482 r.app = null;
4483 r.nowVisible = false;
4484
4485 if (r.finishing && !skipDestroy) {
4486 r.state = ActivityState.DESTROYING;
4487 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4488 msg.obj = r;
4489 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4490 } else {
4491 r.state = ActivityState.DESTROYED;
4492 }
4493 } else {
4494 // remove this record from the history.
4495 if (r.finishing) {
4496 removeActivityFromHistoryLocked(r);
4497 removedFromHistory = true;
4498 } else {
4499 r.state = ActivityState.DESTROYED;
4500 }
4501 }
4502
4503 r.configChangeFlags = 0;
4504
Dianne Hackborn03abb812010-01-04 18:43:19 -08004505 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004506 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 }
4508
4509 return removedFromHistory;
4510 }
4511
Dianne Hackborn03abb812010-01-04 18:43:19 -08004512 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004514 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 TAG, "Removing app " + app + " from list " + list
4516 + " with " + i + " entries");
4517 while (i > 0) {
4518 i--;
4519 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004520 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4522 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004523 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 list.remove(i);
4525 }
4526 }
4527 }
4528
4529 /**
4530 * Main function for removing an existing process from the activity manager
4531 * as a result of that process going away. Clears out all connections
4532 * to the process.
4533 */
4534 private final void handleAppDiedLocked(ProcessRecord app,
4535 boolean restarting) {
4536 cleanUpApplicationRecordLocked(app, restarting, -1);
4537 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004538 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 }
4540
4541 // Just in case...
4542 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004543 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 mPausingActivity = null;
4545 }
4546 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4547 mLastPausedActivity = null;
4548 }
4549
4550 // Remove this application's activities from active lists.
4551 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4552 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4553 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4554 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4555
4556 boolean atTop = true;
4557 boolean hasVisibleActivities = false;
4558
4559 // Clean out the history list.
4560 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 TAG, "Removing app " + app + " from history with " + i + " entries");
4563 while (i > 0) {
4564 i--;
4565 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004566 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4568 if (r.app == app) {
4569 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004570 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 TAG, "Removing this entry! frozen=" + r.haveState
4572 + " finishing=" + r.finishing);
4573 mHistory.remove(i);
4574
4575 r.inHistory = false;
4576 mWindowManager.removeAppToken(r);
4577 if (VALIDATE_TOKENS) {
4578 mWindowManager.validateAppTokens(mHistory);
4579 }
4580 removeActivityUriPermissionsLocked(r);
4581
4582 } else {
4583 // We have the current state for this activity, so
4584 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004585 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 TAG, "Keeping entry, setting app to null");
4587 if (r.visible) {
4588 hasVisibleActivities = true;
4589 }
4590 r.app = null;
4591 r.nowVisible = false;
4592 if (!r.haveState) {
4593 r.icicle = null;
4594 }
4595 }
4596
4597 cleanUpActivityLocked(r, true);
4598 r.state = ActivityState.STOPPED;
4599 }
4600 atTop = false;
4601 }
4602
4603 app.activities.clear();
4604
4605 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004606 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 + " running instrumentation " + app.instrumentationClass);
4608 Bundle info = new Bundle();
4609 info.putString("shortMsg", "Process crashed.");
4610 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4611 }
4612
4613 if (!restarting) {
4614 if (!resumeTopActivityLocked(null)) {
4615 // If there was nothing to resume, and we are not already
4616 // restarting this process, but there is a visible activity that
4617 // is hosted by the process... then make sure all visible
4618 // activities are running, taking care of restarting this
4619 // process.
4620 if (hasVisibleActivities) {
4621 ensureActivitiesVisibleLocked(null, 0);
4622 }
4623 }
4624 }
4625 }
4626
4627 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4628 IBinder threadBinder = thread.asBinder();
4629
4630 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004631 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4632 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4634 return i;
4635 }
4636 }
4637 return -1;
4638 }
4639
4640 private final ProcessRecord getRecordForAppLocked(
4641 IApplicationThread thread) {
4642 if (thread == null) {
4643 return null;
4644 }
4645
4646 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004647 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004648 }
4649
4650 private final void appDiedLocked(ProcessRecord app, int pid,
4651 IApplicationThread thread) {
4652
4653 mProcDeaths[0]++;
4654
Magnus Edlund7bb25812010-02-24 15:45:06 +01004655 // Clean up already done if the process has been re-started.
4656 if (app.pid == pid && app.thread != null &&
4657 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004658 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004660 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004661 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 TAG, "Dying app: " + app + ", pid: " + pid
4663 + ", thread: " + thread.asBinder());
4664 boolean doLowMem = app.instrumentationClass == null;
4665 handleAppDiedLocked(app, false);
4666
4667 if (doLowMem) {
4668 // If there are no longer any background processes running,
4669 // and the app that died was not running instrumentation,
4670 // then tell everyone we are now low on memory.
4671 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004672 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4673 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4675 haveBg = true;
4676 break;
4677 }
4678 }
4679
4680 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004681 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004682 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004683 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004684 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4685 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004686 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004687 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4688 // The low memory report is overriding any current
4689 // state for a GC request. Make sure to do
4690 // visible/foreground processes first.
4691 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4692 rec.lastRequestedGc = 0;
4693 } else {
4694 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004696 rec.reportLowMemory = true;
4697 rec.lastLowMemory = now;
4698 mProcessesToGc.remove(rec);
4699 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 }
4701 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004702 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 }
4704 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004705 } else if (app.pid != pid) {
4706 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004707 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004708 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004709 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004710 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004711 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 + thread.asBinder());
4713 }
4714 }
4715
Dan Egnor42471dd2010-01-07 17:25:22 -08004716 /**
4717 * If a stack trace dump file is configured, dump process stack traces.
4718 * @param pids of dalvik VM processes to dump stack traces for
4719 * @return file containing stack traces, or null if no dump file is configured
4720 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004721 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004722 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4723 if (tracesPath == null || tracesPath.length() == 0) {
4724 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004726
4727 File tracesFile = new File(tracesPath);
4728 try {
4729 File tracesDir = tracesFile.getParentFile();
4730 if (!tracesDir.exists()) tracesFile.mkdirs();
4731 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4732
4733 if (tracesFile.exists()) tracesFile.delete();
4734 tracesFile.createNewFile();
4735 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4736 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004737 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004738 return null;
4739 }
4740
4741 // Use a FileObserver to detect when traces finish writing.
4742 // The order of traces is considered important to maintain for legibility.
4743 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4744 public synchronized void onEvent(int event, String path) { notify(); }
4745 };
4746
4747 try {
4748 observer.startWatching();
4749 int num = pids.size();
4750 for (int i = 0; i < num; i++) {
4751 synchronized (observer) {
4752 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4753 observer.wait(200); // Wait for write-close, give up after 200msec
4754 }
4755 }
4756 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004757 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004758 } finally {
4759 observer.stopWatching();
4760 }
4761
4762 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 }
4764
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004765 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004766 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004767 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004768
4769 synchronized (this) {
4770 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4771 if (mShuttingDown) {
4772 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4773 return;
4774 } else if (app.notResponding) {
4775 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4776 return;
4777 } else if (app.crashing) {
4778 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4779 return;
4780 }
4781
4782 // In case we come through here for the same app before completing
4783 // this one, mark as anring now so we will bail out.
4784 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004785
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004786 // Log the ANR to the event log.
4787 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4788 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004789
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004790 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4791 pids.add(app.pid);
4792
4793 int parentPid = app.pid;
4794 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4795 if (parentPid != app.pid) pids.add(parentPid);
4796
4797 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004798
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004799 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4800 ProcessRecord r = mLruProcesses.get(i);
4801 if (r != null && r.thread != null) {
4802 int pid = r.pid;
4803 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004805 }
4806 }
4807
Dan Egnor42471dd2010-01-07 17:25:22 -08004808 File tracesFile = dumpStackTraces(pids);
4809
4810 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004811 StringBuilder info = mStringBuilder;
4812 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004813 info.append("ANR in ").append(app.processName);
4814 if (activity != null && activity.shortComponentName != null) {
4815 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004816 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004817 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004819 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004821 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004822 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824
Dan Egnor42471dd2010-01-07 17:25:22 -08004825 String cpuInfo = null;
4826 if (MONITOR_CPU_USAGE) {
4827 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004828 synchronized (mProcessStatsThread) {
4829 cpuInfo = mProcessStats.printCurrentState();
4830 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004831 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 }
4833
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004835 if (tracesFile == null) {
4836 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4837 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4838 }
4839
4840 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4841
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004842 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004843 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004844 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4845 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004846 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004847 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4848 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 }
4850 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004851 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 }
4853 }
4854
Dan Egnor42471dd2010-01-07 17:25:22 -08004855 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4856 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4857 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004858
4859 synchronized (this) {
4860 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4861 Process.killProcess(app.pid);
4862 return;
4863 }
4864
4865 // Set the app's notResponding state, and look up the errorReportReceiver
4866 makeAppNotRespondingLocked(app,
4867 activity != null ? activity.shortComponentName : null,
4868 annotation != null ? "ANR " + annotation : "ANR",
4869 info.toString());
4870
4871 // Bring up the infamous App Not Responding dialog
4872 Message msg = Message.obtain();
4873 HashMap map = new HashMap();
4874 msg.what = SHOW_NOT_RESPONDING_MSG;
4875 msg.obj = map;
4876 map.put("app", app);
4877 if (activity != null) {
4878 map.put("activity", activity);
4879 }
4880
4881 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 }
4884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 private final void decPersistentCountLocked(ProcessRecord app)
4886 {
4887 app.persistentActivities--;
4888 if (app.persistentActivities > 0) {
4889 // Still more of 'em...
4890 return;
4891 }
4892 if (app.persistent) {
4893 // Ah, but the application itself is persistent. Whatever!
4894 return;
4895 }
4896
4897 // App is no longer persistent... make sure it and the ones
4898 // following it in the LRU list have the correc oom_adj.
4899 updateOomAdjLocked();
4900 }
4901
4902 public void setPersistent(IBinder token, boolean isPersistent) {
4903 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4904 != PackageManager.PERMISSION_GRANTED) {
4905 String msg = "Permission Denial: setPersistent() from pid="
4906 + Binder.getCallingPid()
4907 + ", uid=" + Binder.getCallingUid()
4908 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004909 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 throw new SecurityException(msg);
4911 }
4912
4913 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004914 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 if (index < 0) {
4916 return;
4917 }
4918 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4919 ProcessRecord app = r.app;
4920
Joe Onorato8a9b2202010-02-26 18:56:32 -08004921 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 TAG, "Setting persistence " + isPersistent + ": " + r);
4923
4924 if (isPersistent) {
4925 if (r.persistent) {
4926 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004927 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 return;
4929 }
4930 r.persistent = true;
4931 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004932 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 if (app.persistentActivities > 1) {
4934 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004935 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 return;
4937 }
4938 if (app.persistent) {
4939 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004940 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 return;
4942 }
4943
4944 // App is now persistent... make sure it and the ones
4945 // following it now have the correct oom_adj.
4946 final long origId = Binder.clearCallingIdentity();
4947 updateOomAdjLocked();
4948 Binder.restoreCallingIdentity(origId);
4949
4950 } else {
4951 if (!r.persistent) {
4952 // Okay okay, I heard you already!
4953 return;
4954 }
4955 r.persistent = false;
4956 final long origId = Binder.clearCallingIdentity();
4957 decPersistentCountLocked(app);
4958 Binder.restoreCallingIdentity(origId);
4959
4960 }
4961 }
4962 }
4963
4964 public boolean clearApplicationUserData(final String packageName,
4965 final IPackageDataObserver observer) {
4966 int uid = Binder.getCallingUid();
4967 int pid = Binder.getCallingPid();
4968 long callingId = Binder.clearCallingIdentity();
4969 try {
4970 IPackageManager pm = ActivityThread.getPackageManager();
4971 int pkgUid = -1;
4972 synchronized(this) {
4973 try {
4974 pkgUid = pm.getPackageUid(packageName);
4975 } catch (RemoteException e) {
4976 }
4977 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004978 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 return false;
4980 }
4981 if (uid == pkgUid || checkComponentPermission(
4982 android.Manifest.permission.CLEAR_APP_USER_DATA,
4983 pid, uid, -1)
4984 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004985 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 } else {
4987 throw new SecurityException(pid+" does not have permission:"+
4988 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4989 "for process:"+packageName);
4990 }
4991 }
4992
4993 try {
4994 //clear application user data
4995 pm.clearApplicationUserData(packageName, observer);
4996 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4997 Uri.fromParts("package", packageName, null));
4998 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06004999 synchronized (this) {
5000 broadcastIntentLocked(null, null, intent,
5001 null, null, 0, null, null, null,
5002 false, false, MY_PID, Process.SYSTEM_UID);
5003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 } catch (RemoteException e) {
5005 }
5006 } finally {
5007 Binder.restoreCallingIdentity(callingId);
5008 }
5009 return true;
5010 }
5011
Dianne Hackborn03abb812010-01-04 18:43:19 -08005012 public void killBackgroundProcesses(final String packageName) {
5013 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5014 != PackageManager.PERMISSION_GRANTED &&
5015 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5016 != PackageManager.PERMISSION_GRANTED) {
5017 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 + Binder.getCallingPid()
5019 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005020 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005021 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 throw new SecurityException(msg);
5023 }
5024
5025 long callingId = Binder.clearCallingIdentity();
5026 try {
5027 IPackageManager pm = ActivityThread.getPackageManager();
5028 int pkgUid = -1;
5029 synchronized(this) {
5030 try {
5031 pkgUid = pm.getPackageUid(packageName);
5032 } catch (RemoteException e) {
5033 }
5034 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005035 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 return;
5037 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005038 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005039 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005040 }
5041 } finally {
5042 Binder.restoreCallingIdentity(callingId);
5043 }
5044 }
5045
5046 public void forceStopPackage(final String packageName) {
5047 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5048 != PackageManager.PERMISSION_GRANTED) {
5049 String msg = "Permission Denial: forceStopPackage() from pid="
5050 + Binder.getCallingPid()
5051 + ", uid=" + Binder.getCallingUid()
5052 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005053 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005054 throw new SecurityException(msg);
5055 }
5056
5057 long callingId = Binder.clearCallingIdentity();
5058 try {
5059 IPackageManager pm = ActivityThread.getPackageManager();
5060 int pkgUid = -1;
5061 synchronized(this) {
5062 try {
5063 pkgUid = pm.getPackageUid(packageName);
5064 } catch (RemoteException e) {
5065 }
5066 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005067 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005068 return;
5069 }
5070 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 }
5072 } finally {
5073 Binder.restoreCallingIdentity(callingId);
5074 }
5075 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005076
5077 /*
5078 * The pkg name and uid have to be specified.
5079 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5080 */
5081 public void killApplicationWithUid(String pkg, int uid) {
5082 if (pkg == null) {
5083 return;
5084 }
5085 // Make sure the uid is valid.
5086 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005087 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005088 return;
5089 }
5090 int callerUid = Binder.getCallingUid();
5091 // Only the system server can kill an application
5092 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005093 // Post an aysnc message to kill the application
5094 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5095 msg.arg1 = uid;
5096 msg.arg2 = 0;
5097 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005098 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005099 } else {
5100 throw new SecurityException(callerUid + " cannot kill pkg: " +
5101 pkg);
5102 }
5103 }
5104
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005105 public void closeSystemDialogs(String reason) {
5106 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5107 if (reason != null) {
5108 intent.putExtra("reason", reason);
5109 }
5110
5111 final int uid = Binder.getCallingUid();
5112 final long origId = Binder.clearCallingIdentity();
5113 synchronized (this) {
5114 int i = mWatchers.beginBroadcast();
5115 while (i > 0) {
5116 i--;
5117 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5118 if (w != null) {
5119 try {
5120 w.closingSystemDialogs(reason);
5121 } catch (RemoteException e) {
5122 }
5123 }
5124 }
5125 mWatchers.finishBroadcast();
5126
Dianne Hackbornffa42482009-09-23 22:20:11 -07005127 mWindowManager.closeSystemDialogs(reason);
5128
5129 for (i=mHistory.size()-1; i>=0; i--) {
5130 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5131 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5132 finishActivityLocked(r, i,
5133 Activity.RESULT_CANCELED, null, "close-sys");
5134 }
5135 }
5136
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005137 broadcastIntentLocked(null, null, intent, null,
5138 null, 0, null, null, null, false, false, -1, uid);
5139 }
5140 Binder.restoreCallingIdentity(origId);
5141 }
5142
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005143 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005144 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005145 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5146 for (int i=pids.length-1; i>=0; i--) {
5147 infos[i] = new Debug.MemoryInfo();
5148 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005149 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005150 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005151 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005152
5153 public void killApplicationProcess(String processName, int uid) {
5154 if (processName == null) {
5155 return;
5156 }
5157
5158 int callerUid = Binder.getCallingUid();
5159 // Only the system server can kill an application
5160 if (callerUid == Process.SYSTEM_UID) {
5161 synchronized (this) {
5162 ProcessRecord app = getProcessRecordLocked(processName, uid);
5163 if (app != null) {
5164 try {
5165 app.thread.scheduleSuicide();
5166 } catch (RemoteException e) {
5167 // If the other end already died, then our work here is done.
5168 }
5169 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005170 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005171 + processName + " / " + uid);
5172 }
5173 }
5174 } else {
5175 throw new SecurityException(callerUid + " cannot kill app process: " +
5176 processName);
5177 }
5178 }
5179
Dianne Hackborn03abb812010-01-04 18:43:19 -08005180 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005181 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5183 Uri.fromParts("package", packageName, null));
5184 intent.putExtra(Intent.EXTRA_UID, uid);
5185 broadcastIntentLocked(null, null, intent,
5186 null, null, 0, null, null, null,
5187 false, false, MY_PID, Process.SYSTEM_UID);
5188 }
5189
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005190 private final boolean killPackageProcessesLocked(String packageName, int uid,
5191 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005192 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193
Dianne Hackborn03abb812010-01-04 18:43:19 -08005194 // Remove all processes this package may have touched: all with the
5195 // same UID (except for the system or root user), and all whose name
5196 // matches the package name.
5197 final String procNamePrefix = packageName + ":";
5198 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5199 final int NA = apps.size();
5200 for (int ia=0; ia<NA; ia++) {
5201 ProcessRecord app = apps.valueAt(ia);
5202 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005203 if (doit) {
5204 procs.add(app);
5205 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005206 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5207 || app.processName.equals(packageName)
5208 || app.processName.startsWith(procNamePrefix)) {
5209 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005210 if (!doit) {
5211 return true;
5212 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005213 app.removed = true;
5214 procs.add(app);
5215 }
5216 }
5217 }
5218 }
5219
5220 int N = procs.size();
5221 for (int i=0; i<N; i++) {
5222 removeProcessLocked(procs.get(i), callerWillRestart);
5223 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005224 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005225 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005226
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005227 private final boolean forceStopPackageLocked(String name, int uid,
5228 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 int i, N;
5230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 if (uid < 0) {
5232 try {
5233 uid = ActivityThread.getPackageManager().getPackageUid(name);
5234 } catch (RemoteException e) {
5235 }
5236 }
5237
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005238 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005239 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005240
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005241 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5242 while (badApps.hasNext()) {
5243 SparseArray<Long> ba = badApps.next();
5244 if (ba.get(uid) != null) {
5245 badApps.remove();
5246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 }
5248 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005249
5250 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5251 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252
5253 for (i=mHistory.size()-1; i>=0; i--) {
5254 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5255 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005256 if (!doit) {
5257 return true;
5258 }
5259 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005260 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 if (r.app != null) {
5262 r.app.removed = true;
5263 }
5264 r.app = null;
5265 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5266 }
5267 }
5268
5269 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5270 for (ServiceRecord service : mServices.values()) {
5271 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005272 if (!doit) {
5273 return true;
5274 }
5275 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005276 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 if (service.app != null) {
5278 service.app.removed = true;
5279 }
5280 service.app = null;
5281 services.add(service);
5282 }
5283 }
5284
5285 N = services.size();
5286 for (i=0; i<N; i++) {
5287 bringDownServiceLocked(services.get(i), true);
5288 }
5289
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005290 if (doit) {
5291 if (purgeCache) {
5292 AttributeCache ac = AttributeCache.instance();
5293 if (ac != null) {
5294 ac.removePackage(name);
5295 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005296 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005297 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005298 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005299
5300 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302
5303 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5304 final String name = app.processName;
5305 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005306 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 TAG, "Force removing process " + app + " (" + name
5308 + "/" + uid + ")");
5309
5310 mProcessNames.remove(name, uid);
5311 boolean needRestart = false;
5312 if (app.pid > 0 && app.pid != MY_PID) {
5313 int pid = app.pid;
5314 synchronized (mPidsSelfLocked) {
5315 mPidsSelfLocked.remove(pid);
5316 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5317 }
5318 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005319 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 Process.killProcess(pid);
5321
5322 if (app.persistent) {
5323 if (!callerWillRestart) {
5324 addAppLocked(app.info);
5325 } else {
5326 needRestart = true;
5327 }
5328 }
5329 } else {
5330 mRemovedProcesses.add(app);
5331 }
5332
5333 return needRestart;
5334 }
5335
5336 private final void processStartTimedOutLocked(ProcessRecord app) {
5337 final int pid = app.pid;
5338 boolean gone = false;
5339 synchronized (mPidsSelfLocked) {
5340 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5341 if (knownApp != null && knownApp.thread == null) {
5342 mPidsSelfLocked.remove(pid);
5343 gone = true;
5344 }
5345 }
5346
5347 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005348 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005349 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005350 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005352 // Take care of any launching providers waiting for this process.
5353 checkAppInLaunchingProvidersLocked(app, true);
5354 // Take care of any services that are waiting for the process.
5355 for (int i=0; i<mPendingServices.size(); i++) {
5356 ServiceRecord sr = mPendingServices.get(i);
5357 if (app.info.uid == sr.appInfo.uid
5358 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005359 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005360 mPendingServices.remove(i);
5361 i--;
5362 bringDownServiceLocked(sr, true);
5363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005365 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005366 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005367 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005368 try {
5369 IBackupManager bm = IBackupManager.Stub.asInterface(
5370 ServiceManager.getService(Context.BACKUP_SERVICE));
5371 bm.agentDisconnected(app.info.packageName);
5372 } catch (RemoteException e) {
5373 // Can't happen; the backup manager is local
5374 }
5375 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005376 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005377 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005378 mPendingBroadcast = null;
5379 scheduleBroadcastsLocked();
5380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005382 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 }
5384 }
5385
5386 private final boolean attachApplicationLocked(IApplicationThread thread,
5387 int pid) {
5388
5389 // Find the application record that is being attached... either via
5390 // the pid if we are running in multiple processes, or just pull the
5391 // next app record if we are emulating process with anonymous threads.
5392 ProcessRecord app;
5393 if (pid != MY_PID && pid >= 0) {
5394 synchronized (mPidsSelfLocked) {
5395 app = mPidsSelfLocked.get(pid);
5396 }
5397 } else if (mStartingProcesses.size() > 0) {
5398 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005399 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 } else {
5401 app = null;
5402 }
5403
5404 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005405 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005407 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 if (pid > 0 && pid != MY_PID) {
5409 Process.killProcess(pid);
5410 } else {
5411 try {
5412 thread.scheduleExit();
5413 } catch (Exception e) {
5414 // Ignore exceptions.
5415 }
5416 }
5417 return false;
5418 }
5419
5420 // If this application record is still attached to a previous
5421 // process, clean it up now.
5422 if (app.thread != null) {
5423 handleAppDiedLocked(app, true);
5424 }
5425
5426 // Tell the process all about itself.
5427
Joe Onorato8a9b2202010-02-26 18:56:32 -08005428 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 TAG, "Binding process pid " + pid + " to record " + app);
5430
5431 String processName = app.processName;
5432 try {
5433 thread.asBinder().linkToDeath(new AppDeathRecipient(
5434 app, pid, thread), 0);
5435 } catch (RemoteException e) {
5436 app.resetPackageList();
5437 startProcessLocked(app, "link fail", processName);
5438 return false;
5439 }
5440
Doug Zongker2bec3d42009-12-04 12:52:44 -08005441 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442
5443 app.thread = thread;
5444 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005445 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5446 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 app.forcingToForeground = null;
5448 app.foregroundServices = false;
5449 app.debugging = false;
5450
5451 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5452
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005453 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5454 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005456 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005457 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005458 }
5459
Joe Onorato8a9b2202010-02-26 18:56:32 -08005460 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005461 TAG, "New app record " + app
5462 + " thread=" + thread.asBinder() + " pid=" + pid);
5463 try {
5464 int testMode = IApplicationThread.DEBUG_OFF;
5465 if (mDebugApp != null && mDebugApp.equals(processName)) {
5466 testMode = mWaitForDebugger
5467 ? IApplicationThread.DEBUG_WAIT
5468 : IApplicationThread.DEBUG_ON;
5469 app.debugging = true;
5470 if (mDebugTransient) {
5471 mDebugApp = mOrigDebugApp;
5472 mWaitForDebugger = mOrigWaitForDebugger;
5473 }
5474 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005475
Christopher Tate181fafa2009-05-14 11:12:14 -07005476 // If the app is being launched for restore or full backup, set it up specially
5477 boolean isRestrictedBackupMode = false;
5478 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5479 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5480 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5481 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005482
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005483 ensurePackageDexOpt(app.instrumentationInfo != null
5484 ? app.instrumentationInfo.packageName
5485 : app.info.packageName);
5486 if (app.instrumentationClass != null) {
5487 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005488 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005489 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005490 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005491 thread.bindApplication(processName, app.instrumentationInfo != null
5492 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 app.instrumentationClass, app.instrumentationProfileFile,
5494 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005495 isRestrictedBackupMode || !normalMode,
5496 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005497 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005498 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 } catch (Exception e) {
5500 // todo: Yikes! What should we do? For now we will try to
5501 // start another process, but that could easily get us in
5502 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005503 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504
5505 app.resetPackageList();
5506 startProcessLocked(app, "bind fail", processName);
5507 return false;
5508 }
5509
5510 // Remove this record from the list of starting applications.
5511 mPersistentStartingProcesses.remove(app);
5512 mProcessesOnHold.remove(app);
5513
5514 boolean badApp = false;
5515 boolean didSomething = false;
5516
5517 // See if the top visible activity is waiting to run in this process...
5518 HistoryRecord hr = topRunningActivityLocked(null);
5519 if (hr != null) {
5520 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5521 && processName.equals(hr.processName)) {
5522 try {
5523 if (realStartActivityLocked(hr, app, true, true)) {
5524 didSomething = true;
5525 }
5526 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005527 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 + hr.intent.getComponent().flattenToShortString(), e);
5529 badApp = true;
5530 }
5531 } else {
5532 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5533 }
5534 }
5535
5536 // Find any services that should be running in this process...
5537 if (!badApp && mPendingServices.size() > 0) {
5538 ServiceRecord sr = null;
5539 try {
5540 for (int i=0; i<mPendingServices.size(); i++) {
5541 sr = mPendingServices.get(i);
5542 if (app.info.uid != sr.appInfo.uid
5543 || !processName.equals(sr.processName)) {
5544 continue;
5545 }
5546
5547 mPendingServices.remove(i);
5548 i--;
5549 realStartServiceLocked(sr, app);
5550 didSomething = true;
5551 }
5552 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005553 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 + sr.shortName, e);
5555 badApp = true;
5556 }
5557 }
5558
5559 // Check if the next broadcast receiver is in this process...
5560 BroadcastRecord br = mPendingBroadcast;
5561 if (!badApp && br != null && br.curApp == app) {
5562 try {
5563 mPendingBroadcast = null;
5564 processCurBroadcastLocked(br, app);
5565 didSomething = true;
5566 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005567 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 + br.curComponent.flattenToShortString(), e);
5569 badApp = true;
5570 logBroadcastReceiverDiscard(br);
5571 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5572 br.resultExtras, br.resultAbort, true);
5573 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005574 // We need to reset the state if we fails to start the receiver.
5575 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 }
5577 }
5578
Christopher Tate181fafa2009-05-14 11:12:14 -07005579 // Check whether the next backup agent is in this process...
5580 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005581 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005582 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005583 try {
5584 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5585 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005586 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005587 e.printStackTrace();
5588 }
5589 }
5590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 if (badApp) {
5592 // todo: Also need to kill application to deal with all
5593 // kinds of exceptions.
5594 handleAppDiedLocked(app, false);
5595 return false;
5596 }
5597
5598 if (!didSomething) {
5599 updateOomAdjLocked();
5600 }
5601
5602 return true;
5603 }
5604
5605 public final void attachApplication(IApplicationThread thread) {
5606 synchronized (this) {
5607 int callingPid = Binder.getCallingPid();
5608 final long origId = Binder.clearCallingIdentity();
5609 attachApplicationLocked(thread, callingPid);
5610 Binder.restoreCallingIdentity(origId);
5611 }
5612 }
5613
Dianne Hackborne88846e2009-09-30 21:34:25 -07005614 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005616 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 Binder.restoreCallingIdentity(origId);
5618 }
5619
5620 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5621 boolean remove) {
5622 int N = mStoppingActivities.size();
5623 if (N <= 0) return null;
5624
5625 ArrayList<HistoryRecord> stops = null;
5626
5627 final boolean nowVisible = mResumedActivity != null
5628 && mResumedActivity.nowVisible
5629 && !mResumedActivity.waitingVisible;
5630 for (int i=0; i<N; i++) {
5631 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005632 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 + nowVisible + " waitingVisible=" + s.waitingVisible
5634 + " finishing=" + s.finishing);
5635 if (s.waitingVisible && nowVisible) {
5636 mWaitingVisibleActivities.remove(s);
5637 s.waitingVisible = false;
5638 if (s.finishing) {
5639 // If this activity is finishing, it is sitting on top of
5640 // everyone else but we now know it is no longer needed...
5641 // so get rid of it. Otherwise, we need to go through the
5642 // normal flow and hide it once we determine that it is
5643 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005644 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 mWindowManager.setAppVisibility(s, false);
5646 }
5647 }
5648 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005649 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 if (stops == null) {
5651 stops = new ArrayList<HistoryRecord>();
5652 }
5653 stops.add(s);
5654 mStoppingActivities.remove(i);
5655 N--;
5656 i--;
5657 }
5658 }
5659
5660 return stops;
5661 }
5662
5663 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005664 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005665 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 mWindowManager.enableScreenAfterBoot();
5667 }
5668
Dianne Hackborne88846e2009-09-30 21:34:25 -07005669 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5670 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005671 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672
5673 ArrayList<HistoryRecord> stops = null;
5674 ArrayList<HistoryRecord> finishes = null;
5675 ArrayList<HistoryRecord> thumbnails = null;
5676 int NS = 0;
5677 int NF = 0;
5678 int NT = 0;
5679 IApplicationThread sendThumbnail = null;
5680 boolean booting = false;
5681 boolean enableScreen = false;
5682
5683 synchronized (this) {
5684 if (token != null) {
5685 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5686 }
5687
5688 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005689 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 if (index >= 0) {
5691 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5692
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005693 if (fromTimeout) {
5694 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5695 }
5696
Dianne Hackborne88846e2009-09-30 21:34:25 -07005697 // This is a hack to semi-deal with a race condition
5698 // in the client where it can be constructed with a
5699 // newer configuration from when we asked it to launch.
5700 // We'll update with whatever configuration it now says
5701 // it used to launch.
5702 if (config != null) {
5703 r.configuration = config;
5704 }
5705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 // No longer need to keep the device awake.
5707 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5708 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5709 mLaunchingActivity.release();
5710 }
5711
5712 // We are now idle. If someone is waiting for a thumbnail from
5713 // us, we can now deliver.
5714 r.idle = true;
5715 scheduleAppGcsLocked();
5716 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5717 sendThumbnail = r.app.thread;
5718 r.thumbnailNeeded = false;
5719 }
5720
5721 // If this activity is fullscreen, set up to hide those under it.
5722
Joe Onorato8a9b2202010-02-26 18:56:32 -08005723 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 ensureActivitiesVisibleLocked(null, 0);
5725
Joe Onorato8a9b2202010-02-26 18:56:32 -08005726 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 if (!mBooted && !fromTimeout) {
5728 mBooted = true;
5729 enableScreen = true;
5730 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005731
5732 } else if (fromTimeout) {
5733 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 }
5735
5736 // Atomically retrieve all of the other things to do.
5737 stops = processStoppingActivitiesLocked(true);
5738 NS = stops != null ? stops.size() : 0;
5739 if ((NF=mFinishingActivities.size()) > 0) {
5740 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5741 mFinishingActivities.clear();
5742 }
5743 if ((NT=mCancelledThumbnails.size()) > 0) {
5744 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5745 mCancelledThumbnails.clear();
5746 }
5747
5748 booting = mBooting;
5749 mBooting = false;
5750 }
5751
5752 int i;
5753
5754 // Send thumbnail if requested.
5755 if (sendThumbnail != null) {
5756 try {
5757 sendThumbnail.requestThumbnail(token);
5758 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005759 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 sendPendingThumbnail(null, token, null, null, true);
5761 }
5762 }
5763
5764 // Stop any activities that are scheduled to do so but have been
5765 // waiting for the next one to start.
5766 for (i=0; i<NS; i++) {
5767 HistoryRecord r = (HistoryRecord)stops.get(i);
5768 synchronized (this) {
5769 if (r.finishing) {
5770 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5771 } else {
5772 stopActivityLocked(r);
5773 }
5774 }
5775 }
5776
5777 // Finish any activities that are scheduled to do so but have been
5778 // waiting for the next one to start.
5779 for (i=0; i<NF; i++) {
5780 HistoryRecord r = (HistoryRecord)finishes.get(i);
5781 synchronized (this) {
5782 destroyActivityLocked(r, true);
5783 }
5784 }
5785
5786 // Report back to any thumbnail receivers.
5787 for (i=0; i<NT; i++) {
5788 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5789 sendPendingThumbnail(r, null, null, null, true);
5790 }
5791
5792 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005793 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 }
5795
5796 trimApplications();
5797 //dump();
5798 //mWindowManager.dump();
5799
5800 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 enableScreenAfterBoot();
5802 }
5803 }
5804
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005805 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005806 IntentFilter pkgFilter = new IntentFilter();
5807 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5808 pkgFilter.addDataScheme("package");
5809 mContext.registerReceiver(new BroadcastReceiver() {
5810 @Override
5811 public void onReceive(Context context, Intent intent) {
5812 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5813 if (pkgs != null) {
5814 for (String pkg : pkgs) {
5815 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5816 setResultCode(Activity.RESULT_OK);
5817 return;
5818 }
5819 }
5820 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005821 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005822 }, pkgFilter);
5823
5824 synchronized (this) {
5825 // Ensure that any processes we had put on hold are now started
5826 // up.
5827 final int NP = mProcessesOnHold.size();
5828 if (NP > 0) {
5829 ArrayList<ProcessRecord> procs =
5830 new ArrayList<ProcessRecord>(mProcessesOnHold);
5831 for (int ip=0; ip<NP; ip++) {
5832 this.startProcessLocked(procs.get(ip), "on-hold", null);
5833 }
5834 }
5835
5836 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5837 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005838 broadcastIntentLocked(null, null,
5839 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5840 null, null, 0, null, null,
5841 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5842 false, false, MY_PID, Process.SYSTEM_UID);
5843 }
5844 }
5845 }
5846
5847 final void ensureBootCompleted() {
5848 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005849 boolean enableScreen;
5850 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005851 booting = mBooting;
5852 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005853 enableScreen = !mBooted;
5854 mBooted = true;
5855 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005856
5857 if (booting) {
5858 finishBooting();
5859 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005860
5861 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005862 enableScreenAfterBoot();
5863 }
5864 }
5865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 public final void activityPaused(IBinder token, Bundle icicle) {
5867 // Refuse possible leaked file descriptors
5868 if (icicle != null && icicle.hasFileDescriptors()) {
5869 throw new IllegalArgumentException("File descriptors passed in Bundle");
5870 }
5871
5872 final long origId = Binder.clearCallingIdentity();
5873 activityPaused(token, icicle, false);
5874 Binder.restoreCallingIdentity(origId);
5875 }
5876
5877 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005878 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5880 + ", timeout=" + timeout);
5881
5882 HistoryRecord r = null;
5883
5884 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005885 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 if (index >= 0) {
5887 r = (HistoryRecord)mHistory.get(index);
5888 if (!timeout) {
5889 r.icicle = icicle;
5890 r.haveState = true;
5891 }
5892 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5893 if (mPausingActivity == r) {
5894 r.state = ActivityState.PAUSED;
5895 completePauseLocked();
5896 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005897 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 System.identityHashCode(r), r.shortComponentName,
5899 mPausingActivity != null
5900 ? mPausingActivity.shortComponentName : "(none)");
5901 }
5902 }
5903 }
5904 }
5905
5906 public final void activityStopped(IBinder token, Bitmap thumbnail,
5907 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005908 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 TAG, "Activity stopped: token=" + token);
5910
5911 HistoryRecord r = null;
5912
5913 final long origId = Binder.clearCallingIdentity();
5914
5915 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005916 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 if (index >= 0) {
5918 r = (HistoryRecord)mHistory.get(index);
5919 r.thumbnail = thumbnail;
5920 r.description = description;
5921 r.stopped = true;
5922 r.state = ActivityState.STOPPED;
5923 if (!r.finishing) {
5924 if (r.configDestroy) {
5925 destroyActivityLocked(r, true);
5926 resumeTopActivityLocked(null);
5927 }
5928 }
5929 }
5930 }
5931
5932 if (r != null) {
5933 sendPendingThumbnail(r, null, null, null, false);
5934 }
5935
5936 trimApplications();
5937
5938 Binder.restoreCallingIdentity(origId);
5939 }
5940
5941 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005942 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 synchronized (this) {
5944 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5945
Dianne Hackborn75b03852009-06-12 15:43:26 -07005946 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 if (index >= 0) {
5948 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5949 if (r.state == ActivityState.DESTROYING) {
5950 final long origId = Binder.clearCallingIdentity();
5951 removeActivityFromHistoryLocked(r);
5952 Binder.restoreCallingIdentity(origId);
5953 }
5954 }
5955 }
5956 }
5957
5958 public String getCallingPackage(IBinder token) {
5959 synchronized (this) {
5960 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005961 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 }
5963 }
5964
5965 public ComponentName getCallingActivity(IBinder token) {
5966 synchronized (this) {
5967 HistoryRecord r = getCallingRecordLocked(token);
5968 return r != null ? r.intent.getComponent() : null;
5969 }
5970 }
5971
5972 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005973 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 if (index >= 0) {
5975 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5976 if (r != null) {
5977 return r.resultTo;
5978 }
5979 }
5980 return null;
5981 }
5982
5983 public ComponentName getActivityClassForToken(IBinder token) {
5984 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005985 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 if (index >= 0) {
5987 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5988 return r.intent.getComponent();
5989 }
5990 return null;
5991 }
5992 }
5993
5994 public String getPackageForToken(IBinder token) {
5995 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005996 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 if (index >= 0) {
5998 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5999 return r.packageName;
6000 }
6001 return null;
6002 }
6003 }
6004
6005 public IIntentSender getIntentSender(int type,
6006 String packageName, IBinder token, String resultWho,
6007 int requestCode, Intent intent, String resolvedType, int flags) {
6008 // Refuse possible leaked file descriptors
6009 if (intent != null && intent.hasFileDescriptors() == true) {
6010 throw new IllegalArgumentException("File descriptors passed in Intent");
6011 }
6012
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006013 if (type == INTENT_SENDER_BROADCAST) {
6014 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6015 throw new IllegalArgumentException(
6016 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6017 }
6018 }
6019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 synchronized(this) {
6021 int callingUid = Binder.getCallingUid();
6022 try {
6023 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6024 Process.supportsProcesses()) {
6025 int uid = ActivityThread.getPackageManager()
6026 .getPackageUid(packageName);
6027 if (uid != Binder.getCallingUid()) {
6028 String msg = "Permission Denial: getIntentSender() from pid="
6029 + Binder.getCallingPid()
6030 + ", uid=" + Binder.getCallingUid()
6031 + ", (need uid=" + uid + ")"
6032 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006033 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006034 throw new SecurityException(msg);
6035 }
6036 }
6037 } catch (RemoteException e) {
6038 throw new SecurityException(e);
6039 }
6040 HistoryRecord activity = null;
6041 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006042 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 if (index < 0) {
6044 return null;
6045 }
6046 activity = (HistoryRecord)mHistory.get(index);
6047 if (activity.finishing) {
6048 return null;
6049 }
6050 }
6051
6052 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6053 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6054 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6055 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6056 |PendingIntent.FLAG_UPDATE_CURRENT);
6057
6058 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6059 type, packageName, activity, resultWho,
6060 requestCode, intent, resolvedType, flags);
6061 WeakReference<PendingIntentRecord> ref;
6062 ref = mIntentSenderRecords.get(key);
6063 PendingIntentRecord rec = ref != null ? ref.get() : null;
6064 if (rec != null) {
6065 if (!cancelCurrent) {
6066 if (updateCurrent) {
6067 rec.key.requestIntent.replaceExtras(intent);
6068 }
6069 return rec;
6070 }
6071 rec.canceled = true;
6072 mIntentSenderRecords.remove(key);
6073 }
6074 if (noCreate) {
6075 return rec;
6076 }
6077 rec = new PendingIntentRecord(this, key, callingUid);
6078 mIntentSenderRecords.put(key, rec.ref);
6079 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6080 if (activity.pendingResults == null) {
6081 activity.pendingResults
6082 = new HashSet<WeakReference<PendingIntentRecord>>();
6083 }
6084 activity.pendingResults.add(rec.ref);
6085 }
6086 return rec;
6087 }
6088 }
6089
6090 public void cancelIntentSender(IIntentSender sender) {
6091 if (!(sender instanceof PendingIntentRecord)) {
6092 return;
6093 }
6094 synchronized(this) {
6095 PendingIntentRecord rec = (PendingIntentRecord)sender;
6096 try {
6097 int uid = ActivityThread.getPackageManager()
6098 .getPackageUid(rec.key.packageName);
6099 if (uid != Binder.getCallingUid()) {
6100 String msg = "Permission Denial: cancelIntentSender() from pid="
6101 + Binder.getCallingPid()
6102 + ", uid=" + Binder.getCallingUid()
6103 + " is not allowed to cancel packges "
6104 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006105 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 throw new SecurityException(msg);
6107 }
6108 } catch (RemoteException e) {
6109 throw new SecurityException(e);
6110 }
6111 cancelIntentSenderLocked(rec, true);
6112 }
6113 }
6114
6115 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6116 rec.canceled = true;
6117 mIntentSenderRecords.remove(rec.key);
6118 if (cleanActivity && rec.key.activity != null) {
6119 rec.key.activity.pendingResults.remove(rec.ref);
6120 }
6121 }
6122
6123 public String getPackageForIntentSender(IIntentSender pendingResult) {
6124 if (!(pendingResult instanceof PendingIntentRecord)) {
6125 return null;
6126 }
6127 synchronized(this) {
6128 try {
6129 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6130 return res.key.packageName;
6131 } catch (ClassCastException e) {
6132 }
6133 }
6134 return null;
6135 }
6136
6137 public void setProcessLimit(int max) {
6138 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6139 "setProcessLimit()");
6140 mProcessLimit = max;
6141 }
6142
6143 public int getProcessLimit() {
6144 return mProcessLimit;
6145 }
6146
6147 void foregroundTokenDied(ForegroundToken token) {
6148 synchronized (ActivityManagerService.this) {
6149 synchronized (mPidsSelfLocked) {
6150 ForegroundToken cur
6151 = mForegroundProcesses.get(token.pid);
6152 if (cur != token) {
6153 return;
6154 }
6155 mForegroundProcesses.remove(token.pid);
6156 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6157 if (pr == null) {
6158 return;
6159 }
6160 pr.forcingToForeground = null;
6161 pr.foregroundServices = false;
6162 }
6163 updateOomAdjLocked();
6164 }
6165 }
6166
6167 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6168 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6169 "setProcessForeground()");
6170 synchronized(this) {
6171 boolean changed = false;
6172
6173 synchronized (mPidsSelfLocked) {
6174 ProcessRecord pr = mPidsSelfLocked.get(pid);
6175 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006176 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 return;
6178 }
6179 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6180 if (oldToken != null) {
6181 oldToken.token.unlinkToDeath(oldToken, 0);
6182 mForegroundProcesses.remove(pid);
6183 pr.forcingToForeground = null;
6184 changed = true;
6185 }
6186 if (isForeground && token != null) {
6187 ForegroundToken newToken = new ForegroundToken() {
6188 public void binderDied() {
6189 foregroundTokenDied(this);
6190 }
6191 };
6192 newToken.pid = pid;
6193 newToken.token = token;
6194 try {
6195 token.linkToDeath(newToken, 0);
6196 mForegroundProcesses.put(pid, newToken);
6197 pr.forcingToForeground = token;
6198 changed = true;
6199 } catch (RemoteException e) {
6200 // If the process died while doing this, we will later
6201 // do the cleanup with the process death link.
6202 }
6203 }
6204 }
6205
6206 if (changed) {
6207 updateOomAdjLocked();
6208 }
6209 }
6210 }
6211
6212 // =========================================================
6213 // PERMISSIONS
6214 // =========================================================
6215
6216 static class PermissionController extends IPermissionController.Stub {
6217 ActivityManagerService mActivityManagerService;
6218 PermissionController(ActivityManagerService activityManagerService) {
6219 mActivityManagerService = activityManagerService;
6220 }
6221
6222 public boolean checkPermission(String permission, int pid, int uid) {
6223 return mActivityManagerService.checkPermission(permission, pid,
6224 uid) == PackageManager.PERMISSION_GRANTED;
6225 }
6226 }
6227
6228 /**
6229 * This can be called with or without the global lock held.
6230 */
6231 int checkComponentPermission(String permission, int pid, int uid,
6232 int reqUid) {
6233 // We might be performing an operation on behalf of an indirect binder
6234 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6235 // client identity accordingly before proceeding.
6236 Identity tlsIdentity = sCallerIdentity.get();
6237 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006238 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006239 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6240 uid = tlsIdentity.uid;
6241 pid = tlsIdentity.pid;
6242 }
6243
6244 // Root, system server and our own process get to do everything.
6245 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6246 !Process.supportsProcesses()) {
6247 return PackageManager.PERMISSION_GRANTED;
6248 }
6249 // If the target requires a specific UID, always fail for others.
6250 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006251 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006252 return PackageManager.PERMISSION_DENIED;
6253 }
6254 if (permission == null) {
6255 return PackageManager.PERMISSION_GRANTED;
6256 }
6257 try {
6258 return ActivityThread.getPackageManager()
6259 .checkUidPermission(permission, uid);
6260 } catch (RemoteException e) {
6261 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006262 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 }
6264 return PackageManager.PERMISSION_DENIED;
6265 }
6266
6267 /**
6268 * As the only public entry point for permissions checking, this method
6269 * can enforce the semantic that requesting a check on a null global
6270 * permission is automatically denied. (Internally a null permission
6271 * string is used when calling {@link #checkComponentPermission} in cases
6272 * when only uid-based security is needed.)
6273 *
6274 * This can be called with or without the global lock held.
6275 */
6276 public int checkPermission(String permission, int pid, int uid) {
6277 if (permission == null) {
6278 return PackageManager.PERMISSION_DENIED;
6279 }
6280 return checkComponentPermission(permission, pid, uid, -1);
6281 }
6282
6283 /**
6284 * Binder IPC calls go through the public entry point.
6285 * This can be called with or without the global lock held.
6286 */
6287 int checkCallingPermission(String permission) {
6288 return checkPermission(permission,
6289 Binder.getCallingPid(),
6290 Binder.getCallingUid());
6291 }
6292
6293 /**
6294 * This can be called with or without the global lock held.
6295 */
6296 void enforceCallingPermission(String permission, String func) {
6297 if (checkCallingPermission(permission)
6298 == PackageManager.PERMISSION_GRANTED) {
6299 return;
6300 }
6301
6302 String msg = "Permission Denial: " + func + " from pid="
6303 + Binder.getCallingPid()
6304 + ", uid=" + Binder.getCallingUid()
6305 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006306 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006307 throw new SecurityException(msg);
6308 }
6309
6310 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6311 ProviderInfo pi, int uid, int modeFlags) {
6312 try {
6313 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6314 if ((pi.readPermission != null) &&
6315 (pm.checkUidPermission(pi.readPermission, uid)
6316 != PackageManager.PERMISSION_GRANTED)) {
6317 return false;
6318 }
6319 }
6320 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6321 if ((pi.writePermission != null) &&
6322 (pm.checkUidPermission(pi.writePermission, uid)
6323 != PackageManager.PERMISSION_GRANTED)) {
6324 return false;
6325 }
6326 }
6327 return true;
6328 } catch (RemoteException e) {
6329 return false;
6330 }
6331 }
6332
6333 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6334 int modeFlags) {
6335 // Root gets to do everything.
6336 if (uid == 0 || !Process.supportsProcesses()) {
6337 return true;
6338 }
6339 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6340 if (perms == null) return false;
6341 UriPermission perm = perms.get(uri);
6342 if (perm == null) return false;
6343 return (modeFlags&perm.modeFlags) == modeFlags;
6344 }
6345
6346 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6347 // Another redirected-binder-call permissions check as in
6348 // {@link checkComponentPermission}.
6349 Identity tlsIdentity = sCallerIdentity.get();
6350 if (tlsIdentity != null) {
6351 uid = tlsIdentity.uid;
6352 pid = tlsIdentity.pid;
6353 }
6354
6355 // Our own process gets to do everything.
6356 if (pid == MY_PID) {
6357 return PackageManager.PERMISSION_GRANTED;
6358 }
6359 synchronized(this) {
6360 return checkUriPermissionLocked(uri, uid, modeFlags)
6361 ? PackageManager.PERMISSION_GRANTED
6362 : PackageManager.PERMISSION_DENIED;
6363 }
6364 }
6365
6366 private void grantUriPermissionLocked(int callingUid,
6367 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6368 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6369 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6370 if (modeFlags == 0) {
6371 return;
6372 }
6373
Joe Onorato8a9b2202010-02-26 18:56:32 -08006374 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006375 "Requested grant " + targetPkg + " permission to " + uri);
6376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 final IPackageManager pm = ActivityThread.getPackageManager();
6378
6379 // If this is not a content: uri, we can't do anything with it.
6380 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006381 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006382 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 return;
6384 }
6385
6386 String name = uri.getAuthority();
6387 ProviderInfo pi = null;
6388 ContentProviderRecord cpr
6389 = (ContentProviderRecord)mProvidersByName.get(name);
6390 if (cpr != null) {
6391 pi = cpr.info;
6392 } else {
6393 try {
6394 pi = pm.resolveContentProvider(name,
6395 PackageManager.GET_URI_PERMISSION_PATTERNS);
6396 } catch (RemoteException ex) {
6397 }
6398 }
6399 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006400 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 return;
6402 }
6403
6404 int targetUid;
6405 try {
6406 targetUid = pm.getPackageUid(targetPkg);
6407 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006408 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006409 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 return;
6411 }
6412 } catch (RemoteException ex) {
6413 return;
6414 }
6415
6416 // First... does the target actually need this permission?
6417 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6418 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006419 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006420 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 return;
6422 }
6423
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006424 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006425 if (!pi.grantUriPermissions) {
6426 throw new SecurityException("Provider " + pi.packageName
6427 + "/" + pi.name
6428 + " does not allow granting of Uri permissions (uri "
6429 + uri + ")");
6430 }
6431 if (pi.uriPermissionPatterns != null) {
6432 final int N = pi.uriPermissionPatterns.length;
6433 boolean allowed = false;
6434 for (int i=0; i<N; i++) {
6435 if (pi.uriPermissionPatterns[i] != null
6436 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6437 allowed = true;
6438 break;
6439 }
6440 }
6441 if (!allowed) {
6442 throw new SecurityException("Provider " + pi.packageName
6443 + "/" + pi.name
6444 + " does not allow granting of permission to path of Uri "
6445 + uri);
6446 }
6447 }
6448
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006449 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006450 // this uri?
6451 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6452 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6453 throw new SecurityException("Uid " + callingUid
6454 + " does not have permission to uri " + uri);
6455 }
6456 }
6457
6458 // Okay! So here we are: the caller has the assumed permission
6459 // to the uri, and the target doesn't. Let's now give this to
6460 // the target.
6461
Joe Onorato8a9b2202010-02-26 18:56:32 -08006462 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006463 "Granting " + targetPkg + " permission to " + uri);
6464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 HashMap<Uri, UriPermission> targetUris
6466 = mGrantedUriPermissions.get(targetUid);
6467 if (targetUris == null) {
6468 targetUris = new HashMap<Uri, UriPermission>();
6469 mGrantedUriPermissions.put(targetUid, targetUris);
6470 }
6471
6472 UriPermission perm = targetUris.get(uri);
6473 if (perm == null) {
6474 perm = new UriPermission(targetUid, uri);
6475 targetUris.put(uri, perm);
6476
6477 }
6478 perm.modeFlags |= modeFlags;
6479 if (activity == null) {
6480 perm.globalModeFlags |= modeFlags;
6481 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6482 perm.readActivities.add(activity);
6483 if (activity.readUriPermissions == null) {
6484 activity.readUriPermissions = new HashSet<UriPermission>();
6485 }
6486 activity.readUriPermissions.add(perm);
6487 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6488 perm.writeActivities.add(activity);
6489 if (activity.writeUriPermissions == null) {
6490 activity.writeUriPermissions = new HashSet<UriPermission>();
6491 }
6492 activity.writeUriPermissions.add(perm);
6493 }
6494 }
6495
6496 private void grantUriPermissionFromIntentLocked(int callingUid,
6497 String targetPkg, Intent intent, HistoryRecord activity) {
6498 if (intent == null) {
6499 return;
6500 }
6501 Uri data = intent.getData();
6502 if (data == null) {
6503 return;
6504 }
6505 grantUriPermissionLocked(callingUid, targetPkg, data,
6506 intent.getFlags(), activity);
6507 }
6508
6509 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6510 Uri uri, int modeFlags) {
6511 synchronized(this) {
6512 final ProcessRecord r = getRecordForAppLocked(caller);
6513 if (r == null) {
6514 throw new SecurityException("Unable to find app for caller "
6515 + caller
6516 + " when granting permission to uri " + uri);
6517 }
6518 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006519 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 return;
6521 }
6522 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006523 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 return;
6525 }
6526
6527 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6528 null);
6529 }
6530 }
6531
6532 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6533 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6534 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6535 HashMap<Uri, UriPermission> perms
6536 = mGrantedUriPermissions.get(perm.uid);
6537 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006538 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006539 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 perms.remove(perm.uri);
6541 if (perms.size() == 0) {
6542 mGrantedUriPermissions.remove(perm.uid);
6543 }
6544 }
6545 }
6546 }
6547
6548 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6549 if (activity.readUriPermissions != null) {
6550 for (UriPermission perm : activity.readUriPermissions) {
6551 perm.readActivities.remove(activity);
6552 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6553 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6554 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6555 removeUriPermissionIfNeededLocked(perm);
6556 }
6557 }
6558 }
6559 if (activity.writeUriPermissions != null) {
6560 for (UriPermission perm : activity.writeUriPermissions) {
6561 perm.writeActivities.remove(activity);
6562 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6563 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6564 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6565 removeUriPermissionIfNeededLocked(perm);
6566 }
6567 }
6568 }
6569 }
6570
6571 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6572 int modeFlags) {
6573 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6574 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6575 if (modeFlags == 0) {
6576 return;
6577 }
6578
Joe Onorato8a9b2202010-02-26 18:56:32 -08006579 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006580 "Revoking all granted permissions to " + uri);
6581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 final IPackageManager pm = ActivityThread.getPackageManager();
6583
6584 final String authority = uri.getAuthority();
6585 ProviderInfo pi = null;
6586 ContentProviderRecord cpr
6587 = (ContentProviderRecord)mProvidersByName.get(authority);
6588 if (cpr != null) {
6589 pi = cpr.info;
6590 } else {
6591 try {
6592 pi = pm.resolveContentProvider(authority,
6593 PackageManager.GET_URI_PERMISSION_PATTERNS);
6594 } catch (RemoteException ex) {
6595 }
6596 }
6597 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006598 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 return;
6600 }
6601
6602 // Does the caller have this permission on the URI?
6603 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6604 // Right now, if you are not the original owner of the permission,
6605 // you are not allowed to revoke it.
6606 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6607 throw new SecurityException("Uid " + callingUid
6608 + " does not have permission to uri " + uri);
6609 //}
6610 }
6611
6612 // Go through all of the permissions and remove any that match.
6613 final List<String> SEGMENTS = uri.getPathSegments();
6614 if (SEGMENTS != null) {
6615 final int NS = SEGMENTS.size();
6616 int N = mGrantedUriPermissions.size();
6617 for (int i=0; i<N; i++) {
6618 HashMap<Uri, UriPermission> perms
6619 = mGrantedUriPermissions.valueAt(i);
6620 Iterator<UriPermission> it = perms.values().iterator();
6621 toploop:
6622 while (it.hasNext()) {
6623 UriPermission perm = it.next();
6624 Uri targetUri = perm.uri;
6625 if (!authority.equals(targetUri.getAuthority())) {
6626 continue;
6627 }
6628 List<String> targetSegments = targetUri.getPathSegments();
6629 if (targetSegments == null) {
6630 continue;
6631 }
6632 if (targetSegments.size() < NS) {
6633 continue;
6634 }
6635 for (int j=0; j<NS; j++) {
6636 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6637 continue toploop;
6638 }
6639 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006640 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006641 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006642 perm.clearModes(modeFlags);
6643 if (perm.modeFlags == 0) {
6644 it.remove();
6645 }
6646 }
6647 if (perms.size() == 0) {
6648 mGrantedUriPermissions.remove(
6649 mGrantedUriPermissions.keyAt(i));
6650 N--;
6651 i--;
6652 }
6653 }
6654 }
6655 }
6656
6657 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6658 int modeFlags) {
6659 synchronized(this) {
6660 final ProcessRecord r = getRecordForAppLocked(caller);
6661 if (r == null) {
6662 throw new SecurityException("Unable to find app for caller "
6663 + caller
6664 + " when revoking permission to uri " + uri);
6665 }
6666 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006667 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 return;
6669 }
6670
6671 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6672 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6673 if (modeFlags == 0) {
6674 return;
6675 }
6676
6677 final IPackageManager pm = ActivityThread.getPackageManager();
6678
6679 final String authority = uri.getAuthority();
6680 ProviderInfo pi = null;
6681 ContentProviderRecord cpr
6682 = (ContentProviderRecord)mProvidersByName.get(authority);
6683 if (cpr != null) {
6684 pi = cpr.info;
6685 } else {
6686 try {
6687 pi = pm.resolveContentProvider(authority,
6688 PackageManager.GET_URI_PERMISSION_PATTERNS);
6689 } catch (RemoteException ex) {
6690 }
6691 }
6692 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006693 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006694 return;
6695 }
6696
6697 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6698 }
6699 }
6700
6701 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6702 synchronized (this) {
6703 ProcessRecord app =
6704 who != null ? getRecordForAppLocked(who) : null;
6705 if (app == null) return;
6706
6707 Message msg = Message.obtain();
6708 msg.what = WAIT_FOR_DEBUGGER_MSG;
6709 msg.obj = app;
6710 msg.arg1 = waiting ? 1 : 0;
6711 mHandler.sendMessage(msg);
6712 }
6713 }
6714
6715 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6716 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006717 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006718 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006719 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 }
6721
6722 // =========================================================
6723 // TASK MANAGEMENT
6724 // =========================================================
6725
6726 public List getTasks(int maxNum, int flags,
6727 IThumbnailReceiver receiver) {
6728 ArrayList list = new ArrayList();
6729
6730 PendingThumbnailsRecord pending = null;
6731 IApplicationThread topThumbnail = null;
6732 HistoryRecord topRecord = null;
6733
6734 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006735 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6737 + ", receiver=" + receiver);
6738
6739 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6740 != PackageManager.PERMISSION_GRANTED) {
6741 if (receiver != null) {
6742 // If the caller wants to wait for pending thumbnails,
6743 // it ain't gonna get them.
6744 try {
6745 receiver.finished();
6746 } catch (RemoteException ex) {
6747 }
6748 }
6749 String msg = "Permission Denial: getTasks() from pid="
6750 + Binder.getCallingPid()
6751 + ", uid=" + Binder.getCallingUid()
6752 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006753 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 throw new SecurityException(msg);
6755 }
6756
6757 int pos = mHistory.size()-1;
6758 HistoryRecord next =
6759 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6760 HistoryRecord top = null;
6761 CharSequence topDescription = null;
6762 TaskRecord curTask = null;
6763 int numActivities = 0;
6764 int numRunning = 0;
6765 while (pos >= 0 && maxNum > 0) {
6766 final HistoryRecord r = next;
6767 pos--;
6768 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6769
6770 // Initialize state for next task if needed.
6771 if (top == null ||
6772 (top.state == ActivityState.INITIALIZING
6773 && top.task == r.task)) {
6774 top = r;
6775 topDescription = r.description;
6776 curTask = r.task;
6777 numActivities = numRunning = 0;
6778 }
6779
6780 // Add 'r' into the current task.
6781 numActivities++;
6782 if (r.app != null && r.app.thread != null) {
6783 numRunning++;
6784 }
6785 if (topDescription == null) {
6786 topDescription = r.description;
6787 }
6788
Joe Onorato8a9b2202010-02-26 18:56:32 -08006789 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 TAG, r.intent.getComponent().flattenToShortString()
6791 + ": task=" + r.task);
6792
6793 // If the next one is a different task, generate a new
6794 // TaskInfo entry for what we have.
6795 if (next == null || next.task != curTask) {
6796 ActivityManager.RunningTaskInfo ci
6797 = new ActivityManager.RunningTaskInfo();
6798 ci.id = curTask.taskId;
6799 ci.baseActivity = r.intent.getComponent();
6800 ci.topActivity = top.intent.getComponent();
6801 ci.thumbnail = top.thumbnail;
6802 ci.description = topDescription;
6803 ci.numActivities = numActivities;
6804 ci.numRunning = numRunning;
6805 //System.out.println(
6806 // "#" + maxNum + ": " + " descr=" + ci.description);
6807 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006808 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 TAG, "State=" + top.state + "Idle=" + top.idle
6810 + " app=" + top.app
6811 + " thr=" + (top.app != null ? top.app.thread : null));
6812 if (top.state == ActivityState.RESUMED
6813 || top.state == ActivityState.PAUSING) {
6814 if (top.idle && top.app != null
6815 && top.app.thread != null) {
6816 topRecord = top;
6817 topThumbnail = top.app.thread;
6818 } else {
6819 top.thumbnailNeeded = true;
6820 }
6821 }
6822 if (pending == null) {
6823 pending = new PendingThumbnailsRecord(receiver);
6824 }
6825 pending.pendingRecords.add(top);
6826 }
6827 list.add(ci);
6828 maxNum--;
6829 top = null;
6830 }
6831 }
6832
6833 if (pending != null) {
6834 mPendingThumbnails.add(pending);
6835 }
6836 }
6837
Joe Onorato8a9b2202010-02-26 18:56:32 -08006838 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839
6840 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006841 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 try {
6843 topThumbnail.requestThumbnail(topRecord);
6844 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006845 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006846 sendPendingThumbnail(null, topRecord, null, null, true);
6847 }
6848 }
6849
6850 if (pending == null && receiver != null) {
6851 // In this case all thumbnails were available and the client
6852 // is being asked to be told when the remaining ones come in...
6853 // which is unusually, since the top-most currently running
6854 // activity should never have a canned thumbnail! Oh well.
6855 try {
6856 receiver.finished();
6857 } catch (RemoteException ex) {
6858 }
6859 }
6860
6861 return list;
6862 }
6863
6864 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6865 int flags) {
6866 synchronized (this) {
6867 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6868 "getRecentTasks()");
6869
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006870 IPackageManager pm = ActivityThread.getPackageManager();
6871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 final int N = mRecentTasks.size();
6873 ArrayList<ActivityManager.RecentTaskInfo> res
6874 = new ArrayList<ActivityManager.RecentTaskInfo>(
6875 maxNum < N ? maxNum : N);
6876 for (int i=0; i<N && maxNum > 0; i++) {
6877 TaskRecord tr = mRecentTasks.get(i);
6878 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6879 || (tr.intent == null)
6880 || ((tr.intent.getFlags()
6881 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6882 ActivityManager.RecentTaskInfo rti
6883 = new ActivityManager.RecentTaskInfo();
6884 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6885 rti.baseIntent = new Intent(
6886 tr.intent != null ? tr.intent : tr.affinityIntent);
6887 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006888
6889 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6890 // Check whether this activity is currently available.
6891 try {
6892 if (rti.origActivity != null) {
6893 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6894 continue;
6895 }
6896 } else if (rti.baseIntent != null) {
6897 if (pm.queryIntentActivities(rti.baseIntent,
6898 null, 0) == null) {
6899 continue;
6900 }
6901 }
6902 } catch (RemoteException e) {
6903 // Will never happen.
6904 }
6905 }
6906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 res.add(rti);
6908 maxNum--;
6909 }
6910 }
6911 return res;
6912 }
6913 }
6914
6915 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6916 int j;
6917 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6918 TaskRecord jt = startTask;
6919
6920 // First look backwards
6921 for (j=startIndex-1; j>=0; j--) {
6922 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6923 if (r.task != jt) {
6924 jt = r.task;
6925 if (affinity.equals(jt.affinity)) {
6926 return j;
6927 }
6928 }
6929 }
6930
6931 // Now look forwards
6932 final int N = mHistory.size();
6933 jt = startTask;
6934 for (j=startIndex+1; j<N; j++) {
6935 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6936 if (r.task != jt) {
6937 if (affinity.equals(jt.affinity)) {
6938 return j;
6939 }
6940 jt = r.task;
6941 }
6942 }
6943
6944 // Might it be at the top?
6945 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6946 return N-1;
6947 }
6948
6949 return -1;
6950 }
6951
6952 /**
6953 * Perform a reset of the given task, if needed as part of launching it.
6954 * Returns the new HistoryRecord at the top of the task.
6955 */
6956 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6957 HistoryRecord newActivity) {
6958 boolean forceReset = (newActivity.info.flags
6959 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6960 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6961 if ((newActivity.info.flags
6962 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6963 forceReset = true;
6964 }
6965 }
6966
6967 final TaskRecord task = taskTop.task;
6968
6969 // We are going to move through the history list so that we can look
6970 // at each activity 'target' with 'below' either the interesting
6971 // activity immediately below it in the stack or null.
6972 HistoryRecord target = null;
6973 int targetI = 0;
6974 int taskTopI = -1;
6975 int replyChainEnd = -1;
6976 int lastReparentPos = -1;
6977 for (int i=mHistory.size()-1; i>=-1; i--) {
6978 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6979
6980 if (below != null && below.finishing) {
6981 continue;
6982 }
6983 if (target == null) {
6984 target = below;
6985 targetI = i;
6986 // If we were in the middle of a reply chain before this
6987 // task, it doesn't appear like the root of the chain wants
6988 // anything interesting, so drop it.
6989 replyChainEnd = -1;
6990 continue;
6991 }
6992
6993 final int flags = target.info.flags;
6994
6995 final boolean finishOnTaskLaunch =
6996 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6997 final boolean allowTaskReparenting =
6998 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6999
7000 if (target.task == task) {
7001 // We are inside of the task being reset... we'll either
7002 // finish this activity, push it out for another task,
7003 // or leave it as-is. We only do this
7004 // for activities that are not the root of the task (since
7005 // if we finish the root, we may no longer have the task!).
7006 if (taskTopI < 0) {
7007 taskTopI = targetI;
7008 }
7009 if (below != null && below.task == task) {
7010 final boolean clearWhenTaskReset =
7011 (target.intent.getFlags()
7012 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007013 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 // If this activity is sending a reply to a previous
7015 // activity, we can't do anything with it now until
7016 // we reach the start of the reply chain.
7017 // XXX note that we are assuming the result is always
7018 // to the previous activity, which is almost always
7019 // the case but we really shouldn't count on.
7020 if (replyChainEnd < 0) {
7021 replyChainEnd = targetI;
7022 }
Ed Heyl73798232009-03-24 21:32:21 -07007023 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 && target.taskAffinity != null
7025 && !target.taskAffinity.equals(task.affinity)) {
7026 // If this activity has an affinity for another
7027 // task, then we need to move it out of here. We will
7028 // move it as far out of the way as possible, to the
7029 // bottom of the activity stack. This also keeps it
7030 // correctly ordered with any activities we previously
7031 // moved.
7032 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7033 if (target.taskAffinity != null
7034 && target.taskAffinity.equals(p.task.affinity)) {
7035 // If the activity currently at the bottom has the
7036 // same task affinity as the one we are moving,
7037 // then merge it into the same task.
7038 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007039 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007040 + " out to bottom task " + p.task);
7041 } else {
7042 mCurTask++;
7043 if (mCurTask <= 0) {
7044 mCurTask = 1;
7045 }
7046 target.task = new TaskRecord(mCurTask, target.info, null,
7047 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7048 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007049 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007050 + " out to new task " + target.task);
7051 }
7052 mWindowManager.setAppGroupId(target, task.taskId);
7053 if (replyChainEnd < 0) {
7054 replyChainEnd = targetI;
7055 }
7056 int dstPos = 0;
7057 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7058 p = (HistoryRecord)mHistory.get(srcPos);
7059 if (p.finishing) {
7060 continue;
7061 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007062 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063 + " out to target's task " + target.task);
7064 task.numActivities--;
7065 p.task = target.task;
7066 target.task.numActivities++;
7067 mHistory.remove(srcPos);
7068 mHistory.add(dstPos, p);
7069 mWindowManager.moveAppToken(dstPos, p);
7070 mWindowManager.setAppGroupId(p, p.task.taskId);
7071 dstPos++;
7072 if (VALIDATE_TOKENS) {
7073 mWindowManager.validateAppTokens(mHistory);
7074 }
7075 i++;
7076 }
7077 if (taskTop == p) {
7078 taskTop = below;
7079 }
7080 if (taskTopI == replyChainEnd) {
7081 taskTopI = -1;
7082 }
7083 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007084 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 } else if (forceReset || finishOnTaskLaunch
7086 || clearWhenTaskReset) {
7087 // If the activity should just be removed -- either
7088 // because it asks for it, or the task should be
7089 // cleared -- then finish it and anything that is
7090 // part of its reply chain.
7091 if (clearWhenTaskReset) {
7092 // In this case, we want to finish this activity
7093 // and everything above it, so be sneaky and pretend
7094 // like these are all in the reply chain.
7095 replyChainEnd = targetI+1;
7096 while (replyChainEnd < mHistory.size() &&
7097 ((HistoryRecord)mHistory.get(
7098 replyChainEnd)).task == task) {
7099 replyChainEnd++;
7100 }
7101 replyChainEnd--;
7102 } else if (replyChainEnd < 0) {
7103 replyChainEnd = targetI;
7104 }
7105 HistoryRecord p = null;
7106 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7107 p = (HistoryRecord)mHistory.get(srcPos);
7108 if (p.finishing) {
7109 continue;
7110 }
7111 if (finishActivityLocked(p, srcPos,
7112 Activity.RESULT_CANCELED, null, "reset")) {
7113 replyChainEnd--;
7114 srcPos--;
7115 }
7116 }
7117 if (taskTop == p) {
7118 taskTop = below;
7119 }
7120 if (taskTopI == replyChainEnd) {
7121 taskTopI = -1;
7122 }
7123 replyChainEnd = -1;
7124 } else {
7125 // If we were in the middle of a chain, well the
7126 // activity that started it all doesn't want anything
7127 // special, so leave it all as-is.
7128 replyChainEnd = -1;
7129 }
7130 } else {
7131 // Reached the bottom of the task -- any reply chain
7132 // should be left as-is.
7133 replyChainEnd = -1;
7134 }
7135
7136 } else if (target.resultTo != null) {
7137 // If this activity is sending a reply to a previous
7138 // activity, we can't do anything with it now until
7139 // we reach the start of the reply chain.
7140 // XXX note that we are assuming the result is always
7141 // to the previous activity, which is almost always
7142 // the case but we really shouldn't count on.
7143 if (replyChainEnd < 0) {
7144 replyChainEnd = targetI;
7145 }
7146
7147 } else if (taskTopI >= 0 && allowTaskReparenting
7148 && task.affinity != null
7149 && task.affinity.equals(target.taskAffinity)) {
7150 // We are inside of another task... if this activity has
7151 // an affinity for our task, then either remove it if we are
7152 // clearing or move it over to our task. Note that
7153 // we currently punt on the case where we are resetting a
7154 // task that is not at the top but who has activities above
7155 // with an affinity to it... this is really not a normal
7156 // case, and we will need to later pull that task to the front
7157 // and usually at that point we will do the reset and pick
7158 // up those remaining activities. (This only happens if
7159 // someone starts an activity in a new task from an activity
7160 // in a task that is not currently on top.)
7161 if (forceReset || finishOnTaskLaunch) {
7162 if (replyChainEnd < 0) {
7163 replyChainEnd = targetI;
7164 }
7165 HistoryRecord p = null;
7166 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7167 p = (HistoryRecord)mHistory.get(srcPos);
7168 if (p.finishing) {
7169 continue;
7170 }
7171 if (finishActivityLocked(p, srcPos,
7172 Activity.RESULT_CANCELED, null, "reset")) {
7173 taskTopI--;
7174 lastReparentPos--;
7175 replyChainEnd--;
7176 srcPos--;
7177 }
7178 }
7179 replyChainEnd = -1;
7180 } else {
7181 if (replyChainEnd < 0) {
7182 replyChainEnd = targetI;
7183 }
7184 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7185 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7186 if (p.finishing) {
7187 continue;
7188 }
7189 if (lastReparentPos < 0) {
7190 lastReparentPos = taskTopI;
7191 taskTop = p;
7192 } else {
7193 lastReparentPos--;
7194 }
7195 mHistory.remove(srcPos);
7196 p.task.numActivities--;
7197 p.task = task;
7198 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007199 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 + " in to resetting task " + task);
7201 task.numActivities++;
7202 mWindowManager.moveAppToken(lastReparentPos, p);
7203 mWindowManager.setAppGroupId(p, p.task.taskId);
7204 if (VALIDATE_TOKENS) {
7205 mWindowManager.validateAppTokens(mHistory);
7206 }
7207 }
7208 replyChainEnd = -1;
7209
7210 // Now we've moved it in to place... but what if this is
7211 // a singleTop activity and we have put it on top of another
7212 // instance of the same activity? Then we drop the instance
7213 // below so it remains singleTop.
7214 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7215 for (int j=lastReparentPos-1; j>=0; j--) {
7216 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7217 if (p.finishing) {
7218 continue;
7219 }
7220 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7221 if (finishActivityLocked(p, j,
7222 Activity.RESULT_CANCELED, null, "replace")) {
7223 taskTopI--;
7224 lastReparentPos--;
7225 }
7226 }
7227 }
7228 }
7229 }
7230 }
7231
7232 target = below;
7233 targetI = i;
7234 }
7235
7236 return taskTop;
7237 }
7238
7239 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007240 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 */
7242 public void moveTaskToFront(int task) {
7243 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7244 "moveTaskToFront()");
7245
7246 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007247 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7248 Binder.getCallingUid(), "Task to front")) {
7249 return;
7250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 final long origId = Binder.clearCallingIdentity();
7252 try {
7253 int N = mRecentTasks.size();
7254 for (int i=0; i<N; i++) {
7255 TaskRecord tr = mRecentTasks.get(i);
7256 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007257 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 return;
7259 }
7260 }
7261 for (int i=mHistory.size()-1; i>=0; i--) {
7262 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7263 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007264 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265 return;
7266 }
7267 }
7268 } finally {
7269 Binder.restoreCallingIdentity(origId);
7270 }
7271 }
7272 }
7273
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007274 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007275 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276
7277 final int task = tr.taskId;
7278 int top = mHistory.size()-1;
7279
7280 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7281 // nothing to do!
7282 return;
7283 }
7284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 ArrayList moved = new ArrayList();
7286
7287 // Applying the affinities may have removed entries from the history,
7288 // so get the size again.
7289 top = mHistory.size()-1;
7290 int pos = top;
7291
7292 // Shift all activities with this task up to the top
7293 // of the stack, keeping them in the same internal order.
7294 while (pos >= 0) {
7295 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007296 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7298 boolean first = true;
7299 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007300 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007301 mHistory.remove(pos);
7302 mHistory.add(top, r);
7303 moved.add(0, r);
7304 top--;
7305 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007306 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 first = false;
7308 }
7309 }
7310 pos--;
7311 }
7312
Joe Onorato8a9b2202010-02-26 18:56:32 -08007313 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007314 "Prepare to front transition: task=" + tr);
7315 if (reason != null &&
7316 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7317 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7318 HistoryRecord r = topRunningActivityLocked(null);
7319 if (r != null) {
7320 mNoAnimActivities.add(r);
7321 }
7322 } else {
7323 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7324 }
7325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 mWindowManager.moveAppTokensToTop(moved);
7327 if (VALIDATE_TOKENS) {
7328 mWindowManager.validateAppTokens(mHistory);
7329 }
7330
Josh Bartel7f208742010-02-25 11:01:44 -06007331 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007332 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 }
7334
Josh Bartel7f208742010-02-25 11:01:44 -06007335 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 resumeTopActivityLocked(null);
7337 }
7338
7339 public void moveTaskToBack(int task) {
7340 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7341 "moveTaskToBack()");
7342
7343 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007344 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7345 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7346 Binder.getCallingUid(), "Task to back")) {
7347 return;
7348 }
7349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007351 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 Binder.restoreCallingIdentity(origId);
7353 }
7354 }
7355
7356 /**
7357 * Moves an activity, and all of the other activities within the same task, to the bottom
7358 * of the history stack. The activity's order within the task is unchanged.
7359 *
7360 * @param token A reference to the activity we wish to move
7361 * @param nonRoot If false then this only works if the activity is the root
7362 * of a task; if true it will work for any activity in a task.
7363 * @return Returns true if the move completed, false if not.
7364 */
7365 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7366 synchronized(this) {
7367 final long origId = Binder.clearCallingIdentity();
7368 int taskId = getTaskForActivityLocked(token, !nonRoot);
7369 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007370 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 }
7372 Binder.restoreCallingIdentity(origId);
7373 }
7374 return false;
7375 }
7376
7377 /**
7378 * Worker method for rearranging history stack. Implements the function of moving all
7379 * activities for a specific task (gathering them if disjoint) into a single group at the
7380 * bottom of the stack.
7381 *
7382 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7383 * to premeptively cancel the move.
7384 *
7385 * @param task The taskId to collect and move to the bottom.
7386 * @return Returns true if the move completed, false if not.
7387 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007388 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007389 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390
7391 // If we have a watcher, preflight the move before committing to it. First check
7392 // for *other* available tasks, but if none are available, then try again allowing the
7393 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007394 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395 HistoryRecord next = topRunningActivityLocked(null, task);
7396 if (next == null) {
7397 next = topRunningActivityLocked(null, 0);
7398 }
7399 if (next != null) {
7400 // ask watcher if this is allowed
7401 boolean moveOK = true;
7402 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007403 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007405 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007406 }
7407 if (!moveOK) {
7408 return false;
7409 }
7410 }
7411 }
7412
7413 ArrayList moved = new ArrayList();
7414
Joe Onorato8a9b2202010-02-26 18:56:32 -08007415 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417
7418 final int N = mHistory.size();
7419 int bottom = 0;
7420 int pos = 0;
7421
7422 // Shift all activities with this task down to the bottom
7423 // of the stack, keeping them in the same internal order.
7424 while (pos < N) {
7425 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007426 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7428 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007429 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 mHistory.remove(pos);
7431 mHistory.add(bottom, r);
7432 moved.add(r);
7433 bottom++;
7434 }
7435 pos++;
7436 }
7437
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007438 if (reason != null &&
7439 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7440 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7441 HistoryRecord r = topRunningActivityLocked(null);
7442 if (r != null) {
7443 mNoAnimActivities.add(r);
7444 }
7445 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007446 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 mWindowManager.moveAppTokensToBottom(moved);
7449 if (VALIDATE_TOKENS) {
7450 mWindowManager.validateAppTokens(mHistory);
7451 }
7452
Josh Bartel7f208742010-02-25 11:01:44 -06007453 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 return true;
7455 }
7456
7457 public void moveTaskBackwards(int task) {
7458 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7459 "moveTaskBackwards()");
7460
7461 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007462 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7463 Binder.getCallingUid(), "Task backwards")) {
7464 return;
7465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 final long origId = Binder.clearCallingIdentity();
7467 moveTaskBackwardsLocked(task);
7468 Binder.restoreCallingIdentity(origId);
7469 }
7470 }
7471
7472 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007473 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 }
7475
7476 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7477 synchronized(this) {
7478 return getTaskForActivityLocked(token, onlyRoot);
7479 }
7480 }
7481
7482 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7483 final int N = mHistory.size();
7484 TaskRecord lastTask = null;
7485 for (int i=0; i<N; i++) {
7486 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7487 if (r == token) {
7488 if (!onlyRoot || lastTask != r.task) {
7489 return r.task.taskId;
7490 }
7491 return -1;
7492 }
7493 lastTask = r.task;
7494 }
7495
7496 return -1;
7497 }
7498
7499 /**
7500 * Returns the top activity in any existing task matching the given
7501 * Intent. Returns null if no such task is found.
7502 */
7503 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7504 ComponentName cls = intent.getComponent();
7505 if (info.targetActivity != null) {
7506 cls = new ComponentName(info.packageName, info.targetActivity);
7507 }
7508
7509 TaskRecord cp = null;
7510
7511 final int N = mHistory.size();
7512 for (int i=(N-1); i>=0; i--) {
7513 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7514 if (!r.finishing && r.task != cp
7515 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7516 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007517 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 // + "/aff=" + r.task.affinity + " to new cls="
7519 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7520 if (r.task.affinity != null) {
7521 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007522 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 return r;
7524 }
7525 } else if (r.task.intent != null
7526 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007527 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007529 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007530 return r;
7531 } else if (r.task.affinityIntent != null
7532 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007533 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007535 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536 return r;
7537 }
7538 }
7539 }
7540
7541 return null;
7542 }
7543
7544 /**
7545 * Returns the first activity (starting from the top of the stack) that
7546 * is the same as the given activity. Returns null if no such activity
7547 * is found.
7548 */
7549 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7550 ComponentName cls = intent.getComponent();
7551 if (info.targetActivity != null) {
7552 cls = new ComponentName(info.packageName, info.targetActivity);
7553 }
7554
7555 final int N = mHistory.size();
7556 for (int i=(N-1); i>=0; i--) {
7557 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7558 if (!r.finishing) {
7559 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007560 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007562 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 return r;
7564 }
7565 }
7566 }
7567
7568 return null;
7569 }
7570
7571 public void finishOtherInstances(IBinder token, ComponentName className) {
7572 synchronized(this) {
7573 final long origId = Binder.clearCallingIdentity();
7574
7575 int N = mHistory.size();
7576 TaskRecord lastTask = null;
7577 for (int i=0; i<N; i++) {
7578 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7579 if (r.realActivity.equals(className)
7580 && r != token && lastTask != r.task) {
7581 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7582 null, "others")) {
7583 i--;
7584 N--;
7585 }
7586 }
7587 lastTask = r.task;
7588 }
7589
7590 Binder.restoreCallingIdentity(origId);
7591 }
7592 }
7593
7594 // =========================================================
7595 // THUMBNAILS
7596 // =========================================================
7597
7598 public void reportThumbnail(IBinder token,
7599 Bitmap thumbnail, CharSequence description) {
7600 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7601 final long origId = Binder.clearCallingIdentity();
7602 sendPendingThumbnail(null, token, thumbnail, description, true);
7603 Binder.restoreCallingIdentity(origId);
7604 }
7605
7606 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7607 Bitmap thumbnail, CharSequence description, boolean always) {
7608 TaskRecord task = null;
7609 ArrayList receivers = null;
7610
7611 //System.out.println("Send pending thumbnail: " + r);
7612
7613 synchronized(this) {
7614 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007615 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007616 if (index < 0) {
7617 return;
7618 }
7619 r = (HistoryRecord)mHistory.get(index);
7620 }
7621 if (thumbnail == null) {
7622 thumbnail = r.thumbnail;
7623 description = r.description;
7624 }
7625 if (thumbnail == null && !always) {
7626 // If there is no thumbnail, and this entry is not actually
7627 // going away, then abort for now and pick up the next
7628 // thumbnail we get.
7629 return;
7630 }
7631 task = r.task;
7632
7633 int N = mPendingThumbnails.size();
7634 int i=0;
7635 while (i<N) {
7636 PendingThumbnailsRecord pr =
7637 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7638 //System.out.println("Looking in " + pr.pendingRecords);
7639 if (pr.pendingRecords.remove(r)) {
7640 if (receivers == null) {
7641 receivers = new ArrayList();
7642 }
7643 receivers.add(pr);
7644 if (pr.pendingRecords.size() == 0) {
7645 pr.finished = true;
7646 mPendingThumbnails.remove(i);
7647 N--;
7648 continue;
7649 }
7650 }
7651 i++;
7652 }
7653 }
7654
7655 if (receivers != null) {
7656 final int N = receivers.size();
7657 for (int i=0; i<N; i++) {
7658 try {
7659 PendingThumbnailsRecord pr =
7660 (PendingThumbnailsRecord)receivers.get(i);
7661 pr.receiver.newThumbnail(
7662 task != null ? task.taskId : -1, thumbnail, description);
7663 if (pr.finished) {
7664 pr.receiver.finished();
7665 }
7666 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007667 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 }
7669 }
7670 }
7671 }
7672
7673 // =========================================================
7674 // CONTENT PROVIDERS
7675 // =========================================================
7676
7677 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7678 List providers = null;
7679 try {
7680 providers = ActivityThread.getPackageManager().
7681 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007682 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 } catch (RemoteException ex) {
7684 }
7685 if (providers != null) {
7686 final int N = providers.size();
7687 for (int i=0; i<N; i++) {
7688 ProviderInfo cpi =
7689 (ProviderInfo)providers.get(i);
7690 ContentProviderRecord cpr =
7691 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7692 if (cpr == null) {
7693 cpr = new ContentProviderRecord(cpi, app.info);
7694 mProvidersByClass.put(cpi.name, cpr);
7695 }
7696 app.pubProviders.put(cpi.name, cpr);
7697 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007698 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 }
7700 }
7701 return providers;
7702 }
7703
7704 private final String checkContentProviderPermissionLocked(
7705 ProviderInfo cpi, ProcessRecord r, int mode) {
7706 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7707 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7708 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7709 cpi.exported ? -1 : cpi.applicationInfo.uid)
7710 == PackageManager.PERMISSION_GRANTED
7711 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7712 return null;
7713 }
7714 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7715 cpi.exported ? -1 : cpi.applicationInfo.uid)
7716 == PackageManager.PERMISSION_GRANTED) {
7717 return null;
7718 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007719
7720 PathPermission[] pps = cpi.pathPermissions;
7721 if (pps != null) {
7722 int i = pps.length;
7723 while (i > 0) {
7724 i--;
7725 PathPermission pp = pps[i];
7726 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7727 cpi.exported ? -1 : cpi.applicationInfo.uid)
7728 == PackageManager.PERMISSION_GRANTED
7729 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7730 return null;
7731 }
7732 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7733 cpi.exported ? -1 : cpi.applicationInfo.uid)
7734 == PackageManager.PERMISSION_GRANTED) {
7735 return null;
7736 }
7737 }
7738 }
7739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 String msg = "Permission Denial: opening provider " + cpi.name
7741 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7742 + ", uid=" + callingUid + ") requires "
7743 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007744 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 return msg;
7746 }
7747
7748 private final ContentProviderHolder getContentProviderImpl(
7749 IApplicationThread caller, String name) {
7750 ContentProviderRecord cpr;
7751 ProviderInfo cpi = null;
7752
7753 synchronized(this) {
7754 ProcessRecord r = null;
7755 if (caller != null) {
7756 r = getRecordForAppLocked(caller);
7757 if (r == null) {
7758 throw new SecurityException(
7759 "Unable to find app for caller " + caller
7760 + " (pid=" + Binder.getCallingPid()
7761 + ") when getting content provider " + name);
7762 }
7763 }
7764
7765 // First check if this content provider has been published...
7766 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7767 if (cpr != null) {
7768 cpi = cpr.info;
7769 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7770 return new ContentProviderHolder(cpi,
7771 cpi.readPermission != null
7772 ? cpi.readPermission : cpi.writePermission);
7773 }
7774
7775 if (r != null && cpr.canRunHere(r)) {
7776 // This provider has been published or is in the process
7777 // of being published... but it is also allowed to run
7778 // in the caller's process, so don't make a connection
7779 // and just let the caller instantiate its own instance.
7780 if (cpr.provider != null) {
7781 // don't give caller the provider object, it needs
7782 // to make its own.
7783 cpr = new ContentProviderRecord(cpr);
7784 }
7785 return cpr;
7786 }
7787
7788 final long origId = Binder.clearCallingIdentity();
7789
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007790 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 // return it right away.
7792 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007793 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007794 "Adding provider requested by "
7795 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007796 + cpr.info.processName);
7797 Integer cnt = r.conProviders.get(cpr);
7798 if (cnt == null) {
7799 r.conProviders.put(cpr, new Integer(1));
7800 } else {
7801 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 cpr.clients.add(r);
7804 } else {
7805 cpr.externals++;
7806 }
7807
7808 if (cpr.app != null) {
7809 updateOomAdjLocked(cpr.app);
7810 }
7811
7812 Binder.restoreCallingIdentity(origId);
7813
7814 } else {
7815 try {
7816 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007817 resolveContentProvider(name,
7818 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 } catch (RemoteException ex) {
7820 }
7821 if (cpi == null) {
7822 return null;
7823 }
7824
7825 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7826 return new ContentProviderHolder(cpi,
7827 cpi.readPermission != null
7828 ? cpi.readPermission : cpi.writePermission);
7829 }
7830
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007831 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7832 && !cpi.processName.equals("system")) {
7833 // If this content provider does not run in the system
7834 // process, and the system is not yet ready to run other
7835 // processes, then fail fast instead of hanging.
7836 throw new IllegalArgumentException(
7837 "Attempt to launch content provider before system ready");
7838 }
7839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7841 final boolean firstClass = cpr == null;
7842 if (firstClass) {
7843 try {
7844 ApplicationInfo ai =
7845 ActivityThread.getPackageManager().
7846 getApplicationInfo(
7847 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007848 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007849 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007850 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 + cpi.name);
7852 return null;
7853 }
7854 cpr = new ContentProviderRecord(cpi, ai);
7855 } catch (RemoteException ex) {
7856 // pm is in same process, this will never happen.
7857 }
7858 }
7859
7860 if (r != null && cpr.canRunHere(r)) {
7861 // If this is a multiprocess provider, then just return its
7862 // info and allow the caller to instantiate it. Only do
7863 // this if the provider is the same user as the caller's
7864 // process, or can run as root (so can be in any process).
7865 return cpr;
7866 }
7867
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007868 if (DEBUG_PROVIDER) {
7869 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007870 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007871 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 }
7873
7874 // This is single process, and our app is now connecting to it.
7875 // See if we are already in the process of launching this
7876 // provider.
7877 final int N = mLaunchingProviders.size();
7878 int i;
7879 for (i=0; i<N; i++) {
7880 if (mLaunchingProviders.get(i) == cpr) {
7881 break;
7882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 }
7884
7885 // If the provider is not already being launched, then get it
7886 // started.
7887 if (i >= N) {
7888 final long origId = Binder.clearCallingIdentity();
7889 ProcessRecord proc = startProcessLocked(cpi.processName,
7890 cpr.appInfo, false, 0, "content provider",
7891 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007892 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007894 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 + cpi.applicationInfo.packageName + "/"
7896 + cpi.applicationInfo.uid + " for provider "
7897 + name + ": process is bad");
7898 return null;
7899 }
7900 cpr.launchingApp = proc;
7901 mLaunchingProviders.add(cpr);
7902 Binder.restoreCallingIdentity(origId);
7903 }
7904
7905 // Make sure the provider is published (the same provider class
7906 // may be published under multiple names).
7907 if (firstClass) {
7908 mProvidersByClass.put(cpi.name, cpr);
7909 }
7910 mProvidersByName.put(name, cpr);
7911
7912 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007913 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007914 "Adding provider requested by "
7915 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007916 + cpr.info.processName);
7917 Integer cnt = r.conProviders.get(cpr);
7918 if (cnt == null) {
7919 r.conProviders.put(cpr, new Integer(1));
7920 } else {
7921 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 cpr.clients.add(r);
7924 } else {
7925 cpr.externals++;
7926 }
7927 }
7928 }
7929
7930 // Wait for the provider to be published...
7931 synchronized (cpr) {
7932 while (cpr.provider == null) {
7933 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007934 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 + cpi.applicationInfo.packageName + "/"
7936 + cpi.applicationInfo.uid + " for provider "
7937 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007938 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939 cpi.applicationInfo.packageName,
7940 cpi.applicationInfo.uid, name);
7941 return null;
7942 }
7943 try {
7944 cpr.wait();
7945 } catch (InterruptedException ex) {
7946 }
7947 }
7948 }
7949 return cpr;
7950 }
7951
7952 public final ContentProviderHolder getContentProvider(
7953 IApplicationThread caller, String name) {
7954 if (caller == null) {
7955 String msg = "null IApplicationThread when getting content provider "
7956 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007957 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958 throw new SecurityException(msg);
7959 }
7960
7961 return getContentProviderImpl(caller, name);
7962 }
7963
7964 private ContentProviderHolder getContentProviderExternal(String name) {
7965 return getContentProviderImpl(null, name);
7966 }
7967
7968 /**
7969 * Drop a content provider from a ProcessRecord's bookkeeping
7970 * @param cpr
7971 */
7972 public void removeContentProvider(IApplicationThread caller, String name) {
7973 synchronized (this) {
7974 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7975 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007976 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007977 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007978 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007979 return;
7980 }
7981 final ProcessRecord r = getRecordForAppLocked(caller);
7982 if (r == null) {
7983 throw new SecurityException(
7984 "Unable to find app for caller " + caller +
7985 " when removing content provider " + name);
7986 }
7987 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007988 ContentProviderRecord localCpr = (ContentProviderRecord)
7989 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007990 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007991 + r.info.processName + " from process "
7992 + localCpr.appInfo.processName);
7993 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007995 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007996 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007997 return;
7998 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007999 Integer cnt = r.conProviders.get(localCpr);
8000 if (cnt == null || cnt.intValue() <= 1) {
8001 localCpr.clients.remove(r);
8002 r.conProviders.remove(localCpr);
8003 } else {
8004 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 }
8007 updateOomAdjLocked();
8008 }
8009 }
8010
8011 private void removeContentProviderExternal(String name) {
8012 synchronized (this) {
8013 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8014 if(cpr == null) {
8015 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008016 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008017 return;
8018 }
8019
8020 //update content provider record entry info
8021 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
8022 localCpr.externals--;
8023 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008024 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 }
8026 updateOomAdjLocked();
8027 }
8028 }
8029
8030 public final void publishContentProviders(IApplicationThread caller,
8031 List<ContentProviderHolder> providers) {
8032 if (providers == null) {
8033 return;
8034 }
8035
8036 synchronized(this) {
8037 final ProcessRecord r = getRecordForAppLocked(caller);
8038 if (r == null) {
8039 throw new SecurityException(
8040 "Unable to find app for caller " + caller
8041 + " (pid=" + Binder.getCallingPid()
8042 + ") when publishing content providers");
8043 }
8044
8045 final long origId = Binder.clearCallingIdentity();
8046
8047 final int N = providers.size();
8048 for (int i=0; i<N; i++) {
8049 ContentProviderHolder src = providers.get(i);
8050 if (src == null || src.info == null || src.provider == null) {
8051 continue;
8052 }
8053 ContentProviderRecord dst =
8054 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8055 if (dst != null) {
8056 mProvidersByClass.put(dst.info.name, dst);
8057 String names[] = dst.info.authority.split(";");
8058 for (int j = 0; j < names.length; j++) {
8059 mProvidersByName.put(names[j], dst);
8060 }
8061
8062 int NL = mLaunchingProviders.size();
8063 int j;
8064 for (j=0; j<NL; j++) {
8065 if (mLaunchingProviders.get(j) == dst) {
8066 mLaunchingProviders.remove(j);
8067 j--;
8068 NL--;
8069 }
8070 }
8071 synchronized (dst) {
8072 dst.provider = src.provider;
8073 dst.app = r;
8074 dst.notifyAll();
8075 }
8076 updateOomAdjLocked(r);
8077 }
8078 }
8079
8080 Binder.restoreCallingIdentity(origId);
8081 }
8082 }
8083
8084 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008085 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008086 synchronized (mSelf) {
8087 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8088 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008089 if (providers != null) {
8090 for (int i=providers.size()-1; i>=0; i--) {
8091 ProviderInfo pi = (ProviderInfo)providers.get(i);
8092 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8093 Slog.w(TAG, "Not installing system proc provider " + pi.name
8094 + ": not system .apk");
8095 providers.remove(i);
8096 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008097 }
8098 }
8099 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008100 if (providers != null) {
8101 mSystemThread.installSystemProviders(providers);
8102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 }
8104
8105 // =========================================================
8106 // GLOBAL MANAGEMENT
8107 // =========================================================
8108
8109 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8110 ApplicationInfo info, String customProcess) {
8111 String proc = customProcess != null ? customProcess : info.processName;
8112 BatteryStatsImpl.Uid.Proc ps = null;
8113 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8114 synchronized (stats) {
8115 ps = stats.getProcessStatsLocked(info.uid, proc);
8116 }
8117 return new ProcessRecord(ps, thread, info, proc);
8118 }
8119
8120 final ProcessRecord addAppLocked(ApplicationInfo info) {
8121 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8122
8123 if (app == null) {
8124 app = newProcessRecordLocked(null, info, null);
8125 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008126 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 }
8128
8129 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8130 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8131 app.persistent = true;
8132 app.maxAdj = CORE_SERVER_ADJ;
8133 }
8134 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8135 mPersistentStartingProcesses.add(app);
8136 startProcessLocked(app, "added application", app.processName);
8137 }
8138
8139 return app;
8140 }
8141
8142 public void unhandledBack() {
8143 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8144 "unhandledBack()");
8145
8146 synchronized(this) {
8147 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008148 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 TAG, "Performing unhandledBack(): stack size = " + count);
8150 if (count > 1) {
8151 final long origId = Binder.clearCallingIdentity();
8152 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8153 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8154 Binder.restoreCallingIdentity(origId);
8155 }
8156 }
8157 }
8158
8159 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8160 String name = uri.getAuthority();
8161 ContentProviderHolder cph = getContentProviderExternal(name);
8162 ParcelFileDescriptor pfd = null;
8163 if (cph != null) {
8164 // We record the binder invoker's uid in thread-local storage before
8165 // going to the content provider to open the file. Later, in the code
8166 // that handles all permissions checks, we look for this uid and use
8167 // that rather than the Activity Manager's own uid. The effect is that
8168 // we do the check against the caller's permissions even though it looks
8169 // to the content provider like the Activity Manager itself is making
8170 // the request.
8171 sCallerIdentity.set(new Identity(
8172 Binder.getCallingPid(), Binder.getCallingUid()));
8173 try {
8174 pfd = cph.provider.openFile(uri, "r");
8175 } catch (FileNotFoundException e) {
8176 // do nothing; pfd will be returned null
8177 } finally {
8178 // Ensure that whatever happens, we clean up the identity state
8179 sCallerIdentity.remove();
8180 }
8181
8182 // We've got the fd now, so we're done with the provider.
8183 removeContentProviderExternal(name);
8184 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008185 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 }
8187 return pfd;
8188 }
8189
8190 public void goingToSleep() {
8191 synchronized(this) {
8192 mSleeping = true;
8193 mWindowManager.setEventDispatching(false);
8194
8195 if (mResumedActivity != null) {
8196 pauseIfSleepingLocked();
8197 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008198 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008199 }
8200 }
8201 }
8202
Dianne Hackborn55280a92009-05-07 15:53:46 -07008203 public boolean shutdown(int timeout) {
8204 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8205 != PackageManager.PERMISSION_GRANTED) {
8206 throw new SecurityException("Requires permission "
8207 + android.Manifest.permission.SHUTDOWN);
8208 }
8209
8210 boolean timedout = false;
8211
8212 synchronized(this) {
8213 mShuttingDown = true;
8214 mWindowManager.setEventDispatching(false);
8215
8216 if (mResumedActivity != null) {
8217 pauseIfSleepingLocked();
8218 final long endTime = System.currentTimeMillis() + timeout;
8219 while (mResumedActivity != null || mPausingActivity != null) {
8220 long delay = endTime - System.currentTimeMillis();
8221 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008222 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008223 timedout = true;
8224 break;
8225 }
8226 try {
8227 this.wait();
8228 } catch (InterruptedException e) {
8229 }
8230 }
8231 }
8232 }
8233
8234 mUsageStatsService.shutdown();
8235 mBatteryStatsService.shutdown();
8236
8237 return timedout;
8238 }
8239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008241 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008242 if (!mGoingToSleep.isHeld()) {
8243 mGoingToSleep.acquire();
8244 if (mLaunchingActivity.isHeld()) {
8245 mLaunchingActivity.release();
8246 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8247 }
8248 }
8249
8250 // If we are not currently pausing an activity, get the current
8251 // one to pause. If we are pausing one, we will just let that stuff
8252 // run and release the wake lock when all done.
8253 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008254 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8255 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 startPausingLocked(false, true);
8257 }
8258 }
8259 }
8260
8261 public void wakingUp() {
8262 synchronized(this) {
8263 if (mGoingToSleep.isHeld()) {
8264 mGoingToSleep.release();
8265 }
8266 mWindowManager.setEventDispatching(true);
8267 mSleeping = false;
8268 resumeTopActivityLocked(null);
8269 }
8270 }
8271
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008272 public void stopAppSwitches() {
8273 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8274 != PackageManager.PERMISSION_GRANTED) {
8275 throw new SecurityException("Requires permission "
8276 + android.Manifest.permission.STOP_APP_SWITCHES);
8277 }
8278
8279 synchronized(this) {
8280 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8281 + APP_SWITCH_DELAY_TIME;
8282 mDidAppSwitch = false;
8283 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8284 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8285 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8286 }
8287 }
8288
8289 public void resumeAppSwitches() {
8290 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8291 != PackageManager.PERMISSION_GRANTED) {
8292 throw new SecurityException("Requires permission "
8293 + android.Manifest.permission.STOP_APP_SWITCHES);
8294 }
8295
8296 synchronized(this) {
8297 // Note that we don't execute any pending app switches... we will
8298 // let those wait until either the timeout, or the next start
8299 // activity request.
8300 mAppSwitchesAllowedTime = 0;
8301 }
8302 }
8303
8304 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8305 String name) {
8306 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8307 return true;
8308 }
8309
8310 final int perm = checkComponentPermission(
8311 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8312 callingUid, -1);
8313 if (perm == PackageManager.PERMISSION_GRANTED) {
8314 return true;
8315 }
8316
Joe Onorato8a9b2202010-02-26 18:56:32 -08008317 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008318 return false;
8319 }
8320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 public void setDebugApp(String packageName, boolean waitForDebugger,
8322 boolean persistent) {
8323 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8324 "setDebugApp()");
8325
8326 // Note that this is not really thread safe if there are multiple
8327 // callers into it at the same time, but that's not a situation we
8328 // care about.
8329 if (persistent) {
8330 final ContentResolver resolver = mContext.getContentResolver();
8331 Settings.System.putString(
8332 resolver, Settings.System.DEBUG_APP,
8333 packageName);
8334 Settings.System.putInt(
8335 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8336 waitForDebugger ? 1 : 0);
8337 }
8338
8339 synchronized (this) {
8340 if (!persistent) {
8341 mOrigDebugApp = mDebugApp;
8342 mOrigWaitForDebugger = mWaitForDebugger;
8343 }
8344 mDebugApp = packageName;
8345 mWaitForDebugger = waitForDebugger;
8346 mDebugTransient = !persistent;
8347 if (packageName != null) {
8348 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008349 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 Binder.restoreCallingIdentity(origId);
8351 }
8352 }
8353 }
8354
8355 public void setAlwaysFinish(boolean enabled) {
8356 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8357 "setAlwaysFinish()");
8358
8359 Settings.System.putInt(
8360 mContext.getContentResolver(),
8361 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8362
8363 synchronized (this) {
8364 mAlwaysFinishActivities = enabled;
8365 }
8366 }
8367
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008368 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008370 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008371 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008372 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008373 }
8374 }
8375
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008376 public boolean isUserAMonkey() {
8377 // For now the fact that there is a controller implies
8378 // we have a monkey.
8379 synchronized (this) {
8380 return mController != null;
8381 }
8382 }
8383
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008384 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008385 synchronized (this) {
8386 mWatchers.register(watcher);
8387 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008388 }
8389
8390 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008391 synchronized (this) {
8392 mWatchers.unregister(watcher);
8393 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008394 }
8395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008396 public final void enterSafeMode() {
8397 synchronized(this) {
8398 // It only makes sense to do this before the system is ready
8399 // and started launching other packages.
8400 if (!mSystemReady) {
8401 try {
8402 ActivityThread.getPackageManager().enterSafeMode();
8403 } catch (RemoteException e) {
8404 }
8405
8406 View v = LayoutInflater.from(mContext).inflate(
8407 com.android.internal.R.layout.safe_mode, null);
8408 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8409 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8410 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8411 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8412 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8413 lp.format = v.getBackground().getOpacity();
8414 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8415 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8416 ((WindowManager)mContext.getSystemService(
8417 Context.WINDOW_SERVICE)).addView(v, lp);
8418 }
8419 }
8420 }
8421
8422 public void noteWakeupAlarm(IIntentSender sender) {
8423 if (!(sender instanceof PendingIntentRecord)) {
8424 return;
8425 }
8426 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8427 synchronized (stats) {
8428 if (mBatteryStatsService.isOnBattery()) {
8429 mBatteryStatsService.enforceCallingPermission();
8430 PendingIntentRecord rec = (PendingIntentRecord)sender;
8431 int MY_UID = Binder.getCallingUid();
8432 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8433 BatteryStatsImpl.Uid.Pkg pkg =
8434 stats.getPackageStatsLocked(uid, rec.key.packageName);
8435 pkg.incWakeupsLocked();
8436 }
8437 }
8438 }
8439
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008440 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008441 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008442 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008444 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 // XXX Note: don't acquire main activity lock here, because the window
8446 // manager calls in with its locks held.
8447
8448 boolean killed = false;
8449 synchronized (mPidsSelfLocked) {
8450 int[] types = new int[pids.length];
8451 int worstType = 0;
8452 for (int i=0; i<pids.length; i++) {
8453 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8454 if (proc != null) {
8455 int type = proc.setAdj;
8456 types[i] = type;
8457 if (type > worstType) {
8458 worstType = type;
8459 }
8460 }
8461 }
8462
8463 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8464 // then constrain it so we will kill all hidden procs.
8465 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8466 worstType = HIDDEN_APP_MIN_ADJ;
8467 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008468 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 for (int i=0; i<pids.length; i++) {
8470 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8471 if (proc == null) {
8472 continue;
8473 }
8474 int adj = proc.setAdj;
8475 if (adj >= worstType) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008476 Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008477 + adj + ")");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008478 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8479 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 killed = true;
8481 Process.killProcess(pids[i]);
8482 }
8483 }
8484 }
8485 return killed;
8486 }
8487
8488 public void reportPss(IApplicationThread caller, int pss) {
8489 Watchdog.PssRequestor req;
8490 String name;
8491 ProcessRecord callerApp;
8492 synchronized (this) {
8493 if (caller == null) {
8494 return;
8495 }
8496 callerApp = getRecordForAppLocked(caller);
8497 if (callerApp == null) {
8498 return;
8499 }
8500 callerApp.lastPss = pss;
8501 req = callerApp;
8502 name = callerApp.processName;
8503 }
8504 Watchdog.getInstance().reportPss(req, name, pss);
8505 if (!callerApp.persistent) {
8506 removeRequestedPss(callerApp);
8507 }
8508 }
8509
8510 public void requestPss(Runnable completeCallback) {
8511 ArrayList<ProcessRecord> procs;
8512 synchronized (this) {
8513 mRequestPssCallback = completeCallback;
8514 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008515 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8516 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 if (!proc.persistent) {
8518 mRequestPssList.add(proc);
8519 }
8520 }
8521 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8522 }
8523
8524 int oldPri = Process.getThreadPriority(Process.myTid());
8525 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8526 for (int i=procs.size()-1; i>=0; i--) {
8527 ProcessRecord proc = procs.get(i);
8528 proc.lastPss = 0;
8529 proc.requestPss();
8530 }
8531 Process.setThreadPriority(oldPri);
8532 }
8533
8534 void removeRequestedPss(ProcessRecord proc) {
8535 Runnable callback = null;
8536 synchronized (this) {
8537 if (mRequestPssList.remove(proc)) {
8538 if (mRequestPssList.size() == 0) {
8539 callback = mRequestPssCallback;
8540 mRequestPssCallback = null;
8541 }
8542 }
8543 }
8544
8545 if (callback != null) {
8546 callback.run();
8547 }
8548 }
8549
8550 public void collectPss(Watchdog.PssStats stats) {
8551 stats.mEmptyPss = 0;
8552 stats.mEmptyCount = 0;
8553 stats.mBackgroundPss = 0;
8554 stats.mBackgroundCount = 0;
8555 stats.mServicePss = 0;
8556 stats.mServiceCount = 0;
8557 stats.mVisiblePss = 0;
8558 stats.mVisibleCount = 0;
8559 stats.mForegroundPss = 0;
8560 stats.mForegroundCount = 0;
8561 stats.mNoPssCount = 0;
8562 synchronized (this) {
8563 int i;
8564 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8565 ? mProcDeaths.length : stats.mProcDeaths.length;
8566 int aggr = 0;
8567 for (i=0; i<NPD; i++) {
8568 aggr += mProcDeaths[i];
8569 stats.mProcDeaths[i] = aggr;
8570 }
8571 while (i<stats.mProcDeaths.length) {
8572 stats.mProcDeaths[i] = 0;
8573 i++;
8574 }
8575
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008576 for (i=mLruProcesses.size()-1; i>=0; i--) {
8577 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008578 if (proc.persistent) {
8579 continue;
8580 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008581 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008582 if (proc.lastPss == 0) {
8583 stats.mNoPssCount++;
8584 continue;
8585 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008586 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8587 if (proc.empty) {
8588 stats.mEmptyPss += proc.lastPss;
8589 stats.mEmptyCount++;
8590 } else {
8591 stats.mBackgroundPss += proc.lastPss;
8592 stats.mBackgroundCount++;
8593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8595 stats.mVisiblePss += proc.lastPss;
8596 stats.mVisibleCount++;
8597 } else {
8598 stats.mForegroundPss += proc.lastPss;
8599 stats.mForegroundCount++;
8600 }
8601 }
8602 }
8603 }
8604
8605 public final void startRunning(String pkg, String cls, String action,
8606 String data) {
8607 synchronized(this) {
8608 if (mStartRunning) {
8609 return;
8610 }
8611 mStartRunning = true;
8612 mTopComponent = pkg != null && cls != null
8613 ? new ComponentName(pkg, cls) : null;
8614 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8615 mTopData = data;
8616 if (!mSystemReady) {
8617 return;
8618 }
8619 }
8620
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008621 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008622 }
8623
8624 private void retrieveSettings() {
8625 final ContentResolver resolver = mContext.getContentResolver();
8626 String debugApp = Settings.System.getString(
8627 resolver, Settings.System.DEBUG_APP);
8628 boolean waitForDebugger = Settings.System.getInt(
8629 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8630 boolean alwaysFinishActivities = Settings.System.getInt(
8631 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8632
8633 Configuration configuration = new Configuration();
8634 Settings.System.getConfiguration(resolver, configuration);
8635
8636 synchronized (this) {
8637 mDebugApp = mOrigDebugApp = debugApp;
8638 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8639 mAlwaysFinishActivities = alwaysFinishActivities;
8640 // This happens before any activities are started, so we can
8641 // change mConfiguration in-place.
8642 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008643 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008644 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 }
8646 }
8647
8648 public boolean testIsSystemReady() {
8649 // no need to synchronize(this) just to read & return the value
8650 return mSystemReady;
8651 }
8652
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008653 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654 // In the simulator, startRunning will never have been called, which
8655 // normally sets a few crucial variables. Do it here instead.
8656 if (!Process.supportsProcesses()) {
8657 mStartRunning = true;
8658 mTopAction = Intent.ACTION_MAIN;
8659 }
8660
8661 synchronized(this) {
8662 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008663 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 return;
8665 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008666
8667 // Check to see if there are any update receivers to run.
8668 if (!mDidUpdate) {
8669 if (mWaitingUpdate) {
8670 return;
8671 }
8672 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8673 List<ResolveInfo> ris = null;
8674 try {
8675 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8676 intent, null, 0);
8677 } catch (RemoteException e) {
8678 }
8679 if (ris != null) {
8680 for (int i=ris.size()-1; i>=0; i--) {
8681 if ((ris.get(i).activityInfo.applicationInfo.flags
8682 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8683 ris.remove(i);
8684 }
8685 }
8686 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8687 for (int i=0; i<ris.size(); i++) {
8688 ActivityInfo ai = ris.get(i).activityInfo;
8689 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8690 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008691 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008692 finisher = new IIntentReceiver.Stub() {
8693 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008694 String data, Bundle extras, boolean ordered,
8695 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008696 throws RemoteException {
8697 synchronized (ActivityManagerService.this) {
8698 mDidUpdate = true;
8699 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008700 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008701 }
8702 };
8703 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008704 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008705 broadcastIntentLocked(null, null, intent, null, finisher,
8706 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008707 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008708 mWaitingUpdate = true;
8709 }
8710 }
8711 }
8712 if (mWaitingUpdate) {
8713 return;
8714 }
8715 mDidUpdate = true;
8716 }
8717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 mSystemReady = true;
8719 if (!mStartRunning) {
8720 return;
8721 }
8722 }
8723
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008724 ArrayList<ProcessRecord> procsToKill = null;
8725 synchronized(mPidsSelfLocked) {
8726 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8727 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8728 if (!isAllowedWhileBooting(proc.info)){
8729 if (procsToKill == null) {
8730 procsToKill = new ArrayList<ProcessRecord>();
8731 }
8732 procsToKill.add(proc);
8733 }
8734 }
8735 }
8736
8737 if (procsToKill != null) {
8738 synchronized(this) {
8739 for (int i=procsToKill.size()-1; i>=0; i--) {
8740 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008741 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008742 removeProcessLocked(proc, true);
8743 }
8744 }
8745 }
8746
Joe Onorato8a9b2202010-02-26 18:56:32 -08008747 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008748 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 SystemClock.uptimeMillis());
8750
8751 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008752 // Make sure we have no pre-ready processes sitting around.
8753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8755 ResolveInfo ri = mContext.getPackageManager()
8756 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008757 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008758 CharSequence errorMsg = null;
8759 if (ri != null) {
8760 ActivityInfo ai = ri.activityInfo;
8761 ApplicationInfo app = ai.applicationInfo;
8762 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8763 mTopAction = Intent.ACTION_FACTORY_TEST;
8764 mTopData = null;
8765 mTopComponent = new ComponentName(app.packageName,
8766 ai.name);
8767 } else {
8768 errorMsg = mContext.getResources().getText(
8769 com.android.internal.R.string.factorytest_not_system);
8770 }
8771 } else {
8772 errorMsg = mContext.getResources().getText(
8773 com.android.internal.R.string.factorytest_no_action);
8774 }
8775 if (errorMsg != null) {
8776 mTopAction = null;
8777 mTopData = null;
8778 mTopComponent = null;
8779 Message msg = Message.obtain();
8780 msg.what = SHOW_FACTORY_ERROR_MSG;
8781 msg.getData().putCharSequence("msg", errorMsg);
8782 mHandler.sendMessage(msg);
8783 }
8784 }
8785 }
8786
8787 retrieveSettings();
8788
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008789 if (goingCallback != null) goingCallback.run();
8790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 synchronized (this) {
8792 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8793 try {
8794 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008795 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008796 if (apps != null) {
8797 int N = apps.size();
8798 int i;
8799 for (i=0; i<N; i++) {
8800 ApplicationInfo info
8801 = (ApplicationInfo)apps.get(i);
8802 if (info != null &&
8803 !info.packageName.equals("android")) {
8804 addAppLocked(info);
8805 }
8806 }
8807 }
8808 } catch (RemoteException ex) {
8809 // pm is in same process, this will never happen.
8810 }
8811 }
8812
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008813 // Start up initial activity.
8814 mBooting = true;
8815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 try {
8817 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8818 Message msg = Message.obtain();
8819 msg.what = SHOW_UID_ERROR_MSG;
8820 mHandler.sendMessage(msg);
8821 }
8822 } catch (RemoteException e) {
8823 }
8824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008825 resumeTopActivityLocked(null);
8826 }
8827 }
8828
Dan Egnorb7f03672009-12-09 16:22:32 -08008829 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008830 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008832 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008833 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 startAppProblemLocked(app);
8835 app.stopFreezingAllLocked();
8836 return handleAppCrashLocked(app);
8837 }
8838
Dan Egnorb7f03672009-12-09 16:22:32 -08008839 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008840 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008841 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008842 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008843 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8844 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 startAppProblemLocked(app);
8846 app.stopFreezingAllLocked();
8847 }
8848
8849 /**
8850 * Generate a process error record, suitable for attachment to a ProcessRecord.
8851 *
8852 * @param app The ProcessRecord in which the error occurred.
8853 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8854 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008855 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008856 * @param shortMsg Short message describing the crash.
8857 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008858 * @param stackTrace Full crash stack trace, may be null.
8859 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 * @return Returns a fully-formed AppErrorStateInfo record.
8861 */
8862 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008863 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008866 report.condition = condition;
8867 report.processName = app.processName;
8868 report.pid = app.pid;
8869 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008870 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871 report.shortMsg = shortMsg;
8872 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008873 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008874
8875 return report;
8876 }
8877
Dan Egnor42471dd2010-01-07 17:25:22 -08008878 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 synchronized (this) {
8880 app.crashing = false;
8881 app.crashingReport = null;
8882 app.notResponding = false;
8883 app.notRespondingReport = null;
8884 if (app.anrDialog == fromDialog) {
8885 app.anrDialog = null;
8886 }
8887 if (app.waitDialog == fromDialog) {
8888 app.waitDialog = null;
8889 }
8890 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008891 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008892 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 + app.processName
8894 + " (pid=" + app.pid + ") at user's request");
8895 Process.killProcess(app.pid);
8896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 }
8898 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008899
Dan Egnorb7f03672009-12-09 16:22:32 -08008900 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008901 long now = SystemClock.uptimeMillis();
8902
8903 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8904 app.info.uid);
8905 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8906 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008907 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008908 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008909 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 app.info.processName, app.info.uid);
8911 killServicesLocked(app, false);
8912 for (int i=mHistory.size()-1; i>=0; i--) {
8913 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8914 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008915 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 + r.intent.getComponent().flattenToShortString());
8917 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8918 }
8919 }
8920 if (!app.persistent) {
8921 // We don't want to start this process again until the user
8922 // explicitly does so... but for persistent process, we really
8923 // need to keep it running. If a persistent process is actually
8924 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008925 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 app.info.processName);
8927 mBadProcesses.put(app.info.processName, app.info.uid, now);
8928 app.bad = true;
8929 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8930 app.removed = true;
8931 removeProcessLocked(app, false);
8932 return false;
8933 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008934 } else {
8935 HistoryRecord r = topRunningActivityLocked(null);
8936 if (r.app == app) {
8937 // If the top running activity is from this crashing
8938 // process, then terminate it to avoid getting in a loop.
8939 Slog.w(TAG, " Force finishing activity "
8940 + r.intent.getComponent().flattenToShortString());
8941 int index = indexOfTokenLocked(r);
8942 finishActivityLocked(r, index,
8943 Activity.RESULT_CANCELED, null, "crashed");
8944 // Also terminate an activities below it that aren't yet
8945 // stopped, to avoid a situation where one will get
8946 // re-start our crashing activity once it gets resumed again.
8947 index--;
8948 if (index >= 0) {
8949 r = (HistoryRecord)mHistory.get(index);
8950 if (r.state == ActivityState.RESUMED
8951 || r.state == ActivityState.PAUSING
8952 || r.state == ActivityState.PAUSED) {
8953 if (!r.isHomeActivity) {
8954 Slog.w(TAG, " Force finishing activity "
8955 + r.intent.getComponent().flattenToShortString());
8956 finishActivityLocked(r, index,
8957 Activity.RESULT_CANCELED, null, "crashed");
8958 }
8959 }
8960 }
8961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 }
8963
8964 // Bump up the crash count of any services currently running in the proc.
8965 if (app.services.size() != 0) {
8966 // Any services running in the application need to be placed
8967 // back in the pending list.
8968 Iterator it = app.services.iterator();
8969 while (it.hasNext()) {
8970 ServiceRecord sr = (ServiceRecord)it.next();
8971 sr.crashCount++;
8972 }
8973 }
8974
8975 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8976 return true;
8977 }
8978
8979 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008980 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8981 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 skipCurrentReceiverLocked(app);
8983 }
8984
8985 void skipCurrentReceiverLocked(ProcessRecord app) {
8986 boolean reschedule = false;
8987 BroadcastRecord r = app.curReceiver;
8988 if (r != null) {
8989 // The current broadcast is waiting for this app's receiver
8990 // to be finished. Looks like that's not going to happen, so
8991 // let the broadcast continue.
8992 logBroadcastReceiverDiscard(r);
8993 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8994 r.resultExtras, r.resultAbort, true);
8995 reschedule = true;
8996 }
8997 r = mPendingBroadcast;
8998 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008999 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 "skip & discard pending app " + r);
9001 logBroadcastReceiverDiscard(r);
9002 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9003 r.resultExtras, r.resultAbort, true);
9004 reschedule = true;
9005 }
9006 if (reschedule) {
9007 scheduleBroadcastsLocked();
9008 }
9009 }
9010
Dan Egnor60d87622009-12-16 16:32:58 -08009011 /**
9012 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9013 * The application process will exit immediately after this call returns.
9014 * @param app object of the crashing app, null for the system server
9015 * @param crashInfo describing the exception
9016 */
9017 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9018 ProcessRecord r = findAppProcess(app);
9019
9020 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9021 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009022 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009023 crashInfo.exceptionClassName,
9024 crashInfo.exceptionMessage,
9025 crashInfo.throwFileName,
9026 crashInfo.throwLineNumber);
9027
Dan Egnor42471dd2010-01-07 17:25:22 -08009028 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009029
9030 crashApplication(r, crashInfo);
9031 }
9032
9033 /**
9034 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9035 * @param app object of the crashing app, null for the system server
9036 * @param tag reported by the caller
9037 * @param crashInfo describing the context of the error
9038 * @return true if the process should exit immediately (WTF is fatal)
9039 */
9040 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009041 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009042 ProcessRecord r = findAppProcess(app);
9043
9044 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9045 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009046 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009047 tag, crashInfo.exceptionMessage);
9048
Dan Egnor42471dd2010-01-07 17:25:22 -08009049 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009050
Doug Zongker43866e02010-01-07 12:09:54 -08009051 if (Settings.Secure.getInt(mContext.getContentResolver(),
9052 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009053 crashApplication(r, crashInfo);
9054 return true;
9055 } else {
9056 return false;
9057 }
9058 }
9059
9060 /**
9061 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9062 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9063 */
9064 private ProcessRecord findAppProcess(IBinder app) {
9065 if (app == null) {
9066 return null;
9067 }
9068
9069 synchronized (this) {
9070 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9071 final int NA = apps.size();
9072 for (int ia=0; ia<NA; ia++) {
9073 ProcessRecord p = apps.valueAt(ia);
9074 if (p.thread != null && p.thread.asBinder() == app) {
9075 return p;
9076 }
9077 }
9078 }
9079
Joe Onorato8a9b2202010-02-26 18:56:32 -08009080 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009081 return null;
9082 }
9083 }
9084
9085 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009086 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009087 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009088 * @param process which caused the error, null means the system server
9089 * @param activity which triggered the error, null if unknown
9090 * @param parent activity related to the error, null if unknown
9091 * @param subject line related to the error, null if absent
9092 * @param report in long form describing the error, null if absent
9093 * @param logFile to include in the report, null if none
9094 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009095 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009096 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009097 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9098 final String report, final File logFile,
9099 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009100 // NOTE -- this must never acquire the ActivityManagerService lock,
9101 // otherwise the watchdog may be prevented from resetting the system.
9102
Dan Egnora455d192010-03-12 08:52:28 -08009103 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009104 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009105 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009106 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009107 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009108 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009109 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009110 }
9111
Dan Egnora455d192010-03-12 08:52:28 -08009112 final String dropboxTag = prefix + eventType;
9113 final DropBoxManager dbox = (DropBoxManager)
9114 mContext.getSystemService(Context.DROPBOX_SERVICE);
9115
9116 // Exit early if the dropbox isn't configured to accept this report type.
9117 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9118
9119 final StringBuilder sb = new StringBuilder(1024);
9120 if (process == null || process.pid == MY_PID) {
9121 sb.append("Process: system_server\n");
9122 } else {
9123 sb.append("Process: ").append(process.processName).append("\n");
9124 }
9125 if (process != null) {
9126 int flags = process.info.flags;
9127 IPackageManager pm = ActivityThread.getPackageManager();
9128 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9129 for (String pkg : process.pkgList) {
9130 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009131 try {
Dan Egnora455d192010-03-12 08:52:28 -08009132 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9133 if (pi != null) {
9134 sb.append(" v").append(pi.versionCode);
9135 if (pi.versionName != null) {
9136 sb.append(" (").append(pi.versionName).append(")");
9137 }
9138 }
9139 } catch (RemoteException e) {
9140 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009141 }
Dan Egnora455d192010-03-12 08:52:28 -08009142 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009143 }
Dan Egnora455d192010-03-12 08:52:28 -08009144 }
9145 if (activity != null) {
9146 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9147 }
9148 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9149 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9150 }
9151 if (parent != null && parent != activity) {
9152 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9153 }
9154 if (subject != null) {
9155 sb.append("Subject: ").append(subject).append("\n");
9156 }
9157 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9158 sb.append("\n");
9159
9160 // Do the rest in a worker thread to avoid blocking the caller on I/O
9161 // (After this point, we shouldn't access AMS internal data structures.)
9162 Thread worker = new Thread("Error dump: " + dropboxTag) {
9163 @Override
9164 public void run() {
9165 if (report != null) {
9166 sb.append(report);
9167 }
9168 if (logFile != null) {
9169 try {
9170 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9171 } catch (IOException e) {
9172 Slog.e(TAG, "Error reading " + logFile, e);
9173 }
9174 }
9175 if (crashInfo != null && crashInfo.stackTrace != null) {
9176 sb.append(crashInfo.stackTrace);
9177 }
9178
9179 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9180 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9181 if (lines > 0) {
9182 sb.append("\n");
9183
9184 // Merge several logcat streams, and take the last N lines
9185 InputStreamReader input = null;
9186 try {
9187 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9188 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9189 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9190
9191 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9192 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9193 input = new InputStreamReader(logcat.getInputStream());
9194
9195 int num;
9196 char[] buf = new char[8192];
9197 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9198 } catch (IOException e) {
9199 Slog.e(TAG, "Error running logcat", e);
9200 } finally {
9201 if (input != null) try { input.close(); } catch (IOException e) {}
9202 }
9203 }
9204
9205 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009206 }
Dan Egnora455d192010-03-12 08:52:28 -08009207 };
9208
9209 if (process == null || process.pid == MY_PID) {
9210 worker.run(); // We may be about to die -- need to run this synchronously
9211 } else {
9212 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009213 }
9214 }
9215
9216 /**
9217 * Bring up the "unexpected error" dialog box for a crashing app.
9218 * Deal with edge cases (intercepts from instrumented applications,
9219 * ActivityController, error intent receivers, that sort of thing).
9220 * @param r the application crashing
9221 * @param crashInfo describing the failure
9222 */
9223 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009224 long timeMillis = System.currentTimeMillis();
9225 String shortMsg = crashInfo.exceptionClassName;
9226 String longMsg = crashInfo.exceptionMessage;
9227 String stackTrace = crashInfo.stackTrace;
9228 if (shortMsg != null && longMsg != null) {
9229 longMsg = shortMsg + ": " + longMsg;
9230 } else if (shortMsg != null) {
9231 longMsg = shortMsg;
9232 }
9233
Dan Egnor60d87622009-12-16 16:32:58 -08009234 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009236 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 try {
9238 String name = r != null ? r.processName : null;
9239 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009240 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009241 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009242 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 + " at watcher's request");
9244 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009245 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 }
9247 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009248 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 }
9250 }
9251
9252 final long origId = Binder.clearCallingIdentity();
9253
9254 // If this process is running instrumentation, finish it.
9255 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009256 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009258 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9259 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009260 Bundle info = new Bundle();
9261 info.putString("shortMsg", shortMsg);
9262 info.putString("longMsg", longMsg);
9263 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9264 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009265 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 }
9267
Dan Egnor60d87622009-12-16 16:32:58 -08009268 // If we can't identify the process or it's already exceeded its crash quota,
9269 // quit right away without showing a crash dialog.
9270 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009272 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 }
9274
9275 Message msg = Message.obtain();
9276 msg.what = SHOW_ERROR_MSG;
9277 HashMap data = new HashMap();
9278 data.put("result", result);
9279 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280 msg.obj = data;
9281 mHandler.sendMessage(msg);
9282
9283 Binder.restoreCallingIdentity(origId);
9284 }
9285
9286 int res = result.get();
9287
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009288 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 synchronized (this) {
9290 if (r != null) {
9291 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9292 SystemClock.uptimeMillis());
9293 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009294 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009295 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009296 }
9297 }
9298
9299 if (appErrorIntent != null) {
9300 try {
9301 mContext.startActivity(appErrorIntent);
9302 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009303 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009307
9308 Intent createAppErrorIntentLocked(ProcessRecord r,
9309 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9310 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009311 if (report == null) {
9312 return null;
9313 }
9314 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9315 result.setComponent(r.errorReportReceiver);
9316 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9317 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9318 return result;
9319 }
9320
Dan Egnorb7f03672009-12-09 16:22:32 -08009321 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9322 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009323 if (r.errorReportReceiver == null) {
9324 return null;
9325 }
9326
9327 if (!r.crashing && !r.notResponding) {
9328 return null;
9329 }
9330
Dan Egnorb7f03672009-12-09 16:22:32 -08009331 ApplicationErrorReport report = new ApplicationErrorReport();
9332 report.packageName = r.info.packageName;
9333 report.installerPackageName = r.errorReportReceiver.getPackageName();
9334 report.processName = r.processName;
9335 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009336 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009337
Dan Egnorb7f03672009-12-09 16:22:32 -08009338 if (r.crashing) {
9339 report.type = ApplicationErrorReport.TYPE_CRASH;
9340 report.crashInfo = crashInfo;
9341 } else if (r.notResponding) {
9342 report.type = ApplicationErrorReport.TYPE_ANR;
9343 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009344
Dan Egnorb7f03672009-12-09 16:22:32 -08009345 report.anrInfo.activity = r.notRespondingReport.tag;
9346 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9347 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009348 }
9349
Dan Egnorb7f03672009-12-09 16:22:32 -08009350 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009351 }
9352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009353 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9354 // assume our apps are happy - lazy create the list
9355 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9356
9357 synchronized (this) {
9358
9359 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009360 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9361 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9363 // This one's in trouble, so we'll generate a report for it
9364 // crashes are higher priority (in case there's a crash *and* an anr)
9365 ActivityManager.ProcessErrorStateInfo report = null;
9366 if (app.crashing) {
9367 report = app.crashingReport;
9368 } else if (app.notResponding) {
9369 report = app.notRespondingReport;
9370 }
9371
9372 if (report != null) {
9373 if (errList == null) {
9374 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9375 }
9376 errList.add(report);
9377 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009378 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 " crashing = " + app.crashing +
9380 " notResponding = " + app.notResponding);
9381 }
9382 }
9383 }
9384 }
9385
9386 return errList;
9387 }
9388
9389 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9390 // Lazy instantiation of list
9391 List<ActivityManager.RunningAppProcessInfo> runList = null;
9392 synchronized (this) {
9393 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009394 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9395 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9397 // Generate process state info for running application
9398 ActivityManager.RunningAppProcessInfo currApp =
9399 new ActivityManager.RunningAppProcessInfo(app.processName,
9400 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009401 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009403 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9405 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9406 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009407 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9408 } else if (adj >= HOME_APP_ADJ) {
9409 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9410 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 } else if (adj >= SECONDARY_SERVER_ADJ) {
9412 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9413 } else if (adj >= VISIBLE_APP_ADJ) {
9414 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9415 } else {
9416 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9417 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009418 currApp.importanceReasonCode = app.adjTypeCode;
9419 if (app.adjSource instanceof ProcessRecord) {
9420 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9421 } else if (app.adjSource instanceof HistoryRecord) {
9422 HistoryRecord r = (HistoryRecord)app.adjSource;
9423 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9424 }
9425 if (app.adjTarget instanceof ComponentName) {
9426 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9427 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009428 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 // + " lru=" + currApp.lru);
9430 if (runList == null) {
9431 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9432 }
9433 runList.add(currApp);
9434 }
9435 }
9436 }
9437 return runList;
9438 }
9439
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009440 public List<ApplicationInfo> getRunningExternalApplications() {
9441 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9442 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9443 if (runningApps != null && runningApps.size() > 0) {
9444 Set<String> extList = new HashSet<String>();
9445 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9446 if (app.pkgList != null) {
9447 for (String pkg : app.pkgList) {
9448 extList.add(pkg);
9449 }
9450 }
9451 }
9452 IPackageManager pm = ActivityThread.getPackageManager();
9453 for (String pkg : extList) {
9454 try {
9455 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9456 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9457 retList.add(info);
9458 }
9459 } catch (RemoteException e) {
9460 }
9461 }
9462 }
9463 return retList;
9464 }
9465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009466 @Override
9467 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009468 if (checkCallingPermission(android.Manifest.permission.DUMP)
9469 != PackageManager.PERMISSION_GRANTED) {
9470 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9471 + Binder.getCallingPid()
9472 + ", uid=" + Binder.getCallingUid()
9473 + " without permission "
9474 + android.Manifest.permission.DUMP);
9475 return;
9476 }
9477
9478 boolean dumpAll = false;
9479
9480 int opti = 0;
9481 while (opti < args.length) {
9482 String opt = args[opti];
9483 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9484 break;
9485 }
9486 opti++;
9487 if ("-a".equals(opt)) {
9488 dumpAll = true;
9489 } else if ("-h".equals(opt)) {
9490 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009491 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009492 pw.println(" cmd may be one of:");
9493 pw.println(" activities: activity stack state");
9494 pw.println(" broadcasts: broadcast state");
9495 pw.println(" intents: pending intent state");
9496 pw.println(" processes: process state");
9497 pw.println(" providers: content provider state");
9498 pw.println(" services: service state");
9499 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009501 } else {
9502 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009504 }
9505
9506 // Is the caller requesting to dump a particular piece of data?
9507 if (opti < args.length) {
9508 String cmd = args[opti];
9509 opti++;
9510 if ("activities".equals(cmd) || "a".equals(cmd)) {
9511 synchronized (this) {
9512 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009513 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009514 return;
9515 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9516 synchronized (this) {
9517 dumpBroadcastsLocked(fd, pw, args, opti, true);
9518 }
9519 return;
9520 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9521 synchronized (this) {
9522 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9523 }
9524 return;
9525 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9526 synchronized (this) {
9527 dumpProcessesLocked(fd, pw, args, opti, true);
9528 }
9529 return;
9530 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9531 synchronized (this) {
9532 dumpProvidersLocked(fd, pw, args, opti, true);
9533 }
9534 return;
9535 } else if ("service".equals(cmd)) {
9536 dumpService(fd, pw, args, opti, true);
9537 return;
9538 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9539 synchronized (this) {
9540 dumpServicesLocked(fd, pw, args, opti, true);
9541 }
9542 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009543 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009544 }
9545
9546 // No piece of data specified, dump everything.
9547 synchronized (this) {
9548 boolean needSep;
9549 if (dumpAll) {
9550 pw.println("Providers in Current Activity Manager State:");
9551 }
9552 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9553 if (needSep) {
9554 pw.println(" ");
9555 }
9556 if (dumpAll) {
9557 pw.println("-------------------------------------------------------------------------------");
9558 pw.println("Broadcasts in Current Activity Manager State:");
9559 }
9560 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9561 if (needSep) {
9562 pw.println(" ");
9563 }
9564 if (dumpAll) {
9565 pw.println("-------------------------------------------------------------------------------");
9566 pw.println("Services in Current Activity Manager State:");
9567 }
9568 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9569 if (needSep) {
9570 pw.println(" ");
9571 }
9572 if (dumpAll) {
9573 pw.println("-------------------------------------------------------------------------------");
9574 pw.println("PendingIntents in Current Activity Manager State:");
9575 }
9576 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9577 if (needSep) {
9578 pw.println(" ");
9579 }
9580 if (dumpAll) {
9581 pw.println("-------------------------------------------------------------------------------");
9582 pw.println("Activities in Current Activity Manager State:");
9583 }
9584 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9585 if (needSep) {
9586 pw.println(" ");
9587 }
9588 if (dumpAll) {
9589 pw.println("-------------------------------------------------------------------------------");
9590 pw.println("Processes in Current Activity Manager State:");
9591 }
9592 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9593 }
9594 }
9595
9596 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9597 int opti, boolean dumpAll, boolean needHeader) {
9598 if (needHeader) {
9599 pw.println(" Activity stack:");
9600 }
9601 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9602 pw.println(" ");
9603 pw.println(" Running activities (most recent first):");
9604 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9605 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009606 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009607 pw.println(" Activities waiting for another to become visible:");
9608 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9609 }
9610 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009612 pw.println(" Activities waiting to stop:");
9613 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9614 }
9615 if (mFinishingActivities.size() > 0) {
9616 pw.println(" ");
9617 pw.println(" Activities waiting to finish:");
9618 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009621 pw.println(" ");
9622 pw.println(" mPausingActivity: " + mPausingActivity);
9623 pw.println(" mResumedActivity: " + mResumedActivity);
9624 pw.println(" mFocusedActivity: " + mFocusedActivity);
9625 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009627 if (dumpAll && mRecentTasks.size() > 0) {
9628 pw.println(" ");
9629 pw.println("Recent tasks in Current Activity Manager State:");
9630
9631 final int N = mRecentTasks.size();
9632 for (int i=0; i<N; i++) {
9633 TaskRecord tr = mRecentTasks.get(i);
9634 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9635 pw.println(tr);
9636 mRecentTasks.get(i).dump(pw, " ");
9637 }
9638 }
9639
9640 pw.println(" ");
9641 pw.println(" mCurTask: " + mCurTask);
9642
9643 return true;
9644 }
9645
9646 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9647 int opti, boolean dumpAll) {
9648 boolean needSep = false;
9649 int numPers = 0;
9650
9651 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9653 final int NA = procs.size();
9654 for (int ia=0; ia<NA; ia++) {
9655 if (!needSep) {
9656 pw.println(" All known processes:");
9657 needSep = true;
9658 }
9659 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009660 pw.print(r.persistent ? " *PERS*" : " *APP*");
9661 pw.print(" UID "); pw.print(procs.keyAt(ia));
9662 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009663 r.dump(pw, " ");
9664 if (r.persistent) {
9665 numPers++;
9666 }
9667 }
9668 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009669 }
9670
9671 if (mLruProcesses.size() > 0) {
9672 if (needSep) pw.println(" ");
9673 needSep = true;
9674 pw.println(" Running processes (most recent first):");
9675 dumpProcessList(pw, this, mLruProcesses, " ",
9676 "App ", "PERS", true);
9677 needSep = true;
9678 }
9679
9680 synchronized (mPidsSelfLocked) {
9681 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009682 if (needSep) pw.println(" ");
9683 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009684 pw.println(" PID mappings:");
9685 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9686 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9687 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688 }
9689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009690 }
9691
9692 if (mForegroundProcesses.size() > 0) {
9693 if (needSep) pw.println(" ");
9694 needSep = true;
9695 pw.println(" Foreground Processes:");
9696 for (int i=0; i<mForegroundProcesses.size(); i++) {
9697 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9698 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009700 }
9701
9702 if (mPersistentStartingProcesses.size() > 0) {
9703 if (needSep) pw.println(" ");
9704 needSep = true;
9705 pw.println(" Persisent processes that are starting:");
9706 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9707 "Starting Norm", "Restarting PERS", false);
9708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009710 if (mStartingProcesses.size() > 0) {
9711 if (needSep) pw.println(" ");
9712 needSep = true;
9713 pw.println(" Processes that are starting:");
9714 dumpProcessList(pw, this, mStartingProcesses, " ",
9715 "Starting Norm", "Starting PERS", false);
9716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009718 if (mRemovedProcesses.size() > 0) {
9719 if (needSep) pw.println(" ");
9720 needSep = true;
9721 pw.println(" Processes that are being removed:");
9722 dumpProcessList(pw, this, mRemovedProcesses, " ",
9723 "Removed Norm", "Removed PERS", false);
9724 }
9725
9726 if (mProcessesOnHold.size() > 0) {
9727 if (needSep) pw.println(" ");
9728 needSep = true;
9729 pw.println(" Processes that are on old until the system is ready:");
9730 dumpProcessList(pw, this, mProcessesOnHold, " ",
9731 "OnHold Norm", "OnHold PERS", false);
9732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009734 if (mProcessesToGc.size() > 0) {
9735 if (needSep) pw.println(" ");
9736 needSep = true;
9737 pw.println(" Processes that are waiting to GC:");
9738 long now = SystemClock.uptimeMillis();
9739 for (int i=0; i<mProcessesToGc.size(); i++) {
9740 ProcessRecord proc = mProcessesToGc.get(i);
9741 pw.print(" Process "); pw.println(proc);
9742 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9743 pw.print(", last gced=");
9744 pw.print(now-proc.lastRequestedGc);
9745 pw.print(" ms ago, last lowMem=");
9746 pw.print(now-proc.lastLowMemory);
9747 pw.println(" ms ago");
9748
9749 }
9750 }
9751
9752 if (mProcessCrashTimes.getMap().size() > 0) {
9753 if (needSep) pw.println(" ");
9754 needSep = true;
9755 pw.println(" Time since processes crashed:");
9756 long now = SystemClock.uptimeMillis();
9757 for (Map.Entry<String, SparseArray<Long>> procs
9758 : mProcessCrashTimes.getMap().entrySet()) {
9759 SparseArray<Long> uids = procs.getValue();
9760 final int N = uids.size();
9761 for (int i=0; i<N; i++) {
9762 pw.print(" Process "); pw.print(procs.getKey());
9763 pw.print(" uid "); pw.print(uids.keyAt(i));
9764 pw.print(": last crashed ");
9765 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009766 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009767 }
9768 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009770
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009771 if (mBadProcesses.getMap().size() > 0) {
9772 if (needSep) pw.println(" ");
9773 needSep = true;
9774 pw.println(" Bad processes:");
9775 for (Map.Entry<String, SparseArray<Long>> procs
9776 : mBadProcesses.getMap().entrySet()) {
9777 SparseArray<Long> uids = procs.getValue();
9778 final int N = uids.size();
9779 for (int i=0; i<N; i++) {
9780 pw.print(" Bad process "); pw.print(procs.getKey());
9781 pw.print(" uid "); pw.print(uids.keyAt(i));
9782 pw.print(": crashed at time ");
9783 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 }
9785 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009787
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009788 pw.println(" ");
9789 pw.println(" mHomeProcess: " + mHomeProcess);
9790 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009791 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009792 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9793 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9794 || mOrigWaitForDebugger) {
9795 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9796 + " mDebugTransient=" + mDebugTransient
9797 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9798 }
9799 if (mAlwaysFinishActivities || mController != null) {
9800 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9801 + " mController=" + mController);
9802 }
9803 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009804 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009805 pw.println(" mStartRunning=" + mStartRunning
9806 + " mSystemReady=" + mSystemReady
9807 + " mBooting=" + mBooting
9808 + " mBooted=" + mBooted
9809 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 pw.println(" mGoingToSleep=" + mGoingToSleep);
9811 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009813
9814 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009815 }
9816
9817 /**
9818 * There are three ways to call this:
9819 * - no service specified: dump all the services
9820 * - a flattened component name that matched an existing service was specified as the
9821 * first arg: dump that one service
9822 * - the first arg isn't the flattened component name of an existing service:
9823 * dump all services whose component contains the first arg as a substring
9824 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009825 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9826 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 String[] newArgs;
9828 String componentNameString;
9829 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009830 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 componentNameString = null;
9832 newArgs = EMPTY_STRING_ARRAY;
9833 r = null;
9834 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009835 componentNameString = args[opti];
9836 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9838 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009839 newArgs = new String[args.length - opti];
9840 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841 }
9842
9843 if (r != null) {
9844 dumpService(fd, pw, r, newArgs);
9845 } else {
9846 for (ServiceRecord r1 : mServices.values()) {
9847 if (componentNameString == null
9848 || r1.name.flattenToString().contains(componentNameString)) {
9849 dumpService(fd, pw, r1, newArgs);
9850 }
9851 }
9852 }
9853 }
9854
9855 /**
9856 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9857 * there is a thread associated with the service.
9858 */
9859 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9860 pw.println(" Service " + r.name.flattenToString());
9861 if (r.app != null && r.app.thread != null) {
9862 try {
9863 // flush anything that is already in the PrintWriter since the thread is going
9864 // to write to the file descriptor directly
9865 pw.flush();
9866 r.app.thread.dumpService(fd, r, args);
9867 pw.print("\n");
9868 } catch (RemoteException e) {
9869 pw.println("got a RemoteException while dumping the service");
9870 }
9871 }
9872 }
9873
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009874 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9875 int opti, boolean dumpAll) {
9876 boolean needSep = false;
9877
9878 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879 if (mRegisteredReceivers.size() > 0) {
9880 pw.println(" ");
9881 pw.println(" Registered Receivers:");
9882 Iterator it = mRegisteredReceivers.values().iterator();
9883 while (it.hasNext()) {
9884 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009885 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886 r.dump(pw, " ");
9887 }
9888 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 pw.println(" ");
9891 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009892 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009893 needSep = true;
9894 }
9895
9896 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9897 || mPendingBroadcast != null) {
9898 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009899 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009900 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009902 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9903 pw.println(" Broadcast #" + i + ":");
9904 mParallelBroadcasts.get(i).dump(pw, " ");
9905 }
9906 if (mOrderedBroadcasts.size() > 0) {
9907 pw.println(" ");
9908 pw.println(" Active serialized broadcasts:");
9909 }
9910 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9911 pw.println(" Serialized Broadcast #" + i + ":");
9912 mOrderedBroadcasts.get(i).dump(pw, " ");
9913 }
9914 pw.println(" ");
9915 pw.println(" Pending broadcast:");
9916 if (mPendingBroadcast != null) {
9917 mPendingBroadcast.dump(pw, " ");
9918 } else {
9919 pw.println(" (null)");
9920 }
9921 needSep = true;
9922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009924 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009926 pw.println(" Historical broadcasts:");
9927 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9928 BroadcastRecord r = mBroadcastHistory[i];
9929 if (r == null) {
9930 break;
9931 }
9932 pw.println(" Historical Broadcast #" + i + ":");
9933 r.dump(pw, " ");
9934 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009935 needSep = true;
9936 }
9937
9938 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009939 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009940 pw.println(" Sticky broadcasts:");
9941 StringBuilder sb = new StringBuilder(128);
9942 for (Map.Entry<String, ArrayList<Intent>> ent
9943 : mStickyBroadcasts.entrySet()) {
9944 pw.print(" * Sticky action "); pw.print(ent.getKey());
9945 pw.println(":");
9946 ArrayList<Intent> intents = ent.getValue();
9947 final int N = intents.size();
9948 for (int i=0; i<N; i++) {
9949 sb.setLength(0);
9950 sb.append(" Intent: ");
9951 intents.get(i).toShortString(sb, true, false);
9952 pw.println(sb.toString());
9953 Bundle bundle = intents.get(i).getExtras();
9954 if (bundle != null) {
9955 pw.print(" ");
9956 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 }
9958 }
9959 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009960 needSep = true;
9961 }
9962
9963 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009964 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009965 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 pw.println(" mHandler:");
9967 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009968 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009969 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009970
9971 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 }
9973
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009974 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9975 int opti, boolean dumpAll) {
9976 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009978 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 if (mServices.size() > 0) {
9980 pw.println(" Active services:");
9981 Iterator<ServiceRecord> it = mServices.values().iterator();
9982 while (it.hasNext()) {
9983 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009984 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 r.dump(pw, " ");
9986 }
9987 needSep = true;
9988 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009991 if (mPendingServices.size() > 0) {
9992 if (needSep) pw.println(" ");
9993 pw.println(" Pending services:");
9994 for (int i=0; i<mPendingServices.size(); i++) {
9995 ServiceRecord r = mPendingServices.get(i);
9996 pw.print(" * Pending "); pw.println(r);
9997 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009998 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009999 needSep = true;
10000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010002 if (mRestartingServices.size() > 0) {
10003 if (needSep) pw.println(" ");
10004 pw.println(" Restarting services:");
10005 for (int i=0; i<mRestartingServices.size(); i++) {
10006 ServiceRecord r = mRestartingServices.get(i);
10007 pw.print(" * Restarting "); pw.println(r);
10008 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010010 needSep = true;
10011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010012
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010013 if (mStoppingServices.size() > 0) {
10014 if (needSep) pw.println(" ");
10015 pw.println(" Stopping services:");
10016 for (int i=0; i<mStoppingServices.size(); i++) {
10017 ServiceRecord r = mStoppingServices.get(i);
10018 pw.print(" * Stopping "); pw.println(r);
10019 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010020 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010021 needSep = true;
10022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010024 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 if (mServiceConnections.size() > 0) {
10026 if (needSep) pw.println(" ");
10027 pw.println(" Connection bindings to services:");
10028 Iterator<ConnectionRecord> it
10029 = mServiceConnections.values().iterator();
10030 while (it.hasNext()) {
10031 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010032 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 r.dump(pw, " ");
10034 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010035 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 }
10037 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010038
10039 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 }
10041
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010042 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10043 int opti, boolean dumpAll) {
10044 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010046 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 if (mProvidersByClass.size() > 0) {
10048 if (needSep) pw.println(" ");
10049 pw.println(" Published content providers (by class):");
10050 Iterator it = mProvidersByClass.entrySet().iterator();
10051 while (it.hasNext()) {
10052 Map.Entry e = (Map.Entry)it.next();
10053 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010054 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 r.dump(pw, " ");
10056 }
10057 needSep = true;
10058 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010059
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010060 if (mProvidersByName.size() > 0) {
10061 pw.println(" ");
10062 pw.println(" Authority to provider mappings:");
10063 Iterator it = mProvidersByName.entrySet().iterator();
10064 while (it.hasNext()) {
10065 Map.Entry e = (Map.Entry)it.next();
10066 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10067 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10068 pw.println(r);
10069 }
10070 needSep = true;
10071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010072 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010073
10074 if (mLaunchingProviders.size() > 0) {
10075 if (needSep) pw.println(" ");
10076 pw.println(" Launching content providers:");
10077 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10078 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10079 pw.println(mLaunchingProviders.get(i));
10080 }
10081 needSep = true;
10082 }
10083
10084 if (mGrantedUriPermissions.size() > 0) {
10085 pw.println();
10086 pw.println("Granted Uri Permissions:");
10087 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10088 int uid = mGrantedUriPermissions.keyAt(i);
10089 HashMap<Uri, UriPermission> perms
10090 = mGrantedUriPermissions.valueAt(i);
10091 pw.print(" * UID "); pw.print(uid);
10092 pw.println(" holds:");
10093 for (UriPermission perm : perms.values()) {
10094 pw.print(" "); pw.println(perm);
10095 perm.dump(pw, " ");
10096 }
10097 }
10098 needSep = true;
10099 }
10100
10101 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 }
10103
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010104 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10105 int opti, boolean dumpAll) {
10106 boolean needSep = false;
10107
10108 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 if (this.mIntentSenderRecords.size() > 0) {
10110 Iterator<WeakReference<PendingIntentRecord>> it
10111 = mIntentSenderRecords.values().iterator();
10112 while (it.hasNext()) {
10113 WeakReference<PendingIntentRecord> ref = it.next();
10114 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010115 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010116 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010117 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010118 rec.dump(pw, " ");
10119 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010120 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 }
10122 }
10123 }
10124 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010125
10126 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010127 }
10128
10129 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010130 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010131 TaskRecord lastTask = null;
10132 for (int i=list.size()-1; i>=0; i--) {
10133 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010134 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 if (lastTask != r.task) {
10136 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010137 pw.print(prefix);
10138 pw.print(full ? "* " : " ");
10139 pw.println(lastTask);
10140 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010141 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010142 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010144 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10145 pw.print(" #"); pw.print(i); pw.print(": ");
10146 pw.println(r);
10147 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010148 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 }
10151 }
10152
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010153 private static String buildOomTag(String prefix, String space, int val, int base) {
10154 if (val == base) {
10155 if (space == null) return prefix;
10156 return prefix + " ";
10157 }
10158 return prefix + "+" + Integer.toString(val-base);
10159 }
10160
10161 private static final int dumpProcessList(PrintWriter pw,
10162 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 String prefix, String normalLabel, String persistentLabel,
10164 boolean inclOomAdj) {
10165 int numPers = 0;
10166 for (int i=list.size()-1; i>=0; i--) {
10167 ProcessRecord r = (ProcessRecord)list.get(i);
10168 if (false) {
10169 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10170 + " #" + i + ":");
10171 r.dump(pw, prefix + " ");
10172 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010173 String oomAdj;
10174 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010175 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010176 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010177 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10178 } else if (r.setAdj >= HOME_APP_ADJ) {
10179 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10180 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10181 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10182 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10183 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10184 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10185 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10186 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10187 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010188 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010189 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010190 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010191 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010192 } else {
10193 oomAdj = Integer.toString(r.setAdj);
10194 }
10195 String schedGroup;
10196 switch (r.setSchedGroup) {
10197 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10198 schedGroup = "B";
10199 break;
10200 case Process.THREAD_GROUP_DEFAULT:
10201 schedGroup = "F";
10202 break;
10203 default:
10204 schedGroup = Integer.toString(r.setSchedGroup);
10205 break;
10206 }
10207 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010208 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010209 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010210 if (r.adjSource != null || r.adjTarget != null) {
10211 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010212 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010214 } else {
10215 pw.println(String.format("%s%s #%2d: %s",
10216 prefix, (r.persistent ? persistentLabel : normalLabel),
10217 i, r.toString()));
10218 }
10219 if (r.persistent) {
10220 numPers++;
10221 }
10222 }
10223 return numPers;
10224 }
10225
Dianne Hackborn472ad872010-04-07 17:31:48 -070010226 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010228 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 long uptime = SystemClock.uptimeMillis();
10230 long realtime = SystemClock.elapsedRealtime();
10231
10232 if (isCheckinRequest) {
10233 // short checkin version
10234 pw.println(uptime + "," + realtime);
10235 pw.flush();
10236 } else {
10237 pw.println("Applications Memory Usage (kB):");
10238 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10239 }
10240 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10241 ProcessRecord r = (ProcessRecord)list.get(i);
10242 if (r.thread != null) {
10243 if (!isCheckinRequest) {
10244 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10245 pw.flush();
10246 }
10247 try {
10248 r.thread.asBinder().dump(fd, args);
10249 } catch (RemoteException e) {
10250 if (!isCheckinRequest) {
10251 pw.println("Got RemoteException!");
10252 pw.flush();
10253 }
10254 }
10255 }
10256 }
10257 }
10258
10259 /**
10260 * Searches array of arguments for the specified string
10261 * @param args array of argument strings
10262 * @param value value to search for
10263 * @return true if the value is contained in the array
10264 */
10265 private static boolean scanArgs(String[] args, String value) {
10266 if (args != null) {
10267 for (String arg : args) {
10268 if (value.equals(arg)) {
10269 return true;
10270 }
10271 }
10272 }
10273 return false;
10274 }
10275
Dianne Hackborn75b03852009-06-12 15:43:26 -070010276 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277 int count = mHistory.size();
10278
10279 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 int index = -1;
10281 for (int i=count-1; i>=0; i--) {
10282 Object o = mHistory.get(i);
10283 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 index = i;
10285 break;
10286 }
10287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288
10289 return index;
10290 }
10291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 private final void killServicesLocked(ProcessRecord app,
10293 boolean allowRestart) {
10294 // Report disconnected services.
10295 if (false) {
10296 // XXX we are letting the client link to the service for
10297 // death notifications.
10298 if (app.services.size() > 0) {
10299 Iterator it = app.services.iterator();
10300 while (it.hasNext()) {
10301 ServiceRecord r = (ServiceRecord)it.next();
10302 if (r.connections.size() > 0) {
10303 Iterator<ConnectionRecord> jt
10304 = r.connections.values().iterator();
10305 while (jt.hasNext()) {
10306 ConnectionRecord c = jt.next();
10307 if (c.binding.client != app) {
10308 try {
10309 //c.conn.connected(r.className, null);
10310 } catch (Exception e) {
10311 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010312 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 + r.shortName
10314 + " from app " + app.processName, e);
10315 }
10316 }
10317 }
10318 }
10319 }
10320 }
10321 }
10322
10323 // Clean up any connections this application has to other services.
10324 if (app.connections.size() > 0) {
10325 Iterator<ConnectionRecord> it = app.connections.iterator();
10326 while (it.hasNext()) {
10327 ConnectionRecord r = it.next();
10328 removeConnectionLocked(r, app, null);
10329 }
10330 }
10331 app.connections.clear();
10332
10333 if (app.services.size() != 0) {
10334 // Any services running in the application need to be placed
10335 // back in the pending list.
10336 Iterator it = app.services.iterator();
10337 while (it.hasNext()) {
10338 ServiceRecord sr = (ServiceRecord)it.next();
10339 synchronized (sr.stats.getBatteryStats()) {
10340 sr.stats.stopLaunchedLocked();
10341 }
10342 sr.app = null;
10343 sr.executeNesting = 0;
10344 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010345
10346 boolean hasClients = sr.bindings.size() > 0;
10347 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 Iterator<IntentBindRecord> bindings
10349 = sr.bindings.values().iterator();
10350 while (bindings.hasNext()) {
10351 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010352 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 + ": shouldUnbind=" + b.hasBound);
10354 b.binder = null;
10355 b.requested = b.received = b.hasBound = false;
10356 }
10357 }
10358
10359 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010360 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010362 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 sr.crashCount, sr.shortName, app.pid);
10364 bringDownServiceLocked(sr, true);
10365 } else if (!allowRestart) {
10366 bringDownServiceLocked(sr, true);
10367 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010368 boolean canceled = scheduleServiceRestartLocked(sr, true);
10369
10370 // Should the service remain running? Note that in the
10371 // extreme case of so many attempts to deliver a command
10372 // that it failed, that we also will stop it here.
10373 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10374 if (sr.pendingStarts.size() == 0) {
10375 sr.startRequested = false;
10376 if (!hasClients) {
10377 // Whoops, no reason to restart!
10378 bringDownServiceLocked(sr, true);
10379 }
10380 }
10381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 }
10383 }
10384
10385 if (!allowRestart) {
10386 app.services.clear();
10387 }
10388 }
10389
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010390 // Make sure we have no more records on the stopping list.
10391 int i = mStoppingServices.size();
10392 while (i > 0) {
10393 i--;
10394 ServiceRecord sr = mStoppingServices.get(i);
10395 if (sr.app == app) {
10396 mStoppingServices.remove(i);
10397 }
10398 }
10399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 app.executingServices.clear();
10401 }
10402
10403 private final void removeDyingProviderLocked(ProcessRecord proc,
10404 ContentProviderRecord cpr) {
10405 synchronized (cpr) {
10406 cpr.launchingApp = null;
10407 cpr.notifyAll();
10408 }
10409
10410 mProvidersByClass.remove(cpr.info.name);
10411 String names[] = cpr.info.authority.split(";");
10412 for (int j = 0; j < names.length; j++) {
10413 mProvidersByName.remove(names[j]);
10414 }
10415
10416 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10417 while (cit.hasNext()) {
10418 ProcessRecord capp = cit.next();
10419 if (!capp.persistent && capp.thread != null
10420 && capp.pid != 0
10421 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010422 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 + " (pid " + capp.pid
10424 + ") because provider " + cpr.info.name
10425 + " is in dying process " + proc.processName);
10426 Process.killProcess(capp.pid);
10427 }
10428 }
10429
10430 mLaunchingProviders.remove(cpr);
10431 }
10432
10433 /**
10434 * Main code for cleaning up a process when it has gone away. This is
10435 * called both as a result of the process dying, or directly when stopping
10436 * a process when running in single process mode.
10437 */
10438 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10439 boolean restarting, int index) {
10440 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010441 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 }
10443
Dianne Hackborn36124872009-10-08 16:22:03 -070010444 mProcessesToGc.remove(app);
10445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 // Dismiss any open dialogs.
10447 if (app.crashDialog != null) {
10448 app.crashDialog.dismiss();
10449 app.crashDialog = null;
10450 }
10451 if (app.anrDialog != null) {
10452 app.anrDialog.dismiss();
10453 app.anrDialog = null;
10454 }
10455 if (app.waitDialog != null) {
10456 app.waitDialog.dismiss();
10457 app.waitDialog = null;
10458 }
10459
10460 app.crashing = false;
10461 app.notResponding = false;
10462
10463 app.resetPackageList();
10464 app.thread = null;
10465 app.forcingToForeground = null;
10466 app.foregroundServices = false;
10467
10468 killServicesLocked(app, true);
10469
10470 boolean restart = false;
10471
10472 int NL = mLaunchingProviders.size();
10473
10474 // Remove published content providers.
10475 if (!app.pubProviders.isEmpty()) {
10476 Iterator it = app.pubProviders.values().iterator();
10477 while (it.hasNext()) {
10478 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10479 cpr.provider = null;
10480 cpr.app = null;
10481
10482 // See if someone is waiting for this provider... in which
10483 // case we don't remove it, but just let it restart.
10484 int i = 0;
10485 if (!app.bad) {
10486 for (; i<NL; i++) {
10487 if (mLaunchingProviders.get(i) == cpr) {
10488 restart = true;
10489 break;
10490 }
10491 }
10492 } else {
10493 i = NL;
10494 }
10495
10496 if (i >= NL) {
10497 removeDyingProviderLocked(app, cpr);
10498 NL = mLaunchingProviders.size();
10499 }
10500 }
10501 app.pubProviders.clear();
10502 }
10503
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010504 // Take care of any launching providers waiting for this process.
10505 if (checkAppInLaunchingProvidersLocked(app, false)) {
10506 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010507 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010509 // Unregister from connected content providers.
10510 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010511 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 while (it.hasNext()) {
10513 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10514 cpr.clients.remove(app);
10515 }
10516 app.conProviders.clear();
10517 }
10518
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010519 // At this point there may be remaining entries in mLaunchingProviders
10520 // where we were the only one waiting, so they are no longer of use.
10521 // Look for these and clean up if found.
10522 // XXX Commented out for now. Trying to figure out a way to reproduce
10523 // the actual situation to identify what is actually going on.
10524 if (false) {
10525 for (int i=0; i<NL; i++) {
10526 ContentProviderRecord cpr = (ContentProviderRecord)
10527 mLaunchingProviders.get(i);
10528 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10529 synchronized (cpr) {
10530 cpr.launchingApp = null;
10531 cpr.notifyAll();
10532 }
10533 }
10534 }
10535 }
10536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010537 skipCurrentReceiverLocked(app);
10538
10539 // Unregister any receivers.
10540 if (app.receivers.size() > 0) {
10541 Iterator<ReceiverList> it = app.receivers.iterator();
10542 while (it.hasNext()) {
10543 removeReceiverLocked(it.next());
10544 }
10545 app.receivers.clear();
10546 }
10547
Christopher Tate181fafa2009-05-14 11:12:14 -070010548 // If the app is undergoing backup, tell the backup manager about it
10549 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010550 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010551 try {
10552 IBackupManager bm = IBackupManager.Stub.asInterface(
10553 ServiceManager.getService(Context.BACKUP_SERVICE));
10554 bm.agentDisconnected(app.info.packageName);
10555 } catch (RemoteException e) {
10556 // can't happen; backup manager is local
10557 }
10558 }
10559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 // If the caller is restarting this app, then leave it in its
10561 // current lists and let the caller take care of it.
10562 if (restarting) {
10563 return;
10564 }
10565
10566 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010567 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 "Removing non-persistent process during cleanup: " + app);
10569 mProcessNames.remove(app.processName, app.info.uid);
10570 } else if (!app.removed) {
10571 // This app is persistent, so we need to keep its record around.
10572 // If it is not already on the pending app list, add it there
10573 // and start a new process for it.
10574 app.thread = null;
10575 app.forcingToForeground = null;
10576 app.foregroundServices = false;
10577 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10578 mPersistentStartingProcesses.add(app);
10579 restart = true;
10580 }
10581 }
10582 mProcessesOnHold.remove(app);
10583
The Android Open Source Project4df24232009-03-05 14:34:35 -080010584 if (app == mHomeProcess) {
10585 mHomeProcess = null;
10586 }
10587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 if (restart) {
10589 // We have components that still need to be running in the
10590 // process, so re-launch it.
10591 mProcessNames.put(app.processName, app.info.uid, app);
10592 startProcessLocked(app, "restart", app.processName);
10593 } else if (app.pid > 0 && app.pid != MY_PID) {
10594 // Goodbye!
10595 synchronized (mPidsSelfLocked) {
10596 mPidsSelfLocked.remove(app.pid);
10597 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10598 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010599 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 }
10601 }
10602
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010603 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10604 // Look through the content providers we are waiting to have launched,
10605 // and if any run in this process then either schedule a restart of
10606 // the process or kill the client waiting for it if this process has
10607 // gone bad.
10608 int NL = mLaunchingProviders.size();
10609 boolean restart = false;
10610 for (int i=0; i<NL; i++) {
10611 ContentProviderRecord cpr = (ContentProviderRecord)
10612 mLaunchingProviders.get(i);
10613 if (cpr.launchingApp == app) {
10614 if (!alwaysBad && !app.bad) {
10615 restart = true;
10616 } else {
10617 removeDyingProviderLocked(app, cpr);
10618 NL = mLaunchingProviders.size();
10619 }
10620 }
10621 }
10622 return restart;
10623 }
10624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625 // =========================================================
10626 // SERVICES
10627 // =========================================================
10628
10629 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10630 ActivityManager.RunningServiceInfo info =
10631 new ActivityManager.RunningServiceInfo();
10632 info.service = r.name;
10633 if (r.app != null) {
10634 info.pid = r.app.pid;
10635 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010636 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010637 info.process = r.processName;
10638 info.foreground = r.isForeground;
10639 info.activeSince = r.createTime;
10640 info.started = r.startRequested;
10641 info.clientCount = r.connections.size();
10642 info.crashCount = r.crashCount;
10643 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010644 if (r.isForeground) {
10645 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10646 }
10647 if (r.startRequested) {
10648 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10649 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010650 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010651 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10652 }
10653 if (r.app != null && r.app.persistent) {
10654 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10655 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010656 for (ConnectionRecord conn : r.connections.values()) {
10657 if (conn.clientLabel != 0) {
10658 info.clientPackage = conn.binding.client.info.packageName;
10659 info.clientLabel = conn.clientLabel;
10660 break;
10661 }
10662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 return info;
10664 }
10665
10666 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10667 int flags) {
10668 synchronized (this) {
10669 ArrayList<ActivityManager.RunningServiceInfo> res
10670 = new ArrayList<ActivityManager.RunningServiceInfo>();
10671
10672 if (mServices.size() > 0) {
10673 Iterator<ServiceRecord> it = mServices.values().iterator();
10674 while (it.hasNext() && res.size() < maxNum) {
10675 res.add(makeRunningServiceInfoLocked(it.next()));
10676 }
10677 }
10678
10679 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10680 ServiceRecord r = mRestartingServices.get(i);
10681 ActivityManager.RunningServiceInfo info =
10682 makeRunningServiceInfoLocked(r);
10683 info.restarting = r.nextRestartTime;
10684 res.add(info);
10685 }
10686
10687 return res;
10688 }
10689 }
10690
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010691 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10692 synchronized (this) {
10693 ServiceRecord r = mServices.get(name);
10694 if (r != null) {
10695 for (ConnectionRecord conn : r.connections.values()) {
10696 if (conn.clientIntent != null) {
10697 return conn.clientIntent;
10698 }
10699 }
10700 }
10701 }
10702 return null;
10703 }
10704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 private final ServiceRecord findServiceLocked(ComponentName name,
10706 IBinder token) {
10707 ServiceRecord r = mServices.get(name);
10708 return r == token ? r : null;
10709 }
10710
10711 private final class ServiceLookupResult {
10712 final ServiceRecord record;
10713 final String permission;
10714
10715 ServiceLookupResult(ServiceRecord _record, String _permission) {
10716 record = _record;
10717 permission = _permission;
10718 }
10719 };
10720
10721 private ServiceLookupResult findServiceLocked(Intent service,
10722 String resolvedType) {
10723 ServiceRecord r = null;
10724 if (service.getComponent() != null) {
10725 r = mServices.get(service.getComponent());
10726 }
10727 if (r == null) {
10728 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10729 r = mServicesByIntent.get(filter);
10730 }
10731
10732 if (r == null) {
10733 try {
10734 ResolveInfo rInfo =
10735 ActivityThread.getPackageManager().resolveService(
10736 service, resolvedType, 0);
10737 ServiceInfo sInfo =
10738 rInfo != null ? rInfo.serviceInfo : null;
10739 if (sInfo == null) {
10740 return null;
10741 }
10742
10743 ComponentName name = new ComponentName(
10744 sInfo.applicationInfo.packageName, sInfo.name);
10745 r = mServices.get(name);
10746 } catch (RemoteException ex) {
10747 // pm is in same process, this will never happen.
10748 }
10749 }
10750 if (r != null) {
10751 int callingPid = Binder.getCallingPid();
10752 int callingUid = Binder.getCallingUid();
10753 if (checkComponentPermission(r.permission,
10754 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10755 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010756 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 + " from pid=" + callingPid
10758 + ", uid=" + callingUid
10759 + " requires " + r.permission);
10760 return new ServiceLookupResult(null, r.permission);
10761 }
10762 return new ServiceLookupResult(r, null);
10763 }
10764 return null;
10765 }
10766
10767 private class ServiceRestarter implements Runnable {
10768 private ServiceRecord mService;
10769
10770 void setService(ServiceRecord service) {
10771 mService = service;
10772 }
10773
10774 public void run() {
10775 synchronized(ActivityManagerService.this) {
10776 performServiceRestartLocked(mService);
10777 }
10778 }
10779 }
10780
10781 private ServiceLookupResult retrieveServiceLocked(Intent service,
10782 String resolvedType, int callingPid, int callingUid) {
10783 ServiceRecord r = null;
10784 if (service.getComponent() != null) {
10785 r = mServices.get(service.getComponent());
10786 }
10787 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10788 r = mServicesByIntent.get(filter);
10789 if (r == null) {
10790 try {
10791 ResolveInfo rInfo =
10792 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010793 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 ServiceInfo sInfo =
10795 rInfo != null ? rInfo.serviceInfo : null;
10796 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010797 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 ": not found");
10799 return null;
10800 }
10801
10802 ComponentName name = new ComponentName(
10803 sInfo.applicationInfo.packageName, sInfo.name);
10804 r = mServices.get(name);
10805 if (r == null) {
10806 filter = new Intent.FilterComparison(service.cloneFilter());
10807 ServiceRestarter res = new ServiceRestarter();
10808 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10809 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10810 synchronized (stats) {
10811 ss = stats.getServiceStatsLocked(
10812 sInfo.applicationInfo.uid, sInfo.packageName,
10813 sInfo.name);
10814 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010815 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 res.setService(r);
10817 mServices.put(name, r);
10818 mServicesByIntent.put(filter, r);
10819
10820 // Make sure this component isn't in the pending list.
10821 int N = mPendingServices.size();
10822 for (int i=0; i<N; i++) {
10823 ServiceRecord pr = mPendingServices.get(i);
10824 if (pr.name.equals(name)) {
10825 mPendingServices.remove(i);
10826 i--;
10827 N--;
10828 }
10829 }
10830 }
10831 } catch (RemoteException ex) {
10832 // pm is in same process, this will never happen.
10833 }
10834 }
10835 if (r != null) {
10836 if (checkComponentPermission(r.permission,
10837 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10838 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010839 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010840 + " from pid=" + Binder.getCallingPid()
10841 + ", uid=" + Binder.getCallingUid()
10842 + " requires " + r.permission);
10843 return new ServiceLookupResult(null, r.permission);
10844 }
10845 return new ServiceLookupResult(r, null);
10846 }
10847 return null;
10848 }
10849
10850 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10851 long now = SystemClock.uptimeMillis();
10852 if (r.executeNesting == 0 && r.app != null) {
10853 if (r.app.executingServices.size() == 0) {
10854 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10855 msg.obj = r.app;
10856 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10857 }
10858 r.app.executingServices.add(r);
10859 }
10860 r.executeNesting++;
10861 r.executingStart = now;
10862 }
10863
10864 private final void sendServiceArgsLocked(ServiceRecord r,
10865 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010866 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867 if (N == 0) {
10868 return;
10869 }
10870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 int i = 0;
10872 while (i < N) {
10873 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010874 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010875 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010876 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010877 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010878 // If somehow we got a dummy start at the front, then
10879 // just drop it here.
10880 i++;
10881 continue;
10882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 bumpServiceExecutingLocked(r);
10884 if (!oomAdjusted) {
10885 oomAdjusted = true;
10886 updateOomAdjLocked(r.app);
10887 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010888 int flags = 0;
10889 if (si.deliveryCount > 0) {
10890 flags |= Service.START_FLAG_RETRY;
10891 }
10892 if (si.doneExecutingCount > 0) {
10893 flags |= Service.START_FLAG_REDELIVERY;
10894 }
10895 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10896 si.deliveredTime = SystemClock.uptimeMillis();
10897 r.deliveredStarts.add(si);
10898 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010900 } catch (RemoteException e) {
10901 // Remote process gone... we'll let the normal cleanup take
10902 // care of this.
10903 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010905 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 break;
10907 }
10908 }
10909 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010910 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 } else {
10912 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010914 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 }
10916 }
10917 }
10918
10919 private final boolean requestServiceBindingLocked(ServiceRecord r,
10920 IntentBindRecord i, boolean rebind) {
10921 if (r.app == null || r.app.thread == null) {
10922 // If service is not currently running, can't yet bind.
10923 return false;
10924 }
10925 if ((!i.requested || rebind) && i.apps.size() > 0) {
10926 try {
10927 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010928 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 + ": shouldUnbind=" + i.hasBound);
10930 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10931 if (!rebind) {
10932 i.requested = true;
10933 }
10934 i.hasBound = true;
10935 i.doRebind = false;
10936 } catch (RemoteException e) {
10937 return false;
10938 }
10939 }
10940 return true;
10941 }
10942
10943 private final void requestServiceBindingsLocked(ServiceRecord r) {
10944 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10945 while (bindings.hasNext()) {
10946 IntentBindRecord i = bindings.next();
10947 if (!requestServiceBindingLocked(r, i, false)) {
10948 break;
10949 }
10950 }
10951 }
10952
10953 private final void realStartServiceLocked(ServiceRecord r,
10954 ProcessRecord app) throws RemoteException {
10955 if (app.thread == null) {
10956 throw new RemoteException();
10957 }
10958
10959 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010960 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961
10962 app.services.add(r);
10963 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010964 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010965
10966 boolean created = false;
10967 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010968 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010970 mStringBuilder.setLength(0);
10971 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010972 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010974 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010975 synchronized (r.stats.getBatteryStats()) {
10976 r.stats.startLaunchedLocked();
10977 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010978 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010980 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 created = true;
10982 } finally {
10983 if (!created) {
10984 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010985 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 }
10987 }
10988
10989 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010990
10991 // If the service is in the started state, and there are no
10992 // pending arguments, then fake up one so its onStartCommand() will
10993 // be called.
10994 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10995 r.lastStartId++;
10996 if (r.lastStartId < 1) {
10997 r.lastStartId = 1;
10998 }
10999 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11000 }
11001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 sendServiceArgsLocked(r, true);
11003 }
11004
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011005 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11006 boolean allowCancel) {
11007 boolean canceled = false;
11008
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011009 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011010 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011011 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011012
11013 // Any delivered but not yet finished starts should be put back
11014 // on the pending list.
11015 final int N = r.deliveredStarts.size();
11016 if (N > 0) {
11017 for (int i=N-1; i>=0; i--) {
11018 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11019 if (si.intent == null) {
11020 // We'll generate this again if needed.
11021 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11022 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11023 r.pendingStarts.add(0, si);
11024 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11025 dur *= 2;
11026 if (minDuration < dur) minDuration = dur;
11027 if (resetTime < dur) resetTime = dur;
11028 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011029 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011030 + r.name);
11031 canceled = true;
11032 }
11033 }
11034 r.deliveredStarts.clear();
11035 }
11036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 r.totalRestartCount++;
11038 if (r.restartDelay == 0) {
11039 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011040 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 } else {
11042 // If it has been a "reasonably long time" since the service
11043 // was started, then reset our restart duration back to
11044 // the beginning, so we don't infinitely increase the duration
11045 // on a service that just occasionally gets killed (which is
11046 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011047 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011049 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011051 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011052 if (r.restartDelay < minDuration) {
11053 r.restartDelay = minDuration;
11054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 }
11056 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011057
11058 r.nextRestartTime = now + r.restartDelay;
11059
11060 // Make sure that we don't end up restarting a bunch of services
11061 // all at the same time.
11062 boolean repeat;
11063 do {
11064 repeat = false;
11065 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11066 ServiceRecord r2 = mRestartingServices.get(i);
11067 if (r2 != r && r.nextRestartTime
11068 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11069 && r.nextRestartTime
11070 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11071 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11072 r.restartDelay = r.nextRestartTime - now;
11073 repeat = true;
11074 break;
11075 }
11076 }
11077 } while (repeat);
11078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 if (!mRestartingServices.contains(r)) {
11080 mRestartingServices.add(r);
11081 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011082
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011083 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011086 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011088 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011090 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 r.shortName, r.restartDelay);
11092
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011093 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 }
11095
11096 final void performServiceRestartLocked(ServiceRecord r) {
11097 if (!mRestartingServices.contains(r)) {
11098 return;
11099 }
11100 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11101 }
11102
11103 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11104 if (r.restartDelay == 0) {
11105 return false;
11106 }
11107 r.resetRestartCounter();
11108 mRestartingServices.remove(r);
11109 mHandler.removeCallbacks(r.restarter);
11110 return true;
11111 }
11112
11113 private final boolean bringUpServiceLocked(ServiceRecord r,
11114 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011115 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 //r.dump(" ");
11117
Dianne Hackborn36124872009-10-08 16:22:03 -070011118 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011119 sendServiceArgsLocked(r, false);
11120 return true;
11121 }
11122
11123 if (!whileRestarting && r.restartDelay > 0) {
11124 // If waiting for a restart, then do nothing.
11125 return true;
11126 }
11127
Joe Onorato8a9b2202010-02-26 18:56:32 -080011128 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 + " " + r.intent);
11130
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011131 // We are now bringing the service up, so no longer in the
11132 // restarting state.
11133 mRestartingServices.remove(r);
11134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 final String appName = r.processName;
11136 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11137 if (app != null && app.thread != null) {
11138 try {
11139 realStartServiceLocked(r, app);
11140 return true;
11141 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011142 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011143 }
11144
11145 // If a dead object exception was thrown -- fall through to
11146 // restart the application.
11147 }
11148
Dianne Hackborn36124872009-10-08 16:22:03 -070011149 // Not running -- get it started, and enqueue this service record
11150 // to be executed when the app comes up.
11151 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11152 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011153 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011154 + r.appInfo.packageName + "/"
11155 + r.appInfo.uid + " for service "
11156 + r.intent.getIntent() + ": process is bad");
11157 bringDownServiceLocked(r, true);
11158 return false;
11159 }
11160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011162 mPendingServices.add(r);
11163 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 return true;
11166 }
11167
11168 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011169 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 //r.dump(" ");
11171
11172 // Does it still need to run?
11173 if (!force && r.startRequested) {
11174 return;
11175 }
11176 if (r.connections.size() > 0) {
11177 if (!force) {
11178 // XXX should probably keep a count of the number of auto-create
11179 // connections directly in the service.
11180 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11181 while (it.hasNext()) {
11182 ConnectionRecord cr = it.next();
11183 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11184 return;
11185 }
11186 }
11187 }
11188
11189 // Report to all of the connections that the service is no longer
11190 // available.
11191 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11192 while (it.hasNext()) {
11193 ConnectionRecord c = it.next();
11194 try {
11195 // todo: shouldn't be a synchronous call!
11196 c.conn.connected(r.name, null);
11197 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011198 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 " to connection " + c.conn.asBinder() +
11200 " (in " + c.binding.client.processName + ")", e);
11201 }
11202 }
11203 }
11204
11205 // Tell the service that it has been unbound.
11206 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11207 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11208 while (it.hasNext()) {
11209 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011210 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 + ": hasBound=" + ibr.hasBound);
11212 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11213 try {
11214 bumpServiceExecutingLocked(r);
11215 updateOomAdjLocked(r.app);
11216 ibr.hasBound = false;
11217 r.app.thread.scheduleUnbindService(r,
11218 ibr.intent.getIntent());
11219 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011220 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 + r.shortName, e);
11222 serviceDoneExecutingLocked(r, true);
11223 }
11224 }
11225 }
11226 }
11227
Joe Onorato8a9b2202010-02-26 18:56:32 -080011228 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011230 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 System.identityHashCode(r), r.shortName,
11232 (r.app != null) ? r.app.pid : -1);
11233
11234 mServices.remove(r.name);
11235 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011236 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 r.totalRestartCount = 0;
11238 unscheduleServiceRestartLocked(r);
11239
11240 // Also make sure it is not on the pending list.
11241 int N = mPendingServices.size();
11242 for (int i=0; i<N; i++) {
11243 if (mPendingServices.get(i) == r) {
11244 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011245 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011246 TAG, "Removed pending service: " + r.shortName);
11247 i--;
11248 N--;
11249 }
11250 }
11251
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011252 r.cancelNotification();
11253 r.isForeground = false;
11254 r.foregroundId = 0;
11255 r.foregroundNoti = null;
11256
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011257 // Clear start entries.
11258 r.deliveredStarts.clear();
11259 r.pendingStarts.clear();
11260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 if (r.app != null) {
11262 synchronized (r.stats.getBatteryStats()) {
11263 r.stats.stopLaunchedLocked();
11264 }
11265 r.app.services.remove(r);
11266 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011268 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011269 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 bumpServiceExecutingLocked(r);
11271 mStoppingServices.add(r);
11272 updateOomAdjLocked(r.app);
11273 r.app.thread.scheduleStopService(r);
11274 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011275 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 + r.shortName, e);
11277 serviceDoneExecutingLocked(r, true);
11278 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011279 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011281 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 TAG, "Removed service that has no process: " + r.shortName);
11283 }
11284 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011285 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 TAG, "Removed service that is not running: " + r.shortName);
11287 }
11288 }
11289
11290 ComponentName startServiceLocked(IApplicationThread caller,
11291 Intent service, String resolvedType,
11292 int callingPid, int callingUid) {
11293 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011294 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 + " type=" + resolvedType + " args=" + service.getExtras());
11296
11297 if (caller != null) {
11298 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11299 if (callerApp == null) {
11300 throw new SecurityException(
11301 "Unable to find app for caller " + caller
11302 + " (pid=" + Binder.getCallingPid()
11303 + ") when starting service " + service);
11304 }
11305 }
11306
11307 ServiceLookupResult res =
11308 retrieveServiceLocked(service, resolvedType,
11309 callingPid, callingUid);
11310 if (res == null) {
11311 return null;
11312 }
11313 if (res.record == null) {
11314 return new ComponentName("!", res.permission != null
11315 ? res.permission : "private to package");
11316 }
11317 ServiceRecord r = res.record;
11318 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011319 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 + r.shortName);
11321 }
11322 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011323 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 r.lastStartId++;
11325 if (r.lastStartId < 1) {
11326 r.lastStartId = 1;
11327 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011328 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 r.lastActivity = SystemClock.uptimeMillis();
11330 synchronized (r.stats.getBatteryStats()) {
11331 r.stats.startRunningLocked();
11332 }
11333 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11334 return new ComponentName("!", "Service process is bad");
11335 }
11336 return r.name;
11337 }
11338 }
11339
11340 public ComponentName startService(IApplicationThread caller, Intent service,
11341 String resolvedType) {
11342 // Refuse possible leaked file descriptors
11343 if (service != null && service.hasFileDescriptors() == true) {
11344 throw new IllegalArgumentException("File descriptors passed in Intent");
11345 }
11346
11347 synchronized(this) {
11348 final int callingPid = Binder.getCallingPid();
11349 final int callingUid = Binder.getCallingUid();
11350 final long origId = Binder.clearCallingIdentity();
11351 ComponentName res = startServiceLocked(caller, service,
11352 resolvedType, callingPid, callingUid);
11353 Binder.restoreCallingIdentity(origId);
11354 return res;
11355 }
11356 }
11357
11358 ComponentName startServiceInPackage(int uid,
11359 Intent service, String resolvedType) {
11360 synchronized(this) {
11361 final long origId = Binder.clearCallingIdentity();
11362 ComponentName res = startServiceLocked(null, service,
11363 resolvedType, -1, uid);
11364 Binder.restoreCallingIdentity(origId);
11365 return res;
11366 }
11367 }
11368
11369 public int stopService(IApplicationThread caller, Intent service,
11370 String resolvedType) {
11371 // Refuse possible leaked file descriptors
11372 if (service != null && service.hasFileDescriptors() == true) {
11373 throw new IllegalArgumentException("File descriptors passed in Intent");
11374 }
11375
11376 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011377 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 + " type=" + resolvedType);
11379
11380 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11381 if (caller != null && callerApp == null) {
11382 throw new SecurityException(
11383 "Unable to find app for caller " + caller
11384 + " (pid=" + Binder.getCallingPid()
11385 + ") when stopping service " + service);
11386 }
11387
11388 // If this service is active, make sure it is stopped.
11389 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11390 if (r != null) {
11391 if (r.record != null) {
11392 synchronized (r.record.stats.getBatteryStats()) {
11393 r.record.stats.stopRunningLocked();
11394 }
11395 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011396 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 final long origId = Binder.clearCallingIdentity();
11398 bringDownServiceLocked(r.record, false);
11399 Binder.restoreCallingIdentity(origId);
11400 return 1;
11401 }
11402 return -1;
11403 }
11404 }
11405
11406 return 0;
11407 }
11408
11409 public IBinder peekService(Intent service, String resolvedType) {
11410 // Refuse possible leaked file descriptors
11411 if (service != null && service.hasFileDescriptors() == true) {
11412 throw new IllegalArgumentException("File descriptors passed in Intent");
11413 }
11414
11415 IBinder ret = null;
11416
11417 synchronized(this) {
11418 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11419
11420 if (r != null) {
11421 // r.record is null if findServiceLocked() failed the caller permission check
11422 if (r.record == null) {
11423 throw new SecurityException(
11424 "Permission Denial: Accessing service " + r.record.name
11425 + " from pid=" + Binder.getCallingPid()
11426 + ", uid=" + Binder.getCallingUid()
11427 + " requires " + r.permission);
11428 }
11429 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11430 if (ib != null) {
11431 ret = ib.binder;
11432 }
11433 }
11434 }
11435
11436 return ret;
11437 }
11438
11439 public boolean stopServiceToken(ComponentName className, IBinder token,
11440 int startId) {
11441 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011442 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 + " " + token + " startId=" + startId);
11444 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011445 if (r != null) {
11446 if (startId >= 0) {
11447 // Asked to only stop if done with all work. Note that
11448 // to avoid leaks, we will take this as dropping all
11449 // start items up to and including this one.
11450 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11451 if (si != null) {
11452 while (r.deliveredStarts.size() > 0) {
11453 if (r.deliveredStarts.remove(0) == si) {
11454 break;
11455 }
11456 }
11457 }
11458
11459 if (r.lastStartId != startId) {
11460 return false;
11461 }
11462
11463 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011464 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011465 + " is last, but have " + r.deliveredStarts.size()
11466 + " remaining args");
11467 }
11468 }
11469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 synchronized (r.stats.getBatteryStats()) {
11471 r.stats.stopRunningLocked();
11472 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011473 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 }
11475 final long origId = Binder.clearCallingIdentity();
11476 bringDownServiceLocked(r, false);
11477 Binder.restoreCallingIdentity(origId);
11478 return true;
11479 }
11480 }
11481 return false;
11482 }
11483
11484 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011485 int id, Notification notification, boolean removeNotification) {
11486 final long origId = Binder.clearCallingIdentity();
11487 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 synchronized(this) {
11489 ServiceRecord r = findServiceLocked(className, token);
11490 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011491 if (id != 0) {
11492 if (notification == null) {
11493 throw new IllegalArgumentException("null notification");
11494 }
11495 if (r.foregroundId != id) {
11496 r.cancelNotification();
11497 r.foregroundId = id;
11498 }
11499 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11500 r.foregroundNoti = notification;
11501 r.isForeground = true;
11502 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 if (r.app != null) {
11504 updateServiceForegroundLocked(r.app, true);
11505 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011506 } else {
11507 if (r.isForeground) {
11508 r.isForeground = false;
11509 if (r.app != null) {
11510 updateServiceForegroundLocked(r.app, true);
11511 }
11512 }
11513 if (removeNotification) {
11514 r.cancelNotification();
11515 r.foregroundId = 0;
11516 r.foregroundNoti = null;
11517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 }
11519 }
11520 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011521 } finally {
11522 Binder.restoreCallingIdentity(origId);
11523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 }
11525
11526 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11527 boolean anyForeground = false;
11528 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11529 if (sr.isForeground) {
11530 anyForeground = true;
11531 break;
11532 }
11533 }
11534 if (anyForeground != proc.foregroundServices) {
11535 proc.foregroundServices = anyForeground;
11536 if (oomAdj) {
11537 updateOomAdjLocked();
11538 }
11539 }
11540 }
11541
11542 public int bindService(IApplicationThread caller, IBinder token,
11543 Intent service, String resolvedType,
11544 IServiceConnection connection, int flags) {
11545 // Refuse possible leaked file descriptors
11546 if (service != null && service.hasFileDescriptors() == true) {
11547 throw new IllegalArgumentException("File descriptors passed in Intent");
11548 }
11549
11550 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011551 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 + " type=" + resolvedType + " conn=" + connection.asBinder()
11553 + " flags=0x" + Integer.toHexString(flags));
11554 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11555 if (callerApp == null) {
11556 throw new SecurityException(
11557 "Unable to find app for caller " + caller
11558 + " (pid=" + Binder.getCallingPid()
11559 + ") when binding service " + service);
11560 }
11561
11562 HistoryRecord activity = null;
11563 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011564 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011565 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011566 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011567 return 0;
11568 }
11569 activity = (HistoryRecord)mHistory.get(aindex);
11570 }
11571
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011572 int clientLabel = 0;
11573 PendingIntent clientIntent = null;
11574
11575 if (callerApp.info.uid == Process.SYSTEM_UID) {
11576 // Hacky kind of thing -- allow system stuff to tell us
11577 // what they are, so we can report this elsewhere for
11578 // others to know why certain services are running.
11579 try {
11580 clientIntent = (PendingIntent)service.getParcelableExtra(
11581 Intent.EXTRA_CLIENT_INTENT);
11582 } catch (RuntimeException e) {
11583 }
11584 if (clientIntent != null) {
11585 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11586 if (clientLabel != 0) {
11587 // There are no useful extras in the intent, trash them.
11588 // System code calling with this stuff just needs to know
11589 // this will happen.
11590 service = service.cloneFilter();
11591 }
11592 }
11593 }
11594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595 ServiceLookupResult res =
11596 retrieveServiceLocked(service, resolvedType,
11597 Binder.getCallingPid(), Binder.getCallingUid());
11598 if (res == null) {
11599 return 0;
11600 }
11601 if (res.record == null) {
11602 return -1;
11603 }
11604 ServiceRecord s = res.record;
11605
11606 final long origId = Binder.clearCallingIdentity();
11607
11608 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011609 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 + s.shortName);
11611 }
11612
11613 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11614 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011615 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616
11617 IBinder binder = connection.asBinder();
11618 s.connections.put(binder, c);
11619 b.connections.add(c);
11620 if (activity != null) {
11621 if (activity.connections == null) {
11622 activity.connections = new HashSet<ConnectionRecord>();
11623 }
11624 activity.connections.add(c);
11625 }
11626 b.client.connections.add(c);
11627 mServiceConnections.put(binder, c);
11628
11629 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11630 s.lastActivity = SystemClock.uptimeMillis();
11631 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11632 return 0;
11633 }
11634 }
11635
11636 if (s.app != null) {
11637 // This could have made the service more important.
11638 updateOomAdjLocked(s.app);
11639 }
11640
Joe Onorato8a9b2202010-02-26 18:56:32 -080011641 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 + ": received=" + b.intent.received
11643 + " apps=" + b.intent.apps.size()
11644 + " doRebind=" + b.intent.doRebind);
11645
11646 if (s.app != null && b.intent.received) {
11647 // Service is already running, so we can immediately
11648 // publish the connection.
11649 try {
11650 c.conn.connected(s.name, b.intent.binder);
11651 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011652 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 + " to connection " + c.conn.asBinder()
11654 + " (in " + c.binding.client.processName + ")", e);
11655 }
11656
11657 // If this is the first app connected back to this binding,
11658 // and the service had previously asked to be told when
11659 // rebound, then do so.
11660 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11661 requestServiceBindingLocked(s, b.intent, true);
11662 }
11663 } else if (!b.intent.requested) {
11664 requestServiceBindingLocked(s, b.intent, false);
11665 }
11666
11667 Binder.restoreCallingIdentity(origId);
11668 }
11669
11670 return 1;
11671 }
11672
11673 private void removeConnectionLocked(
11674 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11675 IBinder binder = c.conn.asBinder();
11676 AppBindRecord b = c.binding;
11677 ServiceRecord s = b.service;
11678 s.connections.remove(binder);
11679 b.connections.remove(c);
11680 if (c.activity != null && c.activity != skipAct) {
11681 if (c.activity.connections != null) {
11682 c.activity.connections.remove(c);
11683 }
11684 }
11685 if (b.client != skipApp) {
11686 b.client.connections.remove(c);
11687 }
11688 mServiceConnections.remove(binder);
11689
11690 if (b.connections.size() == 0) {
11691 b.intent.apps.remove(b.client);
11692 }
11693
Joe Onorato8a9b2202010-02-26 18:56:32 -080011694 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011695 + ": shouldUnbind=" + b.intent.hasBound);
11696 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11697 && b.intent.hasBound) {
11698 try {
11699 bumpServiceExecutingLocked(s);
11700 updateOomAdjLocked(s.app);
11701 b.intent.hasBound = false;
11702 // Assume the client doesn't want to know about a rebind;
11703 // we will deal with that later if it asks for one.
11704 b.intent.doRebind = false;
11705 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11706 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011707 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708 serviceDoneExecutingLocked(s, true);
11709 }
11710 }
11711
11712 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11713 bringDownServiceLocked(s, false);
11714 }
11715 }
11716
11717 public boolean unbindService(IServiceConnection connection) {
11718 synchronized (this) {
11719 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011720 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 ConnectionRecord r = mServiceConnections.get(binder);
11722 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011723 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011724 + connection.asBinder());
11725 return false;
11726 }
11727
11728 final long origId = Binder.clearCallingIdentity();
11729
11730 removeConnectionLocked(r, null, null);
11731
11732 if (r.binding.service.app != null) {
11733 // This could have made the service less important.
11734 updateOomAdjLocked(r.binding.service.app);
11735 }
11736
11737 Binder.restoreCallingIdentity(origId);
11738 }
11739
11740 return true;
11741 }
11742
11743 public void publishService(IBinder token, Intent intent, IBinder service) {
11744 // Refuse possible leaked file descriptors
11745 if (intent != null && intent.hasFileDescriptors() == true) {
11746 throw new IllegalArgumentException("File descriptors passed in Intent");
11747 }
11748
11749 synchronized(this) {
11750 if (!(token instanceof ServiceRecord)) {
11751 throw new IllegalArgumentException("Invalid service token");
11752 }
11753 ServiceRecord r = (ServiceRecord)token;
11754
11755 final long origId = Binder.clearCallingIdentity();
11756
Joe Onorato8a9b2202010-02-26 18:56:32 -080011757 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 + " " + intent + ": " + service);
11759 if (r != null) {
11760 Intent.FilterComparison filter
11761 = new Intent.FilterComparison(intent);
11762 IntentBindRecord b = r.bindings.get(filter);
11763 if (b != null && !b.received) {
11764 b.binder = service;
11765 b.requested = true;
11766 b.received = true;
11767 if (r.connections.size() > 0) {
11768 Iterator<ConnectionRecord> it
11769 = r.connections.values().iterator();
11770 while (it.hasNext()) {
11771 ConnectionRecord c = it.next();
11772 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011773 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011775 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011777 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011778 TAG, "Published intent: " + intent);
11779 continue;
11780 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011781 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782 try {
11783 c.conn.connected(r.name, service);
11784 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011785 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 " to connection " + c.conn.asBinder() +
11787 " (in " + c.binding.client.processName + ")", e);
11788 }
11789 }
11790 }
11791 }
11792
11793 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11794
11795 Binder.restoreCallingIdentity(origId);
11796 }
11797 }
11798 }
11799
11800 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11801 // Refuse possible leaked file descriptors
11802 if (intent != null && intent.hasFileDescriptors() == true) {
11803 throw new IllegalArgumentException("File descriptors passed in Intent");
11804 }
11805
11806 synchronized(this) {
11807 if (!(token instanceof ServiceRecord)) {
11808 throw new IllegalArgumentException("Invalid service token");
11809 }
11810 ServiceRecord r = (ServiceRecord)token;
11811
11812 final long origId = Binder.clearCallingIdentity();
11813
11814 if (r != null) {
11815 Intent.FilterComparison filter
11816 = new Intent.FilterComparison(intent);
11817 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011818 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 + " at " + b + ": apps="
11820 + (b != null ? b.apps.size() : 0));
11821 if (b != null) {
11822 if (b.apps.size() > 0) {
11823 // Applications have already bound since the last
11824 // unbind, so just rebind right here.
11825 requestServiceBindingLocked(r, b, true);
11826 } else {
11827 // Note to tell the service the next time there is
11828 // a new client.
11829 b.doRebind = true;
11830 }
11831 }
11832
11833 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11834
11835 Binder.restoreCallingIdentity(origId);
11836 }
11837 }
11838 }
11839
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011840 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 synchronized(this) {
11842 if (!(token instanceof ServiceRecord)) {
11843 throw new IllegalArgumentException("Invalid service token");
11844 }
11845 ServiceRecord r = (ServiceRecord)token;
11846 boolean inStopping = mStoppingServices.contains(token);
11847 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011848 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011849 + ": nesting=" + r.executeNesting
11850 + ", inStopping=" + inStopping);
11851 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011852 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 + " with incorrect token: given " + token
11854 + ", expected " + r);
11855 return;
11856 }
11857
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011858 if (type == 1) {
11859 // This is a call from a service start... take care of
11860 // book-keeping.
11861 r.callStart = true;
11862 switch (res) {
11863 case Service.START_STICKY_COMPATIBILITY:
11864 case Service.START_STICKY: {
11865 // We are done with the associated start arguments.
11866 r.findDeliveredStart(startId, true);
11867 // Don't stop if killed.
11868 r.stopIfKilled = false;
11869 break;
11870 }
11871 case Service.START_NOT_STICKY: {
11872 // We are done with the associated start arguments.
11873 r.findDeliveredStart(startId, true);
11874 if (r.lastStartId == startId) {
11875 // There is no more work, and this service
11876 // doesn't want to hang around if killed.
11877 r.stopIfKilled = true;
11878 }
11879 break;
11880 }
11881 case Service.START_REDELIVER_INTENT: {
11882 // We'll keep this item until they explicitly
11883 // call stop for it, but keep track of the fact
11884 // that it was delivered.
11885 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11886 if (si != null) {
11887 si.deliveryCount = 0;
11888 si.doneExecutingCount++;
11889 // Don't stop if killed.
11890 r.stopIfKilled = true;
11891 }
11892 break;
11893 }
11894 default:
11895 throw new IllegalArgumentException(
11896 "Unknown service start result: " + res);
11897 }
11898 if (res == Service.START_STICKY_COMPATIBILITY) {
11899 r.callStart = false;
11900 }
11901 }
11902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 final long origId = Binder.clearCallingIdentity();
11904 serviceDoneExecutingLocked(r, inStopping);
11905 Binder.restoreCallingIdentity(origId);
11906 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011907 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011908 + " with token " + token);
11909 }
11910 }
11911 }
11912
11913 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11914 r.executeNesting--;
11915 if (r.executeNesting <= 0 && r.app != null) {
11916 r.app.executingServices.remove(r);
11917 if (r.app.executingServices.size() == 0) {
11918 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11919 }
11920 if (inStopping) {
11921 mStoppingServices.remove(r);
11922 }
11923 updateOomAdjLocked(r.app);
11924 }
11925 }
11926
11927 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011928 String anrMessage = null;
11929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 synchronized(this) {
11931 if (proc.executingServices.size() == 0 || proc.thread == null) {
11932 return;
11933 }
11934 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11935 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11936 ServiceRecord timeout = null;
11937 long nextTime = 0;
11938 while (it.hasNext()) {
11939 ServiceRecord sr = it.next();
11940 if (sr.executingStart < maxTime) {
11941 timeout = sr;
11942 break;
11943 }
11944 if (sr.executingStart > nextTime) {
11945 nextTime = sr.executingStart;
11946 }
11947 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011948 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011949 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011950 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011951 } else {
11952 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11953 msg.obj = proc;
11954 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11955 }
11956 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011957
11958 if (anrMessage != null) {
11959 appNotResponding(proc, null, null, anrMessage);
11960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011961 }
11962
11963 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011964 // BACKUP AND RESTORE
11965 // =========================================================
11966
11967 // Cause the target app to be launched if necessary and its backup agent
11968 // instantiated. The backup agent will invoke backupAgentCreated() on the
11969 // activity manager to announce its creation.
11970 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011971 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011972 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11973
11974 synchronized(this) {
11975 // !!! TODO: currently no check here that we're already bound
11976 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11977 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11978 synchronized (stats) {
11979 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11980 }
11981
11982 BackupRecord r = new BackupRecord(ss, app, backupMode);
11983 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11984 // startProcessLocked() returns existing proc's record if it's already running
11985 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011986 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011987 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011988 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011989 return false;
11990 }
11991
11992 r.app = proc;
11993 mBackupTarget = r;
11994 mBackupAppName = app.packageName;
11995
Christopher Tate6fa95972009-06-05 18:43:55 -070011996 // Try not to kill the process during backup
11997 updateOomAdjLocked(proc);
11998
Christopher Tate181fafa2009-05-14 11:12:14 -070011999 // If the process is already attached, schedule the creation of the backup agent now.
12000 // If it is not yet live, this will be done when it attaches to the framework.
12001 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012002 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012003 try {
12004 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12005 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012006 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012007 }
12008 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012009 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012010 }
12011 // Invariants: at this point, the target app process exists and the application
12012 // is either already running or in the process of coming up. mBackupTarget and
12013 // mBackupAppName describe the app, so that when it binds back to the AM we
12014 // know that it's scheduled for a backup-agent operation.
12015 }
12016
12017 return true;
12018 }
12019
12020 // A backup agent has just come up
12021 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012022 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012023 + " = " + agent);
12024
12025 synchronized(this) {
12026 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012027 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012028 return;
12029 }
12030
Christopher Tate043dadc2009-06-02 16:11:00 -070012031 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012032 try {
12033 IBackupManager bm = IBackupManager.Stub.asInterface(
12034 ServiceManager.getService(Context.BACKUP_SERVICE));
12035 bm.agentConnected(agentPackageName, agent);
12036 } catch (RemoteException e) {
12037 // can't happen; the backup manager service is local
12038 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012039 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012040 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012041 } finally {
12042 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012043 }
12044 }
12045 }
12046
12047 // done with this agent
12048 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012049 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012050 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012051 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012052 return;
12053 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012054
12055 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012056 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012057 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012058 return;
12059 }
12060
Christopher Tate181fafa2009-05-14 11:12:14 -070012061 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012062 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012063 return;
12064 }
12065
Christopher Tate6fa95972009-06-05 18:43:55 -070012066 ProcessRecord proc = mBackupTarget.app;
12067 mBackupTarget = null;
12068 mBackupAppName = null;
12069
12070 // Not backing this app up any more; reset its OOM adjustment
12071 updateOomAdjLocked(proc);
12072
Christopher Tatec7b31e32009-06-10 15:49:30 -070012073 // If the app crashed during backup, 'thread' will be null here
12074 if (proc.thread != null) {
12075 try {
12076 proc.thread.scheduleDestroyBackupAgent(appInfo);
12077 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012078 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012079 e.printStackTrace();
12080 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012081 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012082 }
12083 }
12084 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012085 // BROADCASTS
12086 // =========================================================
12087
Josh Bartel7f208742010-02-25 11:01:44 -060012088 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 List cur) {
12090 final ContentResolver resolver = mContext.getContentResolver();
12091 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12092 if (list == null) {
12093 return cur;
12094 }
12095 int N = list.size();
12096 for (int i=0; i<N; i++) {
12097 Intent intent = list.get(i);
12098 if (filter.match(resolver, intent, true, TAG) >= 0) {
12099 if (cur == null) {
12100 cur = new ArrayList<Intent>();
12101 }
12102 cur.add(intent);
12103 }
12104 }
12105 return cur;
12106 }
12107
12108 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012109 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012110 + mBroadcastsScheduled);
12111
12112 if (mBroadcastsScheduled) {
12113 return;
12114 }
12115 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12116 mBroadcastsScheduled = true;
12117 }
12118
12119 public Intent registerReceiver(IApplicationThread caller,
12120 IIntentReceiver receiver, IntentFilter filter, String permission) {
12121 synchronized(this) {
12122 ProcessRecord callerApp = null;
12123 if (caller != null) {
12124 callerApp = getRecordForAppLocked(caller);
12125 if (callerApp == null) {
12126 throw new SecurityException(
12127 "Unable to find app for caller " + caller
12128 + " (pid=" + Binder.getCallingPid()
12129 + ") when registering receiver " + receiver);
12130 }
12131 }
12132
12133 List allSticky = null;
12134
12135 // Look for any matching sticky broadcasts...
12136 Iterator actions = filter.actionsIterator();
12137 if (actions != null) {
12138 while (actions.hasNext()) {
12139 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012140 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012141 }
12142 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012143 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 }
12145
12146 // The first sticky in the list is returned directly back to
12147 // the client.
12148 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12149
Joe Onorato8a9b2202010-02-26 18:56:32 -080012150 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012151 + ": " + sticky);
12152
12153 if (receiver == null) {
12154 return sticky;
12155 }
12156
12157 ReceiverList rl
12158 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12159 if (rl == null) {
12160 rl = new ReceiverList(this, callerApp,
12161 Binder.getCallingPid(),
12162 Binder.getCallingUid(), receiver);
12163 if (rl.app != null) {
12164 rl.app.receivers.add(rl);
12165 } else {
12166 try {
12167 receiver.asBinder().linkToDeath(rl, 0);
12168 } catch (RemoteException e) {
12169 return sticky;
12170 }
12171 rl.linkedToDeath = true;
12172 }
12173 mRegisteredReceivers.put(receiver.asBinder(), rl);
12174 }
12175 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12176 rl.add(bf);
12177 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012178 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012179 }
12180 mReceiverResolver.addFilter(bf);
12181
12182 // Enqueue broadcasts for all existing stickies that match
12183 // this filter.
12184 if (allSticky != null) {
12185 ArrayList receivers = new ArrayList();
12186 receivers.add(bf);
12187
12188 int N = allSticky.size();
12189 for (int i=0; i<N; i++) {
12190 Intent intent = (Intent)allSticky.get(i);
12191 BroadcastRecord r = new BroadcastRecord(intent, null,
12192 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012193 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 if (mParallelBroadcasts.size() == 0) {
12195 scheduleBroadcastsLocked();
12196 }
12197 mParallelBroadcasts.add(r);
12198 }
12199 }
12200
12201 return sticky;
12202 }
12203 }
12204
12205 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012206 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207
12208 boolean doNext = false;
12209
12210 synchronized(this) {
12211 ReceiverList rl
12212 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12213 if (rl != null) {
12214 if (rl.curBroadcast != null) {
12215 BroadcastRecord r = rl.curBroadcast;
12216 doNext = finishReceiverLocked(
12217 receiver.asBinder(), r.resultCode, r.resultData,
12218 r.resultExtras, r.resultAbort, true);
12219 }
12220
12221 if (rl.app != null) {
12222 rl.app.receivers.remove(rl);
12223 }
12224 removeReceiverLocked(rl);
12225 if (rl.linkedToDeath) {
12226 rl.linkedToDeath = false;
12227 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12228 }
12229 }
12230 }
12231
12232 if (!doNext) {
12233 return;
12234 }
12235
12236 final long origId = Binder.clearCallingIdentity();
12237 processNextBroadcast(false);
12238 trimApplications();
12239 Binder.restoreCallingIdentity(origId);
12240 }
12241
12242 void removeReceiverLocked(ReceiverList rl) {
12243 mRegisteredReceivers.remove(rl.receiver.asBinder());
12244 int N = rl.size();
12245 for (int i=0; i<N; i++) {
12246 mReceiverResolver.removeFilter(rl.get(i));
12247 }
12248 }
12249
12250 private final int broadcastIntentLocked(ProcessRecord callerApp,
12251 String callerPackage, Intent intent, String resolvedType,
12252 IIntentReceiver resultTo, int resultCode, String resultData,
12253 Bundle map, String requiredPermission,
12254 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12255 intent = new Intent(intent);
12256
Joe Onorato8a9b2202010-02-26 18:56:32 -080012257 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12259 + " ordered=" + ordered);
12260 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012261 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 }
12263
12264 // Handle special intents: if this broadcast is from the package
12265 // manager about a package being removed, we need to remove all of
12266 // its activities from the history stack.
12267 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12268 intent.getAction());
12269 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12270 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012271 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 || uidRemoved) {
12273 if (checkComponentPermission(
12274 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12275 callingPid, callingUid, -1)
12276 == PackageManager.PERMISSION_GRANTED) {
12277 if (uidRemoved) {
12278 final Bundle intentExtras = intent.getExtras();
12279 final int uid = intentExtras != null
12280 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12281 if (uid >= 0) {
12282 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12283 synchronized (bs) {
12284 bs.removeUidStatsLocked(uid);
12285 }
12286 }
12287 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012288 // If resources are unvailble just force stop all
12289 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012290 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012291 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12292 if (list != null && (list.length > 0)) {
12293 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012294 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012295 }
12296 }
12297 } else {
12298 Uri data = intent.getData();
12299 String ssp;
12300 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12301 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12302 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012303 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012305 }
12306 }
12307 }
12308 } else {
12309 String msg = "Permission Denial: " + intent.getAction()
12310 + " broadcast from " + callerPackage + " (pid=" + callingPid
12311 + ", uid=" + callingUid + ")"
12312 + " requires "
12313 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012314 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012315 throw new SecurityException(msg);
12316 }
12317 }
12318
12319 /*
12320 * If this is the time zone changed action, queue up a message that will reset the timezone
12321 * of all currently running processes. This message will get queued up before the broadcast
12322 * happens.
12323 */
12324 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12325 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12326 }
12327
Dianne Hackborn854060af2009-07-09 18:14:31 -070012328 /*
12329 * Prevent non-system code (defined here to be non-persistent
12330 * processes) from sending protected broadcasts.
12331 */
12332 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12333 || callingUid == Process.SHELL_UID || callingUid == 0) {
12334 // Always okay.
12335 } else if (callerApp == null || !callerApp.persistent) {
12336 try {
12337 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12338 intent.getAction())) {
12339 String msg = "Permission Denial: not allowed to send broadcast "
12340 + intent.getAction() + " from pid="
12341 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012342 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012343 throw new SecurityException(msg);
12344 }
12345 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012346 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012347 return BROADCAST_SUCCESS;
12348 }
12349 }
12350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012351 // Add to the sticky list if requested.
12352 if (sticky) {
12353 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12354 callingPid, callingUid)
12355 != PackageManager.PERMISSION_GRANTED) {
12356 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12357 + callingPid + ", uid=" + callingUid
12358 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012359 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 throw new SecurityException(msg);
12361 }
12362 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012363 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012364 + " and enforce permission " + requiredPermission);
12365 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12366 }
12367 if (intent.getComponent() != null) {
12368 throw new SecurityException(
12369 "Sticky broadcasts can't target a specific component");
12370 }
12371 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12372 if (list == null) {
12373 list = new ArrayList<Intent>();
12374 mStickyBroadcasts.put(intent.getAction(), list);
12375 }
12376 int N = list.size();
12377 int i;
12378 for (i=0; i<N; i++) {
12379 if (intent.filterEquals(list.get(i))) {
12380 // This sticky already exists, replace it.
12381 list.set(i, new Intent(intent));
12382 break;
12383 }
12384 }
12385 if (i >= N) {
12386 list.add(new Intent(intent));
12387 }
12388 }
12389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012390 // Figure out who all will receive this broadcast.
12391 List receivers = null;
12392 List<BroadcastFilter> registeredReceivers = null;
12393 try {
12394 if (intent.getComponent() != null) {
12395 // Broadcast is going to one specific receiver class...
12396 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012397 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012398 if (ai != null) {
12399 receivers = new ArrayList();
12400 ResolveInfo ri = new ResolveInfo();
12401 ri.activityInfo = ai;
12402 receivers.add(ri);
12403 }
12404 } else {
12405 // Need to resolve the intent to interested receivers...
12406 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12407 == 0) {
12408 receivers =
12409 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012410 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411 }
Mihai Preda074edef2009-05-18 17:13:31 +020012412 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 }
12414 } catch (RemoteException ex) {
12415 // pm is in same process, this will never happen.
12416 }
12417
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012418 final boolean replacePending =
12419 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12420
Joe Onorato8a9b2202010-02-26 18:56:32 -080012421 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012422 + " replacePending=" + replacePending);
12423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12425 if (!ordered && NR > 0) {
12426 // If we are not serializing this broadcast, then send the
12427 // registered receivers separately so they don't wait for the
12428 // components to be launched.
12429 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12430 callerPackage, callingPid, callingUid, requiredPermission,
12431 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012432 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012433 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012434 TAG, "Enqueueing parallel broadcast " + r
12435 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012436 boolean replaced = false;
12437 if (replacePending) {
12438 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12439 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012440 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012441 "***** DROPPING PARALLEL: " + intent);
12442 mParallelBroadcasts.set(i, r);
12443 replaced = true;
12444 break;
12445 }
12446 }
12447 }
12448 if (!replaced) {
12449 mParallelBroadcasts.add(r);
12450 scheduleBroadcastsLocked();
12451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 registeredReceivers = null;
12453 NR = 0;
12454 }
12455
12456 // Merge into one list.
12457 int ir = 0;
12458 if (receivers != null) {
12459 // A special case for PACKAGE_ADDED: do not allow the package
12460 // being added to see this broadcast. This prevents them from
12461 // using this as a back door to get run as soon as they are
12462 // installed. Maybe in the future we want to have a special install
12463 // broadcast or such for apps, but we'd like to deliberately make
12464 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012465 String skipPackages[] = null;
12466 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12467 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12468 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12469 Uri data = intent.getData();
12470 if (data != null) {
12471 String pkgName = data.getSchemeSpecificPart();
12472 if (pkgName != null) {
12473 skipPackages = new String[] { pkgName };
12474 }
12475 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012476 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012477 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012478 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012479 if (skipPackages != null && (skipPackages.length > 0)) {
12480 for (String skipPackage : skipPackages) {
12481 if (skipPackage != null) {
12482 int NT = receivers.size();
12483 for (int it=0; it<NT; it++) {
12484 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12485 if (curt.activityInfo.packageName.equals(skipPackage)) {
12486 receivers.remove(it);
12487 it--;
12488 NT--;
12489 }
12490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012491 }
12492 }
12493 }
12494
12495 int NT = receivers != null ? receivers.size() : 0;
12496 int it = 0;
12497 ResolveInfo curt = null;
12498 BroadcastFilter curr = null;
12499 while (it < NT && ir < NR) {
12500 if (curt == null) {
12501 curt = (ResolveInfo)receivers.get(it);
12502 }
12503 if (curr == null) {
12504 curr = registeredReceivers.get(ir);
12505 }
12506 if (curr.getPriority() >= curt.priority) {
12507 // Insert this broadcast record into the final list.
12508 receivers.add(it, curr);
12509 ir++;
12510 curr = null;
12511 it++;
12512 NT++;
12513 } else {
12514 // Skip to the next ResolveInfo in the final list.
12515 it++;
12516 curt = null;
12517 }
12518 }
12519 }
12520 while (ir < NR) {
12521 if (receivers == null) {
12522 receivers = new ArrayList();
12523 }
12524 receivers.add(registeredReceivers.get(ir));
12525 ir++;
12526 }
12527
12528 if ((receivers != null && receivers.size() > 0)
12529 || resultTo != null) {
12530 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12531 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012532 receivers, resultTo, resultCode, resultData, map, ordered,
12533 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012534 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 TAG, "Enqueueing ordered broadcast " + r
12536 + ": prev had " + mOrderedBroadcasts.size());
12537 if (DEBUG_BROADCAST) {
12538 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012539 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012541 boolean replaced = false;
12542 if (replacePending) {
12543 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12544 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012545 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012546 "***** DROPPING ORDERED: " + intent);
12547 mOrderedBroadcasts.set(i, r);
12548 replaced = true;
12549 break;
12550 }
12551 }
12552 }
12553 if (!replaced) {
12554 mOrderedBroadcasts.add(r);
12555 scheduleBroadcastsLocked();
12556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012557 }
12558
12559 return BROADCAST_SUCCESS;
12560 }
12561
12562 public final int broadcastIntent(IApplicationThread caller,
12563 Intent intent, String resolvedType, IIntentReceiver resultTo,
12564 int resultCode, String resultData, Bundle map,
12565 String requiredPermission, boolean serialized, boolean sticky) {
12566 // Refuse possible leaked file descriptors
12567 if (intent != null && intent.hasFileDescriptors() == true) {
12568 throw new IllegalArgumentException("File descriptors passed in Intent");
12569 }
12570
12571 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012572 int flags = intent.getFlags();
12573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 if (!mSystemReady) {
12575 // if the caller really truly claims to know what they're doing, go
12576 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12578 intent = new Intent(intent);
12579 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12580 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012581 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012582 + " before boot completion");
12583 throw new IllegalStateException("Cannot broadcast before boot completed");
12584 }
12585 }
12586
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012587 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12588 throw new IllegalArgumentException(
12589 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12590 }
12591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012592 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12593 final int callingPid = Binder.getCallingPid();
12594 final int callingUid = Binder.getCallingUid();
12595 final long origId = Binder.clearCallingIdentity();
12596 int res = broadcastIntentLocked(callerApp,
12597 callerApp != null ? callerApp.info.packageName : null,
12598 intent, resolvedType, resultTo,
12599 resultCode, resultData, map, requiredPermission, serialized,
12600 sticky, callingPid, callingUid);
12601 Binder.restoreCallingIdentity(origId);
12602 return res;
12603 }
12604 }
12605
12606 int broadcastIntentInPackage(String packageName, int uid,
12607 Intent intent, String resolvedType, IIntentReceiver resultTo,
12608 int resultCode, String resultData, Bundle map,
12609 String requiredPermission, boolean serialized, boolean sticky) {
12610 synchronized(this) {
12611 final long origId = Binder.clearCallingIdentity();
12612 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12613 resultTo, resultCode, resultData, map, requiredPermission,
12614 serialized, sticky, -1, uid);
12615 Binder.restoreCallingIdentity(origId);
12616 return res;
12617 }
12618 }
12619
12620 public final void unbroadcastIntent(IApplicationThread caller,
12621 Intent intent) {
12622 // Refuse possible leaked file descriptors
12623 if (intent != null && intent.hasFileDescriptors() == true) {
12624 throw new IllegalArgumentException("File descriptors passed in Intent");
12625 }
12626
12627 synchronized(this) {
12628 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12629 != PackageManager.PERMISSION_GRANTED) {
12630 String msg = "Permission Denial: unbroadcastIntent() from pid="
12631 + Binder.getCallingPid()
12632 + ", uid=" + Binder.getCallingUid()
12633 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012634 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 throw new SecurityException(msg);
12636 }
12637 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12638 if (list != null) {
12639 int N = list.size();
12640 int i;
12641 for (i=0; i<N; i++) {
12642 if (intent.filterEquals(list.get(i))) {
12643 list.remove(i);
12644 break;
12645 }
12646 }
12647 }
12648 }
12649 }
12650
12651 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12652 String resultData, Bundle resultExtras, boolean resultAbort,
12653 boolean explicit) {
12654 if (mOrderedBroadcasts.size() == 0) {
12655 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012656 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012657 }
12658 return false;
12659 }
12660 BroadcastRecord r = mOrderedBroadcasts.get(0);
12661 if (r.receiver == null) {
12662 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012663 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012664 }
12665 return false;
12666 }
12667 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012668 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669 return false;
12670 }
12671 int state = r.state;
12672 r.state = r.IDLE;
12673 if (state == r.IDLE) {
12674 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012675 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676 }
12677 }
12678 r.receiver = null;
12679 r.intent.setComponent(null);
12680 if (r.curApp != null) {
12681 r.curApp.curReceiver = null;
12682 }
12683 if (r.curFilter != null) {
12684 r.curFilter.receiverList.curBroadcast = null;
12685 }
12686 r.curFilter = null;
12687 r.curApp = null;
12688 r.curComponent = null;
12689 r.curReceiver = null;
12690 mPendingBroadcast = null;
12691
12692 r.resultCode = resultCode;
12693 r.resultData = resultData;
12694 r.resultExtras = resultExtras;
12695 r.resultAbort = resultAbort;
12696
12697 // We will process the next receiver right now if this is finishing
12698 // an app receiver (which is always asynchronous) or after we have
12699 // come back from calling a receiver.
12700 return state == BroadcastRecord.APP_RECEIVE
12701 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12702 }
12703
12704 public void finishReceiver(IBinder who, int resultCode, String resultData,
12705 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012706 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707
12708 // Refuse possible leaked file descriptors
12709 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12710 throw new IllegalArgumentException("File descriptors passed in Bundle");
12711 }
12712
12713 boolean doNext;
12714
12715 final long origId = Binder.clearCallingIdentity();
12716
12717 synchronized(this) {
12718 doNext = finishReceiverLocked(
12719 who, resultCode, resultData, resultExtras, resultAbort, true);
12720 }
12721
12722 if (doNext) {
12723 processNextBroadcast(false);
12724 }
12725 trimApplications();
12726
12727 Binder.restoreCallingIdentity(origId);
12728 }
12729
12730 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12731 if (r.nextReceiver > 0) {
12732 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12733 if (curReceiver instanceof BroadcastFilter) {
12734 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012735 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012736 System.identityHashCode(r),
12737 r.intent.getAction(),
12738 r.nextReceiver - 1,
12739 System.identityHashCode(bf));
12740 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012741 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012742 System.identityHashCode(r),
12743 r.intent.getAction(),
12744 r.nextReceiver - 1,
12745 ((ResolveInfo)curReceiver).toString());
12746 }
12747 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012748 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012749 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012750 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012751 System.identityHashCode(r),
12752 r.intent.getAction(),
12753 r.nextReceiver,
12754 "NONE");
12755 }
12756 }
12757
12758 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012759 ProcessRecord app = null;
12760 String anrMessage = null;
12761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012762 synchronized (this) {
12763 if (mOrderedBroadcasts.size() == 0) {
12764 return;
12765 }
12766 long now = SystemClock.uptimeMillis();
12767 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012768 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012771 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012772 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012773 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012774 return;
12775 }
12776
Joe Onorato8a9b2202010-02-26 18:56:32 -080012777 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012778 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012779 r.anrCount++;
12780
12781 // Current receiver has passed its expiration date.
12782 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012783 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012784 return;
12785 }
12786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012788 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012789 logBroadcastReceiverDiscard(r);
12790 if (curReceiver instanceof BroadcastFilter) {
12791 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12792 if (bf.receiverList.pid != 0
12793 && bf.receiverList.pid != MY_PID) {
12794 synchronized (this.mPidsSelfLocked) {
12795 app = this.mPidsSelfLocked.get(
12796 bf.receiverList.pid);
12797 }
12798 }
12799 } else {
12800 app = r.curApp;
12801 }
12802
12803 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012804 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 }
12806
12807 if (mPendingBroadcast == r) {
12808 mPendingBroadcast = null;
12809 }
12810
12811 // Move on to the next receiver.
12812 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12813 r.resultExtras, r.resultAbort, true);
12814 scheduleBroadcastsLocked();
12815 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012816
12817 if (anrMessage != null) {
12818 appNotResponding(app, null, null, anrMessage);
12819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012820 }
12821
12822 private final void processCurBroadcastLocked(BroadcastRecord r,
12823 ProcessRecord app) throws RemoteException {
12824 if (app.thread == null) {
12825 throw new RemoteException();
12826 }
12827 r.receiver = app.thread.asBinder();
12828 r.curApp = app;
12829 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012830 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012831
12832 // Tell the application to launch this receiver.
12833 r.intent.setComponent(r.curComponent);
12834
12835 boolean started = false;
12836 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012837 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012838 "Delivering to component " + r.curComponent
12839 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012840 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012841 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12842 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12843 started = true;
12844 } finally {
12845 if (!started) {
12846 r.receiver = null;
12847 r.curApp = null;
12848 app.curReceiver = null;
12849 }
12850 }
12851
12852 }
12853
12854 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012855 Intent intent, int resultCode, String data, Bundle extras,
12856 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857 if (app != null && app.thread != null) {
12858 // If we have an app thread, do the call through that so it is
12859 // correctly ordered with other one-way calls.
12860 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012861 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012862 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012863 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 }
12865 }
12866
12867 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12868 BroadcastFilter filter, boolean ordered) {
12869 boolean skip = false;
12870 if (filter.requiredPermission != null) {
12871 int perm = checkComponentPermission(filter.requiredPermission,
12872 r.callingPid, r.callingUid, -1);
12873 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012874 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012875 + r.intent.toString()
12876 + " from " + r.callerPackage + " (pid="
12877 + r.callingPid + ", uid=" + r.callingUid + ")"
12878 + " requires " + filter.requiredPermission
12879 + " due to registered receiver " + filter);
12880 skip = true;
12881 }
12882 }
12883 if (r.requiredPermission != null) {
12884 int perm = checkComponentPermission(r.requiredPermission,
12885 filter.receiverList.pid, filter.receiverList.uid, -1);
12886 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012887 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 + r.intent.toString()
12889 + " to " + filter.receiverList.app
12890 + " (pid=" + filter.receiverList.pid
12891 + ", uid=" + filter.receiverList.uid + ")"
12892 + " requires " + r.requiredPermission
12893 + " due to sender " + r.callerPackage
12894 + " (uid " + r.callingUid + ")");
12895 skip = true;
12896 }
12897 }
12898
12899 if (!skip) {
12900 // If this is not being sent as an ordered broadcast, then we
12901 // don't want to touch the fields that keep track of the current
12902 // state of ordered broadcasts.
12903 if (ordered) {
12904 r.receiver = filter.receiverList.receiver.asBinder();
12905 r.curFilter = filter;
12906 filter.receiverList.curBroadcast = r;
12907 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012908 if (filter.receiverList.app != null) {
12909 // Bump hosting application to no longer be in background
12910 // scheduling class. Note that we can't do that if there
12911 // isn't an app... but we can only be in that case for
12912 // things that directly call the IActivityManager API, which
12913 // are already core system stuff so don't matter for this.
12914 r.curApp = filter.receiverList.app;
12915 filter.receiverList.app.curReceiver = r;
12916 updateOomAdjLocked();
12917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012918 }
12919 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012920 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012921 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012922 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012923 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012924 }
12925 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12926 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012927 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012928 if (ordered) {
12929 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12930 }
12931 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012932 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012933 if (ordered) {
12934 r.receiver = null;
12935 r.curFilter = null;
12936 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012937 if (filter.receiverList.app != null) {
12938 filter.receiverList.app.curReceiver = null;
12939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012940 }
12941 }
12942 }
12943 }
12944
Dianne Hackborn12527f92009-11-11 17:39:50 -080012945 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12946 if (r.callingUid < 0) {
12947 // This was from a registerReceiver() call; ignore it.
12948 return;
12949 }
12950 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12951 MAX_BROADCAST_HISTORY-1);
12952 r.finishTime = SystemClock.uptimeMillis();
12953 mBroadcastHistory[0] = r;
12954 }
12955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012956 private final void processNextBroadcast(boolean fromMsg) {
12957 synchronized(this) {
12958 BroadcastRecord r;
12959
Joe Onorato8a9b2202010-02-26 18:56:32 -080012960 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012961 + mParallelBroadcasts.size() + " broadcasts, "
12962 + mOrderedBroadcasts.size() + " serialized broadcasts");
12963
12964 updateCpuStats();
12965
12966 if (fromMsg) {
12967 mBroadcastsScheduled = false;
12968 }
12969
12970 // First, deliver any non-serialized broadcasts right away.
12971 while (mParallelBroadcasts.size() > 0) {
12972 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012973 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012974 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012975 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012976 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012977 for (int i=0; i<N; i++) {
12978 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012979 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012980 "Delivering non-serialized to registered "
12981 + target + ": " + r);
12982 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12983 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012984 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012985 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012986 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012987 }
12988
12989 // Now take care of the next serialized one...
12990
12991 // If we are waiting for a process to come up to handle the next
12992 // broadcast, then do nothing at this point. Just in case, we
12993 // check that the process we're waiting for still exists.
12994 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012995 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012996 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012997 + mPendingBroadcast.curApp);
12998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012999
13000 boolean isDead;
13001 synchronized (mPidsSelfLocked) {
13002 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13003 }
13004 if (!isDead) {
13005 // It's still alive, so keep waiting
13006 return;
13007 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013008 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 + " died before responding to broadcast");
13010 mPendingBroadcast = null;
13011 }
13012 }
13013
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013014 boolean looped = false;
13015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013016 do {
13017 if (mOrderedBroadcasts.size() == 0) {
13018 // No more broadcasts pending, so all done!
13019 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013020 if (looped) {
13021 // If we had finished the last ordered broadcast, then
13022 // make sure all processes have correct oom and sched
13023 // adjustments.
13024 updateOomAdjLocked();
13025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013026 return;
13027 }
13028 r = mOrderedBroadcasts.get(0);
13029 boolean forceReceive = false;
13030
13031 // Ensure that even if something goes awry with the timeout
13032 // detection, we catch "hung" broadcasts here, discard them,
13033 // and continue to make progress.
13034 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
13035 long now = SystemClock.uptimeMillis();
13036 if (r.dispatchTime > 0) {
13037 if ((numReceivers > 0) &&
13038 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013039 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013040 + " now=" + now
13041 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013042 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013043 + " intent=" + r.intent
13044 + " numReceivers=" + numReceivers
13045 + " nextReceiver=" + r.nextReceiver
13046 + " state=" + r.state);
13047 broadcastTimeout(); // forcibly finish this broadcast
13048 forceReceive = true;
13049 r.state = BroadcastRecord.IDLE;
13050 }
13051 }
13052
13053 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013054 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013055 "processNextBroadcast() called when not idle (state="
13056 + r.state + ")");
13057 return;
13058 }
13059
13060 if (r.receivers == null || r.nextReceiver >= numReceivers
13061 || r.resultAbort || forceReceive) {
13062 // No more receivers for this broadcast! Send the final
13063 // result if requested...
13064 if (r.resultTo != null) {
13065 try {
13066 if (DEBUG_BROADCAST) {
13067 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013068 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013069 + " seq=" + seq + " app=" + r.callerApp);
13070 }
13071 performReceive(r.callerApp, r.resultTo,
13072 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013073 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013074 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013075 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013076 }
13077 }
13078
Joe Onorato8a9b2202010-02-26 18:56:32 -080013079 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013080 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13081
Joe Onorato8a9b2202010-02-26 18:56:32 -080013082 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013083 + r);
13084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013085 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013086 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013087 mOrderedBroadcasts.remove(0);
13088 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013089 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013090 continue;
13091 }
13092 } while (r == null);
13093
13094 // Get the next receiver...
13095 int recIdx = r.nextReceiver++;
13096
13097 // Keep track of when this receiver started, and make sure there
13098 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013099 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013100 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013101 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102
Joe Onorato8a9b2202010-02-26 18:56:32 -080013103 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013104 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013105 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013106 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013107 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013108 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013109 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 }
13111
13112 Object nextReceiver = r.receivers.get(recIdx);
13113 if (nextReceiver instanceof BroadcastFilter) {
13114 // Simple case: this is a registered receiver who gets
13115 // a direct call.
13116 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013117 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013118 "Delivering serialized to registered "
13119 + filter + ": " + r);
13120 deliverToRegisteredReceiver(r, filter, r.ordered);
13121 if (r.receiver == null || !r.ordered) {
13122 // The receiver has already finished, so schedule to
13123 // process the next one.
13124 r.state = BroadcastRecord.IDLE;
13125 scheduleBroadcastsLocked();
13126 }
13127 return;
13128 }
13129
13130 // Hard case: need to instantiate the receiver, possibly
13131 // starting its application process to host it.
13132
13133 ResolveInfo info =
13134 (ResolveInfo)nextReceiver;
13135
13136 boolean skip = false;
13137 int perm = checkComponentPermission(info.activityInfo.permission,
13138 r.callingPid, r.callingUid,
13139 info.activityInfo.exported
13140 ? -1 : info.activityInfo.applicationInfo.uid);
13141 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013142 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013143 + r.intent.toString()
13144 + " from " + r.callerPackage + " (pid=" + r.callingPid
13145 + ", uid=" + r.callingUid + ")"
13146 + " requires " + info.activityInfo.permission
13147 + " due to receiver " + info.activityInfo.packageName
13148 + "/" + info.activityInfo.name);
13149 skip = true;
13150 }
13151 if (r.callingUid != Process.SYSTEM_UID &&
13152 r.requiredPermission != null) {
13153 try {
13154 perm = ActivityThread.getPackageManager().
13155 checkPermission(r.requiredPermission,
13156 info.activityInfo.applicationInfo.packageName);
13157 } catch (RemoteException e) {
13158 perm = PackageManager.PERMISSION_DENIED;
13159 }
13160 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013161 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 + r.intent + " to "
13163 + info.activityInfo.applicationInfo.packageName
13164 + " requires " + r.requiredPermission
13165 + " due to sender " + r.callerPackage
13166 + " (uid " + r.callingUid + ")");
13167 skip = true;
13168 }
13169 }
13170 if (r.curApp != null && r.curApp.crashing) {
13171 // If the target process is crashing, just skip it.
13172 skip = true;
13173 }
13174
13175 if (skip) {
13176 r.receiver = null;
13177 r.curFilter = null;
13178 r.state = BroadcastRecord.IDLE;
13179 scheduleBroadcastsLocked();
13180 return;
13181 }
13182
13183 r.state = BroadcastRecord.APP_RECEIVE;
13184 String targetProcess = info.activityInfo.processName;
13185 r.curComponent = new ComponentName(
13186 info.activityInfo.applicationInfo.packageName,
13187 info.activityInfo.name);
13188 r.curReceiver = info.activityInfo;
13189
13190 // Is this receiver's application already running?
13191 ProcessRecord app = getProcessRecordLocked(targetProcess,
13192 info.activityInfo.applicationInfo.uid);
13193 if (app != null && app.thread != null) {
13194 try {
13195 processCurBroadcastLocked(r, app);
13196 return;
13197 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013198 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199 + r.curComponent, e);
13200 }
13201
13202 // If a dead object exception was thrown -- fall through to
13203 // restart the application.
13204 }
13205
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013206 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013207 if ((r.curApp=startProcessLocked(targetProcess,
13208 info.activityInfo.applicationInfo, true,
13209 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013210 "broadcast", r.curComponent,
13211 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13212 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013213 // Ah, this recipient is unavailable. Finish it if necessary,
13214 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013215 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 + info.activityInfo.applicationInfo.packageName + "/"
13217 + info.activityInfo.applicationInfo.uid + " for broadcast "
13218 + r.intent + ": process is bad");
13219 logBroadcastReceiverDiscard(r);
13220 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13221 r.resultExtras, r.resultAbort, true);
13222 scheduleBroadcastsLocked();
13223 r.state = BroadcastRecord.IDLE;
13224 return;
13225 }
13226
13227 mPendingBroadcast = r;
13228 }
13229 }
13230
13231 // =========================================================
13232 // INSTRUMENTATION
13233 // =========================================================
13234
13235 public boolean startInstrumentation(ComponentName className,
13236 String profileFile, int flags, Bundle arguments,
13237 IInstrumentationWatcher watcher) {
13238 // Refuse possible leaked file descriptors
13239 if (arguments != null && arguments.hasFileDescriptors()) {
13240 throw new IllegalArgumentException("File descriptors passed in Bundle");
13241 }
13242
13243 synchronized(this) {
13244 InstrumentationInfo ii = null;
13245 ApplicationInfo ai = null;
13246 try {
13247 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013248 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013249 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013250 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013251 } catch (PackageManager.NameNotFoundException e) {
13252 }
13253 if (ii == null) {
13254 reportStartInstrumentationFailure(watcher, className,
13255 "Unable to find instrumentation info for: " + className);
13256 return false;
13257 }
13258 if (ai == null) {
13259 reportStartInstrumentationFailure(watcher, className,
13260 "Unable to find instrumentation target package: " + ii.targetPackage);
13261 return false;
13262 }
13263
13264 int match = mContext.getPackageManager().checkSignatures(
13265 ii.targetPackage, ii.packageName);
13266 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13267 String msg = "Permission Denial: starting instrumentation "
13268 + className + " from pid="
13269 + Binder.getCallingPid()
13270 + ", uid=" + Binder.getCallingPid()
13271 + " not allowed because package " + ii.packageName
13272 + " does not have a signature matching the target "
13273 + ii.targetPackage;
13274 reportStartInstrumentationFailure(watcher, className, msg);
13275 throw new SecurityException(msg);
13276 }
13277
13278 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013279 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013280 ProcessRecord app = addAppLocked(ai);
13281 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013282 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 app.instrumentationProfileFile = profileFile;
13284 app.instrumentationArguments = arguments;
13285 app.instrumentationWatcher = watcher;
13286 app.instrumentationResultClass = className;
13287 Binder.restoreCallingIdentity(origId);
13288 }
13289
13290 return true;
13291 }
13292
13293 /**
13294 * Report errors that occur while attempting to start Instrumentation. Always writes the
13295 * error to the logs, but if somebody is watching, send the report there too. This enables
13296 * the "am" command to report errors with more information.
13297 *
13298 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13299 * @param cn The component name of the instrumentation.
13300 * @param report The error report.
13301 */
13302 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13303 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013304 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013305 try {
13306 if (watcher != null) {
13307 Bundle results = new Bundle();
13308 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13309 results.putString("Error", report);
13310 watcher.instrumentationStatus(cn, -1, results);
13311 }
13312 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013313 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013314 }
13315 }
13316
13317 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13318 if (app.instrumentationWatcher != null) {
13319 try {
13320 // NOTE: IInstrumentationWatcher *must* be oneway here
13321 app.instrumentationWatcher.instrumentationFinished(
13322 app.instrumentationClass,
13323 resultCode,
13324 results);
13325 } catch (RemoteException e) {
13326 }
13327 }
13328 app.instrumentationWatcher = null;
13329 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013330 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 app.instrumentationProfileFile = null;
13332 app.instrumentationArguments = null;
13333
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013334 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013335 }
13336
13337 public void finishInstrumentation(IApplicationThread target,
13338 int resultCode, Bundle results) {
13339 // Refuse possible leaked file descriptors
13340 if (results != null && results.hasFileDescriptors()) {
13341 throw new IllegalArgumentException("File descriptors passed in Intent");
13342 }
13343
13344 synchronized(this) {
13345 ProcessRecord app = getRecordForAppLocked(target);
13346 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013347 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013348 return;
13349 }
13350 final long origId = Binder.clearCallingIdentity();
13351 finishInstrumentationLocked(app, resultCode, results);
13352 Binder.restoreCallingIdentity(origId);
13353 }
13354 }
13355
13356 // =========================================================
13357 // CONFIGURATION
13358 // =========================================================
13359
13360 public ConfigurationInfo getDeviceConfigurationInfo() {
13361 ConfigurationInfo config = new ConfigurationInfo();
13362 synchronized (this) {
13363 config.reqTouchScreen = mConfiguration.touchscreen;
13364 config.reqKeyboardType = mConfiguration.keyboard;
13365 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013366 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13367 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13369 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013370 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13371 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013372 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13373 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013374 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013375 }
13376 return config;
13377 }
13378
13379 public Configuration getConfiguration() {
13380 Configuration ci;
13381 synchronized(this) {
13382 ci = new Configuration(mConfiguration);
13383 }
13384 return ci;
13385 }
13386
13387 public void updateConfiguration(Configuration values) {
13388 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13389 "updateConfiguration()");
13390
13391 synchronized(this) {
13392 if (values == null && mWindowManager != null) {
13393 // sentinel: fetch the current configuration from the window manager
13394 values = mWindowManager.computeNewConfiguration();
13395 }
13396
13397 final long origId = Binder.clearCallingIdentity();
13398 updateConfigurationLocked(values, null);
13399 Binder.restoreCallingIdentity(origId);
13400 }
13401 }
13402
13403 /**
13404 * Do either or both things: (1) change the current configuration, and (2)
13405 * make sure the given activity is running with the (now) current
13406 * configuration. Returns true if the activity has been left running, or
13407 * false if <var>starting</var> is being destroyed to match the new
13408 * configuration.
13409 */
13410 public boolean updateConfigurationLocked(Configuration values,
13411 HistoryRecord starting) {
13412 int changes = 0;
13413
13414 boolean kept = true;
13415
13416 if (values != null) {
13417 Configuration newConfig = new Configuration(mConfiguration);
13418 changes = newConfig.updateFrom(values);
13419 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013420 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013421 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 }
13423
Doug Zongker2bec3d42009-12-04 12:52:44 -080013424 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013425
13426 if (values.locale != null) {
13427 saveLocaleLocked(values.locale,
13428 !values.locale.equals(mConfiguration.locale),
13429 values.userSetLocale);
13430 }
13431
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013432 mConfigurationSeq++;
13433 if (mConfigurationSeq <= 0) {
13434 mConfigurationSeq = 1;
13435 }
13436 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013437 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013438 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013439
13440 AttributeCache ac = AttributeCache.instance();
13441 if (ac != null) {
13442 ac.updateConfiguration(mConfiguration);
13443 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013444
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013445 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13446 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13447 msg.obj = new Configuration(mConfiguration);
13448 mHandler.sendMessage(msg);
13449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013450
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013451 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13452 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013453 try {
13454 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013455 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013456 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457 app.thread.scheduleConfigurationChanged(mConfiguration);
13458 }
13459 } catch (Exception e) {
13460 }
13461 }
13462 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013463 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13464 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013465 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13466 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013467 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13468 broadcastIntentLocked(null, null,
13469 new Intent(Intent.ACTION_LOCALE_CHANGED),
13470 null, null, 0, null, null,
13471 null, false, false, MY_PID, Process.SYSTEM_UID);
13472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013473 }
13474 }
13475
13476 if (changes != 0 && starting == null) {
13477 // If the configuration changed, and the caller is not already
13478 // in the process of starting an activity, then find the top
13479 // activity to check if its configuration needs to change.
13480 starting = topRunningActivityLocked(null);
13481 }
13482
13483 if (starting != null) {
13484 kept = ensureActivityConfigurationLocked(starting, changes);
13485 if (kept) {
13486 // If this didn't result in the starting activity being
13487 // destroyed, then we need to make sure at this point that all
13488 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013489 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013490 + ", ensuring others are correct.");
13491 ensureActivitiesVisibleLocked(starting, changes);
13492 }
13493 }
13494
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013495 if (values != null && mWindowManager != null) {
13496 mWindowManager.setNewConfiguration(mConfiguration);
13497 }
13498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013499 return kept;
13500 }
13501
13502 private final boolean relaunchActivityLocked(HistoryRecord r,
13503 int changes, boolean andResume) {
13504 List<ResultInfo> results = null;
13505 List<Intent> newIntents = null;
13506 if (andResume) {
13507 results = r.results;
13508 newIntents = r.newIntents;
13509 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013510 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013511 + " with results=" + results + " newIntents=" + newIntents
13512 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013513 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13514 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 r.task.taskId, r.shortComponentName);
13516
13517 r.startFreezingScreenLocked(r.app, 0);
13518
13519 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013520 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013521 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013522 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 // Note: don't need to call pauseIfSleepingLocked() here, because
13524 // the caller will only pass in 'andResume' if this activity is
13525 // currently resumed, which implies we aren't sleeping.
13526 } catch (RemoteException e) {
13527 return false;
13528 }
13529
13530 if (andResume) {
13531 r.results = null;
13532 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013533 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013534 }
13535
13536 return true;
13537 }
13538
13539 /**
13540 * Make sure the given activity matches the current configuration. Returns
13541 * false if the activity had to be destroyed. Returns true if the
13542 * configuration is the same, or the activity will remain running as-is
13543 * for whatever reason. Ensures the HistoryRecord is updated with the
13544 * correct configuration and all other bookkeeping is handled.
13545 */
13546 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13547 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013548 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013549 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13550 "Skipping config check (will change): " + r);
13551 return true;
13552 }
13553
Joe Onorato8a9b2202010-02-26 18:56:32 -080013554 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013555 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556
13557 // Short circuit: if the two configurations are the exact same
13558 // object (the common case), then there is nothing to do.
13559 Configuration newConfig = mConfiguration;
13560 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013561 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013562 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013563 return true;
13564 }
13565
13566 // We don't worry about activities that are finishing.
13567 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013568 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569 "Configuration doesn't matter in finishing " + r);
13570 r.stopFreezingScreenLocked(false);
13571 return true;
13572 }
13573
13574 // Okay we now are going to make this activity have the new config.
13575 // But then we need to figure out how it needs to deal with that.
13576 Configuration oldConfig = r.configuration;
13577 r.configuration = newConfig;
13578
13579 // If the activity isn't currently running, just leave the new
13580 // configuration and it will pick that up next time it starts.
13581 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013582 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013583 "Configuration doesn't matter not running " + r);
13584 r.stopFreezingScreenLocked(false);
13585 return true;
13586 }
13587
13588 // If the activity isn't persistent, there is a chance we will
13589 // need to restart it.
13590 if (!r.persistent) {
13591
13592 // Figure out what has changed between the two configurations.
13593 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013594 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013595 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013596 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013597 + Integer.toHexString(r.info.configChanges)
13598 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013599 }
13600 if ((changes&(~r.info.configChanges)) != 0) {
13601 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13602 r.configChangeFlags |= changes;
13603 r.startFreezingScreenLocked(r.app, globalChanges);
13604 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013605 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013606 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013607 destroyActivityLocked(r, true);
13608 } else if (r.state == ActivityState.PAUSING) {
13609 // A little annoying: we are waiting for this activity to
13610 // finish pausing. Let's not do anything now, but just
13611 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013612 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013613 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013614 r.configDestroy = true;
13615 return true;
13616 } else if (r.state == ActivityState.RESUMED) {
13617 // Try to optimize this case: the configuration is changing
13618 // and we need to restart the top, resumed activity.
13619 // Instead of doing the normal handshaking, just say
13620 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013621 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013622 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623 relaunchActivityLocked(r, r.configChangeFlags, true);
13624 r.configChangeFlags = 0;
13625 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013626 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013627 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013628 relaunchActivityLocked(r, r.configChangeFlags, false);
13629 r.configChangeFlags = 0;
13630 }
13631
13632 // All done... tell the caller we weren't able to keep this
13633 // activity around.
13634 return false;
13635 }
13636 }
13637
13638 // Default case: the activity can handle this new configuration, so
13639 // hand it over. Note that we don't need to give it the new
13640 // configuration, since we always send configuration changes to all
13641 // process when they happen so it can just use whatever configuration
13642 // it last got.
13643 if (r.app != null && r.app.thread != null) {
13644 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013645 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013646 r.app.thread.scheduleActivityConfigurationChanged(r);
13647 } catch (RemoteException e) {
13648 // If process died, whatever.
13649 }
13650 }
13651 r.stopFreezingScreenLocked(false);
13652
13653 return true;
13654 }
13655
13656 /**
13657 * Save the locale. You must be inside a synchronized (this) block.
13658 */
13659 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13660 if(isDiff) {
13661 SystemProperties.set("user.language", l.getLanguage());
13662 SystemProperties.set("user.region", l.getCountry());
13663 }
13664
13665 if(isPersist) {
13666 SystemProperties.set("persist.sys.language", l.getLanguage());
13667 SystemProperties.set("persist.sys.country", l.getCountry());
13668 SystemProperties.set("persist.sys.localevar", l.getVariant());
13669 }
13670 }
13671
13672 // =========================================================
13673 // LIFETIME MANAGEMENT
13674 // =========================================================
13675
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013676 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13677 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013678 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013679 // This adjustment has already been computed. If we are calling
13680 // from the top, we may have already computed our adjustment with
13681 // an earlier hidden adjustment that isn't really for us... if
13682 // so, use the new hidden adjustment.
13683 if (!recursed && app.hidden) {
13684 app.curAdj = hiddenAdj;
13685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013686 return app.curAdj;
13687 }
13688
13689 if (app.thread == null) {
13690 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013691 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013692 return (app.curAdj=EMPTY_APP_ADJ);
13693 }
13694
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013695 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13696 // The max adjustment doesn't allow this app to be anything
13697 // below foreground, so it is not worth doing work for it.
13698 app.adjType = "fixed";
13699 app.adjSeq = mAdjSeq;
13700 app.curRawAdj = app.maxAdj;
13701 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13702 return (app.curAdj=app.maxAdj);
13703 }
13704
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013705 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013706 app.adjSource = null;
13707 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013708 app.empty = false;
13709 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013710
The Android Open Source Project4df24232009-03-05 14:34:35 -080013711 // Determine the importance of the process, starting with most
13712 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013713 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013714 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013715 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013716 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013717 // The last app on the list is the foreground app.
13718 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013719 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013720 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013721 } else if (app.instrumentationClass != null) {
13722 // Don't want to kill running instrumentation.
13723 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013724 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013725 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013726 } else if (app.persistentActivities > 0) {
13727 // Special persistent activities... shouldn't be used these days.
13728 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013729 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013730 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 } else if (app.curReceiver != null ||
13732 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13733 // An app that is currently receiving a broadcast also
13734 // counts as being in the foreground.
13735 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013736 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013737 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013738 } else if (app.executingServices.size() > 0) {
13739 // An app that is currently executing a service callback also
13740 // counts as being in the foreground.
13741 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013742 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013743 app.adjType = "exec-service";
13744 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013745 // The user is aware of this app, so make it visible.
13746 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013747 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013748 app.adjType = "foreground-service";
13749 } else if (app.forcingToForeground != null) {
13750 // The user is aware of this app, so make it visible.
13751 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013752 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013753 app.adjType = "force-foreground";
13754 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013755 } else if (app == mHomeProcess) {
13756 // This process is hosting what we currently consider to be the
13757 // home app, so we don't want to let it go into the background.
13758 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013759 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013760 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013761 } else if ((N=app.activities.size()) != 0) {
13762 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013763 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013764 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013765 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013766 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013767 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013768 for (int j=0; j<N; j++) {
13769 if (((HistoryRecord)app.activities.get(j)).visible) {
13770 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013771 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013772 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013773 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013774 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013775 break;
13776 }
13777 }
13778 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013779 // A very not-needed process. If this is lower in the lru list,
13780 // we will push it in to the empty bucket.
13781 app.hidden = true;
13782 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013783 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013784 adj = hiddenAdj;
13785 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013786 }
13787
Joe Onorato8a9b2202010-02-26 18:56:32 -080013788 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013789
The Android Open Source Project4df24232009-03-05 14:34:35 -080013790 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013791 // there are applications dependent on our services or providers, but
13792 // this gives us a baseline and makes sure we don't get into an
13793 // infinite recursion.
13794 app.adjSeq = mAdjSeq;
13795 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013796
Christopher Tate6fa95972009-06-05 18:43:55 -070013797 if (mBackupTarget != null && app == mBackupTarget.app) {
13798 // If possible we want to avoid killing apps while they're being backed up
13799 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013800 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013801 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013802 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013803 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013804 }
13805 }
13806
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013807 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13808 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013809 final long now = SystemClock.uptimeMillis();
13810 // This process is more important if the top activity is
13811 // bound to the service.
13812 Iterator jt = app.services.iterator();
13813 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13814 ServiceRecord s = (ServiceRecord)jt.next();
13815 if (s.startRequested) {
13816 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13817 // This service has seen some activity within
13818 // recent memory, so we will keep its process ahead
13819 // of the background processes.
13820 if (adj > SECONDARY_SERVER_ADJ) {
13821 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013822 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013823 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013824 }
13825 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013826 // If we have let the service slide into the background
13827 // state, still have some text describing what it is doing
13828 // even though the service no longer has an impact.
13829 if (adj > SECONDARY_SERVER_ADJ) {
13830 app.adjType = "started-bg-services";
13831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013832 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013833 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13834 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013835 Iterator<ConnectionRecord> kt
13836 = s.connections.values().iterator();
13837 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13838 // XXX should compute this based on the max of
13839 // all connected clients.
13840 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013841 if (cr.binding.client == app) {
13842 // Binding to ourself is not interesting.
13843 continue;
13844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013845 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13846 ProcessRecord client = cr.binding.client;
13847 int myHiddenAdj = hiddenAdj;
13848 if (myHiddenAdj > client.hiddenAdj) {
13849 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13850 myHiddenAdj = client.hiddenAdj;
13851 } else {
13852 myHiddenAdj = VISIBLE_APP_ADJ;
13853 }
13854 }
13855 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013856 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013857 if (adj > clientAdj) {
13858 adj = clientAdj > VISIBLE_APP_ADJ
13859 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013860 if (!client.hidden) {
13861 app.hidden = false;
13862 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013863 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013864 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13865 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013866 app.adjSource = cr.binding.client;
13867 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013868 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013869 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13870 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13871 schedGroup = Process.THREAD_GROUP_DEFAULT;
13872 }
13873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 }
13875 HistoryRecord a = cr.activity;
13876 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013877 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013878 //}
13879 if (a != null && adj > FOREGROUND_APP_ADJ &&
13880 (a.state == ActivityState.RESUMED
13881 || a.state == ActivityState.PAUSING)) {
13882 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013883 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013884 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013885 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013886 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13887 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013888 app.adjSource = a;
13889 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013890 }
13891 }
13892 }
13893 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013894
13895 // Finally, f this process has active services running in it, we
13896 // would like to avoid killing it unless it would prevent the current
13897 // application from running. By default we put the process in
13898 // with the rest of the background processes; as we scan through
13899 // its services we may bump it up from there.
13900 if (adj > hiddenAdj) {
13901 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013902 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013903 app.adjType = "bg-services";
13904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013905 }
13906
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013907 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13908 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013909 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013910 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13911 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013912 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13913 if (cpr.clients.size() != 0) {
13914 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13915 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13916 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013917 if (client == app) {
13918 // Being our own client is not interesting.
13919 continue;
13920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013921 int myHiddenAdj = hiddenAdj;
13922 if (myHiddenAdj > client.hiddenAdj) {
13923 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13924 myHiddenAdj = client.hiddenAdj;
13925 } else {
13926 myHiddenAdj = FOREGROUND_APP_ADJ;
13927 }
13928 }
13929 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013930 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013931 if (adj > clientAdj) {
13932 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013933 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013934 if (!client.hidden) {
13935 app.hidden = false;
13936 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013937 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013938 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13939 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013940 app.adjSource = client;
13941 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013942 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013943 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13944 schedGroup = Process.THREAD_GROUP_DEFAULT;
13945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013946 }
13947 }
13948 // If the provider has external (non-framework) process
13949 // dependencies, ensure that its adjustment is at least
13950 // FOREGROUND_APP_ADJ.
13951 if (cpr.externals != 0) {
13952 if (adj > FOREGROUND_APP_ADJ) {
13953 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013954 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013955 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013956 app.adjType = "provider";
13957 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013958 }
13959 }
13960 }
13961 }
13962
13963 app.curRawAdj = adj;
13964
Joe Onorato8a9b2202010-02-26 18:56:32 -080013965 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013966 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13967 if (adj > app.maxAdj) {
13968 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013969 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13970 schedGroup = Process.THREAD_GROUP_DEFAULT;
13971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013972 }
13973
13974 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013975 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013977 return adj;
13978 }
13979
13980 /**
13981 * Ask a given process to GC right now.
13982 */
13983 final void performAppGcLocked(ProcessRecord app) {
13984 try {
13985 app.lastRequestedGc = SystemClock.uptimeMillis();
13986 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013987 if (app.reportLowMemory) {
13988 app.reportLowMemory = false;
13989 app.thread.scheduleLowMemory();
13990 } else {
13991 app.thread.processInBackground();
13992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013993 }
13994 } catch (Exception e) {
13995 // whatever.
13996 }
13997 }
13998
13999 /**
14000 * Returns true if things are idle enough to perform GCs.
14001 */
Josh Bartel7f208742010-02-25 11:01:44 -060014002 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014003 return mParallelBroadcasts.size() == 0
14004 && mOrderedBroadcasts.size() == 0
14005 && (mSleeping || (mResumedActivity != null &&
14006 mResumedActivity.idle));
14007 }
14008
14009 /**
14010 * Perform GCs on all processes that are waiting for it, but only
14011 * if things are idle.
14012 */
14013 final void performAppGcsLocked() {
14014 final int N = mProcessesToGc.size();
14015 if (N <= 0) {
14016 return;
14017 }
Josh Bartel7f208742010-02-25 11:01:44 -060014018 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014019 while (mProcessesToGc.size() > 0) {
14020 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014021 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14022 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14023 <= SystemClock.uptimeMillis()) {
14024 // To avoid spamming the system, we will GC processes one
14025 // at a time, waiting a few seconds between each.
14026 performAppGcLocked(proc);
14027 scheduleAppGcsLocked();
14028 return;
14029 } else {
14030 // It hasn't been long enough since we last GCed this
14031 // process... put it in the list to wait for its time.
14032 addProcessToGcListLocked(proc);
14033 break;
14034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014035 }
14036 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014037
14038 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014039 }
14040 }
14041
14042 /**
14043 * If all looks good, perform GCs on all processes waiting for them.
14044 */
14045 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014046 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014047 performAppGcsLocked();
14048 return;
14049 }
14050 // Still not idle, wait some more.
14051 scheduleAppGcsLocked();
14052 }
14053
14054 /**
14055 * Schedule the execution of all pending app GCs.
14056 */
14057 final void scheduleAppGcsLocked() {
14058 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014059
14060 if (mProcessesToGc.size() > 0) {
14061 // Schedule a GC for the time to the next process.
14062 ProcessRecord proc = mProcessesToGc.get(0);
14063 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14064
14065 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14066 long now = SystemClock.uptimeMillis();
14067 if (when < (now+GC_TIMEOUT)) {
14068 when = now + GC_TIMEOUT;
14069 }
14070 mHandler.sendMessageAtTime(msg, when);
14071 }
14072 }
14073
14074 /**
14075 * Add a process to the array of processes waiting to be GCed. Keeps the
14076 * list in sorted order by the last GC time. The process can't already be
14077 * on the list.
14078 */
14079 final void addProcessToGcListLocked(ProcessRecord proc) {
14080 boolean added = false;
14081 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14082 if (mProcessesToGc.get(i).lastRequestedGc <
14083 proc.lastRequestedGc) {
14084 added = true;
14085 mProcessesToGc.add(i+1, proc);
14086 break;
14087 }
14088 }
14089 if (!added) {
14090 mProcessesToGc.add(0, proc);
14091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014092 }
14093
14094 /**
14095 * Set up to ask a process to GC itself. This will either do it
14096 * immediately, or put it on the list of processes to gc the next
14097 * time things are idle.
14098 */
14099 final void scheduleAppGcLocked(ProcessRecord app) {
14100 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014101 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014102 return;
14103 }
14104 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014105 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014106 scheduleAppGcsLocked();
14107 }
14108 }
14109
14110 private final boolean updateOomAdjLocked(
14111 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14112 app.hiddenAdj = hiddenAdj;
14113
14114 if (app.thread == null) {
14115 return true;
14116 }
14117
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014118 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014120 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014121 if (app.curRawAdj != app.setRawAdj) {
14122 if (app.curRawAdj > FOREGROUND_APP_ADJ
14123 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14124 // If this app is transitioning from foreground to
14125 // non-foreground, have it do a gc.
14126 scheduleAppGcLocked(app);
14127 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14128 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14129 // Likewise do a gc when an app is moving in to the
14130 // background (such as a service stopping).
14131 scheduleAppGcLocked(app);
14132 }
14133 app.setRawAdj = app.curRawAdj;
14134 }
14135 if (adj != app.setAdj) {
14136 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014137 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014138 TAG, "Set app " + app.processName +
14139 " oom adj to " + adj);
14140 app.setAdj = adj;
14141 } else {
14142 return false;
14143 }
14144 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014145 if (app.setSchedGroup != app.curSchedGroup) {
14146 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014147 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014148 "Setting process group of " + app.processName
14149 + " to " + app.curSchedGroup);
14150 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014151 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014152 try {
14153 Process.setProcessGroup(app.pid, app.curSchedGroup);
14154 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014155 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014156 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014157 e.printStackTrace();
14158 } finally {
14159 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014160 }
14161 }
14162 if (false) {
14163 if (app.thread != null) {
14164 try {
14165 app.thread.setSchedulingGroup(app.curSchedGroup);
14166 } catch (RemoteException e) {
14167 }
14168 }
14169 }
14170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014171 }
14172
14173 return true;
14174 }
14175
14176 private final HistoryRecord resumedAppLocked() {
14177 HistoryRecord resumedActivity = mResumedActivity;
14178 if (resumedActivity == null || resumedActivity.app == null) {
14179 resumedActivity = mPausingActivity;
14180 if (resumedActivity == null || resumedActivity.app == null) {
14181 resumedActivity = topRunningActivityLocked(null);
14182 }
14183 }
14184 return resumedActivity;
14185 }
14186
14187 private final boolean updateOomAdjLocked(ProcessRecord app) {
14188 final HistoryRecord TOP_ACT = resumedAppLocked();
14189 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14190 int curAdj = app.curAdj;
14191 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14192 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14193
14194 mAdjSeq++;
14195
14196 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14197 if (res) {
14198 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14199 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14200 if (nowHidden != wasHidden) {
14201 // Changed to/from hidden state, so apps after it in the LRU
14202 // list may also be changed.
14203 updateOomAdjLocked();
14204 }
14205 }
14206 return res;
14207 }
14208
14209 private final boolean updateOomAdjLocked() {
14210 boolean didOomAdj = true;
14211 final HistoryRecord TOP_ACT = resumedAppLocked();
14212 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14213
14214 if (false) {
14215 RuntimeException e = new RuntimeException();
14216 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014217 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014218 }
14219
14220 mAdjSeq++;
14221
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014222 // Let's determine how many processes we have running vs.
14223 // how many slots we have for background processes; we may want
14224 // to put multiple processes in a slot of there are enough of
14225 // them.
14226 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14227 int factor = (mLruProcesses.size()-4)/numSlots;
14228 if (factor < 1) factor = 1;
14229 int step = 0;
14230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014231 // First try updating the OOM adjustment for each of the
14232 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014233 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014234 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14235 while (i > 0) {
14236 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014237 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014238 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014239 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014240 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014241 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014242 step++;
14243 if (step >= factor) {
14244 step = 0;
14245 curHiddenAdj++;
14246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014247 }
14248 } else {
14249 didOomAdj = false;
14250 }
14251 }
14252
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014253 // If we return false, we will fall back on killing processes to
14254 // have a fixed limit. Do this if a limit has been requested; else
14255 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014256 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14257 }
14258
14259 private final void trimApplications() {
14260 synchronized (this) {
14261 int i;
14262
14263 // First remove any unused application processes whose package
14264 // has been removed.
14265 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14266 final ProcessRecord app = mRemovedProcesses.get(i);
14267 if (app.activities.size() == 0
14268 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014269 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014270 TAG, "Exiting empty application process "
14271 + app.processName + " ("
14272 + (app.thread != null ? app.thread.asBinder() : null)
14273 + ")\n");
14274 if (app.pid > 0 && app.pid != MY_PID) {
14275 Process.killProcess(app.pid);
14276 } else {
14277 try {
14278 app.thread.scheduleExit();
14279 } catch (Exception e) {
14280 // Ignore exceptions.
14281 }
14282 }
14283 cleanUpApplicationRecordLocked(app, false, -1);
14284 mRemovedProcesses.remove(i);
14285
14286 if (app.persistent) {
14287 if (app.persistent) {
14288 addAppLocked(app.info);
14289 }
14290 }
14291 }
14292 }
14293
14294 // Now try updating the OOM adjustment for each of the
14295 // application processes based on their current state.
14296 // If the setOomAdj() API is not supported, then go with our
14297 // back-up plan...
14298 if (!updateOomAdjLocked()) {
14299
14300 // Count how many processes are running services.
14301 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014302 for (i=mLruProcesses.size()-1; i>=0; i--) {
14303 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014304
14305 if (app.persistent || app.services.size() != 0
14306 || app.curReceiver != null
14307 || app.persistentActivities > 0) {
14308 // Don't count processes holding services against our
14309 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014310 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014311 TAG, "Not trimming app " + app + " with services: "
14312 + app.services);
14313 numServiceProcs++;
14314 }
14315 }
14316
14317 int curMaxProcs = mProcessLimit;
14318 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14319 if (mAlwaysFinishActivities) {
14320 curMaxProcs = 1;
14321 }
14322 curMaxProcs += numServiceProcs;
14323
14324 // Quit as many processes as we can to get down to the desired
14325 // process count. First remove any processes that no longer
14326 // have activites running in them.
14327 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014328 i<mLruProcesses.size()
14329 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014330 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014331 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014332 // Quit an application only if it is not currently
14333 // running any activities.
14334 if (!app.persistent && app.activities.size() == 0
14335 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014336 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014337 TAG, "Exiting empty application process "
14338 + app.processName + " ("
14339 + (app.thread != null ? app.thread.asBinder() : null)
14340 + ")\n");
14341 if (app.pid > 0 && app.pid != MY_PID) {
14342 Process.killProcess(app.pid);
14343 } else {
14344 try {
14345 app.thread.scheduleExit();
14346 } catch (Exception e) {
14347 // Ignore exceptions.
14348 }
14349 }
14350 // todo: For now we assume the application is not buggy
14351 // or evil, and will quit as a result of our request.
14352 // Eventually we need to drive this off of the death
14353 // notification, and kill the process if it takes too long.
14354 cleanUpApplicationRecordLocked(app, false, i);
14355 i--;
14356 }
14357 }
14358
14359 // If we still have too many processes, now from the least
14360 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014361 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014362 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014363 " of " + curMaxProcs + " processes");
14364 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014365 i<mLruProcesses.size()
14366 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014367 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014368 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014369 // Quit the application only if we have a state saved for
14370 // all of its activities.
14371 boolean canQuit = !app.persistent && app.curReceiver == null
14372 && app.services.size() == 0
14373 && app.persistentActivities == 0;
14374 int NUMA = app.activities.size();
14375 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014376 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014377 TAG, "Looking to quit " + app.processName);
14378 for (j=0; j<NUMA && canQuit; j++) {
14379 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014380 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014381 TAG, " " + r.intent.getComponent().flattenToShortString()
14382 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14383 canQuit = (r.haveState || !r.stateNotNeeded)
14384 && !r.visible && r.stopped;
14385 }
14386 if (canQuit) {
14387 // Finish all of the activities, and then the app itself.
14388 for (j=0; j<NUMA; j++) {
14389 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14390 if (!r.finishing) {
14391 destroyActivityLocked(r, false);
14392 }
14393 r.resultTo = null;
14394 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014395 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014396 + app.processName + " ("
14397 + (app.thread != null ? app.thread.asBinder() : null)
14398 + ")\n");
14399 if (app.pid > 0 && app.pid != MY_PID) {
14400 Process.killProcess(app.pid);
14401 } else {
14402 try {
14403 app.thread.scheduleExit();
14404 } catch (Exception e) {
14405 // Ignore exceptions.
14406 }
14407 }
14408 // todo: For now we assume the application is not buggy
14409 // or evil, and will quit as a result of our request.
14410 // Eventually we need to drive this off of the death
14411 // notification, and kill the process if it takes too long.
14412 cleanUpApplicationRecordLocked(app, false, i);
14413 i--;
14414 //dump();
14415 }
14416 }
14417
14418 }
14419
14420 int curMaxActivities = MAX_ACTIVITIES;
14421 if (mAlwaysFinishActivities) {
14422 curMaxActivities = 1;
14423 }
14424
14425 // Finally, if there are too many activities now running, try to
14426 // finish as many as we can to get back down to the limit.
14427 for ( i=0;
14428 i<mLRUActivities.size()
14429 && mLRUActivities.size() > curMaxActivities;
14430 i++) {
14431 final HistoryRecord r
14432 = (HistoryRecord)mLRUActivities.get(i);
14433
14434 // We can finish this one if we have its icicle saved and
14435 // it is not persistent.
14436 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14437 && r.stopped && !r.persistent && !r.finishing) {
14438 final int origSize = mLRUActivities.size();
14439 destroyActivityLocked(r, true);
14440
14441 // This will remove it from the LRU list, so keep
14442 // our index at the same value. Note that this check to
14443 // see if the size changes is just paranoia -- if
14444 // something unexpected happens, we don't want to end up
14445 // in an infinite loop.
14446 if (origSize > mLRUActivities.size()) {
14447 i--;
14448 }
14449 }
14450 }
14451 }
14452 }
14453
14454 /** This method sends the specified signal to each of the persistent apps */
14455 public void signalPersistentProcesses(int sig) throws RemoteException {
14456 if (sig != Process.SIGNAL_USR1) {
14457 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14458 }
14459
14460 synchronized (this) {
14461 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14462 != PackageManager.PERMISSION_GRANTED) {
14463 throw new SecurityException("Requires permission "
14464 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14465 }
14466
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014467 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14468 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014469 if (r.thread != null && r.persistent) {
14470 Process.sendSignal(r.pid, sig);
14471 }
14472 }
14473 }
14474 }
14475
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014476 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014477 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014478
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014479 try {
14480 synchronized (this) {
14481 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14482 // its own permission.
14483 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14484 != PackageManager.PERMISSION_GRANTED) {
14485 throw new SecurityException("Requires permission "
14486 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014487 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014488
14489 if (start && fd == null) {
14490 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014491 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014492
14493 ProcessRecord proc = null;
14494 try {
14495 int pid = Integer.parseInt(process);
14496 synchronized (mPidsSelfLocked) {
14497 proc = mPidsSelfLocked.get(pid);
14498 }
14499 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014500 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014501
14502 if (proc == null) {
14503 HashMap<String, SparseArray<ProcessRecord>> all
14504 = mProcessNames.getMap();
14505 SparseArray<ProcessRecord> procs = all.get(process);
14506 if (procs != null && procs.size() > 0) {
14507 proc = procs.valueAt(0);
14508 }
14509 }
14510
14511 if (proc == null || proc.thread == null) {
14512 throw new IllegalArgumentException("Unknown process: " + process);
14513 }
14514
14515 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14516 if (isSecure) {
14517 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14518 throw new SecurityException("Process not debuggable: " + proc);
14519 }
14520 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014521
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014522 proc.thread.profilerControl(start, path, fd);
14523 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014524 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014525 }
14526 } catch (RemoteException e) {
14527 throw new IllegalStateException("Process disappeared");
14528 } finally {
14529 if (fd != null) {
14530 try {
14531 fd.close();
14532 } catch (IOException e) {
14533 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014534 }
14535 }
14536 }
14537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014538 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14539 public void monitor() {
14540 synchronized (this) { }
14541 }
14542}