blob: 3bd65cbae8a6fe079045d056ea6b6702683b74e0 [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 Hackborndd71fc82009-12-16 19:24:32 -08001372 procs = 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) {
2999 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
3000 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;
3673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 int res = startActivityLocked(caller, intent, resolvedType,
3677 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003678 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003679 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003680
3681 if (config != null && mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003682 // If the caller also wants to switch to a new configuration,
3683 // do so now. This allows a clean switch, as we are waiting
3684 // for the current activity to pause (so we will not destroy
3685 // it), and have not yet started the next activity.
3686 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3687 "updateConfiguration()");
3688 updateConfigurationLocked(config, null);
3689 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003692
3693 if (outResult != null) {
3694 outResult.result = res;
3695 if (res == IActivityManager.START_SUCCESS) {
3696 mWaitingActivityLaunched.add(outResult);
3697 do {
3698 try {
3699 wait();
3700 } catch (InterruptedException e) {
3701 }
3702 } while (!outResult.timeout && outResult.who == null);
3703 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3704 HistoryRecord r = this.topRunningActivityLocked(null);
3705 if (r.nowVisible) {
3706 outResult.timeout = false;
3707 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3708 outResult.totalTime = 0;
3709 outResult.thisTime = 0;
3710 } else {
3711 outResult.thisTime = SystemClock.uptimeMillis();
3712 mWaitingActivityVisible.add(outResult);
3713 do {
3714 try {
3715 wait();
3716 } catch (InterruptedException e) {
3717 }
3718 } while (!outResult.timeout && outResult.who == null);
3719 }
3720 }
3721 }
3722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 return res;
3724 }
3725 }
3726
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003727 public final int startActivity(IApplicationThread caller,
3728 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3729 int grantedMode, IBinder resultTo,
3730 String resultWho, int requestCode, boolean onlyIfNeeded,
3731 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003732 return startActivityMayWait(caller, intent, resolvedType,
3733 grantedUriPermissions, grantedMode, resultTo, resultWho,
3734 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003735 }
3736
3737 public final WaitResult startActivityAndWait(IApplicationThread caller,
3738 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3739 int grantedMode, IBinder resultTo,
3740 String resultWho, int requestCode, boolean onlyIfNeeded,
3741 boolean debug) {
3742 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003743 startActivityMayWait(caller, intent, resolvedType,
3744 grantedUriPermissions, grantedMode, resultTo, resultWho,
3745 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003746 return res;
3747 }
3748
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003749 public final int startActivityWithConfig(IApplicationThread caller,
3750 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3751 int grantedMode, IBinder resultTo,
3752 String resultWho, int requestCode, boolean onlyIfNeeded,
3753 boolean debug, Configuration config) {
3754 return startActivityMayWait(caller, intent, resolvedType,
3755 grantedUriPermissions, grantedMode, resultTo, resultWho,
3756 requestCode, onlyIfNeeded, debug, null, config);
3757 }
3758
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003759 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003760 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003761 IBinder resultTo, String resultWho, int requestCode,
3762 int flagsMask, int flagsValues) {
3763 // Refuse possible leaked file descriptors
3764 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3765 throw new IllegalArgumentException("File descriptors passed in Intent");
3766 }
3767
3768 IIntentSender sender = intent.getTarget();
3769 if (!(sender instanceof PendingIntentRecord)) {
3770 throw new IllegalArgumentException("Bad PendingIntent object");
3771 }
3772
3773 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003774
3775 synchronized (this) {
3776 // If this is coming from the currently resumed activity, it is
3777 // effectively saying that app switches are allowed at this point.
3778 if (mResumedActivity != null
3779 && mResumedActivity.info.applicationInfo.uid ==
3780 Binder.getCallingUid()) {
3781 mAppSwitchesAllowedTime = 0;
3782 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003783 }
3784
3785 return pir.sendInner(0, fillInIntent, resolvedType,
3786 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3787 }
3788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 public boolean startNextMatchingActivity(IBinder callingActivity,
3790 Intent intent) {
3791 // Refuse possible leaked file descriptors
3792 if (intent != null && intent.hasFileDescriptors() == true) {
3793 throw new IllegalArgumentException("File descriptors passed in Intent");
3794 }
3795
3796 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003797 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 if (index < 0) {
3799 return false;
3800 }
3801 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3802 if (r.app == null || r.app.thread == null) {
3803 // The caller is not running... d'oh!
3804 return false;
3805 }
3806 intent = new Intent(intent);
3807 // The caller is not allowed to change the data.
3808 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3809 // And we are resetting to find the next component...
3810 intent.setComponent(null);
3811
3812 ActivityInfo aInfo = null;
3813 try {
3814 List<ResolveInfo> resolves =
3815 ActivityThread.getPackageManager().queryIntentActivities(
3816 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003817 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818
3819 // Look for the original activity in the list...
3820 final int N = resolves != null ? resolves.size() : 0;
3821 for (int i=0; i<N; i++) {
3822 ResolveInfo rInfo = resolves.get(i);
3823 if (rInfo.activityInfo.packageName.equals(r.packageName)
3824 && rInfo.activityInfo.name.equals(r.info.name)) {
3825 // We found the current one... the next matching is
3826 // after it.
3827 i++;
3828 if (i<N) {
3829 aInfo = resolves.get(i).activityInfo;
3830 }
3831 break;
3832 }
3833 }
3834 } catch (RemoteException e) {
3835 }
3836
3837 if (aInfo == null) {
3838 // Nobody who is next!
3839 return false;
3840 }
3841
3842 intent.setComponent(new ComponentName(
3843 aInfo.applicationInfo.packageName, aInfo.name));
3844 intent.setFlags(intent.getFlags()&~(
3845 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3846 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3847 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3848 Intent.FLAG_ACTIVITY_NEW_TASK));
3849
3850 // Okay now we need to start the new activity, replacing the
3851 // currently running activity. This is a little tricky because
3852 // we want to start the new one as if the current one is finished,
3853 // but not finish the current one first so that there is no flicker.
3854 // And thus...
3855 final boolean wasFinishing = r.finishing;
3856 r.finishing = true;
3857
3858 // Propagate reply information over to the new activity.
3859 final HistoryRecord resultTo = r.resultTo;
3860 final String resultWho = r.resultWho;
3861 final int requestCode = r.requestCode;
3862 r.resultTo = null;
3863 if (resultTo != null) {
3864 resultTo.removeResultsLocked(r, resultWho, requestCode);
3865 }
3866
3867 final long origId = Binder.clearCallingIdentity();
3868 // XXX we are not dealing with propagating grantedUriPermissions...
3869 // those are not yet exposed to user code, so there is no need.
3870 int res = startActivityLocked(r.app.thread, intent,
3871 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003872 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 Binder.restoreCallingIdentity(origId);
3874
3875 r.finishing = wasFinishing;
3876 if (res != START_SUCCESS) {
3877 return false;
3878 }
3879 return true;
3880 }
3881 }
3882
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003883 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 Intent intent, String resolvedType, IBinder resultTo,
3885 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003886
3887 // This is so super not safe, that only the system (or okay root)
3888 // can do it.
3889 final int callingUid = Binder.getCallingUid();
3890 if (callingUid != 0 && callingUid != Process.myUid()) {
3891 throw new SecurityException(
3892 "startActivityInPackage only available to the system");
3893 }
3894
The Android Open Source Project4df24232009-03-05 14:34:35 -08003895 final boolean componentSpecified = intent.getComponent() != null;
3896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 // Don't modify the client's object!
3898 intent = new Intent(intent);
3899
3900 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 ActivityInfo aInfo;
3902 try {
3903 ResolveInfo rInfo =
3904 ActivityThread.getPackageManager().resolveIntent(
3905 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003906 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003907 aInfo = rInfo != null ? rInfo.activityInfo : null;
3908 } catch (RemoteException e) {
3909 aInfo = null;
3910 }
3911
3912 if (aInfo != null) {
3913 // Store the found target back into the intent, because now that
3914 // we have it we never want to do this again. For example, if the
3915 // user navigates back to this point in the history, we should
3916 // always restart the exact same activity.
3917 intent.setComponent(new ComponentName(
3918 aInfo.applicationInfo.packageName, aInfo.name));
3919 }
3920
3921 synchronized(this) {
3922 return startActivityLocked(null, intent, resolvedType,
3923 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003924 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 }
3926 }
3927
Josh Bartel7f208742010-02-25 11:01:44 -06003928 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 // Remove any existing entries that are the same kind of task.
3930 int N = mRecentTasks.size();
3931 for (int i=0; i<N; i++) {
3932 TaskRecord tr = mRecentTasks.get(i);
3933 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3934 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3935 mRecentTasks.remove(i);
3936 i--;
3937 N--;
3938 if (task.intent == null) {
3939 // If the new recent task we are adding is not fully
3940 // specified, then replace it with the existing recent task.
3941 task = tr;
3942 }
3943 }
3944 }
3945 if (N >= MAX_RECENT_TASKS) {
3946 mRecentTasks.remove(N-1);
3947 }
3948 mRecentTasks.add(0, task);
3949 }
3950
3951 public void setRequestedOrientation(IBinder token,
3952 int requestedOrientation) {
3953 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003954 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 if (index < 0) {
3956 return;
3957 }
3958 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3959 final long origId = Binder.clearCallingIdentity();
3960 mWindowManager.setAppOrientation(r, requestedOrientation);
3961 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003962 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 r.mayFreezeScreenLocked(r.app) ? r : null);
3964 if (config != null) {
3965 r.frozenBeforeDestroy = true;
3966 if (!updateConfigurationLocked(config, r)) {
3967 resumeTopActivityLocked(null);
3968 }
3969 }
3970 Binder.restoreCallingIdentity(origId);
3971 }
3972 }
3973
3974 public int getRequestedOrientation(IBinder token) {
3975 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003976 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 if (index < 0) {
3978 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3979 }
3980 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3981 return mWindowManager.getAppOrientation(r);
3982 }
3983 }
3984
3985 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003986 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3988 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3989 if (!r.finishing) {
3990 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3991 "no-history");
3992 }
3993 } else if (r.app != null && r.app.thread != null) {
3994 if (mFocusedActivity == r) {
3995 setFocusedActivityLocked(topRunningActivityLocked(null));
3996 }
3997 r.resumeKeyDispatchingLocked();
3998 try {
3999 r.stopped = false;
4000 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004001 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 TAG, "Stopping visible=" + r.visible + " for " + r);
4003 if (!r.visible) {
4004 mWindowManager.setAppVisibility(r, false);
4005 }
4006 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4007 } catch (Exception e) {
4008 // Maybe just ignore exceptions here... if the process
4009 // has crashed, our death notification will clean things
4010 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004011 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 // Just in case, assume it to be stopped.
4013 r.stopped = true;
4014 r.state = ActivityState.STOPPED;
4015 if (r.configDestroy) {
4016 destroyActivityLocked(r, true);
4017 }
4018 }
4019 }
4020 }
4021
4022 /**
4023 * @return Returns true if the activity is being finished, false if for
4024 * some reason it is being left as-is.
4025 */
4026 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4027 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004028 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 TAG, "Finishing activity: token=" + token
4030 + ", result=" + resultCode + ", data=" + resultData);
4031
Dianne Hackborn75b03852009-06-12 15:43:26 -07004032 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 if (index < 0) {
4034 return false;
4035 }
4036 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4037
4038 // Is this the last activity left?
4039 boolean lastActivity = true;
4040 for (int i=mHistory.size()-1; i>=0; i--) {
4041 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4042 if (!p.finishing && p != r) {
4043 lastActivity = false;
4044 break;
4045 }
4046 }
4047
4048 // If this is the last activity, but it is the home activity, then
4049 // just don't finish it.
4050 if (lastActivity) {
4051 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4052 return false;
4053 }
4054 }
4055
4056 finishActivityLocked(r, index, resultCode, resultData, reason);
4057 return true;
4058 }
4059
4060 /**
4061 * @return Returns true if this activity has been removed from the history
4062 * list, or false if it is still in the list and will be removed later.
4063 */
4064 private final boolean finishActivityLocked(HistoryRecord r, int index,
4065 int resultCode, Intent resultData, String reason) {
4066 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004067 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068 return false;
4069 }
4070
4071 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004072 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 System.identityHashCode(r),
4074 r.task.taskId, r.shortComponentName, reason);
4075 r.task.numActivities--;
4076 if (r.frontOfTask && index < (mHistory.size()-1)) {
4077 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4078 if (next.task == r.task) {
4079 next.frontOfTask = true;
4080 }
4081 }
4082
4083 r.pauseKeyDispatchingLocked();
4084 if (mFocusedActivity == r) {
4085 setFocusedActivityLocked(topRunningActivityLocked(null));
4086 }
4087
4088 // send the result
4089 HistoryRecord resultTo = r.resultTo;
4090 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004091 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004092 + " who=" + r.resultWho + " req=" + r.requestCode
4093 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 if (r.info.applicationInfo.uid > 0) {
4095 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4096 r.packageName, resultData, r);
4097 }
4098 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4099 resultData);
4100 r.resultTo = null;
4101 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004102 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103
4104 // Make sure this HistoryRecord is not holding on to other resources,
4105 // because clients have remote IPC references to this object so we
4106 // can't assume that will go away and want to avoid circular IPC refs.
4107 r.results = null;
4108 r.pendingResults = null;
4109 r.newIntents = null;
4110 r.icicle = null;
4111
4112 if (mPendingThumbnails.size() > 0) {
4113 // There are clients waiting to receive thumbnails so, in case
4114 // this is an activity that someone is waiting for, add it
4115 // to the pending list so we can correctly update the clients.
4116 mCancelledThumbnails.add(r);
4117 }
4118
4119 if (mResumedActivity == r) {
4120 boolean endTask = index <= 0
4121 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004122 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 "Prepare close transition: finishing " + r);
4124 mWindowManager.prepareAppTransition(endTask
4125 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4126 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4127
4128 // Tell window manager to prepare for this one to be removed.
4129 mWindowManager.setAppVisibility(r, false);
4130
4131 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004132 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4133 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 startPausingLocked(false, false);
4135 }
4136
4137 } else if (r.state != ActivityState.PAUSING) {
4138 // If the activity is PAUSING, we will complete the finish once
4139 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004140 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 return finishCurrentActivityLocked(r, index,
4142 FINISH_AFTER_PAUSE) == null;
4143 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004145 }
4146
4147 return false;
4148 }
4149
4150 private static final int FINISH_IMMEDIATELY = 0;
4151 private static final int FINISH_AFTER_PAUSE = 1;
4152 private static final int FINISH_AFTER_VISIBLE = 2;
4153
4154 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4155 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004156 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 if (index < 0) {
4158 return null;
4159 }
4160
4161 return finishCurrentActivityLocked(r, index, mode);
4162 }
4163
4164 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4165 int index, int mode) {
4166 // First things first: if this activity is currently visible,
4167 // and the resumed activity is not yet visible, then hold off on
4168 // finishing until the resumed one becomes visible.
4169 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4170 if (!mStoppingActivities.contains(r)) {
4171 mStoppingActivities.add(r);
4172 if (mStoppingActivities.size() > 3) {
4173 // If we already have a few activities waiting to stop,
4174 // then give up on things going idle and start clearing
4175 // them out.
4176 Message msg = Message.obtain();
4177 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4178 mHandler.sendMessage(msg);
4179 }
4180 }
4181 r.state = ActivityState.STOPPING;
4182 updateOomAdjLocked();
4183 return r;
4184 }
4185
4186 // make sure the record is cleaned out of other places.
4187 mStoppingActivities.remove(r);
4188 mWaitingVisibleActivities.remove(r);
4189 if (mResumedActivity == r) {
4190 mResumedActivity = null;
4191 }
4192 final ActivityState prevState = r.state;
4193 r.state = ActivityState.FINISHING;
4194
4195 if (mode == FINISH_IMMEDIATELY
4196 || prevState == ActivityState.STOPPED
4197 || prevState == ActivityState.INITIALIZING) {
4198 // If this activity is already stopped, we can just finish
4199 // it right now.
4200 return destroyActivityLocked(r, true) ? null : r;
4201 } else {
4202 // Need to go through the full pause cycle to get this
4203 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004204 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 mFinishingActivities.add(r);
4206 resumeTopActivityLocked(null);
4207 }
4208 return r;
4209 }
4210
4211 /**
4212 * This is the internal entry point for handling Activity.finish().
4213 *
4214 * @param token The Binder token referencing the Activity we want to finish.
4215 * @param resultCode Result code, if any, from this Activity.
4216 * @param resultData Result data (Intent), if any, from this Activity.
4217 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004218 * @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 -08004219 */
4220 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4221 // Refuse possible leaked file descriptors
4222 if (resultData != null && resultData.hasFileDescriptors() == true) {
4223 throw new IllegalArgumentException("File descriptors passed in Intent");
4224 }
4225
4226 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004227 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 // Find the first activity that is not finishing.
4229 HistoryRecord next = topRunningActivityLocked(token, 0);
4230 if (next != null) {
4231 // ask watcher if this is allowed
4232 boolean resumeOK = true;
4233 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004234 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004236 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
4238
4239 if (!resumeOK) {
4240 return false;
4241 }
4242 }
4243 }
4244 final long origId = Binder.clearCallingIdentity();
4245 boolean res = requestFinishActivityLocked(token, resultCode,
4246 resultData, "app-request");
4247 Binder.restoreCallingIdentity(origId);
4248 return res;
4249 }
4250 }
4251
4252 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4253 String resultWho, int requestCode, int resultCode, Intent data) {
4254
4255 if (callingUid > 0) {
4256 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4257 data, r);
4258 }
4259
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004261 + " : who=" + resultWho + " req=" + requestCode
4262 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4264 try {
4265 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4266 list.add(new ResultInfo(resultWho, requestCode,
4267 resultCode, data));
4268 r.app.thread.scheduleSendResult(r, list);
4269 return;
4270 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 }
4273 }
4274
4275 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4276 }
4277
4278 public final void finishSubActivity(IBinder token, String resultWho,
4279 int requestCode) {
4280 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004281 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 if (index < 0) {
4283 return;
4284 }
4285 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4286
4287 final long origId = Binder.clearCallingIdentity();
4288
4289 int i;
4290 for (i=mHistory.size()-1; i>=0; i--) {
4291 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4292 if (r.resultTo == self && r.requestCode == requestCode) {
4293 if ((r.resultWho == null && resultWho == null) ||
4294 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4295 finishActivityLocked(r, i,
4296 Activity.RESULT_CANCELED, null, "request-sub");
4297 }
4298 }
4299 }
4300
4301 Binder.restoreCallingIdentity(origId);
4302 }
4303 }
4304
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004305 public boolean willActivityBeVisible(IBinder token) {
4306 synchronized(this) {
4307 int i;
4308 for (i=mHistory.size()-1; i>=0; i--) {
4309 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4310 if (r == token) {
4311 return true;
4312 }
4313 if (r.fullscreen && !r.finishing) {
4314 return false;
4315 }
4316 }
4317 return true;
4318 }
4319 }
4320
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004321 public void overridePendingTransition(IBinder token, String packageName,
4322 int enterAnim, int exitAnim) {
4323 synchronized(this) {
4324 int index = indexOfTokenLocked(token);
4325 if (index < 0) {
4326 return;
4327 }
4328 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4329
4330 final long origId = Binder.clearCallingIdentity();
4331
4332 if (self.state == ActivityState.RESUMED
4333 || self.state == ActivityState.PAUSING) {
4334 mWindowManager.overridePendingAppTransition(packageName,
4335 enterAnim, exitAnim);
4336 }
4337
4338 Binder.restoreCallingIdentity(origId);
4339 }
4340 }
4341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 /**
4343 * Perform clean-up of service connections in an activity record.
4344 */
4345 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4346 // Throw away any services that have been bound by this activity.
4347 if (r.connections != null) {
4348 Iterator<ConnectionRecord> it = r.connections.iterator();
4349 while (it.hasNext()) {
4350 ConnectionRecord c = it.next();
4351 removeConnectionLocked(c, null, r);
4352 }
4353 r.connections = null;
4354 }
4355 }
4356
4357 /**
4358 * Perform the common clean-up of an activity record. This is called both
4359 * as part of destroyActivityLocked() (when destroying the client-side
4360 * representation) and cleaning things up as a result of its hosting
4361 * processing going away, in which case there is no remaining client-side
4362 * state to destroy so only the cleanup here is needed.
4363 */
4364 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4365 if (mResumedActivity == r) {
4366 mResumedActivity = null;
4367 }
4368 if (mFocusedActivity == r) {
4369 mFocusedActivity = null;
4370 }
4371
4372 r.configDestroy = false;
4373 r.frozenBeforeDestroy = false;
4374
4375 // Make sure this record is no longer in the pending finishes list.
4376 // This could happen, for example, if we are trimming activities
4377 // down to the max limit while they are still waiting to finish.
4378 mFinishingActivities.remove(r);
4379 mWaitingVisibleActivities.remove(r);
4380
4381 // Remove any pending results.
4382 if (r.finishing && r.pendingResults != null) {
4383 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4384 PendingIntentRecord rec = apr.get();
4385 if (rec != null) {
4386 cancelIntentSenderLocked(rec, false);
4387 }
4388 }
4389 r.pendingResults = null;
4390 }
4391
4392 if (cleanServices) {
4393 cleanUpActivityServicesLocked(r);
4394 }
4395
4396 if (mPendingThumbnails.size() > 0) {
4397 // There are clients waiting to receive thumbnails so, in case
4398 // this is an activity that someone is waiting for, add it
4399 // to the pending list so we can correctly update the clients.
4400 mCancelledThumbnails.add(r);
4401 }
4402
4403 // Get rid of any pending idle timeouts.
4404 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4405 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4406 }
4407
4408 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4409 if (r.state != ActivityState.DESTROYED) {
4410 mHistory.remove(r);
4411 r.inHistory = false;
4412 r.state = ActivityState.DESTROYED;
4413 mWindowManager.removeAppToken(r);
4414 if (VALIDATE_TOKENS) {
4415 mWindowManager.validateAppTokens(mHistory);
4416 }
4417 cleanUpActivityServicesLocked(r);
4418 removeActivityUriPermissionsLocked(r);
4419 }
4420 }
4421
4422 /**
4423 * Destroy the current CLIENT SIDE instance of an activity. This may be
4424 * called both when actually finishing an activity, or when performing
4425 * a configuration switch where we destroy the current client-side object
4426 * but then create a new client-side object for this same HistoryRecord.
4427 */
4428 private final boolean destroyActivityLocked(HistoryRecord r,
4429 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004430 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 TAG, "Removing activity: token=" + r
4432 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004433 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 System.identityHashCode(r),
4435 r.task.taskId, r.shortComponentName);
4436
4437 boolean removedFromHistory = false;
4438
4439 cleanUpActivityLocked(r, false);
4440
Dianne Hackborn03abb812010-01-04 18:43:19 -08004441 final boolean hadApp = r.app != null;
4442
4443 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 if (removeFromApp) {
4445 int idx = r.app.activities.indexOf(r);
4446 if (idx >= 0) {
4447 r.app.activities.remove(idx);
4448 }
4449 if (r.persistent) {
4450 decPersistentCountLocked(r.app);
4451 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004452 if (r.app.activities.size() == 0) {
4453 // No longer have activities, so update location in
4454 // LRU list.
4455 updateLruProcessLocked(r.app, true, false);
4456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 }
4458
4459 boolean skipDestroy = false;
4460
4461 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004462 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4464 r.configChangeFlags);
4465 } catch (Exception e) {
4466 // We can just ignore exceptions here... if the process
4467 // has crashed, our death notification will clean things
4468 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004469 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 if (r.finishing) {
4471 removeActivityFromHistoryLocked(r);
4472 removedFromHistory = true;
4473 skipDestroy = true;
4474 }
4475 }
4476
4477 r.app = null;
4478 r.nowVisible = false;
4479
4480 if (r.finishing && !skipDestroy) {
4481 r.state = ActivityState.DESTROYING;
4482 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4483 msg.obj = r;
4484 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4485 } else {
4486 r.state = ActivityState.DESTROYED;
4487 }
4488 } else {
4489 // remove this record from the history.
4490 if (r.finishing) {
4491 removeActivityFromHistoryLocked(r);
4492 removedFromHistory = true;
4493 } else {
4494 r.state = ActivityState.DESTROYED;
4495 }
4496 }
4497
4498 r.configChangeFlags = 0;
4499
Dianne Hackborn03abb812010-01-04 18:43:19 -08004500 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004501 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 }
4503
4504 return removedFromHistory;
4505 }
4506
Dianne Hackborn03abb812010-01-04 18:43:19 -08004507 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004509 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 TAG, "Removing app " + app + " from list " + list
4511 + " with " + i + " entries");
4512 while (i > 0) {
4513 i--;
4514 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004515 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4517 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004518 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 list.remove(i);
4520 }
4521 }
4522 }
4523
4524 /**
4525 * Main function for removing an existing process from the activity manager
4526 * as a result of that process going away. Clears out all connections
4527 * to the process.
4528 */
4529 private final void handleAppDiedLocked(ProcessRecord app,
4530 boolean restarting) {
4531 cleanUpApplicationRecordLocked(app, restarting, -1);
4532 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004533 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 }
4535
4536 // Just in case...
4537 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004538 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 mPausingActivity = null;
4540 }
4541 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4542 mLastPausedActivity = null;
4543 }
4544
4545 // Remove this application's activities from active lists.
4546 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4547 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4548 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4549 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4550
4551 boolean atTop = true;
4552 boolean hasVisibleActivities = false;
4553
4554 // Clean out the history list.
4555 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004556 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004557 TAG, "Removing app " + app + " from history with " + i + " entries");
4558 while (i > 0) {
4559 i--;
4560 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4563 if (r.app == app) {
4564 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004565 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 TAG, "Removing this entry! frozen=" + r.haveState
4567 + " finishing=" + r.finishing);
4568 mHistory.remove(i);
4569
4570 r.inHistory = false;
4571 mWindowManager.removeAppToken(r);
4572 if (VALIDATE_TOKENS) {
4573 mWindowManager.validateAppTokens(mHistory);
4574 }
4575 removeActivityUriPermissionsLocked(r);
4576
4577 } else {
4578 // We have the current state for this activity, so
4579 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004580 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 TAG, "Keeping entry, setting app to null");
4582 if (r.visible) {
4583 hasVisibleActivities = true;
4584 }
4585 r.app = null;
4586 r.nowVisible = false;
4587 if (!r.haveState) {
4588 r.icicle = null;
4589 }
4590 }
4591
4592 cleanUpActivityLocked(r, true);
4593 r.state = ActivityState.STOPPED;
4594 }
4595 atTop = false;
4596 }
4597
4598 app.activities.clear();
4599
4600 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004601 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 + " running instrumentation " + app.instrumentationClass);
4603 Bundle info = new Bundle();
4604 info.putString("shortMsg", "Process crashed.");
4605 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4606 }
4607
4608 if (!restarting) {
4609 if (!resumeTopActivityLocked(null)) {
4610 // If there was nothing to resume, and we are not already
4611 // restarting this process, but there is a visible activity that
4612 // is hosted by the process... then make sure all visible
4613 // activities are running, taking care of restarting this
4614 // process.
4615 if (hasVisibleActivities) {
4616 ensureActivitiesVisibleLocked(null, 0);
4617 }
4618 }
4619 }
4620 }
4621
4622 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4623 IBinder threadBinder = thread.asBinder();
4624
4625 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004626 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4627 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4629 return i;
4630 }
4631 }
4632 return -1;
4633 }
4634
4635 private final ProcessRecord getRecordForAppLocked(
4636 IApplicationThread thread) {
4637 if (thread == null) {
4638 return null;
4639 }
4640
4641 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004642 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 }
4644
4645 private final void appDiedLocked(ProcessRecord app, int pid,
4646 IApplicationThread thread) {
4647
4648 mProcDeaths[0]++;
4649
Magnus Edlund7bb25812010-02-24 15:45:06 +01004650 // Clean up already done if the process has been re-started.
4651 if (app.pid == pid && app.thread != null &&
4652 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004653 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004655 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004656 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 TAG, "Dying app: " + app + ", pid: " + pid
4658 + ", thread: " + thread.asBinder());
4659 boolean doLowMem = app.instrumentationClass == null;
4660 handleAppDiedLocked(app, false);
4661
4662 if (doLowMem) {
4663 // If there are no longer any background processes running,
4664 // and the app that died was not running instrumentation,
4665 // then tell everyone we are now low on memory.
4666 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004667 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4668 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4670 haveBg = true;
4671 break;
4672 }
4673 }
4674
4675 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004676 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004677 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004678 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004679 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4680 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004681 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004682 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4683 // The low memory report is overriding any current
4684 // state for a GC request. Make sure to do
4685 // visible/foreground processes first.
4686 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4687 rec.lastRequestedGc = 0;
4688 } else {
4689 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004690 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004691 rec.reportLowMemory = true;
4692 rec.lastLowMemory = now;
4693 mProcessesToGc.remove(rec);
4694 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 }
4696 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004697 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 }
4699 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004700 } else if (app.pid != pid) {
4701 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004702 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004703 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004704 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004705 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004706 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 + thread.asBinder());
4708 }
4709 }
4710
Dan Egnor42471dd2010-01-07 17:25:22 -08004711 /**
4712 * If a stack trace dump file is configured, dump process stack traces.
4713 * @param pids of dalvik VM processes to dump stack traces for
4714 * @return file containing stack traces, or null if no dump file is configured
4715 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004716 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004717 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4718 if (tracesPath == null || tracesPath.length() == 0) {
4719 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004721
4722 File tracesFile = new File(tracesPath);
4723 try {
4724 File tracesDir = tracesFile.getParentFile();
4725 if (!tracesDir.exists()) tracesFile.mkdirs();
4726 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4727
4728 if (tracesFile.exists()) tracesFile.delete();
4729 tracesFile.createNewFile();
4730 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4731 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004732 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004733 return null;
4734 }
4735
4736 // Use a FileObserver to detect when traces finish writing.
4737 // The order of traces is considered important to maintain for legibility.
4738 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4739 public synchronized void onEvent(int event, String path) { notify(); }
4740 };
4741
4742 try {
4743 observer.startWatching();
4744 int num = pids.size();
4745 for (int i = 0; i < num; i++) {
4746 synchronized (observer) {
4747 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4748 observer.wait(200); // Wait for write-close, give up after 200msec
4749 }
4750 }
4751 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004752 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004753 } finally {
4754 observer.stopWatching();
4755 }
4756
4757 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004758 }
4759
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004760 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004761 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004762 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004763
4764 synchronized (this) {
4765 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4766 if (mShuttingDown) {
4767 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4768 return;
4769 } else if (app.notResponding) {
4770 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4771 return;
4772 } else if (app.crashing) {
4773 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4774 return;
4775 }
4776
4777 // In case we come through here for the same app before completing
4778 // this one, mark as anring now so we will bail out.
4779 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004780
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004781 // Log the ANR to the event log.
4782 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4783 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004784
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004785 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4786 pids.add(app.pid);
4787
4788 int parentPid = app.pid;
4789 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4790 if (parentPid != app.pid) pids.add(parentPid);
4791
4792 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004793
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004794 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4795 ProcessRecord r = mLruProcesses.get(i);
4796 if (r != null && r.thread != null) {
4797 int pid = r.pid;
4798 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 }
4801 }
4802
Dan Egnor42471dd2010-01-07 17:25:22 -08004803 File tracesFile = dumpStackTraces(pids);
4804
4805 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004806 StringBuilder info = mStringBuilder;
4807 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004808 info.append("ANR in ").append(app.processName);
4809 if (activity != null && activity.shortComponentName != null) {
4810 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004811 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004812 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004814 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004816 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004817 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819
Dan Egnor42471dd2010-01-07 17:25:22 -08004820 String cpuInfo = null;
4821 if (MONITOR_CPU_USAGE) {
4822 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004823 synchronized (mProcessStatsThread) {
4824 cpuInfo = mProcessStats.printCurrentState();
4825 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004826 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 }
4828
Joe Onorato8a9b2202010-02-26 18:56:32 -08004829 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004830 if (tracesFile == null) {
4831 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4832 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4833 }
4834
4835 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4836
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004837 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004839 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4840 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004842 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4843 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 }
4845 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004846 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 }
4848 }
4849
Dan Egnor42471dd2010-01-07 17:25:22 -08004850 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4851 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4852 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004853
4854 synchronized (this) {
4855 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4856 Process.killProcess(app.pid);
4857 return;
4858 }
4859
4860 // Set the app's notResponding state, and look up the errorReportReceiver
4861 makeAppNotRespondingLocked(app,
4862 activity != null ? activity.shortComponentName : null,
4863 annotation != null ? "ANR " + annotation : "ANR",
4864 info.toString());
4865
4866 // Bring up the infamous App Not Responding dialog
4867 Message msg = Message.obtain();
4868 HashMap map = new HashMap();
4869 msg.what = SHOW_NOT_RESPONDING_MSG;
4870 msg.obj = map;
4871 map.put("app", app);
4872 if (activity != null) {
4873 map.put("activity", activity);
4874 }
4875
4876 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 }
4879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 private final void decPersistentCountLocked(ProcessRecord app)
4881 {
4882 app.persistentActivities--;
4883 if (app.persistentActivities > 0) {
4884 // Still more of 'em...
4885 return;
4886 }
4887 if (app.persistent) {
4888 // Ah, but the application itself is persistent. Whatever!
4889 return;
4890 }
4891
4892 // App is no longer persistent... make sure it and the ones
4893 // following it in the LRU list have the correc oom_adj.
4894 updateOomAdjLocked();
4895 }
4896
4897 public void setPersistent(IBinder token, boolean isPersistent) {
4898 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4899 != PackageManager.PERMISSION_GRANTED) {
4900 String msg = "Permission Denial: setPersistent() from pid="
4901 + Binder.getCallingPid()
4902 + ", uid=" + Binder.getCallingUid()
4903 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004904 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 throw new SecurityException(msg);
4906 }
4907
4908 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004909 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 if (index < 0) {
4911 return;
4912 }
4913 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4914 ProcessRecord app = r.app;
4915
Joe Onorato8a9b2202010-02-26 18:56:32 -08004916 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 TAG, "Setting persistence " + isPersistent + ": " + r);
4918
4919 if (isPersistent) {
4920 if (r.persistent) {
4921 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004922 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 return;
4924 }
4925 r.persistent = true;
4926 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004927 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 if (app.persistentActivities > 1) {
4929 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004930 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 return;
4932 }
4933 if (app.persistent) {
4934 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004935 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 return;
4937 }
4938
4939 // App is now persistent... make sure it and the ones
4940 // following it now have the correct oom_adj.
4941 final long origId = Binder.clearCallingIdentity();
4942 updateOomAdjLocked();
4943 Binder.restoreCallingIdentity(origId);
4944
4945 } else {
4946 if (!r.persistent) {
4947 // Okay okay, I heard you already!
4948 return;
4949 }
4950 r.persistent = false;
4951 final long origId = Binder.clearCallingIdentity();
4952 decPersistentCountLocked(app);
4953 Binder.restoreCallingIdentity(origId);
4954
4955 }
4956 }
4957 }
4958
4959 public boolean clearApplicationUserData(final String packageName,
4960 final IPackageDataObserver observer) {
4961 int uid = Binder.getCallingUid();
4962 int pid = Binder.getCallingPid();
4963 long callingId = Binder.clearCallingIdentity();
4964 try {
4965 IPackageManager pm = ActivityThread.getPackageManager();
4966 int pkgUid = -1;
4967 synchronized(this) {
4968 try {
4969 pkgUid = pm.getPackageUid(packageName);
4970 } catch (RemoteException e) {
4971 }
4972 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004973 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004974 return false;
4975 }
4976 if (uid == pkgUid || checkComponentPermission(
4977 android.Manifest.permission.CLEAR_APP_USER_DATA,
4978 pid, uid, -1)
4979 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004980 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 } else {
4982 throw new SecurityException(pid+" does not have permission:"+
4983 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4984 "for process:"+packageName);
4985 }
4986 }
4987
4988 try {
4989 //clear application user data
4990 pm.clearApplicationUserData(packageName, observer);
4991 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4992 Uri.fromParts("package", packageName, null));
4993 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06004994 synchronized (this) {
4995 broadcastIntentLocked(null, null, intent,
4996 null, null, 0, null, null, null,
4997 false, false, MY_PID, Process.SYSTEM_UID);
4998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 } catch (RemoteException e) {
5000 }
5001 } finally {
5002 Binder.restoreCallingIdentity(callingId);
5003 }
5004 return true;
5005 }
5006
Dianne Hackborn03abb812010-01-04 18:43:19 -08005007 public void killBackgroundProcesses(final String packageName) {
5008 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5009 != PackageManager.PERMISSION_GRANTED &&
5010 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5011 != PackageManager.PERMISSION_GRANTED) {
5012 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 + Binder.getCallingPid()
5014 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005015 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005016 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 throw new SecurityException(msg);
5018 }
5019
5020 long callingId = Binder.clearCallingIdentity();
5021 try {
5022 IPackageManager pm = ActivityThread.getPackageManager();
5023 int pkgUid = -1;
5024 synchronized(this) {
5025 try {
5026 pkgUid = pm.getPackageUid(packageName);
5027 } catch (RemoteException e) {
5028 }
5029 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005030 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 return;
5032 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005033 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005034 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005035 }
5036 } finally {
5037 Binder.restoreCallingIdentity(callingId);
5038 }
5039 }
5040
5041 public void forceStopPackage(final String packageName) {
5042 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5043 != PackageManager.PERMISSION_GRANTED) {
5044 String msg = "Permission Denial: forceStopPackage() from pid="
5045 + Binder.getCallingPid()
5046 + ", uid=" + Binder.getCallingUid()
5047 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005048 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005049 throw new SecurityException(msg);
5050 }
5051
5052 long callingId = Binder.clearCallingIdentity();
5053 try {
5054 IPackageManager pm = ActivityThread.getPackageManager();
5055 int pkgUid = -1;
5056 synchronized(this) {
5057 try {
5058 pkgUid = pm.getPackageUid(packageName);
5059 } catch (RemoteException e) {
5060 }
5061 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005062 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005063 return;
5064 }
5065 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 }
5067 } finally {
5068 Binder.restoreCallingIdentity(callingId);
5069 }
5070 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005071
5072 /*
5073 * The pkg name and uid have to be specified.
5074 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5075 */
5076 public void killApplicationWithUid(String pkg, int uid) {
5077 if (pkg == null) {
5078 return;
5079 }
5080 // Make sure the uid is valid.
5081 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005082 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005083 return;
5084 }
5085 int callerUid = Binder.getCallingUid();
5086 // Only the system server can kill an application
5087 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005088 // Post an aysnc message to kill the application
5089 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5090 msg.arg1 = uid;
5091 msg.arg2 = 0;
5092 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005093 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005094 } else {
5095 throw new SecurityException(callerUid + " cannot kill pkg: " +
5096 pkg);
5097 }
5098 }
5099
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005100 public void closeSystemDialogs(String reason) {
5101 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5102 if (reason != null) {
5103 intent.putExtra("reason", reason);
5104 }
5105
5106 final int uid = Binder.getCallingUid();
5107 final long origId = Binder.clearCallingIdentity();
5108 synchronized (this) {
5109 int i = mWatchers.beginBroadcast();
5110 while (i > 0) {
5111 i--;
5112 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5113 if (w != null) {
5114 try {
5115 w.closingSystemDialogs(reason);
5116 } catch (RemoteException e) {
5117 }
5118 }
5119 }
5120 mWatchers.finishBroadcast();
5121
Dianne Hackbornffa42482009-09-23 22:20:11 -07005122 mWindowManager.closeSystemDialogs(reason);
5123
5124 for (i=mHistory.size()-1; i>=0; i--) {
5125 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5126 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5127 finishActivityLocked(r, i,
5128 Activity.RESULT_CANCELED, null, "close-sys");
5129 }
5130 }
5131
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005132 broadcastIntentLocked(null, null, intent, null,
5133 null, 0, null, null, null, false, false, -1, uid);
5134 }
5135 Binder.restoreCallingIdentity(origId);
5136 }
5137
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005138 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005139 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005140 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5141 for (int i=pids.length-1; i>=0; i--) {
5142 infos[i] = new Debug.MemoryInfo();
5143 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005144 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005145 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005146 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005147
5148 public void killApplicationProcess(String processName, int uid) {
5149 if (processName == null) {
5150 return;
5151 }
5152
5153 int callerUid = Binder.getCallingUid();
5154 // Only the system server can kill an application
5155 if (callerUid == Process.SYSTEM_UID) {
5156 synchronized (this) {
5157 ProcessRecord app = getProcessRecordLocked(processName, uid);
5158 if (app != null) {
5159 try {
5160 app.thread.scheduleSuicide();
5161 } catch (RemoteException e) {
5162 // If the other end already died, then our work here is done.
5163 }
5164 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005165 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005166 + processName + " / " + uid);
5167 }
5168 }
5169 } else {
5170 throw new SecurityException(callerUid + " cannot kill app process: " +
5171 processName);
5172 }
5173 }
5174
Dianne Hackborn03abb812010-01-04 18:43:19 -08005175 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005176 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5178 Uri.fromParts("package", packageName, null));
5179 intent.putExtra(Intent.EXTRA_UID, uid);
5180 broadcastIntentLocked(null, null, intent,
5181 null, null, 0, null, null, null,
5182 false, false, MY_PID, Process.SYSTEM_UID);
5183 }
5184
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005185 private final boolean killPackageProcessesLocked(String packageName, int uid,
5186 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005187 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188
Dianne Hackborn03abb812010-01-04 18:43:19 -08005189 // Remove all processes this package may have touched: all with the
5190 // same UID (except for the system or root user), and all whose name
5191 // matches the package name.
5192 final String procNamePrefix = packageName + ":";
5193 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5194 final int NA = apps.size();
5195 for (int ia=0; ia<NA; ia++) {
5196 ProcessRecord app = apps.valueAt(ia);
5197 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005198 if (doit) {
5199 procs.add(app);
5200 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005201 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5202 || app.processName.equals(packageName)
5203 || app.processName.startsWith(procNamePrefix)) {
5204 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005205 if (!doit) {
5206 return true;
5207 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005208 app.removed = true;
5209 procs.add(app);
5210 }
5211 }
5212 }
5213 }
5214
5215 int N = procs.size();
5216 for (int i=0; i<N; i++) {
5217 removeProcessLocked(procs.get(i), callerWillRestart);
5218 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005219 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005220 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005221
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005222 private final boolean forceStopPackageLocked(String name, int uid,
5223 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 int i, N;
5225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 if (uid < 0) {
5227 try {
5228 uid = ActivityThread.getPackageManager().getPackageUid(name);
5229 } catch (RemoteException e) {
5230 }
5231 }
5232
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005233 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005234 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005235
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005236 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5237 while (badApps.hasNext()) {
5238 SparseArray<Long> ba = badApps.next();
5239 if (ba.get(uid) != null) {
5240 badApps.remove();
5241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 }
5243 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005244
5245 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5246 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247
5248 for (i=mHistory.size()-1; i>=0; i--) {
5249 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5250 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005251 if (!doit) {
5252 return true;
5253 }
5254 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005255 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 if (r.app != null) {
5257 r.app.removed = true;
5258 }
5259 r.app = null;
5260 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5261 }
5262 }
5263
5264 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5265 for (ServiceRecord service : mServices.values()) {
5266 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005267 if (!doit) {
5268 return true;
5269 }
5270 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005271 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 if (service.app != null) {
5273 service.app.removed = true;
5274 }
5275 service.app = null;
5276 services.add(service);
5277 }
5278 }
5279
5280 N = services.size();
5281 for (i=0; i<N; i++) {
5282 bringDownServiceLocked(services.get(i), true);
5283 }
5284
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005285 if (doit) {
5286 if (purgeCache) {
5287 AttributeCache ac = AttributeCache.instance();
5288 if (ac != null) {
5289 ac.removePackage(name);
5290 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005291 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005292 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005293 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005294
5295 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 }
5297
5298 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5299 final String name = app.processName;
5300 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005301 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 TAG, "Force removing process " + app + " (" + name
5303 + "/" + uid + ")");
5304
5305 mProcessNames.remove(name, uid);
5306 boolean needRestart = false;
5307 if (app.pid > 0 && app.pid != MY_PID) {
5308 int pid = app.pid;
5309 synchronized (mPidsSelfLocked) {
5310 mPidsSelfLocked.remove(pid);
5311 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5312 }
5313 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005314 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 Process.killProcess(pid);
5316
5317 if (app.persistent) {
5318 if (!callerWillRestart) {
5319 addAppLocked(app.info);
5320 } else {
5321 needRestart = true;
5322 }
5323 }
5324 } else {
5325 mRemovedProcesses.add(app);
5326 }
5327
5328 return needRestart;
5329 }
5330
5331 private final void processStartTimedOutLocked(ProcessRecord app) {
5332 final int pid = app.pid;
5333 boolean gone = false;
5334 synchronized (mPidsSelfLocked) {
5335 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5336 if (knownApp != null && knownApp.thread == null) {
5337 mPidsSelfLocked.remove(pid);
5338 gone = true;
5339 }
5340 }
5341
5342 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005343 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005344 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005345 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005347 // Take care of any launching providers waiting for this process.
5348 checkAppInLaunchingProvidersLocked(app, true);
5349 // Take care of any services that are waiting for the process.
5350 for (int i=0; i<mPendingServices.size(); i++) {
5351 ServiceRecord sr = mPendingServices.get(i);
5352 if (app.info.uid == sr.appInfo.uid
5353 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005354 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005355 mPendingServices.remove(i);
5356 i--;
5357 bringDownServiceLocked(sr, true);
5358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005360 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005361 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005362 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005363 try {
5364 IBackupManager bm = IBackupManager.Stub.asInterface(
5365 ServiceManager.getService(Context.BACKUP_SERVICE));
5366 bm.agentDisconnected(app.info.packageName);
5367 } catch (RemoteException e) {
5368 // Can't happen; the backup manager is local
5369 }
5370 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005371 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005372 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005373 mPendingBroadcast = null;
5374 scheduleBroadcastsLocked();
5375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005377 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 }
5379 }
5380
5381 private final boolean attachApplicationLocked(IApplicationThread thread,
5382 int pid) {
5383
5384 // Find the application record that is being attached... either via
5385 // the pid if we are running in multiple processes, or just pull the
5386 // next app record if we are emulating process with anonymous threads.
5387 ProcessRecord app;
5388 if (pid != MY_PID && pid >= 0) {
5389 synchronized (mPidsSelfLocked) {
5390 app = mPidsSelfLocked.get(pid);
5391 }
5392 } else if (mStartingProcesses.size() > 0) {
5393 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005394 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 } else {
5396 app = null;
5397 }
5398
5399 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005402 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 if (pid > 0 && pid != MY_PID) {
5404 Process.killProcess(pid);
5405 } else {
5406 try {
5407 thread.scheduleExit();
5408 } catch (Exception e) {
5409 // Ignore exceptions.
5410 }
5411 }
5412 return false;
5413 }
5414
5415 // If this application record is still attached to a previous
5416 // process, clean it up now.
5417 if (app.thread != null) {
5418 handleAppDiedLocked(app, true);
5419 }
5420
5421 // Tell the process all about itself.
5422
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 TAG, "Binding process pid " + pid + " to record " + app);
5425
5426 String processName = app.processName;
5427 try {
5428 thread.asBinder().linkToDeath(new AppDeathRecipient(
5429 app, pid, thread), 0);
5430 } catch (RemoteException e) {
5431 app.resetPackageList();
5432 startProcessLocked(app, "link fail", processName);
5433 return false;
5434 }
5435
Doug Zongker2bec3d42009-12-04 12:52:44 -08005436 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437
5438 app.thread = thread;
5439 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005440 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5441 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 app.forcingToForeground = null;
5443 app.foregroundServices = false;
5444 app.debugging = false;
5445
5446 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5447
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005448 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5449 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005450
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005451 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005452 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005453 }
5454
Joe Onorato8a9b2202010-02-26 18:56:32 -08005455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 TAG, "New app record " + app
5457 + " thread=" + thread.asBinder() + " pid=" + pid);
5458 try {
5459 int testMode = IApplicationThread.DEBUG_OFF;
5460 if (mDebugApp != null && mDebugApp.equals(processName)) {
5461 testMode = mWaitForDebugger
5462 ? IApplicationThread.DEBUG_WAIT
5463 : IApplicationThread.DEBUG_ON;
5464 app.debugging = true;
5465 if (mDebugTransient) {
5466 mDebugApp = mOrigDebugApp;
5467 mWaitForDebugger = mOrigWaitForDebugger;
5468 }
5469 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005470
Christopher Tate181fafa2009-05-14 11:12:14 -07005471 // If the app is being launched for restore or full backup, set it up specially
5472 boolean isRestrictedBackupMode = false;
5473 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5474 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5475 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5476 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005477
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005478 ensurePackageDexOpt(app.instrumentationInfo != null
5479 ? app.instrumentationInfo.packageName
5480 : app.info.packageName);
5481 if (app.instrumentationClass != null) {
5482 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005483 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005484 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005485 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005486 thread.bindApplication(processName, app.instrumentationInfo != null
5487 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 app.instrumentationClass, app.instrumentationProfileFile,
5489 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005490 isRestrictedBackupMode || !normalMode,
5491 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005492 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005493 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 } catch (Exception e) {
5495 // todo: Yikes! What should we do? For now we will try to
5496 // start another process, but that could easily get us in
5497 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005498 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499
5500 app.resetPackageList();
5501 startProcessLocked(app, "bind fail", processName);
5502 return false;
5503 }
5504
5505 // Remove this record from the list of starting applications.
5506 mPersistentStartingProcesses.remove(app);
5507 mProcessesOnHold.remove(app);
5508
5509 boolean badApp = false;
5510 boolean didSomething = false;
5511
5512 // See if the top visible activity is waiting to run in this process...
5513 HistoryRecord hr = topRunningActivityLocked(null);
5514 if (hr != null) {
5515 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5516 && processName.equals(hr.processName)) {
5517 try {
5518 if (realStartActivityLocked(hr, app, true, true)) {
5519 didSomething = true;
5520 }
5521 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005522 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 + hr.intent.getComponent().flattenToShortString(), e);
5524 badApp = true;
5525 }
5526 } else {
5527 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5528 }
5529 }
5530
5531 // Find any services that should be running in this process...
5532 if (!badApp && mPendingServices.size() > 0) {
5533 ServiceRecord sr = null;
5534 try {
5535 for (int i=0; i<mPendingServices.size(); i++) {
5536 sr = mPendingServices.get(i);
5537 if (app.info.uid != sr.appInfo.uid
5538 || !processName.equals(sr.processName)) {
5539 continue;
5540 }
5541
5542 mPendingServices.remove(i);
5543 i--;
5544 realStartServiceLocked(sr, app);
5545 didSomething = true;
5546 }
5547 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005548 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 + sr.shortName, e);
5550 badApp = true;
5551 }
5552 }
5553
5554 // Check if the next broadcast receiver is in this process...
5555 BroadcastRecord br = mPendingBroadcast;
5556 if (!badApp && br != null && br.curApp == app) {
5557 try {
5558 mPendingBroadcast = null;
5559 processCurBroadcastLocked(br, app);
5560 didSomething = true;
5561 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005562 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 + br.curComponent.flattenToShortString(), e);
5564 badApp = true;
5565 logBroadcastReceiverDiscard(br);
5566 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5567 br.resultExtras, br.resultAbort, true);
5568 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005569 // We need to reset the state if we fails to start the receiver.
5570 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 }
5572 }
5573
Christopher Tate181fafa2009-05-14 11:12:14 -07005574 // Check whether the next backup agent is in this process...
5575 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005576 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005577 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005578 try {
5579 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5580 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005581 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005582 e.printStackTrace();
5583 }
5584 }
5585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 if (badApp) {
5587 // todo: Also need to kill application to deal with all
5588 // kinds of exceptions.
5589 handleAppDiedLocked(app, false);
5590 return false;
5591 }
5592
5593 if (!didSomething) {
5594 updateOomAdjLocked();
5595 }
5596
5597 return true;
5598 }
5599
5600 public final void attachApplication(IApplicationThread thread) {
5601 synchronized (this) {
5602 int callingPid = Binder.getCallingPid();
5603 final long origId = Binder.clearCallingIdentity();
5604 attachApplicationLocked(thread, callingPid);
5605 Binder.restoreCallingIdentity(origId);
5606 }
5607 }
5608
Dianne Hackborne88846e2009-09-30 21:34:25 -07005609 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005610 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005611 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 Binder.restoreCallingIdentity(origId);
5613 }
5614
5615 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5616 boolean remove) {
5617 int N = mStoppingActivities.size();
5618 if (N <= 0) return null;
5619
5620 ArrayList<HistoryRecord> stops = null;
5621
5622 final boolean nowVisible = mResumedActivity != null
5623 && mResumedActivity.nowVisible
5624 && !mResumedActivity.waitingVisible;
5625 for (int i=0; i<N; i++) {
5626 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005627 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 + nowVisible + " waitingVisible=" + s.waitingVisible
5629 + " finishing=" + s.finishing);
5630 if (s.waitingVisible && nowVisible) {
5631 mWaitingVisibleActivities.remove(s);
5632 s.waitingVisible = false;
5633 if (s.finishing) {
5634 // If this activity is finishing, it is sitting on top of
5635 // everyone else but we now know it is no longer needed...
5636 // so get rid of it. Otherwise, we need to go through the
5637 // normal flow and hide it once we determine that it is
5638 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005639 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 mWindowManager.setAppVisibility(s, false);
5641 }
5642 }
5643 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005644 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 if (stops == null) {
5646 stops = new ArrayList<HistoryRecord>();
5647 }
5648 stops.add(s);
5649 mStoppingActivities.remove(i);
5650 N--;
5651 i--;
5652 }
5653 }
5654
5655 return stops;
5656 }
5657
5658 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005659 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005660 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 mWindowManager.enableScreenAfterBoot();
5662 }
5663
Dianne Hackborne88846e2009-09-30 21:34:25 -07005664 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5665 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005666 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667
5668 ArrayList<HistoryRecord> stops = null;
5669 ArrayList<HistoryRecord> finishes = null;
5670 ArrayList<HistoryRecord> thumbnails = null;
5671 int NS = 0;
5672 int NF = 0;
5673 int NT = 0;
5674 IApplicationThread sendThumbnail = null;
5675 boolean booting = false;
5676 boolean enableScreen = false;
5677
5678 synchronized (this) {
5679 if (token != null) {
5680 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5681 }
5682
5683 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005684 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 if (index >= 0) {
5686 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5687
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005688 if (fromTimeout) {
5689 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5690 }
5691
Dianne Hackborne88846e2009-09-30 21:34:25 -07005692 // This is a hack to semi-deal with a race condition
5693 // in the client where it can be constructed with a
5694 // newer configuration from when we asked it to launch.
5695 // We'll update with whatever configuration it now says
5696 // it used to launch.
5697 if (config != null) {
5698 r.configuration = config;
5699 }
5700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 // No longer need to keep the device awake.
5702 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5703 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5704 mLaunchingActivity.release();
5705 }
5706
5707 // We are now idle. If someone is waiting for a thumbnail from
5708 // us, we can now deliver.
5709 r.idle = true;
5710 scheduleAppGcsLocked();
5711 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5712 sendThumbnail = r.app.thread;
5713 r.thumbnailNeeded = false;
5714 }
5715
5716 // If this activity is fullscreen, set up to hide those under it.
5717
Joe Onorato8a9b2202010-02-26 18:56:32 -08005718 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 ensureActivitiesVisibleLocked(null, 0);
5720
Joe Onorato8a9b2202010-02-26 18:56:32 -08005721 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 if (!mBooted && !fromTimeout) {
5723 mBooted = true;
5724 enableScreen = true;
5725 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005726
5727 } else if (fromTimeout) {
5728 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005729 }
5730
5731 // Atomically retrieve all of the other things to do.
5732 stops = processStoppingActivitiesLocked(true);
5733 NS = stops != null ? stops.size() : 0;
5734 if ((NF=mFinishingActivities.size()) > 0) {
5735 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5736 mFinishingActivities.clear();
5737 }
5738 if ((NT=mCancelledThumbnails.size()) > 0) {
5739 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5740 mCancelledThumbnails.clear();
5741 }
5742
5743 booting = mBooting;
5744 mBooting = false;
5745 }
5746
5747 int i;
5748
5749 // Send thumbnail if requested.
5750 if (sendThumbnail != null) {
5751 try {
5752 sendThumbnail.requestThumbnail(token);
5753 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005754 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 sendPendingThumbnail(null, token, null, null, true);
5756 }
5757 }
5758
5759 // Stop any activities that are scheduled to do so but have been
5760 // waiting for the next one to start.
5761 for (i=0; i<NS; i++) {
5762 HistoryRecord r = (HistoryRecord)stops.get(i);
5763 synchronized (this) {
5764 if (r.finishing) {
5765 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5766 } else {
5767 stopActivityLocked(r);
5768 }
5769 }
5770 }
5771
5772 // Finish any activities that are scheduled to do so but have been
5773 // waiting for the next one to start.
5774 for (i=0; i<NF; i++) {
5775 HistoryRecord r = (HistoryRecord)finishes.get(i);
5776 synchronized (this) {
5777 destroyActivityLocked(r, true);
5778 }
5779 }
5780
5781 // Report back to any thumbnail receivers.
5782 for (i=0; i<NT; i++) {
5783 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5784 sendPendingThumbnail(r, null, null, null, true);
5785 }
5786
5787 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005788 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005789 }
5790
5791 trimApplications();
5792 //dump();
5793 //mWindowManager.dump();
5794
5795 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005796 enableScreenAfterBoot();
5797 }
5798 }
5799
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005800 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005801 IntentFilter pkgFilter = new IntentFilter();
5802 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5803 pkgFilter.addDataScheme("package");
5804 mContext.registerReceiver(new BroadcastReceiver() {
5805 @Override
5806 public void onReceive(Context context, Intent intent) {
5807 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5808 if (pkgs != null) {
5809 for (String pkg : pkgs) {
5810 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5811 setResultCode(Activity.RESULT_OK);
5812 return;
5813 }
5814 }
5815 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005816 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005817 }, pkgFilter);
5818
5819 synchronized (this) {
5820 // Ensure that any processes we had put on hold are now started
5821 // up.
5822 final int NP = mProcessesOnHold.size();
5823 if (NP > 0) {
5824 ArrayList<ProcessRecord> procs =
5825 new ArrayList<ProcessRecord>(mProcessesOnHold);
5826 for (int ip=0; ip<NP; ip++) {
5827 this.startProcessLocked(procs.get(ip), "on-hold", null);
5828 }
5829 }
5830
5831 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5832 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005833 broadcastIntentLocked(null, null,
5834 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5835 null, null, 0, null, null,
5836 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5837 false, false, MY_PID, Process.SYSTEM_UID);
5838 }
5839 }
5840 }
5841
5842 final void ensureBootCompleted() {
5843 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005844 boolean enableScreen;
5845 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005846 booting = mBooting;
5847 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005848 enableScreen = !mBooted;
5849 mBooted = true;
5850 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005851
5852 if (booting) {
5853 finishBooting();
5854 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005855
5856 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005857 enableScreenAfterBoot();
5858 }
5859 }
5860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 public final void activityPaused(IBinder token, Bundle icicle) {
5862 // Refuse possible leaked file descriptors
5863 if (icicle != null && icicle.hasFileDescriptors()) {
5864 throw new IllegalArgumentException("File descriptors passed in Bundle");
5865 }
5866
5867 final long origId = Binder.clearCallingIdentity();
5868 activityPaused(token, icicle, false);
5869 Binder.restoreCallingIdentity(origId);
5870 }
5871
5872 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005873 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5875 + ", timeout=" + timeout);
5876
5877 HistoryRecord r = null;
5878
5879 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005880 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 if (index >= 0) {
5882 r = (HistoryRecord)mHistory.get(index);
5883 if (!timeout) {
5884 r.icicle = icicle;
5885 r.haveState = true;
5886 }
5887 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5888 if (mPausingActivity == r) {
5889 r.state = ActivityState.PAUSED;
5890 completePauseLocked();
5891 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005892 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005893 System.identityHashCode(r), r.shortComponentName,
5894 mPausingActivity != null
5895 ? mPausingActivity.shortComponentName : "(none)");
5896 }
5897 }
5898 }
5899 }
5900
5901 public final void activityStopped(IBinder token, Bitmap thumbnail,
5902 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005903 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 TAG, "Activity stopped: token=" + token);
5905
5906 HistoryRecord r = null;
5907
5908 final long origId = Binder.clearCallingIdentity();
5909
5910 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005911 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 if (index >= 0) {
5913 r = (HistoryRecord)mHistory.get(index);
5914 r.thumbnail = thumbnail;
5915 r.description = description;
5916 r.stopped = true;
5917 r.state = ActivityState.STOPPED;
5918 if (!r.finishing) {
5919 if (r.configDestroy) {
5920 destroyActivityLocked(r, true);
5921 resumeTopActivityLocked(null);
5922 }
5923 }
5924 }
5925 }
5926
5927 if (r != null) {
5928 sendPendingThumbnail(r, null, null, null, false);
5929 }
5930
5931 trimApplications();
5932
5933 Binder.restoreCallingIdentity(origId);
5934 }
5935
5936 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005937 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 synchronized (this) {
5939 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5940
Dianne Hackborn75b03852009-06-12 15:43:26 -07005941 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 if (index >= 0) {
5943 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5944 if (r.state == ActivityState.DESTROYING) {
5945 final long origId = Binder.clearCallingIdentity();
5946 removeActivityFromHistoryLocked(r);
5947 Binder.restoreCallingIdentity(origId);
5948 }
5949 }
5950 }
5951 }
5952
5953 public String getCallingPackage(IBinder token) {
5954 synchronized (this) {
5955 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005956 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 }
5958 }
5959
5960 public ComponentName getCallingActivity(IBinder token) {
5961 synchronized (this) {
5962 HistoryRecord r = getCallingRecordLocked(token);
5963 return r != null ? r.intent.getComponent() : null;
5964 }
5965 }
5966
5967 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005968 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 if (index >= 0) {
5970 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5971 if (r != null) {
5972 return r.resultTo;
5973 }
5974 }
5975 return null;
5976 }
5977
5978 public ComponentName getActivityClassForToken(IBinder token) {
5979 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005980 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 if (index >= 0) {
5982 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5983 return r.intent.getComponent();
5984 }
5985 return null;
5986 }
5987 }
5988
5989 public String getPackageForToken(IBinder token) {
5990 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005991 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005992 if (index >= 0) {
5993 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5994 return r.packageName;
5995 }
5996 return null;
5997 }
5998 }
5999
6000 public IIntentSender getIntentSender(int type,
6001 String packageName, IBinder token, String resultWho,
6002 int requestCode, Intent intent, String resolvedType, int flags) {
6003 // Refuse possible leaked file descriptors
6004 if (intent != null && intent.hasFileDescriptors() == true) {
6005 throw new IllegalArgumentException("File descriptors passed in Intent");
6006 }
6007
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006008 if (type == INTENT_SENDER_BROADCAST) {
6009 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6010 throw new IllegalArgumentException(
6011 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6012 }
6013 }
6014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 synchronized(this) {
6016 int callingUid = Binder.getCallingUid();
6017 try {
6018 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6019 Process.supportsProcesses()) {
6020 int uid = ActivityThread.getPackageManager()
6021 .getPackageUid(packageName);
6022 if (uid != Binder.getCallingUid()) {
6023 String msg = "Permission Denial: getIntentSender() from pid="
6024 + Binder.getCallingPid()
6025 + ", uid=" + Binder.getCallingUid()
6026 + ", (need uid=" + uid + ")"
6027 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006028 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 throw new SecurityException(msg);
6030 }
6031 }
6032 } catch (RemoteException e) {
6033 throw new SecurityException(e);
6034 }
6035 HistoryRecord activity = null;
6036 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006037 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 if (index < 0) {
6039 return null;
6040 }
6041 activity = (HistoryRecord)mHistory.get(index);
6042 if (activity.finishing) {
6043 return null;
6044 }
6045 }
6046
6047 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6048 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6049 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6050 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6051 |PendingIntent.FLAG_UPDATE_CURRENT);
6052
6053 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6054 type, packageName, activity, resultWho,
6055 requestCode, intent, resolvedType, flags);
6056 WeakReference<PendingIntentRecord> ref;
6057 ref = mIntentSenderRecords.get(key);
6058 PendingIntentRecord rec = ref != null ? ref.get() : null;
6059 if (rec != null) {
6060 if (!cancelCurrent) {
6061 if (updateCurrent) {
6062 rec.key.requestIntent.replaceExtras(intent);
6063 }
6064 return rec;
6065 }
6066 rec.canceled = true;
6067 mIntentSenderRecords.remove(key);
6068 }
6069 if (noCreate) {
6070 return rec;
6071 }
6072 rec = new PendingIntentRecord(this, key, callingUid);
6073 mIntentSenderRecords.put(key, rec.ref);
6074 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6075 if (activity.pendingResults == null) {
6076 activity.pendingResults
6077 = new HashSet<WeakReference<PendingIntentRecord>>();
6078 }
6079 activity.pendingResults.add(rec.ref);
6080 }
6081 return rec;
6082 }
6083 }
6084
6085 public void cancelIntentSender(IIntentSender sender) {
6086 if (!(sender instanceof PendingIntentRecord)) {
6087 return;
6088 }
6089 synchronized(this) {
6090 PendingIntentRecord rec = (PendingIntentRecord)sender;
6091 try {
6092 int uid = ActivityThread.getPackageManager()
6093 .getPackageUid(rec.key.packageName);
6094 if (uid != Binder.getCallingUid()) {
6095 String msg = "Permission Denial: cancelIntentSender() from pid="
6096 + Binder.getCallingPid()
6097 + ", uid=" + Binder.getCallingUid()
6098 + " is not allowed to cancel packges "
6099 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006100 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 throw new SecurityException(msg);
6102 }
6103 } catch (RemoteException e) {
6104 throw new SecurityException(e);
6105 }
6106 cancelIntentSenderLocked(rec, true);
6107 }
6108 }
6109
6110 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6111 rec.canceled = true;
6112 mIntentSenderRecords.remove(rec.key);
6113 if (cleanActivity && rec.key.activity != null) {
6114 rec.key.activity.pendingResults.remove(rec.ref);
6115 }
6116 }
6117
6118 public String getPackageForIntentSender(IIntentSender pendingResult) {
6119 if (!(pendingResult instanceof PendingIntentRecord)) {
6120 return null;
6121 }
6122 synchronized(this) {
6123 try {
6124 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6125 return res.key.packageName;
6126 } catch (ClassCastException e) {
6127 }
6128 }
6129 return null;
6130 }
6131
6132 public void setProcessLimit(int max) {
6133 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6134 "setProcessLimit()");
6135 mProcessLimit = max;
6136 }
6137
6138 public int getProcessLimit() {
6139 return mProcessLimit;
6140 }
6141
6142 void foregroundTokenDied(ForegroundToken token) {
6143 synchronized (ActivityManagerService.this) {
6144 synchronized (mPidsSelfLocked) {
6145 ForegroundToken cur
6146 = mForegroundProcesses.get(token.pid);
6147 if (cur != token) {
6148 return;
6149 }
6150 mForegroundProcesses.remove(token.pid);
6151 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6152 if (pr == null) {
6153 return;
6154 }
6155 pr.forcingToForeground = null;
6156 pr.foregroundServices = false;
6157 }
6158 updateOomAdjLocked();
6159 }
6160 }
6161
6162 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6163 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6164 "setProcessForeground()");
6165 synchronized(this) {
6166 boolean changed = false;
6167
6168 synchronized (mPidsSelfLocked) {
6169 ProcessRecord pr = mPidsSelfLocked.get(pid);
6170 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006171 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006172 return;
6173 }
6174 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6175 if (oldToken != null) {
6176 oldToken.token.unlinkToDeath(oldToken, 0);
6177 mForegroundProcesses.remove(pid);
6178 pr.forcingToForeground = null;
6179 changed = true;
6180 }
6181 if (isForeground && token != null) {
6182 ForegroundToken newToken = new ForegroundToken() {
6183 public void binderDied() {
6184 foregroundTokenDied(this);
6185 }
6186 };
6187 newToken.pid = pid;
6188 newToken.token = token;
6189 try {
6190 token.linkToDeath(newToken, 0);
6191 mForegroundProcesses.put(pid, newToken);
6192 pr.forcingToForeground = token;
6193 changed = true;
6194 } catch (RemoteException e) {
6195 // If the process died while doing this, we will later
6196 // do the cleanup with the process death link.
6197 }
6198 }
6199 }
6200
6201 if (changed) {
6202 updateOomAdjLocked();
6203 }
6204 }
6205 }
6206
6207 // =========================================================
6208 // PERMISSIONS
6209 // =========================================================
6210
6211 static class PermissionController extends IPermissionController.Stub {
6212 ActivityManagerService mActivityManagerService;
6213 PermissionController(ActivityManagerService activityManagerService) {
6214 mActivityManagerService = activityManagerService;
6215 }
6216
6217 public boolean checkPermission(String permission, int pid, int uid) {
6218 return mActivityManagerService.checkPermission(permission, pid,
6219 uid) == PackageManager.PERMISSION_GRANTED;
6220 }
6221 }
6222
6223 /**
6224 * This can be called with or without the global lock held.
6225 */
6226 int checkComponentPermission(String permission, int pid, int uid,
6227 int reqUid) {
6228 // We might be performing an operation on behalf of an indirect binder
6229 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6230 // client identity accordingly before proceeding.
6231 Identity tlsIdentity = sCallerIdentity.get();
6232 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006233 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6235 uid = tlsIdentity.uid;
6236 pid = tlsIdentity.pid;
6237 }
6238
6239 // Root, system server and our own process get to do everything.
6240 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6241 !Process.supportsProcesses()) {
6242 return PackageManager.PERMISSION_GRANTED;
6243 }
6244 // If the target requires a specific UID, always fail for others.
6245 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006246 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006247 return PackageManager.PERMISSION_DENIED;
6248 }
6249 if (permission == null) {
6250 return PackageManager.PERMISSION_GRANTED;
6251 }
6252 try {
6253 return ActivityThread.getPackageManager()
6254 .checkUidPermission(permission, uid);
6255 } catch (RemoteException e) {
6256 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006257 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 }
6259 return PackageManager.PERMISSION_DENIED;
6260 }
6261
6262 /**
6263 * As the only public entry point for permissions checking, this method
6264 * can enforce the semantic that requesting a check on a null global
6265 * permission is automatically denied. (Internally a null permission
6266 * string is used when calling {@link #checkComponentPermission} in cases
6267 * when only uid-based security is needed.)
6268 *
6269 * This can be called with or without the global lock held.
6270 */
6271 public int checkPermission(String permission, int pid, int uid) {
6272 if (permission == null) {
6273 return PackageManager.PERMISSION_DENIED;
6274 }
6275 return checkComponentPermission(permission, pid, uid, -1);
6276 }
6277
6278 /**
6279 * Binder IPC calls go through the public entry point.
6280 * This can be called with or without the global lock held.
6281 */
6282 int checkCallingPermission(String permission) {
6283 return checkPermission(permission,
6284 Binder.getCallingPid(),
6285 Binder.getCallingUid());
6286 }
6287
6288 /**
6289 * This can be called with or without the global lock held.
6290 */
6291 void enforceCallingPermission(String permission, String func) {
6292 if (checkCallingPermission(permission)
6293 == PackageManager.PERMISSION_GRANTED) {
6294 return;
6295 }
6296
6297 String msg = "Permission Denial: " + func + " from pid="
6298 + Binder.getCallingPid()
6299 + ", uid=" + Binder.getCallingUid()
6300 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006301 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 throw new SecurityException(msg);
6303 }
6304
6305 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6306 ProviderInfo pi, int uid, int modeFlags) {
6307 try {
6308 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6309 if ((pi.readPermission != null) &&
6310 (pm.checkUidPermission(pi.readPermission, uid)
6311 != PackageManager.PERMISSION_GRANTED)) {
6312 return false;
6313 }
6314 }
6315 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6316 if ((pi.writePermission != null) &&
6317 (pm.checkUidPermission(pi.writePermission, uid)
6318 != PackageManager.PERMISSION_GRANTED)) {
6319 return false;
6320 }
6321 }
6322 return true;
6323 } catch (RemoteException e) {
6324 return false;
6325 }
6326 }
6327
6328 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6329 int modeFlags) {
6330 // Root gets to do everything.
6331 if (uid == 0 || !Process.supportsProcesses()) {
6332 return true;
6333 }
6334 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6335 if (perms == null) return false;
6336 UriPermission perm = perms.get(uri);
6337 if (perm == null) return false;
6338 return (modeFlags&perm.modeFlags) == modeFlags;
6339 }
6340
6341 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6342 // Another redirected-binder-call permissions check as in
6343 // {@link checkComponentPermission}.
6344 Identity tlsIdentity = sCallerIdentity.get();
6345 if (tlsIdentity != null) {
6346 uid = tlsIdentity.uid;
6347 pid = tlsIdentity.pid;
6348 }
6349
6350 // Our own process gets to do everything.
6351 if (pid == MY_PID) {
6352 return PackageManager.PERMISSION_GRANTED;
6353 }
6354 synchronized(this) {
6355 return checkUriPermissionLocked(uri, uid, modeFlags)
6356 ? PackageManager.PERMISSION_GRANTED
6357 : PackageManager.PERMISSION_DENIED;
6358 }
6359 }
6360
6361 private void grantUriPermissionLocked(int callingUid,
6362 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6363 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6364 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6365 if (modeFlags == 0) {
6366 return;
6367 }
6368
Joe Onorato8a9b2202010-02-26 18:56:32 -08006369 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006370 "Requested grant " + targetPkg + " permission to " + uri);
6371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 final IPackageManager pm = ActivityThread.getPackageManager();
6373
6374 // If this is not a content: uri, we can't do anything with it.
6375 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006376 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006377 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 return;
6379 }
6380
6381 String name = uri.getAuthority();
6382 ProviderInfo pi = null;
6383 ContentProviderRecord cpr
6384 = (ContentProviderRecord)mProvidersByName.get(name);
6385 if (cpr != null) {
6386 pi = cpr.info;
6387 } else {
6388 try {
6389 pi = pm.resolveContentProvider(name,
6390 PackageManager.GET_URI_PERMISSION_PATTERNS);
6391 } catch (RemoteException ex) {
6392 }
6393 }
6394 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006395 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 return;
6397 }
6398
6399 int targetUid;
6400 try {
6401 targetUid = pm.getPackageUid(targetPkg);
6402 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006403 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006404 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 return;
6406 }
6407 } catch (RemoteException ex) {
6408 return;
6409 }
6410
6411 // First... does the target actually need this permission?
6412 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6413 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006414 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006415 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 return;
6417 }
6418
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006419 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 if (!pi.grantUriPermissions) {
6421 throw new SecurityException("Provider " + pi.packageName
6422 + "/" + pi.name
6423 + " does not allow granting of Uri permissions (uri "
6424 + uri + ")");
6425 }
6426 if (pi.uriPermissionPatterns != null) {
6427 final int N = pi.uriPermissionPatterns.length;
6428 boolean allowed = false;
6429 for (int i=0; i<N; i++) {
6430 if (pi.uriPermissionPatterns[i] != null
6431 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6432 allowed = true;
6433 break;
6434 }
6435 }
6436 if (!allowed) {
6437 throw new SecurityException("Provider " + pi.packageName
6438 + "/" + pi.name
6439 + " does not allow granting of permission to path of Uri "
6440 + uri);
6441 }
6442 }
6443
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006444 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 // this uri?
6446 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6447 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6448 throw new SecurityException("Uid " + callingUid
6449 + " does not have permission to uri " + uri);
6450 }
6451 }
6452
6453 // Okay! So here we are: the caller has the assumed permission
6454 // to the uri, and the target doesn't. Let's now give this to
6455 // the target.
6456
Joe Onorato8a9b2202010-02-26 18:56:32 -08006457 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006458 "Granting " + targetPkg + " permission to " + uri);
6459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460 HashMap<Uri, UriPermission> targetUris
6461 = mGrantedUriPermissions.get(targetUid);
6462 if (targetUris == null) {
6463 targetUris = new HashMap<Uri, UriPermission>();
6464 mGrantedUriPermissions.put(targetUid, targetUris);
6465 }
6466
6467 UriPermission perm = targetUris.get(uri);
6468 if (perm == null) {
6469 perm = new UriPermission(targetUid, uri);
6470 targetUris.put(uri, perm);
6471
6472 }
6473 perm.modeFlags |= modeFlags;
6474 if (activity == null) {
6475 perm.globalModeFlags |= modeFlags;
6476 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6477 perm.readActivities.add(activity);
6478 if (activity.readUriPermissions == null) {
6479 activity.readUriPermissions = new HashSet<UriPermission>();
6480 }
6481 activity.readUriPermissions.add(perm);
6482 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6483 perm.writeActivities.add(activity);
6484 if (activity.writeUriPermissions == null) {
6485 activity.writeUriPermissions = new HashSet<UriPermission>();
6486 }
6487 activity.writeUriPermissions.add(perm);
6488 }
6489 }
6490
6491 private void grantUriPermissionFromIntentLocked(int callingUid,
6492 String targetPkg, Intent intent, HistoryRecord activity) {
6493 if (intent == null) {
6494 return;
6495 }
6496 Uri data = intent.getData();
6497 if (data == null) {
6498 return;
6499 }
6500 grantUriPermissionLocked(callingUid, targetPkg, data,
6501 intent.getFlags(), activity);
6502 }
6503
6504 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6505 Uri uri, int modeFlags) {
6506 synchronized(this) {
6507 final ProcessRecord r = getRecordForAppLocked(caller);
6508 if (r == null) {
6509 throw new SecurityException("Unable to find app for caller "
6510 + caller
6511 + " when granting permission to uri " + uri);
6512 }
6513 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006514 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 return;
6516 }
6517 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006518 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 return;
6520 }
6521
6522 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6523 null);
6524 }
6525 }
6526
6527 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6528 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6529 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6530 HashMap<Uri, UriPermission> perms
6531 = mGrantedUriPermissions.get(perm.uid);
6532 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006533 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006534 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535 perms.remove(perm.uri);
6536 if (perms.size() == 0) {
6537 mGrantedUriPermissions.remove(perm.uid);
6538 }
6539 }
6540 }
6541 }
6542
6543 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6544 if (activity.readUriPermissions != null) {
6545 for (UriPermission perm : activity.readUriPermissions) {
6546 perm.readActivities.remove(activity);
6547 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6548 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6549 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6550 removeUriPermissionIfNeededLocked(perm);
6551 }
6552 }
6553 }
6554 if (activity.writeUriPermissions != null) {
6555 for (UriPermission perm : activity.writeUriPermissions) {
6556 perm.writeActivities.remove(activity);
6557 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6558 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6559 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6560 removeUriPermissionIfNeededLocked(perm);
6561 }
6562 }
6563 }
6564 }
6565
6566 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6567 int modeFlags) {
6568 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6569 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6570 if (modeFlags == 0) {
6571 return;
6572 }
6573
Joe Onorato8a9b2202010-02-26 18:56:32 -08006574 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006575 "Revoking all granted permissions to " + uri);
6576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006577 final IPackageManager pm = ActivityThread.getPackageManager();
6578
6579 final String authority = uri.getAuthority();
6580 ProviderInfo pi = null;
6581 ContentProviderRecord cpr
6582 = (ContentProviderRecord)mProvidersByName.get(authority);
6583 if (cpr != null) {
6584 pi = cpr.info;
6585 } else {
6586 try {
6587 pi = pm.resolveContentProvider(authority,
6588 PackageManager.GET_URI_PERMISSION_PATTERNS);
6589 } catch (RemoteException ex) {
6590 }
6591 }
6592 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006593 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 return;
6595 }
6596
6597 // Does the caller have this permission on the URI?
6598 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6599 // Right now, if you are not the original owner of the permission,
6600 // you are not allowed to revoke it.
6601 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6602 throw new SecurityException("Uid " + callingUid
6603 + " does not have permission to uri " + uri);
6604 //}
6605 }
6606
6607 // Go through all of the permissions and remove any that match.
6608 final List<String> SEGMENTS = uri.getPathSegments();
6609 if (SEGMENTS != null) {
6610 final int NS = SEGMENTS.size();
6611 int N = mGrantedUriPermissions.size();
6612 for (int i=0; i<N; i++) {
6613 HashMap<Uri, UriPermission> perms
6614 = mGrantedUriPermissions.valueAt(i);
6615 Iterator<UriPermission> it = perms.values().iterator();
6616 toploop:
6617 while (it.hasNext()) {
6618 UriPermission perm = it.next();
6619 Uri targetUri = perm.uri;
6620 if (!authority.equals(targetUri.getAuthority())) {
6621 continue;
6622 }
6623 List<String> targetSegments = targetUri.getPathSegments();
6624 if (targetSegments == null) {
6625 continue;
6626 }
6627 if (targetSegments.size() < NS) {
6628 continue;
6629 }
6630 for (int j=0; j<NS; j++) {
6631 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6632 continue toploop;
6633 }
6634 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006635 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006636 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006637 perm.clearModes(modeFlags);
6638 if (perm.modeFlags == 0) {
6639 it.remove();
6640 }
6641 }
6642 if (perms.size() == 0) {
6643 mGrantedUriPermissions.remove(
6644 mGrantedUriPermissions.keyAt(i));
6645 N--;
6646 i--;
6647 }
6648 }
6649 }
6650 }
6651
6652 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6653 int modeFlags) {
6654 synchronized(this) {
6655 final ProcessRecord r = getRecordForAppLocked(caller);
6656 if (r == null) {
6657 throw new SecurityException("Unable to find app for caller "
6658 + caller
6659 + " when revoking permission to uri " + uri);
6660 }
6661 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006662 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 return;
6664 }
6665
6666 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6667 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6668 if (modeFlags == 0) {
6669 return;
6670 }
6671
6672 final IPackageManager pm = ActivityThread.getPackageManager();
6673
6674 final String authority = uri.getAuthority();
6675 ProviderInfo pi = null;
6676 ContentProviderRecord cpr
6677 = (ContentProviderRecord)mProvidersByName.get(authority);
6678 if (cpr != null) {
6679 pi = cpr.info;
6680 } else {
6681 try {
6682 pi = pm.resolveContentProvider(authority,
6683 PackageManager.GET_URI_PERMISSION_PATTERNS);
6684 } catch (RemoteException ex) {
6685 }
6686 }
6687 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006688 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006689 return;
6690 }
6691
6692 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6693 }
6694 }
6695
6696 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6697 synchronized (this) {
6698 ProcessRecord app =
6699 who != null ? getRecordForAppLocked(who) : null;
6700 if (app == null) return;
6701
6702 Message msg = Message.obtain();
6703 msg.what = WAIT_FOR_DEBUGGER_MSG;
6704 msg.obj = app;
6705 msg.arg1 = waiting ? 1 : 0;
6706 mHandler.sendMessage(msg);
6707 }
6708 }
6709
6710 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6711 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006712 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006714 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 }
6716
6717 // =========================================================
6718 // TASK MANAGEMENT
6719 // =========================================================
6720
6721 public List getTasks(int maxNum, int flags,
6722 IThumbnailReceiver receiver) {
6723 ArrayList list = new ArrayList();
6724
6725 PendingThumbnailsRecord pending = null;
6726 IApplicationThread topThumbnail = null;
6727 HistoryRecord topRecord = null;
6728
6729 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006730 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6732 + ", receiver=" + receiver);
6733
6734 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6735 != PackageManager.PERMISSION_GRANTED) {
6736 if (receiver != null) {
6737 // If the caller wants to wait for pending thumbnails,
6738 // it ain't gonna get them.
6739 try {
6740 receiver.finished();
6741 } catch (RemoteException ex) {
6742 }
6743 }
6744 String msg = "Permission Denial: getTasks() from pid="
6745 + Binder.getCallingPid()
6746 + ", uid=" + Binder.getCallingUid()
6747 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006748 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 throw new SecurityException(msg);
6750 }
6751
6752 int pos = mHistory.size()-1;
6753 HistoryRecord next =
6754 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6755 HistoryRecord top = null;
6756 CharSequence topDescription = null;
6757 TaskRecord curTask = null;
6758 int numActivities = 0;
6759 int numRunning = 0;
6760 while (pos >= 0 && maxNum > 0) {
6761 final HistoryRecord r = next;
6762 pos--;
6763 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6764
6765 // Initialize state for next task if needed.
6766 if (top == null ||
6767 (top.state == ActivityState.INITIALIZING
6768 && top.task == r.task)) {
6769 top = r;
6770 topDescription = r.description;
6771 curTask = r.task;
6772 numActivities = numRunning = 0;
6773 }
6774
6775 // Add 'r' into the current task.
6776 numActivities++;
6777 if (r.app != null && r.app.thread != null) {
6778 numRunning++;
6779 }
6780 if (topDescription == null) {
6781 topDescription = r.description;
6782 }
6783
Joe Onorato8a9b2202010-02-26 18:56:32 -08006784 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 TAG, r.intent.getComponent().flattenToShortString()
6786 + ": task=" + r.task);
6787
6788 // If the next one is a different task, generate a new
6789 // TaskInfo entry for what we have.
6790 if (next == null || next.task != curTask) {
6791 ActivityManager.RunningTaskInfo ci
6792 = new ActivityManager.RunningTaskInfo();
6793 ci.id = curTask.taskId;
6794 ci.baseActivity = r.intent.getComponent();
6795 ci.topActivity = top.intent.getComponent();
6796 ci.thumbnail = top.thumbnail;
6797 ci.description = topDescription;
6798 ci.numActivities = numActivities;
6799 ci.numRunning = numRunning;
6800 //System.out.println(
6801 // "#" + maxNum + ": " + " descr=" + ci.description);
6802 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006803 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 TAG, "State=" + top.state + "Idle=" + top.idle
6805 + " app=" + top.app
6806 + " thr=" + (top.app != null ? top.app.thread : null));
6807 if (top.state == ActivityState.RESUMED
6808 || top.state == ActivityState.PAUSING) {
6809 if (top.idle && top.app != null
6810 && top.app.thread != null) {
6811 topRecord = top;
6812 topThumbnail = top.app.thread;
6813 } else {
6814 top.thumbnailNeeded = true;
6815 }
6816 }
6817 if (pending == null) {
6818 pending = new PendingThumbnailsRecord(receiver);
6819 }
6820 pending.pendingRecords.add(top);
6821 }
6822 list.add(ci);
6823 maxNum--;
6824 top = null;
6825 }
6826 }
6827
6828 if (pending != null) {
6829 mPendingThumbnails.add(pending);
6830 }
6831 }
6832
Joe Onorato8a9b2202010-02-26 18:56:32 -08006833 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006834
6835 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006836 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 try {
6838 topThumbnail.requestThumbnail(topRecord);
6839 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006840 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006841 sendPendingThumbnail(null, topRecord, null, null, true);
6842 }
6843 }
6844
6845 if (pending == null && receiver != null) {
6846 // In this case all thumbnails were available and the client
6847 // is being asked to be told when the remaining ones come in...
6848 // which is unusually, since the top-most currently running
6849 // activity should never have a canned thumbnail! Oh well.
6850 try {
6851 receiver.finished();
6852 } catch (RemoteException ex) {
6853 }
6854 }
6855
6856 return list;
6857 }
6858
6859 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6860 int flags) {
6861 synchronized (this) {
6862 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6863 "getRecentTasks()");
6864
6865 final int N = mRecentTasks.size();
6866 ArrayList<ActivityManager.RecentTaskInfo> res
6867 = new ArrayList<ActivityManager.RecentTaskInfo>(
6868 maxNum < N ? maxNum : N);
6869 for (int i=0; i<N && maxNum > 0; i++) {
6870 TaskRecord tr = mRecentTasks.get(i);
6871 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6872 || (tr.intent == null)
6873 || ((tr.intent.getFlags()
6874 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6875 ActivityManager.RecentTaskInfo rti
6876 = new ActivityManager.RecentTaskInfo();
6877 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6878 rti.baseIntent = new Intent(
6879 tr.intent != null ? tr.intent : tr.affinityIntent);
6880 rti.origActivity = tr.origActivity;
6881 res.add(rti);
6882 maxNum--;
6883 }
6884 }
6885 return res;
6886 }
6887 }
6888
6889 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6890 int j;
6891 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6892 TaskRecord jt = startTask;
6893
6894 // First look backwards
6895 for (j=startIndex-1; j>=0; j--) {
6896 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6897 if (r.task != jt) {
6898 jt = r.task;
6899 if (affinity.equals(jt.affinity)) {
6900 return j;
6901 }
6902 }
6903 }
6904
6905 // Now look forwards
6906 final int N = mHistory.size();
6907 jt = startTask;
6908 for (j=startIndex+1; j<N; j++) {
6909 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6910 if (r.task != jt) {
6911 if (affinity.equals(jt.affinity)) {
6912 return j;
6913 }
6914 jt = r.task;
6915 }
6916 }
6917
6918 // Might it be at the top?
6919 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6920 return N-1;
6921 }
6922
6923 return -1;
6924 }
6925
6926 /**
6927 * Perform a reset of the given task, if needed as part of launching it.
6928 * Returns the new HistoryRecord at the top of the task.
6929 */
6930 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6931 HistoryRecord newActivity) {
6932 boolean forceReset = (newActivity.info.flags
6933 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6934 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6935 if ((newActivity.info.flags
6936 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6937 forceReset = true;
6938 }
6939 }
6940
6941 final TaskRecord task = taskTop.task;
6942
6943 // We are going to move through the history list so that we can look
6944 // at each activity 'target' with 'below' either the interesting
6945 // activity immediately below it in the stack or null.
6946 HistoryRecord target = null;
6947 int targetI = 0;
6948 int taskTopI = -1;
6949 int replyChainEnd = -1;
6950 int lastReparentPos = -1;
6951 for (int i=mHistory.size()-1; i>=-1; i--) {
6952 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6953
6954 if (below != null && below.finishing) {
6955 continue;
6956 }
6957 if (target == null) {
6958 target = below;
6959 targetI = i;
6960 // If we were in the middle of a reply chain before this
6961 // task, it doesn't appear like the root of the chain wants
6962 // anything interesting, so drop it.
6963 replyChainEnd = -1;
6964 continue;
6965 }
6966
6967 final int flags = target.info.flags;
6968
6969 final boolean finishOnTaskLaunch =
6970 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6971 final boolean allowTaskReparenting =
6972 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6973
6974 if (target.task == task) {
6975 // We are inside of the task being reset... we'll either
6976 // finish this activity, push it out for another task,
6977 // or leave it as-is. We only do this
6978 // for activities that are not the root of the task (since
6979 // if we finish the root, we may no longer have the task!).
6980 if (taskTopI < 0) {
6981 taskTopI = targetI;
6982 }
6983 if (below != null && below.task == task) {
6984 final boolean clearWhenTaskReset =
6985 (target.intent.getFlags()
6986 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006987 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006988 // If this activity is sending a reply to a previous
6989 // activity, we can't do anything with it now until
6990 // we reach the start of the reply chain.
6991 // XXX note that we are assuming the result is always
6992 // to the previous activity, which is almost always
6993 // the case but we really shouldn't count on.
6994 if (replyChainEnd < 0) {
6995 replyChainEnd = targetI;
6996 }
Ed Heyl73798232009-03-24 21:32:21 -07006997 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 && target.taskAffinity != null
6999 && !target.taskAffinity.equals(task.affinity)) {
7000 // If this activity has an affinity for another
7001 // task, then we need to move it out of here. We will
7002 // move it as far out of the way as possible, to the
7003 // bottom of the activity stack. This also keeps it
7004 // correctly ordered with any activities we previously
7005 // moved.
7006 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7007 if (target.taskAffinity != null
7008 && target.taskAffinity.equals(p.task.affinity)) {
7009 // If the activity currently at the bottom has the
7010 // same task affinity as the one we are moving,
7011 // then merge it into the same task.
7012 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007013 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 + " out to bottom task " + p.task);
7015 } else {
7016 mCurTask++;
7017 if (mCurTask <= 0) {
7018 mCurTask = 1;
7019 }
7020 target.task = new TaskRecord(mCurTask, target.info, null,
7021 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7022 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007023 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 + " out to new task " + target.task);
7025 }
7026 mWindowManager.setAppGroupId(target, task.taskId);
7027 if (replyChainEnd < 0) {
7028 replyChainEnd = targetI;
7029 }
7030 int dstPos = 0;
7031 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7032 p = (HistoryRecord)mHistory.get(srcPos);
7033 if (p.finishing) {
7034 continue;
7035 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007036 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 + " out to target's task " + target.task);
7038 task.numActivities--;
7039 p.task = target.task;
7040 target.task.numActivities++;
7041 mHistory.remove(srcPos);
7042 mHistory.add(dstPos, p);
7043 mWindowManager.moveAppToken(dstPos, p);
7044 mWindowManager.setAppGroupId(p, p.task.taskId);
7045 dstPos++;
7046 if (VALIDATE_TOKENS) {
7047 mWindowManager.validateAppTokens(mHistory);
7048 }
7049 i++;
7050 }
7051 if (taskTop == p) {
7052 taskTop = below;
7053 }
7054 if (taskTopI == replyChainEnd) {
7055 taskTopI = -1;
7056 }
7057 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007058 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 } else if (forceReset || finishOnTaskLaunch
7060 || clearWhenTaskReset) {
7061 // If the activity should just be removed -- either
7062 // because it asks for it, or the task should be
7063 // cleared -- then finish it and anything that is
7064 // part of its reply chain.
7065 if (clearWhenTaskReset) {
7066 // In this case, we want to finish this activity
7067 // and everything above it, so be sneaky and pretend
7068 // like these are all in the reply chain.
7069 replyChainEnd = targetI+1;
7070 while (replyChainEnd < mHistory.size() &&
7071 ((HistoryRecord)mHistory.get(
7072 replyChainEnd)).task == task) {
7073 replyChainEnd++;
7074 }
7075 replyChainEnd--;
7076 } else if (replyChainEnd < 0) {
7077 replyChainEnd = targetI;
7078 }
7079 HistoryRecord p = null;
7080 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7081 p = (HistoryRecord)mHistory.get(srcPos);
7082 if (p.finishing) {
7083 continue;
7084 }
7085 if (finishActivityLocked(p, srcPos,
7086 Activity.RESULT_CANCELED, null, "reset")) {
7087 replyChainEnd--;
7088 srcPos--;
7089 }
7090 }
7091 if (taskTop == p) {
7092 taskTop = below;
7093 }
7094 if (taskTopI == replyChainEnd) {
7095 taskTopI = -1;
7096 }
7097 replyChainEnd = -1;
7098 } else {
7099 // If we were in the middle of a chain, well the
7100 // activity that started it all doesn't want anything
7101 // special, so leave it all as-is.
7102 replyChainEnd = -1;
7103 }
7104 } else {
7105 // Reached the bottom of the task -- any reply chain
7106 // should be left as-is.
7107 replyChainEnd = -1;
7108 }
7109
7110 } else if (target.resultTo != null) {
7111 // If this activity is sending a reply to a previous
7112 // activity, we can't do anything with it now until
7113 // we reach the start of the reply chain.
7114 // XXX note that we are assuming the result is always
7115 // to the previous activity, which is almost always
7116 // the case but we really shouldn't count on.
7117 if (replyChainEnd < 0) {
7118 replyChainEnd = targetI;
7119 }
7120
7121 } else if (taskTopI >= 0 && allowTaskReparenting
7122 && task.affinity != null
7123 && task.affinity.equals(target.taskAffinity)) {
7124 // We are inside of another task... if this activity has
7125 // an affinity for our task, then either remove it if we are
7126 // clearing or move it over to our task. Note that
7127 // we currently punt on the case where we are resetting a
7128 // task that is not at the top but who has activities above
7129 // with an affinity to it... this is really not a normal
7130 // case, and we will need to later pull that task to the front
7131 // and usually at that point we will do the reset and pick
7132 // up those remaining activities. (This only happens if
7133 // someone starts an activity in a new task from an activity
7134 // in a task that is not currently on top.)
7135 if (forceReset || finishOnTaskLaunch) {
7136 if (replyChainEnd < 0) {
7137 replyChainEnd = targetI;
7138 }
7139 HistoryRecord p = null;
7140 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7141 p = (HistoryRecord)mHistory.get(srcPos);
7142 if (p.finishing) {
7143 continue;
7144 }
7145 if (finishActivityLocked(p, srcPos,
7146 Activity.RESULT_CANCELED, null, "reset")) {
7147 taskTopI--;
7148 lastReparentPos--;
7149 replyChainEnd--;
7150 srcPos--;
7151 }
7152 }
7153 replyChainEnd = -1;
7154 } else {
7155 if (replyChainEnd < 0) {
7156 replyChainEnd = targetI;
7157 }
7158 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7159 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7160 if (p.finishing) {
7161 continue;
7162 }
7163 if (lastReparentPos < 0) {
7164 lastReparentPos = taskTopI;
7165 taskTop = p;
7166 } else {
7167 lastReparentPos--;
7168 }
7169 mHistory.remove(srcPos);
7170 p.task.numActivities--;
7171 p.task = task;
7172 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007173 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 + " in to resetting task " + task);
7175 task.numActivities++;
7176 mWindowManager.moveAppToken(lastReparentPos, p);
7177 mWindowManager.setAppGroupId(p, p.task.taskId);
7178 if (VALIDATE_TOKENS) {
7179 mWindowManager.validateAppTokens(mHistory);
7180 }
7181 }
7182 replyChainEnd = -1;
7183
7184 // Now we've moved it in to place... but what if this is
7185 // a singleTop activity and we have put it on top of another
7186 // instance of the same activity? Then we drop the instance
7187 // below so it remains singleTop.
7188 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7189 for (int j=lastReparentPos-1; j>=0; j--) {
7190 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7191 if (p.finishing) {
7192 continue;
7193 }
7194 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7195 if (finishActivityLocked(p, j,
7196 Activity.RESULT_CANCELED, null, "replace")) {
7197 taskTopI--;
7198 lastReparentPos--;
7199 }
7200 }
7201 }
7202 }
7203 }
7204 }
7205
7206 target = below;
7207 targetI = i;
7208 }
7209
7210 return taskTop;
7211 }
7212
7213 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007214 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007215 */
7216 public void moveTaskToFront(int task) {
7217 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7218 "moveTaskToFront()");
7219
7220 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007221 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7222 Binder.getCallingUid(), "Task to front")) {
7223 return;
7224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 final long origId = Binder.clearCallingIdentity();
7226 try {
7227 int N = mRecentTasks.size();
7228 for (int i=0; i<N; i++) {
7229 TaskRecord tr = mRecentTasks.get(i);
7230 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007231 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 return;
7233 }
7234 }
7235 for (int i=mHistory.size()-1; i>=0; i--) {
7236 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7237 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007238 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007239 return;
7240 }
7241 }
7242 } finally {
7243 Binder.restoreCallingIdentity(origId);
7244 }
7245 }
7246 }
7247
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007248 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007249 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250
7251 final int task = tr.taskId;
7252 int top = mHistory.size()-1;
7253
7254 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7255 // nothing to do!
7256 return;
7257 }
7258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 ArrayList moved = new ArrayList();
7260
7261 // Applying the affinities may have removed entries from the history,
7262 // so get the size again.
7263 top = mHistory.size()-1;
7264 int pos = top;
7265
7266 // Shift all activities with this task up to the top
7267 // of the stack, keeping them in the same internal order.
7268 while (pos >= 0) {
7269 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007270 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7272 boolean first = true;
7273 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007274 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 mHistory.remove(pos);
7276 mHistory.add(top, r);
7277 moved.add(0, r);
7278 top--;
7279 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007280 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 first = false;
7282 }
7283 }
7284 pos--;
7285 }
7286
Joe Onorato8a9b2202010-02-26 18:56:32 -08007287 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007288 "Prepare to front transition: task=" + tr);
7289 if (reason != null &&
7290 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7291 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7292 HistoryRecord r = topRunningActivityLocked(null);
7293 if (r != null) {
7294 mNoAnimActivities.add(r);
7295 }
7296 } else {
7297 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7298 }
7299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 mWindowManager.moveAppTokensToTop(moved);
7301 if (VALIDATE_TOKENS) {
7302 mWindowManager.validateAppTokens(mHistory);
7303 }
7304
Josh Bartel7f208742010-02-25 11:01:44 -06007305 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007306 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 }
7308
Josh Bartel7f208742010-02-25 11:01:44 -06007309 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 resumeTopActivityLocked(null);
7311 }
7312
7313 public void moveTaskToBack(int task) {
7314 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7315 "moveTaskToBack()");
7316
7317 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007318 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7319 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7320 Binder.getCallingUid(), "Task to back")) {
7321 return;
7322 }
7323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007325 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 Binder.restoreCallingIdentity(origId);
7327 }
7328 }
7329
7330 /**
7331 * Moves an activity, and all of the other activities within the same task, to the bottom
7332 * of the history stack. The activity's order within the task is unchanged.
7333 *
7334 * @param token A reference to the activity we wish to move
7335 * @param nonRoot If false then this only works if the activity is the root
7336 * of a task; if true it will work for any activity in a task.
7337 * @return Returns true if the move completed, false if not.
7338 */
7339 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7340 synchronized(this) {
7341 final long origId = Binder.clearCallingIdentity();
7342 int taskId = getTaskForActivityLocked(token, !nonRoot);
7343 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007344 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007345 }
7346 Binder.restoreCallingIdentity(origId);
7347 }
7348 return false;
7349 }
7350
7351 /**
7352 * Worker method for rearranging history stack. Implements the function of moving all
7353 * activities for a specific task (gathering them if disjoint) into a single group at the
7354 * bottom of the stack.
7355 *
7356 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7357 * to premeptively cancel the move.
7358 *
7359 * @param task The taskId to collect and move to the bottom.
7360 * @return Returns true if the move completed, false if not.
7361 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007362 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007363 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364
7365 // If we have a watcher, preflight the move before committing to it. First check
7366 // for *other* available tasks, but if none are available, then try again allowing the
7367 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007368 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 HistoryRecord next = topRunningActivityLocked(null, task);
7370 if (next == null) {
7371 next = topRunningActivityLocked(null, 0);
7372 }
7373 if (next != null) {
7374 // ask watcher if this is allowed
7375 boolean moveOK = true;
7376 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007377 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007379 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 }
7381 if (!moveOK) {
7382 return false;
7383 }
7384 }
7385 }
7386
7387 ArrayList moved = new ArrayList();
7388
Joe Onorato8a9b2202010-02-26 18:56:32 -08007389 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391
7392 final int N = mHistory.size();
7393 int bottom = 0;
7394 int pos = 0;
7395
7396 // Shift all activities with this task down to the bottom
7397 // of the stack, keeping them in the same internal order.
7398 while (pos < N) {
7399 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007400 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7402 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007403 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 mHistory.remove(pos);
7405 mHistory.add(bottom, r);
7406 moved.add(r);
7407 bottom++;
7408 }
7409 pos++;
7410 }
7411
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007412 if (reason != null &&
7413 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7414 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7415 HistoryRecord r = topRunningActivityLocked(null);
7416 if (r != null) {
7417 mNoAnimActivities.add(r);
7418 }
7419 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007420 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 mWindowManager.moveAppTokensToBottom(moved);
7423 if (VALIDATE_TOKENS) {
7424 mWindowManager.validateAppTokens(mHistory);
7425 }
7426
Josh Bartel7f208742010-02-25 11:01:44 -06007427 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 return true;
7429 }
7430
7431 public void moveTaskBackwards(int task) {
7432 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7433 "moveTaskBackwards()");
7434
7435 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007436 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7437 Binder.getCallingUid(), "Task backwards")) {
7438 return;
7439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 final long origId = Binder.clearCallingIdentity();
7441 moveTaskBackwardsLocked(task);
7442 Binder.restoreCallingIdentity(origId);
7443 }
7444 }
7445
7446 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007447 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 }
7449
7450 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7451 synchronized(this) {
7452 return getTaskForActivityLocked(token, onlyRoot);
7453 }
7454 }
7455
7456 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7457 final int N = mHistory.size();
7458 TaskRecord lastTask = null;
7459 for (int i=0; i<N; i++) {
7460 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7461 if (r == token) {
7462 if (!onlyRoot || lastTask != r.task) {
7463 return r.task.taskId;
7464 }
7465 return -1;
7466 }
7467 lastTask = r.task;
7468 }
7469
7470 return -1;
7471 }
7472
7473 /**
7474 * Returns the top activity in any existing task matching the given
7475 * Intent. Returns null if no such task is found.
7476 */
7477 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7478 ComponentName cls = intent.getComponent();
7479 if (info.targetActivity != null) {
7480 cls = new ComponentName(info.packageName, info.targetActivity);
7481 }
7482
7483 TaskRecord cp = null;
7484
7485 final int N = mHistory.size();
7486 for (int i=(N-1); i>=0; i--) {
7487 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7488 if (!r.finishing && r.task != cp
7489 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7490 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007491 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 // + "/aff=" + r.task.affinity + " to new cls="
7493 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7494 if (r.task.affinity != null) {
7495 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007496 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007497 return r;
7498 }
7499 } else if (r.task.intent != null
7500 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007501 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007503 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007504 return r;
7505 } else if (r.task.affinityIntent != null
7506 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007507 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007508 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007509 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 return r;
7511 }
7512 }
7513 }
7514
7515 return null;
7516 }
7517
7518 /**
7519 * Returns the first activity (starting from the top of the stack) that
7520 * is the same as the given activity. Returns null if no such activity
7521 * is found.
7522 */
7523 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7524 ComponentName cls = intent.getComponent();
7525 if (info.targetActivity != null) {
7526 cls = new ComponentName(info.packageName, info.targetActivity);
7527 }
7528
7529 final int N = mHistory.size();
7530 for (int i=(N-1); i>=0; i--) {
7531 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7532 if (!r.finishing) {
7533 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007534 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007536 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 return r;
7538 }
7539 }
7540 }
7541
7542 return null;
7543 }
7544
7545 public void finishOtherInstances(IBinder token, ComponentName className) {
7546 synchronized(this) {
7547 final long origId = Binder.clearCallingIdentity();
7548
7549 int N = mHistory.size();
7550 TaskRecord lastTask = null;
7551 for (int i=0; i<N; i++) {
7552 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7553 if (r.realActivity.equals(className)
7554 && r != token && lastTask != r.task) {
7555 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7556 null, "others")) {
7557 i--;
7558 N--;
7559 }
7560 }
7561 lastTask = r.task;
7562 }
7563
7564 Binder.restoreCallingIdentity(origId);
7565 }
7566 }
7567
7568 // =========================================================
7569 // THUMBNAILS
7570 // =========================================================
7571
7572 public void reportThumbnail(IBinder token,
7573 Bitmap thumbnail, CharSequence description) {
7574 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7575 final long origId = Binder.clearCallingIdentity();
7576 sendPendingThumbnail(null, token, thumbnail, description, true);
7577 Binder.restoreCallingIdentity(origId);
7578 }
7579
7580 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7581 Bitmap thumbnail, CharSequence description, boolean always) {
7582 TaskRecord task = null;
7583 ArrayList receivers = null;
7584
7585 //System.out.println("Send pending thumbnail: " + r);
7586
7587 synchronized(this) {
7588 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007589 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 if (index < 0) {
7591 return;
7592 }
7593 r = (HistoryRecord)mHistory.get(index);
7594 }
7595 if (thumbnail == null) {
7596 thumbnail = r.thumbnail;
7597 description = r.description;
7598 }
7599 if (thumbnail == null && !always) {
7600 // If there is no thumbnail, and this entry is not actually
7601 // going away, then abort for now and pick up the next
7602 // thumbnail we get.
7603 return;
7604 }
7605 task = r.task;
7606
7607 int N = mPendingThumbnails.size();
7608 int i=0;
7609 while (i<N) {
7610 PendingThumbnailsRecord pr =
7611 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7612 //System.out.println("Looking in " + pr.pendingRecords);
7613 if (pr.pendingRecords.remove(r)) {
7614 if (receivers == null) {
7615 receivers = new ArrayList();
7616 }
7617 receivers.add(pr);
7618 if (pr.pendingRecords.size() == 0) {
7619 pr.finished = true;
7620 mPendingThumbnails.remove(i);
7621 N--;
7622 continue;
7623 }
7624 }
7625 i++;
7626 }
7627 }
7628
7629 if (receivers != null) {
7630 final int N = receivers.size();
7631 for (int i=0; i<N; i++) {
7632 try {
7633 PendingThumbnailsRecord pr =
7634 (PendingThumbnailsRecord)receivers.get(i);
7635 pr.receiver.newThumbnail(
7636 task != null ? task.taskId : -1, thumbnail, description);
7637 if (pr.finished) {
7638 pr.receiver.finished();
7639 }
7640 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007641 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 }
7643 }
7644 }
7645 }
7646
7647 // =========================================================
7648 // CONTENT PROVIDERS
7649 // =========================================================
7650
7651 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7652 List providers = null;
7653 try {
7654 providers = ActivityThread.getPackageManager().
7655 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007656 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 } catch (RemoteException ex) {
7658 }
7659 if (providers != null) {
7660 final int N = providers.size();
7661 for (int i=0; i<N; i++) {
7662 ProviderInfo cpi =
7663 (ProviderInfo)providers.get(i);
7664 ContentProviderRecord cpr =
7665 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7666 if (cpr == null) {
7667 cpr = new ContentProviderRecord(cpi, app.info);
7668 mProvidersByClass.put(cpi.name, cpr);
7669 }
7670 app.pubProviders.put(cpi.name, cpr);
7671 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007672 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 }
7674 }
7675 return providers;
7676 }
7677
7678 private final String checkContentProviderPermissionLocked(
7679 ProviderInfo cpi, ProcessRecord r, int mode) {
7680 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7681 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7682 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7683 cpi.exported ? -1 : cpi.applicationInfo.uid)
7684 == PackageManager.PERMISSION_GRANTED
7685 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7686 return null;
7687 }
7688 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7689 cpi.exported ? -1 : cpi.applicationInfo.uid)
7690 == PackageManager.PERMISSION_GRANTED) {
7691 return null;
7692 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007693
7694 PathPermission[] pps = cpi.pathPermissions;
7695 if (pps != null) {
7696 int i = pps.length;
7697 while (i > 0) {
7698 i--;
7699 PathPermission pp = pps[i];
7700 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7701 cpi.exported ? -1 : cpi.applicationInfo.uid)
7702 == PackageManager.PERMISSION_GRANTED
7703 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7704 return null;
7705 }
7706 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7707 cpi.exported ? -1 : cpi.applicationInfo.uid)
7708 == PackageManager.PERMISSION_GRANTED) {
7709 return null;
7710 }
7711 }
7712 }
7713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 String msg = "Permission Denial: opening provider " + cpi.name
7715 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7716 + ", uid=" + callingUid + ") requires "
7717 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007718 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 return msg;
7720 }
7721
7722 private final ContentProviderHolder getContentProviderImpl(
7723 IApplicationThread caller, String name) {
7724 ContentProviderRecord cpr;
7725 ProviderInfo cpi = null;
7726
7727 synchronized(this) {
7728 ProcessRecord r = null;
7729 if (caller != null) {
7730 r = getRecordForAppLocked(caller);
7731 if (r == null) {
7732 throw new SecurityException(
7733 "Unable to find app for caller " + caller
7734 + " (pid=" + Binder.getCallingPid()
7735 + ") when getting content provider " + name);
7736 }
7737 }
7738
7739 // First check if this content provider has been published...
7740 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7741 if (cpr != null) {
7742 cpi = cpr.info;
7743 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7744 return new ContentProviderHolder(cpi,
7745 cpi.readPermission != null
7746 ? cpi.readPermission : cpi.writePermission);
7747 }
7748
7749 if (r != null && cpr.canRunHere(r)) {
7750 // This provider has been published or is in the process
7751 // of being published... but it is also allowed to run
7752 // in the caller's process, so don't make a connection
7753 // and just let the caller instantiate its own instance.
7754 if (cpr.provider != null) {
7755 // don't give caller the provider object, it needs
7756 // to make its own.
7757 cpr = new ContentProviderRecord(cpr);
7758 }
7759 return cpr;
7760 }
7761
7762 final long origId = Binder.clearCallingIdentity();
7763
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007764 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765 // return it right away.
7766 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007767 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007768 "Adding provider requested by "
7769 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007770 + cpr.info.processName);
7771 Integer cnt = r.conProviders.get(cpr);
7772 if (cnt == null) {
7773 r.conProviders.put(cpr, new Integer(1));
7774 } else {
7775 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 cpr.clients.add(r);
7778 } else {
7779 cpr.externals++;
7780 }
7781
7782 if (cpr.app != null) {
7783 updateOomAdjLocked(cpr.app);
7784 }
7785
7786 Binder.restoreCallingIdentity(origId);
7787
7788 } else {
7789 try {
7790 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007791 resolveContentProvider(name,
7792 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 } catch (RemoteException ex) {
7794 }
7795 if (cpi == null) {
7796 return null;
7797 }
7798
7799 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7800 return new ContentProviderHolder(cpi,
7801 cpi.readPermission != null
7802 ? cpi.readPermission : cpi.writePermission);
7803 }
7804
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007805 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7806 && !cpi.processName.equals("system")) {
7807 // If this content provider does not run in the system
7808 // process, and the system is not yet ready to run other
7809 // processes, then fail fast instead of hanging.
7810 throw new IllegalArgumentException(
7811 "Attempt to launch content provider before system ready");
7812 }
7813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7815 final boolean firstClass = cpr == null;
7816 if (firstClass) {
7817 try {
7818 ApplicationInfo ai =
7819 ActivityThread.getPackageManager().
7820 getApplicationInfo(
7821 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007822 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007824 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 + cpi.name);
7826 return null;
7827 }
7828 cpr = new ContentProviderRecord(cpi, ai);
7829 } catch (RemoteException ex) {
7830 // pm is in same process, this will never happen.
7831 }
7832 }
7833
7834 if (r != null && cpr.canRunHere(r)) {
7835 // If this is a multiprocess provider, then just return its
7836 // info and allow the caller to instantiate it. Only do
7837 // this if the provider is the same user as the caller's
7838 // process, or can run as root (so can be in any process).
7839 return cpr;
7840 }
7841
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007842 if (DEBUG_PROVIDER) {
7843 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007844 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007845 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 }
7847
7848 // This is single process, and our app is now connecting to it.
7849 // See if we are already in the process of launching this
7850 // provider.
7851 final int N = mLaunchingProviders.size();
7852 int i;
7853 for (i=0; i<N; i++) {
7854 if (mLaunchingProviders.get(i) == cpr) {
7855 break;
7856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 }
7858
7859 // If the provider is not already being launched, then get it
7860 // started.
7861 if (i >= N) {
7862 final long origId = Binder.clearCallingIdentity();
7863 ProcessRecord proc = startProcessLocked(cpi.processName,
7864 cpr.appInfo, false, 0, "content provider",
7865 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007866 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007868 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007869 + cpi.applicationInfo.packageName + "/"
7870 + cpi.applicationInfo.uid + " for provider "
7871 + name + ": process is bad");
7872 return null;
7873 }
7874 cpr.launchingApp = proc;
7875 mLaunchingProviders.add(cpr);
7876 Binder.restoreCallingIdentity(origId);
7877 }
7878
7879 // Make sure the provider is published (the same provider class
7880 // may be published under multiple names).
7881 if (firstClass) {
7882 mProvidersByClass.put(cpi.name, cpr);
7883 }
7884 mProvidersByName.put(name, cpr);
7885
7886 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007887 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007888 "Adding provider requested by "
7889 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007890 + cpr.info.processName);
7891 Integer cnt = r.conProviders.get(cpr);
7892 if (cnt == null) {
7893 r.conProviders.put(cpr, new Integer(1));
7894 } else {
7895 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 cpr.clients.add(r);
7898 } else {
7899 cpr.externals++;
7900 }
7901 }
7902 }
7903
7904 // Wait for the provider to be published...
7905 synchronized (cpr) {
7906 while (cpr.provider == null) {
7907 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007908 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007909 + cpi.applicationInfo.packageName + "/"
7910 + cpi.applicationInfo.uid + " for provider "
7911 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007912 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 cpi.applicationInfo.packageName,
7914 cpi.applicationInfo.uid, name);
7915 return null;
7916 }
7917 try {
7918 cpr.wait();
7919 } catch (InterruptedException ex) {
7920 }
7921 }
7922 }
7923 return cpr;
7924 }
7925
7926 public final ContentProviderHolder getContentProvider(
7927 IApplicationThread caller, String name) {
7928 if (caller == null) {
7929 String msg = "null IApplicationThread when getting content provider "
7930 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007931 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 throw new SecurityException(msg);
7933 }
7934
7935 return getContentProviderImpl(caller, name);
7936 }
7937
7938 private ContentProviderHolder getContentProviderExternal(String name) {
7939 return getContentProviderImpl(null, name);
7940 }
7941
7942 /**
7943 * Drop a content provider from a ProcessRecord's bookkeeping
7944 * @param cpr
7945 */
7946 public void removeContentProvider(IApplicationThread caller, String name) {
7947 synchronized (this) {
7948 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7949 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007950 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007951 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007952 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 return;
7954 }
7955 final ProcessRecord r = getRecordForAppLocked(caller);
7956 if (r == null) {
7957 throw new SecurityException(
7958 "Unable to find app for caller " + caller +
7959 " when removing content provider " + name);
7960 }
7961 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007962 ContentProviderRecord localCpr = (ContentProviderRecord)
7963 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007964 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007965 + r.info.processName + " from process "
7966 + localCpr.appInfo.processName);
7967 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007968 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007969 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007970 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 return;
7972 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007973 Integer cnt = r.conProviders.get(localCpr);
7974 if (cnt == null || cnt.intValue() <= 1) {
7975 localCpr.clients.remove(r);
7976 r.conProviders.remove(localCpr);
7977 } else {
7978 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 }
7981 updateOomAdjLocked();
7982 }
7983 }
7984
7985 private void removeContentProviderExternal(String name) {
7986 synchronized (this) {
7987 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7988 if(cpr == null) {
7989 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007990 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007991 return;
7992 }
7993
7994 //update content provider record entry info
7995 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7996 localCpr.externals--;
7997 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007998 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 }
8000 updateOomAdjLocked();
8001 }
8002 }
8003
8004 public final void publishContentProviders(IApplicationThread caller,
8005 List<ContentProviderHolder> providers) {
8006 if (providers == null) {
8007 return;
8008 }
8009
8010 synchronized(this) {
8011 final ProcessRecord r = getRecordForAppLocked(caller);
8012 if (r == null) {
8013 throw new SecurityException(
8014 "Unable to find app for caller " + caller
8015 + " (pid=" + Binder.getCallingPid()
8016 + ") when publishing content providers");
8017 }
8018
8019 final long origId = Binder.clearCallingIdentity();
8020
8021 final int N = providers.size();
8022 for (int i=0; i<N; i++) {
8023 ContentProviderHolder src = providers.get(i);
8024 if (src == null || src.info == null || src.provider == null) {
8025 continue;
8026 }
8027 ContentProviderRecord dst =
8028 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8029 if (dst != null) {
8030 mProvidersByClass.put(dst.info.name, dst);
8031 String names[] = dst.info.authority.split(";");
8032 for (int j = 0; j < names.length; j++) {
8033 mProvidersByName.put(names[j], dst);
8034 }
8035
8036 int NL = mLaunchingProviders.size();
8037 int j;
8038 for (j=0; j<NL; j++) {
8039 if (mLaunchingProviders.get(j) == dst) {
8040 mLaunchingProviders.remove(j);
8041 j--;
8042 NL--;
8043 }
8044 }
8045 synchronized (dst) {
8046 dst.provider = src.provider;
8047 dst.app = r;
8048 dst.notifyAll();
8049 }
8050 updateOomAdjLocked(r);
8051 }
8052 }
8053
8054 Binder.restoreCallingIdentity(origId);
8055 }
8056 }
8057
8058 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008059 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008060 synchronized (mSelf) {
8061 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8062 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008063 if (providers != null) {
8064 for (int i=providers.size()-1; i>=0; i--) {
8065 ProviderInfo pi = (ProviderInfo)providers.get(i);
8066 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8067 Slog.w(TAG, "Not installing system proc provider " + pi.name
8068 + ": not system .apk");
8069 providers.remove(i);
8070 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008071 }
8072 }
8073 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008074 if (providers != null) {
8075 mSystemThread.installSystemProviders(providers);
8076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 }
8078
8079 // =========================================================
8080 // GLOBAL MANAGEMENT
8081 // =========================================================
8082
8083 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8084 ApplicationInfo info, String customProcess) {
8085 String proc = customProcess != null ? customProcess : info.processName;
8086 BatteryStatsImpl.Uid.Proc ps = null;
8087 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8088 synchronized (stats) {
8089 ps = stats.getProcessStatsLocked(info.uid, proc);
8090 }
8091 return new ProcessRecord(ps, thread, info, proc);
8092 }
8093
8094 final ProcessRecord addAppLocked(ApplicationInfo info) {
8095 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8096
8097 if (app == null) {
8098 app = newProcessRecordLocked(null, info, null);
8099 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008100 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 }
8102
8103 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8104 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8105 app.persistent = true;
8106 app.maxAdj = CORE_SERVER_ADJ;
8107 }
8108 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8109 mPersistentStartingProcesses.add(app);
8110 startProcessLocked(app, "added application", app.processName);
8111 }
8112
8113 return app;
8114 }
8115
8116 public void unhandledBack() {
8117 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8118 "unhandledBack()");
8119
8120 synchronized(this) {
8121 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008122 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 TAG, "Performing unhandledBack(): stack size = " + count);
8124 if (count > 1) {
8125 final long origId = Binder.clearCallingIdentity();
8126 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8127 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8128 Binder.restoreCallingIdentity(origId);
8129 }
8130 }
8131 }
8132
8133 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8134 String name = uri.getAuthority();
8135 ContentProviderHolder cph = getContentProviderExternal(name);
8136 ParcelFileDescriptor pfd = null;
8137 if (cph != null) {
8138 // We record the binder invoker's uid in thread-local storage before
8139 // going to the content provider to open the file. Later, in the code
8140 // that handles all permissions checks, we look for this uid and use
8141 // that rather than the Activity Manager's own uid. The effect is that
8142 // we do the check against the caller's permissions even though it looks
8143 // to the content provider like the Activity Manager itself is making
8144 // the request.
8145 sCallerIdentity.set(new Identity(
8146 Binder.getCallingPid(), Binder.getCallingUid()));
8147 try {
8148 pfd = cph.provider.openFile(uri, "r");
8149 } catch (FileNotFoundException e) {
8150 // do nothing; pfd will be returned null
8151 } finally {
8152 // Ensure that whatever happens, we clean up the identity state
8153 sCallerIdentity.remove();
8154 }
8155
8156 // We've got the fd now, so we're done with the provider.
8157 removeContentProviderExternal(name);
8158 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008159 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008160 }
8161 return pfd;
8162 }
8163
8164 public void goingToSleep() {
8165 synchronized(this) {
8166 mSleeping = true;
8167 mWindowManager.setEventDispatching(false);
8168
8169 if (mResumedActivity != null) {
8170 pauseIfSleepingLocked();
8171 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008172 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 }
8174 }
8175 }
8176
Dianne Hackborn55280a92009-05-07 15:53:46 -07008177 public boolean shutdown(int timeout) {
8178 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8179 != PackageManager.PERMISSION_GRANTED) {
8180 throw new SecurityException("Requires permission "
8181 + android.Manifest.permission.SHUTDOWN);
8182 }
8183
8184 boolean timedout = false;
8185
8186 synchronized(this) {
8187 mShuttingDown = true;
8188 mWindowManager.setEventDispatching(false);
8189
8190 if (mResumedActivity != null) {
8191 pauseIfSleepingLocked();
8192 final long endTime = System.currentTimeMillis() + timeout;
8193 while (mResumedActivity != null || mPausingActivity != null) {
8194 long delay = endTime - System.currentTimeMillis();
8195 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008196 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008197 timedout = true;
8198 break;
8199 }
8200 try {
8201 this.wait();
8202 } catch (InterruptedException e) {
8203 }
8204 }
8205 }
8206 }
8207
8208 mUsageStatsService.shutdown();
8209 mBatteryStatsService.shutdown();
8210
8211 return timedout;
8212 }
8213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008214 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008215 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008216 if (!mGoingToSleep.isHeld()) {
8217 mGoingToSleep.acquire();
8218 if (mLaunchingActivity.isHeld()) {
8219 mLaunchingActivity.release();
8220 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8221 }
8222 }
8223
8224 // If we are not currently pausing an activity, get the current
8225 // one to pause. If we are pausing one, we will just let that stuff
8226 // run and release the wake lock when all done.
8227 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008228 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8229 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 startPausingLocked(false, true);
8231 }
8232 }
8233 }
8234
8235 public void wakingUp() {
8236 synchronized(this) {
8237 if (mGoingToSleep.isHeld()) {
8238 mGoingToSleep.release();
8239 }
8240 mWindowManager.setEventDispatching(true);
8241 mSleeping = false;
8242 resumeTopActivityLocked(null);
8243 }
8244 }
8245
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008246 public void stopAppSwitches() {
8247 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8248 != PackageManager.PERMISSION_GRANTED) {
8249 throw new SecurityException("Requires permission "
8250 + android.Manifest.permission.STOP_APP_SWITCHES);
8251 }
8252
8253 synchronized(this) {
8254 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8255 + APP_SWITCH_DELAY_TIME;
8256 mDidAppSwitch = false;
8257 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8258 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8259 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8260 }
8261 }
8262
8263 public void resumeAppSwitches() {
8264 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8265 != PackageManager.PERMISSION_GRANTED) {
8266 throw new SecurityException("Requires permission "
8267 + android.Manifest.permission.STOP_APP_SWITCHES);
8268 }
8269
8270 synchronized(this) {
8271 // Note that we don't execute any pending app switches... we will
8272 // let those wait until either the timeout, or the next start
8273 // activity request.
8274 mAppSwitchesAllowedTime = 0;
8275 }
8276 }
8277
8278 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8279 String name) {
8280 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8281 return true;
8282 }
8283
8284 final int perm = checkComponentPermission(
8285 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8286 callingUid, -1);
8287 if (perm == PackageManager.PERMISSION_GRANTED) {
8288 return true;
8289 }
8290
Joe Onorato8a9b2202010-02-26 18:56:32 -08008291 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008292 return false;
8293 }
8294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 public void setDebugApp(String packageName, boolean waitForDebugger,
8296 boolean persistent) {
8297 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8298 "setDebugApp()");
8299
8300 // Note that this is not really thread safe if there are multiple
8301 // callers into it at the same time, but that's not a situation we
8302 // care about.
8303 if (persistent) {
8304 final ContentResolver resolver = mContext.getContentResolver();
8305 Settings.System.putString(
8306 resolver, Settings.System.DEBUG_APP,
8307 packageName);
8308 Settings.System.putInt(
8309 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8310 waitForDebugger ? 1 : 0);
8311 }
8312
8313 synchronized (this) {
8314 if (!persistent) {
8315 mOrigDebugApp = mDebugApp;
8316 mOrigWaitForDebugger = mWaitForDebugger;
8317 }
8318 mDebugApp = packageName;
8319 mWaitForDebugger = waitForDebugger;
8320 mDebugTransient = !persistent;
8321 if (packageName != null) {
8322 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008323 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 Binder.restoreCallingIdentity(origId);
8325 }
8326 }
8327 }
8328
8329 public void setAlwaysFinish(boolean enabled) {
8330 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8331 "setAlwaysFinish()");
8332
8333 Settings.System.putInt(
8334 mContext.getContentResolver(),
8335 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8336
8337 synchronized (this) {
8338 mAlwaysFinishActivities = enabled;
8339 }
8340 }
8341
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008342 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008344 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008346 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 }
8348 }
8349
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008350 public boolean isUserAMonkey() {
8351 // For now the fact that there is a controller implies
8352 // we have a monkey.
8353 synchronized (this) {
8354 return mController != null;
8355 }
8356 }
8357
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008358 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008359 synchronized (this) {
8360 mWatchers.register(watcher);
8361 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008362 }
8363
8364 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008365 synchronized (this) {
8366 mWatchers.unregister(watcher);
8367 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008368 }
8369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 public final void enterSafeMode() {
8371 synchronized(this) {
8372 // It only makes sense to do this before the system is ready
8373 // and started launching other packages.
8374 if (!mSystemReady) {
8375 try {
8376 ActivityThread.getPackageManager().enterSafeMode();
8377 } catch (RemoteException e) {
8378 }
8379
8380 View v = LayoutInflater.from(mContext).inflate(
8381 com.android.internal.R.layout.safe_mode, null);
8382 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8383 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8384 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8385 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8386 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8387 lp.format = v.getBackground().getOpacity();
8388 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8389 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8390 ((WindowManager)mContext.getSystemService(
8391 Context.WINDOW_SERVICE)).addView(v, lp);
8392 }
8393 }
8394 }
8395
8396 public void noteWakeupAlarm(IIntentSender sender) {
8397 if (!(sender instanceof PendingIntentRecord)) {
8398 return;
8399 }
8400 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8401 synchronized (stats) {
8402 if (mBatteryStatsService.isOnBattery()) {
8403 mBatteryStatsService.enforceCallingPermission();
8404 PendingIntentRecord rec = (PendingIntentRecord)sender;
8405 int MY_UID = Binder.getCallingUid();
8406 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8407 BatteryStatsImpl.Uid.Pkg pkg =
8408 stats.getPackageStatsLocked(uid, rec.key.packageName);
8409 pkg.incWakeupsLocked();
8410 }
8411 }
8412 }
8413
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008414 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008416 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008417 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008418 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 // XXX Note: don't acquire main activity lock here, because the window
8420 // manager calls in with its locks held.
8421
8422 boolean killed = false;
8423 synchronized (mPidsSelfLocked) {
8424 int[] types = new int[pids.length];
8425 int worstType = 0;
8426 for (int i=0; i<pids.length; i++) {
8427 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8428 if (proc != null) {
8429 int type = proc.setAdj;
8430 types[i] = type;
8431 if (type > worstType) {
8432 worstType = type;
8433 }
8434 }
8435 }
8436
8437 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8438 // then constrain it so we will kill all hidden procs.
8439 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8440 worstType = HIDDEN_APP_MIN_ADJ;
8441 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008442 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 for (int i=0; i<pids.length; i++) {
8444 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8445 if (proc == null) {
8446 continue;
8447 }
8448 int adj = proc.setAdj;
8449 if (adj >= worstType) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008450 Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008451 + adj + ")");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008452 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8453 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008454 killed = true;
8455 Process.killProcess(pids[i]);
8456 }
8457 }
8458 }
8459 return killed;
8460 }
8461
8462 public void reportPss(IApplicationThread caller, int pss) {
8463 Watchdog.PssRequestor req;
8464 String name;
8465 ProcessRecord callerApp;
8466 synchronized (this) {
8467 if (caller == null) {
8468 return;
8469 }
8470 callerApp = getRecordForAppLocked(caller);
8471 if (callerApp == null) {
8472 return;
8473 }
8474 callerApp.lastPss = pss;
8475 req = callerApp;
8476 name = callerApp.processName;
8477 }
8478 Watchdog.getInstance().reportPss(req, name, pss);
8479 if (!callerApp.persistent) {
8480 removeRequestedPss(callerApp);
8481 }
8482 }
8483
8484 public void requestPss(Runnable completeCallback) {
8485 ArrayList<ProcessRecord> procs;
8486 synchronized (this) {
8487 mRequestPssCallback = completeCallback;
8488 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008489 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8490 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008491 if (!proc.persistent) {
8492 mRequestPssList.add(proc);
8493 }
8494 }
8495 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8496 }
8497
8498 int oldPri = Process.getThreadPriority(Process.myTid());
8499 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8500 for (int i=procs.size()-1; i>=0; i--) {
8501 ProcessRecord proc = procs.get(i);
8502 proc.lastPss = 0;
8503 proc.requestPss();
8504 }
8505 Process.setThreadPriority(oldPri);
8506 }
8507
8508 void removeRequestedPss(ProcessRecord proc) {
8509 Runnable callback = null;
8510 synchronized (this) {
8511 if (mRequestPssList.remove(proc)) {
8512 if (mRequestPssList.size() == 0) {
8513 callback = mRequestPssCallback;
8514 mRequestPssCallback = null;
8515 }
8516 }
8517 }
8518
8519 if (callback != null) {
8520 callback.run();
8521 }
8522 }
8523
8524 public void collectPss(Watchdog.PssStats stats) {
8525 stats.mEmptyPss = 0;
8526 stats.mEmptyCount = 0;
8527 stats.mBackgroundPss = 0;
8528 stats.mBackgroundCount = 0;
8529 stats.mServicePss = 0;
8530 stats.mServiceCount = 0;
8531 stats.mVisiblePss = 0;
8532 stats.mVisibleCount = 0;
8533 stats.mForegroundPss = 0;
8534 stats.mForegroundCount = 0;
8535 stats.mNoPssCount = 0;
8536 synchronized (this) {
8537 int i;
8538 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8539 ? mProcDeaths.length : stats.mProcDeaths.length;
8540 int aggr = 0;
8541 for (i=0; i<NPD; i++) {
8542 aggr += mProcDeaths[i];
8543 stats.mProcDeaths[i] = aggr;
8544 }
8545 while (i<stats.mProcDeaths.length) {
8546 stats.mProcDeaths[i] = 0;
8547 i++;
8548 }
8549
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008550 for (i=mLruProcesses.size()-1; i>=0; i--) {
8551 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 if (proc.persistent) {
8553 continue;
8554 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008555 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 if (proc.lastPss == 0) {
8557 stats.mNoPssCount++;
8558 continue;
8559 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008560 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8561 if (proc.empty) {
8562 stats.mEmptyPss += proc.lastPss;
8563 stats.mEmptyCount++;
8564 } else {
8565 stats.mBackgroundPss += proc.lastPss;
8566 stats.mBackgroundCount++;
8567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8569 stats.mVisiblePss += proc.lastPss;
8570 stats.mVisibleCount++;
8571 } else {
8572 stats.mForegroundPss += proc.lastPss;
8573 stats.mForegroundCount++;
8574 }
8575 }
8576 }
8577 }
8578
8579 public final void startRunning(String pkg, String cls, String action,
8580 String data) {
8581 synchronized(this) {
8582 if (mStartRunning) {
8583 return;
8584 }
8585 mStartRunning = true;
8586 mTopComponent = pkg != null && cls != null
8587 ? new ComponentName(pkg, cls) : null;
8588 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8589 mTopData = data;
8590 if (!mSystemReady) {
8591 return;
8592 }
8593 }
8594
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008595 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008596 }
8597
8598 private void retrieveSettings() {
8599 final ContentResolver resolver = mContext.getContentResolver();
8600 String debugApp = Settings.System.getString(
8601 resolver, Settings.System.DEBUG_APP);
8602 boolean waitForDebugger = Settings.System.getInt(
8603 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8604 boolean alwaysFinishActivities = Settings.System.getInt(
8605 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8606
8607 Configuration configuration = new Configuration();
8608 Settings.System.getConfiguration(resolver, configuration);
8609
8610 synchronized (this) {
8611 mDebugApp = mOrigDebugApp = debugApp;
8612 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8613 mAlwaysFinishActivities = alwaysFinishActivities;
8614 // This happens before any activities are started, so we can
8615 // change mConfiguration in-place.
8616 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008617 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008618 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008619 }
8620 }
8621
8622 public boolean testIsSystemReady() {
8623 // no need to synchronize(this) just to read & return the value
8624 return mSystemReady;
8625 }
8626
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008627 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008628 // In the simulator, startRunning will never have been called, which
8629 // normally sets a few crucial variables. Do it here instead.
8630 if (!Process.supportsProcesses()) {
8631 mStartRunning = true;
8632 mTopAction = Intent.ACTION_MAIN;
8633 }
8634
8635 synchronized(this) {
8636 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008637 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008638 return;
8639 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008640
8641 // Check to see if there are any update receivers to run.
8642 if (!mDidUpdate) {
8643 if (mWaitingUpdate) {
8644 return;
8645 }
8646 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8647 List<ResolveInfo> ris = null;
8648 try {
8649 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8650 intent, null, 0);
8651 } catch (RemoteException e) {
8652 }
8653 if (ris != null) {
8654 for (int i=ris.size()-1; i>=0; i--) {
8655 if ((ris.get(i).activityInfo.applicationInfo.flags
8656 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8657 ris.remove(i);
8658 }
8659 }
8660 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8661 for (int i=0; i<ris.size(); i++) {
8662 ActivityInfo ai = ris.get(i).activityInfo;
8663 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8664 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008665 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008666 finisher = new IIntentReceiver.Stub() {
8667 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008668 String data, Bundle extras, boolean ordered,
8669 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008670 throws RemoteException {
8671 synchronized (ActivityManagerService.this) {
8672 mDidUpdate = true;
8673 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008674 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008675 }
8676 };
8677 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008678 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008679 broadcastIntentLocked(null, null, intent, null, finisher,
8680 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008681 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008682 mWaitingUpdate = true;
8683 }
8684 }
8685 }
8686 if (mWaitingUpdate) {
8687 return;
8688 }
8689 mDidUpdate = true;
8690 }
8691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 mSystemReady = true;
8693 if (!mStartRunning) {
8694 return;
8695 }
8696 }
8697
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008698 ArrayList<ProcessRecord> procsToKill = null;
8699 synchronized(mPidsSelfLocked) {
8700 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8701 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8702 if (!isAllowedWhileBooting(proc.info)){
8703 if (procsToKill == null) {
8704 procsToKill = new ArrayList<ProcessRecord>();
8705 }
8706 procsToKill.add(proc);
8707 }
8708 }
8709 }
8710
8711 if (procsToKill != null) {
8712 synchronized(this) {
8713 for (int i=procsToKill.size()-1; i>=0; i--) {
8714 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008715 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008716 removeProcessLocked(proc, true);
8717 }
8718 }
8719 }
8720
Joe Onorato8a9b2202010-02-26 18:56:32 -08008721 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008722 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 SystemClock.uptimeMillis());
8724
8725 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008726 // Make sure we have no pre-ready processes sitting around.
8727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8729 ResolveInfo ri = mContext.getPackageManager()
8730 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008731 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 CharSequence errorMsg = null;
8733 if (ri != null) {
8734 ActivityInfo ai = ri.activityInfo;
8735 ApplicationInfo app = ai.applicationInfo;
8736 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8737 mTopAction = Intent.ACTION_FACTORY_TEST;
8738 mTopData = null;
8739 mTopComponent = new ComponentName(app.packageName,
8740 ai.name);
8741 } else {
8742 errorMsg = mContext.getResources().getText(
8743 com.android.internal.R.string.factorytest_not_system);
8744 }
8745 } else {
8746 errorMsg = mContext.getResources().getText(
8747 com.android.internal.R.string.factorytest_no_action);
8748 }
8749 if (errorMsg != null) {
8750 mTopAction = null;
8751 mTopData = null;
8752 mTopComponent = null;
8753 Message msg = Message.obtain();
8754 msg.what = SHOW_FACTORY_ERROR_MSG;
8755 msg.getData().putCharSequence("msg", errorMsg);
8756 mHandler.sendMessage(msg);
8757 }
8758 }
8759 }
8760
8761 retrieveSettings();
8762
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008763 if (goingCallback != null) goingCallback.run();
8764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 synchronized (this) {
8766 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8767 try {
8768 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008769 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770 if (apps != null) {
8771 int N = apps.size();
8772 int i;
8773 for (i=0; i<N; i++) {
8774 ApplicationInfo info
8775 = (ApplicationInfo)apps.get(i);
8776 if (info != null &&
8777 !info.packageName.equals("android")) {
8778 addAppLocked(info);
8779 }
8780 }
8781 }
8782 } catch (RemoteException ex) {
8783 // pm is in same process, this will never happen.
8784 }
8785 }
8786
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008787 // Start up initial activity.
8788 mBooting = true;
8789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 try {
8791 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8792 Message msg = Message.obtain();
8793 msg.what = SHOW_UID_ERROR_MSG;
8794 mHandler.sendMessage(msg);
8795 }
8796 } catch (RemoteException e) {
8797 }
8798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 resumeTopActivityLocked(null);
8800 }
8801 }
8802
Dan Egnorb7f03672009-12-09 16:22:32 -08008803 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008804 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008806 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008807 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008808 startAppProblemLocked(app);
8809 app.stopFreezingAllLocked();
8810 return handleAppCrashLocked(app);
8811 }
8812
Dan Egnorb7f03672009-12-09 16:22:32 -08008813 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008814 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008815 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008816 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008817 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8818 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 startAppProblemLocked(app);
8820 app.stopFreezingAllLocked();
8821 }
8822
8823 /**
8824 * Generate a process error record, suitable for attachment to a ProcessRecord.
8825 *
8826 * @param app The ProcessRecord in which the error occurred.
8827 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8828 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008829 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 * @param shortMsg Short message describing the crash.
8831 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008832 * @param stackTrace Full crash stack trace, may be null.
8833 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 * @return Returns a fully-formed AppErrorStateInfo record.
8835 */
8836 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008837 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 report.condition = condition;
8841 report.processName = app.processName;
8842 report.pid = app.pid;
8843 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008844 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 report.shortMsg = shortMsg;
8846 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008847 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848
8849 return report;
8850 }
8851
Dan Egnor42471dd2010-01-07 17:25:22 -08008852 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 synchronized (this) {
8854 app.crashing = false;
8855 app.crashingReport = null;
8856 app.notResponding = false;
8857 app.notRespondingReport = null;
8858 if (app.anrDialog == fromDialog) {
8859 app.anrDialog = null;
8860 }
8861 if (app.waitDialog == fromDialog) {
8862 app.waitDialog = null;
8863 }
8864 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008865 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008866 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008867 + app.processName
8868 + " (pid=" + app.pid + ") at user's request");
8869 Process.killProcess(app.pid);
8870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871 }
8872 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008873
Dan Egnorb7f03672009-12-09 16:22:32 -08008874 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008875 long now = SystemClock.uptimeMillis();
8876
8877 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8878 app.info.uid);
8879 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8880 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008881 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008882 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008883 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008884 app.info.processName, app.info.uid);
8885 killServicesLocked(app, false);
8886 for (int i=mHistory.size()-1; i>=0; i--) {
8887 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8888 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008889 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 + r.intent.getComponent().flattenToShortString());
8891 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8892 }
8893 }
8894 if (!app.persistent) {
8895 // We don't want to start this process again until the user
8896 // explicitly does so... but for persistent process, we really
8897 // need to keep it running. If a persistent process is actually
8898 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008899 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 app.info.processName);
8901 mBadProcesses.put(app.info.processName, app.info.uid, now);
8902 app.bad = true;
8903 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8904 app.removed = true;
8905 removeProcessLocked(app, false);
8906 return false;
8907 }
8908 }
8909
8910 // Bump up the crash count of any services currently running in the proc.
8911 if (app.services.size() != 0) {
8912 // Any services running in the application need to be placed
8913 // back in the pending list.
8914 Iterator it = app.services.iterator();
8915 while (it.hasNext()) {
8916 ServiceRecord sr = (ServiceRecord)it.next();
8917 sr.crashCount++;
8918 }
8919 }
8920
8921 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8922 return true;
8923 }
8924
8925 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008926 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8927 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 skipCurrentReceiverLocked(app);
8929 }
8930
8931 void skipCurrentReceiverLocked(ProcessRecord app) {
8932 boolean reschedule = false;
8933 BroadcastRecord r = app.curReceiver;
8934 if (r != null) {
8935 // The current broadcast is waiting for this app's receiver
8936 // to be finished. Looks like that's not going to happen, so
8937 // let the broadcast continue.
8938 logBroadcastReceiverDiscard(r);
8939 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8940 r.resultExtras, r.resultAbort, true);
8941 reschedule = true;
8942 }
8943 r = mPendingBroadcast;
8944 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008945 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 "skip & discard pending app " + r);
8947 logBroadcastReceiverDiscard(r);
8948 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8949 r.resultExtras, r.resultAbort, true);
8950 reschedule = true;
8951 }
8952 if (reschedule) {
8953 scheduleBroadcastsLocked();
8954 }
8955 }
8956
Dan Egnor60d87622009-12-16 16:32:58 -08008957 /**
8958 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8959 * The application process will exit immediately after this call returns.
8960 * @param app object of the crashing app, null for the system server
8961 * @param crashInfo describing the exception
8962 */
8963 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8964 ProcessRecord r = findAppProcess(app);
8965
8966 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8967 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008968 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008969 crashInfo.exceptionClassName,
8970 crashInfo.exceptionMessage,
8971 crashInfo.throwFileName,
8972 crashInfo.throwLineNumber);
8973
Dan Egnor42471dd2010-01-07 17:25:22 -08008974 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008975
8976 crashApplication(r, crashInfo);
8977 }
8978
8979 /**
8980 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8981 * @param app object of the crashing app, null for the system server
8982 * @param tag reported by the caller
8983 * @param crashInfo describing the context of the error
8984 * @return true if the process should exit immediately (WTF is fatal)
8985 */
8986 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008987 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008988 ProcessRecord r = findAppProcess(app);
8989
8990 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8991 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008992 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008993 tag, crashInfo.exceptionMessage);
8994
Dan Egnor42471dd2010-01-07 17:25:22 -08008995 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008996
Doug Zongker43866e02010-01-07 12:09:54 -08008997 if (Settings.Secure.getInt(mContext.getContentResolver(),
8998 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008999 crashApplication(r, crashInfo);
9000 return true;
9001 } else {
9002 return false;
9003 }
9004 }
9005
9006 /**
9007 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9008 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9009 */
9010 private ProcessRecord findAppProcess(IBinder app) {
9011 if (app == null) {
9012 return null;
9013 }
9014
9015 synchronized (this) {
9016 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9017 final int NA = apps.size();
9018 for (int ia=0; ia<NA; ia++) {
9019 ProcessRecord p = apps.valueAt(ia);
9020 if (p.thread != null && p.thread.asBinder() == app) {
9021 return p;
9022 }
9023 }
9024 }
9025
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009027 return null;
9028 }
9029 }
9030
9031 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009032 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009033 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009034 * @param process which caused the error, null means the system server
9035 * @param activity which triggered the error, null if unknown
9036 * @param parent activity related to the error, null if unknown
9037 * @param subject line related to the error, null if absent
9038 * @param report in long form describing the error, null if absent
9039 * @param logFile to include in the report, null if none
9040 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009041 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009042 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009043 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9044 final String report, final File logFile,
9045 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009046 // NOTE -- this must never acquire the ActivityManagerService lock,
9047 // otherwise the watchdog may be prevented from resetting the system.
9048
Dan Egnora455d192010-03-12 08:52:28 -08009049 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009050 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009051 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009052 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009053 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009054 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009055 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009056 }
9057
Dan Egnora455d192010-03-12 08:52:28 -08009058 final String dropboxTag = prefix + eventType;
9059 final DropBoxManager dbox = (DropBoxManager)
9060 mContext.getSystemService(Context.DROPBOX_SERVICE);
9061
9062 // Exit early if the dropbox isn't configured to accept this report type.
9063 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9064
9065 final StringBuilder sb = new StringBuilder(1024);
9066 if (process == null || process.pid == MY_PID) {
9067 sb.append("Process: system_server\n");
9068 } else {
9069 sb.append("Process: ").append(process.processName).append("\n");
9070 }
9071 if (process != null) {
9072 int flags = process.info.flags;
9073 IPackageManager pm = ActivityThread.getPackageManager();
9074 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9075 for (String pkg : process.pkgList) {
9076 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009077 try {
Dan Egnora455d192010-03-12 08:52:28 -08009078 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9079 if (pi != null) {
9080 sb.append(" v").append(pi.versionCode);
9081 if (pi.versionName != null) {
9082 sb.append(" (").append(pi.versionName).append(")");
9083 }
9084 }
9085 } catch (RemoteException e) {
9086 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009087 }
Dan Egnora455d192010-03-12 08:52:28 -08009088 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009089 }
Dan Egnora455d192010-03-12 08:52:28 -08009090 }
9091 if (activity != null) {
9092 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9093 }
9094 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9095 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9096 }
9097 if (parent != null && parent != activity) {
9098 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9099 }
9100 if (subject != null) {
9101 sb.append("Subject: ").append(subject).append("\n");
9102 }
9103 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9104 sb.append("\n");
9105
9106 // Do the rest in a worker thread to avoid blocking the caller on I/O
9107 // (After this point, we shouldn't access AMS internal data structures.)
9108 Thread worker = new Thread("Error dump: " + dropboxTag) {
9109 @Override
9110 public void run() {
9111 if (report != null) {
9112 sb.append(report);
9113 }
9114 if (logFile != null) {
9115 try {
9116 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9117 } catch (IOException e) {
9118 Slog.e(TAG, "Error reading " + logFile, e);
9119 }
9120 }
9121 if (crashInfo != null && crashInfo.stackTrace != null) {
9122 sb.append(crashInfo.stackTrace);
9123 }
9124
9125 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9126 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9127 if (lines > 0) {
9128 sb.append("\n");
9129
9130 // Merge several logcat streams, and take the last N lines
9131 InputStreamReader input = null;
9132 try {
9133 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9134 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9135 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9136
9137 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9138 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9139 input = new InputStreamReader(logcat.getInputStream());
9140
9141 int num;
9142 char[] buf = new char[8192];
9143 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9144 } catch (IOException e) {
9145 Slog.e(TAG, "Error running logcat", e);
9146 } finally {
9147 if (input != null) try { input.close(); } catch (IOException e) {}
9148 }
9149 }
9150
9151 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009152 }
Dan Egnora455d192010-03-12 08:52:28 -08009153 };
9154
9155 if (process == null || process.pid == MY_PID) {
9156 worker.run(); // We may be about to die -- need to run this synchronously
9157 } else {
9158 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009159 }
9160 }
9161
9162 /**
9163 * Bring up the "unexpected error" dialog box for a crashing app.
9164 * Deal with edge cases (intercepts from instrumented applications,
9165 * ActivityController, error intent receivers, that sort of thing).
9166 * @param r the application crashing
9167 * @param crashInfo describing the failure
9168 */
9169 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009170 long timeMillis = System.currentTimeMillis();
9171 String shortMsg = crashInfo.exceptionClassName;
9172 String longMsg = crashInfo.exceptionMessage;
9173 String stackTrace = crashInfo.stackTrace;
9174 if (shortMsg != null && longMsg != null) {
9175 longMsg = shortMsg + ": " + longMsg;
9176 } else if (shortMsg != null) {
9177 longMsg = shortMsg;
9178 }
9179
Dan Egnor60d87622009-12-16 16:32:58 -08009180 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009182 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 try {
9184 String name = r != null ? r.processName : null;
9185 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009186 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009187 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009188 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 + " at watcher's request");
9190 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009191 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 }
9193 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009194 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 }
9196 }
9197
9198 final long origId = Binder.clearCallingIdentity();
9199
9200 // If this process is running instrumentation, finish it.
9201 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009202 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009204 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9205 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 Bundle info = new Bundle();
9207 info.putString("shortMsg", shortMsg);
9208 info.putString("longMsg", longMsg);
9209 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9210 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009211 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 }
9213
Dan Egnor60d87622009-12-16 16:32:58 -08009214 // If we can't identify the process or it's already exceeded its crash quota,
9215 // quit right away without showing a crash dialog.
9216 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009218 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 }
9220
9221 Message msg = Message.obtain();
9222 msg.what = SHOW_ERROR_MSG;
9223 HashMap data = new HashMap();
9224 data.put("result", result);
9225 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 msg.obj = data;
9227 mHandler.sendMessage(msg);
9228
9229 Binder.restoreCallingIdentity(origId);
9230 }
9231
9232 int res = result.get();
9233
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009234 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 synchronized (this) {
9236 if (r != null) {
9237 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9238 SystemClock.uptimeMillis());
9239 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009240 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009241 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009242 }
9243 }
9244
9245 if (appErrorIntent != null) {
9246 try {
9247 mContext.startActivity(appErrorIntent);
9248 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009249 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009253
9254 Intent createAppErrorIntentLocked(ProcessRecord r,
9255 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9256 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009257 if (report == null) {
9258 return null;
9259 }
9260 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9261 result.setComponent(r.errorReportReceiver);
9262 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9263 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9264 return result;
9265 }
9266
Dan Egnorb7f03672009-12-09 16:22:32 -08009267 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9268 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009269 if (r.errorReportReceiver == null) {
9270 return null;
9271 }
9272
9273 if (!r.crashing && !r.notResponding) {
9274 return null;
9275 }
9276
Dan Egnorb7f03672009-12-09 16:22:32 -08009277 ApplicationErrorReport report = new ApplicationErrorReport();
9278 report.packageName = r.info.packageName;
9279 report.installerPackageName = r.errorReportReceiver.getPackageName();
9280 report.processName = r.processName;
9281 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009282 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009283
Dan Egnorb7f03672009-12-09 16:22:32 -08009284 if (r.crashing) {
9285 report.type = ApplicationErrorReport.TYPE_CRASH;
9286 report.crashInfo = crashInfo;
9287 } else if (r.notResponding) {
9288 report.type = ApplicationErrorReport.TYPE_ANR;
9289 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009290
Dan Egnorb7f03672009-12-09 16:22:32 -08009291 report.anrInfo.activity = r.notRespondingReport.tag;
9292 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9293 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009294 }
9295
Dan Egnorb7f03672009-12-09 16:22:32 -08009296 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009297 }
9298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009299 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9300 // assume our apps are happy - lazy create the list
9301 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9302
9303 synchronized (this) {
9304
9305 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009306 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9307 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9309 // This one's in trouble, so we'll generate a report for it
9310 // crashes are higher priority (in case there's a crash *and* an anr)
9311 ActivityManager.ProcessErrorStateInfo report = null;
9312 if (app.crashing) {
9313 report = app.crashingReport;
9314 } else if (app.notResponding) {
9315 report = app.notRespondingReport;
9316 }
9317
9318 if (report != null) {
9319 if (errList == null) {
9320 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9321 }
9322 errList.add(report);
9323 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009324 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 " crashing = " + app.crashing +
9326 " notResponding = " + app.notResponding);
9327 }
9328 }
9329 }
9330 }
9331
9332 return errList;
9333 }
9334
9335 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9336 // Lazy instantiation of list
9337 List<ActivityManager.RunningAppProcessInfo> runList = null;
9338 synchronized (this) {
9339 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009340 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9341 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9343 // Generate process state info for running application
9344 ActivityManager.RunningAppProcessInfo currApp =
9345 new ActivityManager.RunningAppProcessInfo(app.processName,
9346 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009347 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009348 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009349 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009350 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9351 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9352 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009353 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9354 } else if (adj >= HOME_APP_ADJ) {
9355 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9356 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 } else if (adj >= SECONDARY_SERVER_ADJ) {
9358 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9359 } else if (adj >= VISIBLE_APP_ADJ) {
9360 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9361 } else {
9362 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9363 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009364 currApp.importanceReasonCode = app.adjTypeCode;
9365 if (app.adjSource instanceof ProcessRecord) {
9366 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9367 } else if (app.adjSource instanceof HistoryRecord) {
9368 HistoryRecord r = (HistoryRecord)app.adjSource;
9369 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9370 }
9371 if (app.adjTarget instanceof ComponentName) {
9372 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9373 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009374 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 // + " lru=" + currApp.lru);
9376 if (runList == null) {
9377 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9378 }
9379 runList.add(currApp);
9380 }
9381 }
9382 }
9383 return runList;
9384 }
9385
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009386 public List<ApplicationInfo> getRunningExternalApplications() {
9387 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9388 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9389 if (runningApps != null && runningApps.size() > 0) {
9390 Set<String> extList = new HashSet<String>();
9391 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9392 if (app.pkgList != null) {
9393 for (String pkg : app.pkgList) {
9394 extList.add(pkg);
9395 }
9396 }
9397 }
9398 IPackageManager pm = ActivityThread.getPackageManager();
9399 for (String pkg : extList) {
9400 try {
9401 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9402 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9403 retList.add(info);
9404 }
9405 } catch (RemoteException e) {
9406 }
9407 }
9408 }
9409 return retList;
9410 }
9411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 @Override
9413 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009414 if (checkCallingPermission(android.Manifest.permission.DUMP)
9415 != PackageManager.PERMISSION_GRANTED) {
9416 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9417 + Binder.getCallingPid()
9418 + ", uid=" + Binder.getCallingUid()
9419 + " without permission "
9420 + android.Manifest.permission.DUMP);
9421 return;
9422 }
9423
9424 boolean dumpAll = false;
9425
9426 int opti = 0;
9427 while (opti < args.length) {
9428 String opt = args[opti];
9429 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9430 break;
9431 }
9432 opti++;
9433 if ("-a".equals(opt)) {
9434 dumpAll = true;
9435 } else if ("-h".equals(opt)) {
9436 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009437 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009438 pw.println(" cmd may be one of:");
9439 pw.println(" activities: activity stack state");
9440 pw.println(" broadcasts: broadcast state");
9441 pw.println(" intents: pending intent state");
9442 pw.println(" processes: process state");
9443 pw.println(" providers: content provider state");
9444 pw.println(" services: service state");
9445 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009447 } else {
9448 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009450 }
9451
9452 // Is the caller requesting to dump a particular piece of data?
9453 if (opti < args.length) {
9454 String cmd = args[opti];
9455 opti++;
9456 if ("activities".equals(cmd) || "a".equals(cmd)) {
9457 synchronized (this) {
9458 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009460 return;
9461 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9462 synchronized (this) {
9463 dumpBroadcastsLocked(fd, pw, args, opti, true);
9464 }
9465 return;
9466 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9467 synchronized (this) {
9468 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9469 }
9470 return;
9471 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9472 synchronized (this) {
9473 dumpProcessesLocked(fd, pw, args, opti, true);
9474 }
9475 return;
9476 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9477 synchronized (this) {
9478 dumpProvidersLocked(fd, pw, args, opti, true);
9479 }
9480 return;
9481 } else if ("service".equals(cmd)) {
9482 dumpService(fd, pw, args, opti, true);
9483 return;
9484 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9485 synchronized (this) {
9486 dumpServicesLocked(fd, pw, args, opti, true);
9487 }
9488 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009490 }
9491
9492 // No piece of data specified, dump everything.
9493 synchronized (this) {
9494 boolean needSep;
9495 if (dumpAll) {
9496 pw.println("Providers in Current Activity Manager State:");
9497 }
9498 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9499 if (needSep) {
9500 pw.println(" ");
9501 }
9502 if (dumpAll) {
9503 pw.println("-------------------------------------------------------------------------------");
9504 pw.println("Broadcasts in Current Activity Manager State:");
9505 }
9506 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9507 if (needSep) {
9508 pw.println(" ");
9509 }
9510 if (dumpAll) {
9511 pw.println("-------------------------------------------------------------------------------");
9512 pw.println("Services in Current Activity Manager State:");
9513 }
9514 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9515 if (needSep) {
9516 pw.println(" ");
9517 }
9518 if (dumpAll) {
9519 pw.println("-------------------------------------------------------------------------------");
9520 pw.println("PendingIntents in Current Activity Manager State:");
9521 }
9522 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9523 if (needSep) {
9524 pw.println(" ");
9525 }
9526 if (dumpAll) {
9527 pw.println("-------------------------------------------------------------------------------");
9528 pw.println("Activities in Current Activity Manager State:");
9529 }
9530 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9531 if (needSep) {
9532 pw.println(" ");
9533 }
9534 if (dumpAll) {
9535 pw.println("-------------------------------------------------------------------------------");
9536 pw.println("Processes in Current Activity Manager State:");
9537 }
9538 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9539 }
9540 }
9541
9542 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9543 int opti, boolean dumpAll, boolean needHeader) {
9544 if (needHeader) {
9545 pw.println(" Activity stack:");
9546 }
9547 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9548 pw.println(" ");
9549 pw.println(" Running activities (most recent first):");
9550 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9551 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009553 pw.println(" Activities waiting for another to become visible:");
9554 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9555 }
9556 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009557 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009558 pw.println(" Activities waiting to stop:");
9559 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9560 }
9561 if (mFinishingActivities.size() > 0) {
9562 pw.println(" ");
9563 pw.println(" Activities waiting to finish:");
9564 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009567 pw.println(" ");
9568 pw.println(" mPausingActivity: " + mPausingActivity);
9569 pw.println(" mResumedActivity: " + mResumedActivity);
9570 pw.println(" mFocusedActivity: " + mFocusedActivity);
9571 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009573 if (dumpAll && mRecentTasks.size() > 0) {
9574 pw.println(" ");
9575 pw.println("Recent tasks in Current Activity Manager State:");
9576
9577 final int N = mRecentTasks.size();
9578 for (int i=0; i<N; i++) {
9579 TaskRecord tr = mRecentTasks.get(i);
9580 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9581 pw.println(tr);
9582 mRecentTasks.get(i).dump(pw, " ");
9583 }
9584 }
9585
9586 pw.println(" ");
9587 pw.println(" mCurTask: " + mCurTask);
9588
9589 return true;
9590 }
9591
9592 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9593 int opti, boolean dumpAll) {
9594 boolean needSep = false;
9595 int numPers = 0;
9596
9597 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9599 final int NA = procs.size();
9600 for (int ia=0; ia<NA; ia++) {
9601 if (!needSep) {
9602 pw.println(" All known processes:");
9603 needSep = true;
9604 }
9605 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009606 pw.print(r.persistent ? " *PERS*" : " *APP*");
9607 pw.print(" UID "); pw.print(procs.keyAt(ia));
9608 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009609 r.dump(pw, " ");
9610 if (r.persistent) {
9611 numPers++;
9612 }
9613 }
9614 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009615 }
9616
9617 if (mLruProcesses.size() > 0) {
9618 if (needSep) pw.println(" ");
9619 needSep = true;
9620 pw.println(" Running processes (most recent first):");
9621 dumpProcessList(pw, this, mLruProcesses, " ",
9622 "App ", "PERS", true);
9623 needSep = true;
9624 }
9625
9626 synchronized (mPidsSelfLocked) {
9627 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009628 if (needSep) pw.println(" ");
9629 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009630 pw.println(" PID mappings:");
9631 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9632 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9633 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 }
9635 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009636 }
9637
9638 if (mForegroundProcesses.size() > 0) {
9639 if (needSep) pw.println(" ");
9640 needSep = true;
9641 pw.println(" Foreground Processes:");
9642 for (int i=0; i<mForegroundProcesses.size(); i++) {
9643 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9644 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009646 }
9647
9648 if (mPersistentStartingProcesses.size() > 0) {
9649 if (needSep) pw.println(" ");
9650 needSep = true;
9651 pw.println(" Persisent processes that are starting:");
9652 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9653 "Starting Norm", "Restarting PERS", false);
9654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009656 if (mStartingProcesses.size() > 0) {
9657 if (needSep) pw.println(" ");
9658 needSep = true;
9659 pw.println(" Processes that are starting:");
9660 dumpProcessList(pw, this, mStartingProcesses, " ",
9661 "Starting Norm", "Starting PERS", false);
9662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009663
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009664 if (mRemovedProcesses.size() > 0) {
9665 if (needSep) pw.println(" ");
9666 needSep = true;
9667 pw.println(" Processes that are being removed:");
9668 dumpProcessList(pw, this, mRemovedProcesses, " ",
9669 "Removed Norm", "Removed PERS", false);
9670 }
9671
9672 if (mProcessesOnHold.size() > 0) {
9673 if (needSep) pw.println(" ");
9674 needSep = true;
9675 pw.println(" Processes that are on old until the system is ready:");
9676 dumpProcessList(pw, this, mProcessesOnHold, " ",
9677 "OnHold Norm", "OnHold PERS", false);
9678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009680 if (mProcessesToGc.size() > 0) {
9681 if (needSep) pw.println(" ");
9682 needSep = true;
9683 pw.println(" Processes that are waiting to GC:");
9684 long now = SystemClock.uptimeMillis();
9685 for (int i=0; i<mProcessesToGc.size(); i++) {
9686 ProcessRecord proc = mProcessesToGc.get(i);
9687 pw.print(" Process "); pw.println(proc);
9688 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9689 pw.print(", last gced=");
9690 pw.print(now-proc.lastRequestedGc);
9691 pw.print(" ms ago, last lowMem=");
9692 pw.print(now-proc.lastLowMemory);
9693 pw.println(" ms ago");
9694
9695 }
9696 }
9697
9698 if (mProcessCrashTimes.getMap().size() > 0) {
9699 if (needSep) pw.println(" ");
9700 needSep = true;
9701 pw.println(" Time since processes crashed:");
9702 long now = SystemClock.uptimeMillis();
9703 for (Map.Entry<String, SparseArray<Long>> procs
9704 : mProcessCrashTimes.getMap().entrySet()) {
9705 SparseArray<Long> uids = procs.getValue();
9706 final int N = uids.size();
9707 for (int i=0; i<N; i++) {
9708 pw.print(" Process "); pw.print(procs.getKey());
9709 pw.print(" uid "); pw.print(uids.keyAt(i));
9710 pw.print(": last crashed ");
9711 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009712 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009713 }
9714 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009717 if (mBadProcesses.getMap().size() > 0) {
9718 if (needSep) pw.println(" ");
9719 needSep = true;
9720 pw.println(" Bad processes:");
9721 for (Map.Entry<String, SparseArray<Long>> procs
9722 : mBadProcesses.getMap().entrySet()) {
9723 SparseArray<Long> uids = procs.getValue();
9724 final int N = uids.size();
9725 for (int i=0; i<N; i++) {
9726 pw.print(" Bad process "); pw.print(procs.getKey());
9727 pw.print(" uid "); pw.print(uids.keyAt(i));
9728 pw.print(": crashed at time ");
9729 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 }
9731 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009734 pw.println(" ");
9735 pw.println(" mHomeProcess: " + mHomeProcess);
9736 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009737 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009738 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9739 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9740 || mOrigWaitForDebugger) {
9741 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9742 + " mDebugTransient=" + mDebugTransient
9743 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9744 }
9745 if (mAlwaysFinishActivities || mController != null) {
9746 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9747 + " mController=" + mController);
9748 }
9749 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 pw.println(" mStartRunning=" + mStartRunning
9752 + " mSystemReady=" + mSystemReady
9753 + " mBooting=" + mBooting
9754 + " mBooted=" + mBooted
9755 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756 pw.println(" mGoingToSleep=" + mGoingToSleep);
9757 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009759
9760 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 }
9762
9763 /**
9764 * There are three ways to call this:
9765 * - no service specified: dump all the services
9766 * - a flattened component name that matched an existing service was specified as the
9767 * first arg: dump that one service
9768 * - the first arg isn't the flattened component name of an existing service:
9769 * dump all services whose component contains the first arg as a substring
9770 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009771 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9772 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 String[] newArgs;
9774 String componentNameString;
9775 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009776 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 componentNameString = null;
9778 newArgs = EMPTY_STRING_ARRAY;
9779 r = null;
9780 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009781 componentNameString = args[opti];
9782 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9784 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009785 newArgs = new String[args.length - opti];
9786 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009787 }
9788
9789 if (r != null) {
9790 dumpService(fd, pw, r, newArgs);
9791 } else {
9792 for (ServiceRecord r1 : mServices.values()) {
9793 if (componentNameString == null
9794 || r1.name.flattenToString().contains(componentNameString)) {
9795 dumpService(fd, pw, r1, newArgs);
9796 }
9797 }
9798 }
9799 }
9800
9801 /**
9802 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9803 * there is a thread associated with the service.
9804 */
9805 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9806 pw.println(" Service " + r.name.flattenToString());
9807 if (r.app != null && r.app.thread != null) {
9808 try {
9809 // flush anything that is already in the PrintWriter since the thread is going
9810 // to write to the file descriptor directly
9811 pw.flush();
9812 r.app.thread.dumpService(fd, r, args);
9813 pw.print("\n");
9814 } catch (RemoteException e) {
9815 pw.println("got a RemoteException while dumping the service");
9816 }
9817 }
9818 }
9819
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009820 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9821 int opti, boolean dumpAll) {
9822 boolean needSep = false;
9823
9824 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 if (mRegisteredReceivers.size() > 0) {
9826 pw.println(" ");
9827 pw.println(" Registered Receivers:");
9828 Iterator it = mRegisteredReceivers.values().iterator();
9829 while (it.hasNext()) {
9830 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009831 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 r.dump(pw, " ");
9833 }
9834 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009836 pw.println(" ");
9837 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009838 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009839 needSep = true;
9840 }
9841
9842 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9843 || mPendingBroadcast != null) {
9844 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009846 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009848 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9849 pw.println(" Broadcast #" + i + ":");
9850 mParallelBroadcasts.get(i).dump(pw, " ");
9851 }
9852 if (mOrderedBroadcasts.size() > 0) {
9853 pw.println(" ");
9854 pw.println(" Active serialized broadcasts:");
9855 }
9856 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9857 pw.println(" Serialized Broadcast #" + i + ":");
9858 mOrderedBroadcasts.get(i).dump(pw, " ");
9859 }
9860 pw.println(" ");
9861 pw.println(" Pending broadcast:");
9862 if (mPendingBroadcast != null) {
9863 mPendingBroadcast.dump(pw, " ");
9864 } else {
9865 pw.println(" (null)");
9866 }
9867 needSep = true;
9868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009870 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009872 pw.println(" Historical broadcasts:");
9873 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9874 BroadcastRecord r = mBroadcastHistory[i];
9875 if (r == null) {
9876 break;
9877 }
9878 pw.println(" Historical Broadcast #" + i + ":");
9879 r.dump(pw, " ");
9880 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009881 needSep = true;
9882 }
9883
9884 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009885 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009886 pw.println(" Sticky broadcasts:");
9887 StringBuilder sb = new StringBuilder(128);
9888 for (Map.Entry<String, ArrayList<Intent>> ent
9889 : mStickyBroadcasts.entrySet()) {
9890 pw.print(" * Sticky action "); pw.print(ent.getKey());
9891 pw.println(":");
9892 ArrayList<Intent> intents = ent.getValue();
9893 final int N = intents.size();
9894 for (int i=0; i<N; i++) {
9895 sb.setLength(0);
9896 sb.append(" Intent: ");
9897 intents.get(i).toShortString(sb, true, false);
9898 pw.println(sb.toString());
9899 Bundle bundle = intents.get(i).getExtras();
9900 if (bundle != null) {
9901 pw.print(" ");
9902 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 }
9904 }
9905 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009906 needSep = true;
9907 }
9908
9909 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009911 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912 pw.println(" mHandler:");
9913 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009914 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009915 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009916
9917 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 }
9919
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009920 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9921 int opti, boolean dumpAll) {
9922 boolean needSep = false;
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 if (mServices.size() > 0) {
9926 pw.println(" Active services:");
9927 Iterator<ServiceRecord> it = mServices.values().iterator();
9928 while (it.hasNext()) {
9929 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009930 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 r.dump(pw, " ");
9932 }
9933 needSep = true;
9934 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009937 if (mPendingServices.size() > 0) {
9938 if (needSep) pw.println(" ");
9939 pw.println(" Pending services:");
9940 for (int i=0; i<mPendingServices.size(); i++) {
9941 ServiceRecord r = mPendingServices.get(i);
9942 pw.print(" * Pending "); pw.println(r);
9943 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009944 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009945 needSep = true;
9946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009947
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009948 if (mRestartingServices.size() > 0) {
9949 if (needSep) pw.println(" ");
9950 pw.println(" Restarting services:");
9951 for (int i=0; i<mRestartingServices.size(); i++) {
9952 ServiceRecord r = mRestartingServices.get(i);
9953 pw.print(" * Restarting "); pw.println(r);
9954 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009955 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009956 needSep = true;
9957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009959 if (mStoppingServices.size() > 0) {
9960 if (needSep) pw.println(" ");
9961 pw.println(" Stopping services:");
9962 for (int i=0; i<mStoppingServices.size(); i++) {
9963 ServiceRecord r = mStoppingServices.get(i);
9964 pw.print(" * Stopping "); pw.println(r);
9965 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009967 needSep = true;
9968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009969
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009970 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 if (mServiceConnections.size() > 0) {
9972 if (needSep) pw.println(" ");
9973 pw.println(" Connection bindings to services:");
9974 Iterator<ConnectionRecord> it
9975 = mServiceConnections.values().iterator();
9976 while (it.hasNext()) {
9977 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009978 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 r.dump(pw, " ");
9980 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009981 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 }
9983 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009984
9985 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009986 }
9987
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009988 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9989 int opti, boolean dumpAll) {
9990 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009992 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009993 if (mProvidersByClass.size() > 0) {
9994 if (needSep) pw.println(" ");
9995 pw.println(" Published content providers (by class):");
9996 Iterator it = mProvidersByClass.entrySet().iterator();
9997 while (it.hasNext()) {
9998 Map.Entry e = (Map.Entry)it.next();
9999 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010000 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 r.dump(pw, " ");
10002 }
10003 needSep = true;
10004 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010005
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010006 if (mProvidersByName.size() > 0) {
10007 pw.println(" ");
10008 pw.println(" Authority to provider mappings:");
10009 Iterator it = mProvidersByName.entrySet().iterator();
10010 while (it.hasNext()) {
10011 Map.Entry e = (Map.Entry)it.next();
10012 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10013 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10014 pw.println(r);
10015 }
10016 needSep = true;
10017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010019
10020 if (mLaunchingProviders.size() > 0) {
10021 if (needSep) pw.println(" ");
10022 pw.println(" Launching content providers:");
10023 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10024 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10025 pw.println(mLaunchingProviders.get(i));
10026 }
10027 needSep = true;
10028 }
10029
10030 if (mGrantedUriPermissions.size() > 0) {
10031 pw.println();
10032 pw.println("Granted Uri Permissions:");
10033 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10034 int uid = mGrantedUriPermissions.keyAt(i);
10035 HashMap<Uri, UriPermission> perms
10036 = mGrantedUriPermissions.valueAt(i);
10037 pw.print(" * UID "); pw.print(uid);
10038 pw.println(" holds:");
10039 for (UriPermission perm : perms.values()) {
10040 pw.print(" "); pw.println(perm);
10041 perm.dump(pw, " ");
10042 }
10043 }
10044 needSep = true;
10045 }
10046
10047 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010048 }
10049
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010050 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10051 int opti, boolean dumpAll) {
10052 boolean needSep = false;
10053
10054 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 if (this.mIntentSenderRecords.size() > 0) {
10056 Iterator<WeakReference<PendingIntentRecord>> it
10057 = mIntentSenderRecords.values().iterator();
10058 while (it.hasNext()) {
10059 WeakReference<PendingIntentRecord> ref = it.next();
10060 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010061 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010063 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 rec.dump(pw, " ");
10065 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010066 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 }
10068 }
10069 }
10070 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010071
10072 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010073 }
10074
10075 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010076 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 TaskRecord lastTask = null;
10078 for (int i=list.size()-1; i>=0; i--) {
10079 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010080 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 if (lastTask != r.task) {
10082 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010083 pw.print(prefix);
10084 pw.print(full ? "* " : " ");
10085 pw.println(lastTask);
10086 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010087 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010090 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10091 pw.print(" #"); pw.print(i); pw.print(": ");
10092 pw.println(r);
10093 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010094 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 }
10097 }
10098
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010099 private static String buildOomTag(String prefix, String space, int val, int base) {
10100 if (val == base) {
10101 if (space == null) return prefix;
10102 return prefix + " ";
10103 }
10104 return prefix + "+" + Integer.toString(val-base);
10105 }
10106
10107 private static final int dumpProcessList(PrintWriter pw,
10108 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 String prefix, String normalLabel, String persistentLabel,
10110 boolean inclOomAdj) {
10111 int numPers = 0;
10112 for (int i=list.size()-1; i>=0; i--) {
10113 ProcessRecord r = (ProcessRecord)list.get(i);
10114 if (false) {
10115 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10116 + " #" + i + ":");
10117 r.dump(pw, prefix + " ");
10118 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010119 String oomAdj;
10120 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010121 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010122 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010123 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10124 } else if (r.setAdj >= HOME_APP_ADJ) {
10125 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10126 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10127 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10128 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10129 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10130 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10131 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10132 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10133 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010134 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010135 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010136 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010137 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010138 } else {
10139 oomAdj = Integer.toString(r.setAdj);
10140 }
10141 String schedGroup;
10142 switch (r.setSchedGroup) {
10143 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10144 schedGroup = "B";
10145 break;
10146 case Process.THREAD_GROUP_DEFAULT:
10147 schedGroup = "F";
10148 break;
10149 default:
10150 schedGroup = Integer.toString(r.setSchedGroup);
10151 break;
10152 }
10153 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010154 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010155 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010156 if (r.adjSource != null || r.adjTarget != null) {
10157 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010158 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010160 } else {
10161 pw.println(String.format("%s%s #%2d: %s",
10162 prefix, (r.persistent ? persistentLabel : normalLabel),
10163 i, r.toString()));
10164 }
10165 if (r.persistent) {
10166 numPers++;
10167 }
10168 }
10169 return numPers;
10170 }
10171
10172 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10173 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010174 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 long uptime = SystemClock.uptimeMillis();
10176 long realtime = SystemClock.elapsedRealtime();
10177
10178 if (isCheckinRequest) {
10179 // short checkin version
10180 pw.println(uptime + "," + realtime);
10181 pw.flush();
10182 } else {
10183 pw.println("Applications Memory Usage (kB):");
10184 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10185 }
10186 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10187 ProcessRecord r = (ProcessRecord)list.get(i);
10188 if (r.thread != null) {
10189 if (!isCheckinRequest) {
10190 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10191 pw.flush();
10192 }
10193 try {
10194 r.thread.asBinder().dump(fd, args);
10195 } catch (RemoteException e) {
10196 if (!isCheckinRequest) {
10197 pw.println("Got RemoteException!");
10198 pw.flush();
10199 }
10200 }
10201 }
10202 }
10203 }
10204
10205 /**
10206 * Searches array of arguments for the specified string
10207 * @param args array of argument strings
10208 * @param value value to search for
10209 * @return true if the value is contained in the array
10210 */
10211 private static boolean scanArgs(String[] args, String value) {
10212 if (args != null) {
10213 for (String arg : args) {
10214 if (value.equals(arg)) {
10215 return true;
10216 }
10217 }
10218 }
10219 return false;
10220 }
10221
Dianne Hackborn75b03852009-06-12 15:43:26 -070010222 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 int count = mHistory.size();
10224
10225 // convert the token to an entry in the history.
10226 HistoryRecord r = null;
10227 int index = -1;
10228 for (int i=count-1; i>=0; i--) {
10229 Object o = mHistory.get(i);
10230 if (o == token) {
10231 r = (HistoryRecord)o;
10232 index = i;
10233 break;
10234 }
10235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236
10237 return index;
10238 }
10239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010240 private final void killServicesLocked(ProcessRecord app,
10241 boolean allowRestart) {
10242 // Report disconnected services.
10243 if (false) {
10244 // XXX we are letting the client link to the service for
10245 // death notifications.
10246 if (app.services.size() > 0) {
10247 Iterator it = app.services.iterator();
10248 while (it.hasNext()) {
10249 ServiceRecord r = (ServiceRecord)it.next();
10250 if (r.connections.size() > 0) {
10251 Iterator<ConnectionRecord> jt
10252 = r.connections.values().iterator();
10253 while (jt.hasNext()) {
10254 ConnectionRecord c = jt.next();
10255 if (c.binding.client != app) {
10256 try {
10257 //c.conn.connected(r.className, null);
10258 } catch (Exception e) {
10259 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010260 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 + r.shortName
10262 + " from app " + app.processName, e);
10263 }
10264 }
10265 }
10266 }
10267 }
10268 }
10269 }
10270
10271 // Clean up any connections this application has to other services.
10272 if (app.connections.size() > 0) {
10273 Iterator<ConnectionRecord> it = app.connections.iterator();
10274 while (it.hasNext()) {
10275 ConnectionRecord r = it.next();
10276 removeConnectionLocked(r, app, null);
10277 }
10278 }
10279 app.connections.clear();
10280
10281 if (app.services.size() != 0) {
10282 // Any services running in the application need to be placed
10283 // back in the pending list.
10284 Iterator it = app.services.iterator();
10285 while (it.hasNext()) {
10286 ServiceRecord sr = (ServiceRecord)it.next();
10287 synchronized (sr.stats.getBatteryStats()) {
10288 sr.stats.stopLaunchedLocked();
10289 }
10290 sr.app = null;
10291 sr.executeNesting = 0;
10292 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010293
10294 boolean hasClients = sr.bindings.size() > 0;
10295 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 Iterator<IntentBindRecord> bindings
10297 = sr.bindings.values().iterator();
10298 while (bindings.hasNext()) {
10299 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010300 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 + ": shouldUnbind=" + b.hasBound);
10302 b.binder = null;
10303 b.requested = b.received = b.hasBound = false;
10304 }
10305 }
10306
10307 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010308 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010310 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010311 sr.crashCount, sr.shortName, app.pid);
10312 bringDownServiceLocked(sr, true);
10313 } else if (!allowRestart) {
10314 bringDownServiceLocked(sr, true);
10315 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010316 boolean canceled = scheduleServiceRestartLocked(sr, true);
10317
10318 // Should the service remain running? Note that in the
10319 // extreme case of so many attempts to deliver a command
10320 // that it failed, that we also will stop it here.
10321 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10322 if (sr.pendingStarts.size() == 0) {
10323 sr.startRequested = false;
10324 if (!hasClients) {
10325 // Whoops, no reason to restart!
10326 bringDownServiceLocked(sr, true);
10327 }
10328 }
10329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010330 }
10331 }
10332
10333 if (!allowRestart) {
10334 app.services.clear();
10335 }
10336 }
10337
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010338 // Make sure we have no more records on the stopping list.
10339 int i = mStoppingServices.size();
10340 while (i > 0) {
10341 i--;
10342 ServiceRecord sr = mStoppingServices.get(i);
10343 if (sr.app == app) {
10344 mStoppingServices.remove(i);
10345 }
10346 }
10347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 app.executingServices.clear();
10349 }
10350
10351 private final void removeDyingProviderLocked(ProcessRecord proc,
10352 ContentProviderRecord cpr) {
10353 synchronized (cpr) {
10354 cpr.launchingApp = null;
10355 cpr.notifyAll();
10356 }
10357
10358 mProvidersByClass.remove(cpr.info.name);
10359 String names[] = cpr.info.authority.split(";");
10360 for (int j = 0; j < names.length; j++) {
10361 mProvidersByName.remove(names[j]);
10362 }
10363
10364 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10365 while (cit.hasNext()) {
10366 ProcessRecord capp = cit.next();
10367 if (!capp.persistent && capp.thread != null
10368 && capp.pid != 0
10369 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010370 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 + " (pid " + capp.pid
10372 + ") because provider " + cpr.info.name
10373 + " is in dying process " + proc.processName);
10374 Process.killProcess(capp.pid);
10375 }
10376 }
10377
10378 mLaunchingProviders.remove(cpr);
10379 }
10380
10381 /**
10382 * Main code for cleaning up a process when it has gone away. This is
10383 * called both as a result of the process dying, or directly when stopping
10384 * a process when running in single process mode.
10385 */
10386 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10387 boolean restarting, int index) {
10388 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010389 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010390 }
10391
Dianne Hackborn36124872009-10-08 16:22:03 -070010392 mProcessesToGc.remove(app);
10393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 // Dismiss any open dialogs.
10395 if (app.crashDialog != null) {
10396 app.crashDialog.dismiss();
10397 app.crashDialog = null;
10398 }
10399 if (app.anrDialog != null) {
10400 app.anrDialog.dismiss();
10401 app.anrDialog = null;
10402 }
10403 if (app.waitDialog != null) {
10404 app.waitDialog.dismiss();
10405 app.waitDialog = null;
10406 }
10407
10408 app.crashing = false;
10409 app.notResponding = false;
10410
10411 app.resetPackageList();
10412 app.thread = null;
10413 app.forcingToForeground = null;
10414 app.foregroundServices = false;
10415
10416 killServicesLocked(app, true);
10417
10418 boolean restart = false;
10419
10420 int NL = mLaunchingProviders.size();
10421
10422 // Remove published content providers.
10423 if (!app.pubProviders.isEmpty()) {
10424 Iterator it = app.pubProviders.values().iterator();
10425 while (it.hasNext()) {
10426 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10427 cpr.provider = null;
10428 cpr.app = null;
10429
10430 // See if someone is waiting for this provider... in which
10431 // case we don't remove it, but just let it restart.
10432 int i = 0;
10433 if (!app.bad) {
10434 for (; i<NL; i++) {
10435 if (mLaunchingProviders.get(i) == cpr) {
10436 restart = true;
10437 break;
10438 }
10439 }
10440 } else {
10441 i = NL;
10442 }
10443
10444 if (i >= NL) {
10445 removeDyingProviderLocked(app, cpr);
10446 NL = mLaunchingProviders.size();
10447 }
10448 }
10449 app.pubProviders.clear();
10450 }
10451
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010452 // Take care of any launching providers waiting for this process.
10453 if (checkAppInLaunchingProvidersLocked(app, false)) {
10454 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010455 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 // Unregister from connected content providers.
10458 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010459 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 while (it.hasNext()) {
10461 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10462 cpr.clients.remove(app);
10463 }
10464 app.conProviders.clear();
10465 }
10466
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010467 // At this point there may be remaining entries in mLaunchingProviders
10468 // where we were the only one waiting, so they are no longer of use.
10469 // Look for these and clean up if found.
10470 // XXX Commented out for now. Trying to figure out a way to reproduce
10471 // the actual situation to identify what is actually going on.
10472 if (false) {
10473 for (int i=0; i<NL; i++) {
10474 ContentProviderRecord cpr = (ContentProviderRecord)
10475 mLaunchingProviders.get(i);
10476 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10477 synchronized (cpr) {
10478 cpr.launchingApp = null;
10479 cpr.notifyAll();
10480 }
10481 }
10482 }
10483 }
10484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 skipCurrentReceiverLocked(app);
10486
10487 // Unregister any receivers.
10488 if (app.receivers.size() > 0) {
10489 Iterator<ReceiverList> it = app.receivers.iterator();
10490 while (it.hasNext()) {
10491 removeReceiverLocked(it.next());
10492 }
10493 app.receivers.clear();
10494 }
10495
Christopher Tate181fafa2009-05-14 11:12:14 -070010496 // If the app is undergoing backup, tell the backup manager about it
10497 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010498 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010499 try {
10500 IBackupManager bm = IBackupManager.Stub.asInterface(
10501 ServiceManager.getService(Context.BACKUP_SERVICE));
10502 bm.agentDisconnected(app.info.packageName);
10503 } catch (RemoteException e) {
10504 // can't happen; backup manager is local
10505 }
10506 }
10507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 // If the caller is restarting this app, then leave it in its
10509 // current lists and let the caller take care of it.
10510 if (restarting) {
10511 return;
10512 }
10513
10514 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 "Removing non-persistent process during cleanup: " + app);
10517 mProcessNames.remove(app.processName, app.info.uid);
10518 } else if (!app.removed) {
10519 // This app is persistent, so we need to keep its record around.
10520 // If it is not already on the pending app list, add it there
10521 // and start a new process for it.
10522 app.thread = null;
10523 app.forcingToForeground = null;
10524 app.foregroundServices = false;
10525 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10526 mPersistentStartingProcesses.add(app);
10527 restart = true;
10528 }
10529 }
10530 mProcessesOnHold.remove(app);
10531
The Android Open Source Project4df24232009-03-05 14:34:35 -080010532 if (app == mHomeProcess) {
10533 mHomeProcess = null;
10534 }
10535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 if (restart) {
10537 // We have components that still need to be running in the
10538 // process, so re-launch it.
10539 mProcessNames.put(app.processName, app.info.uid, app);
10540 startProcessLocked(app, "restart", app.processName);
10541 } else if (app.pid > 0 && app.pid != MY_PID) {
10542 // Goodbye!
10543 synchronized (mPidsSelfLocked) {
10544 mPidsSelfLocked.remove(app.pid);
10545 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10546 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010547 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 }
10549 }
10550
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010551 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10552 // Look through the content providers we are waiting to have launched,
10553 // and if any run in this process then either schedule a restart of
10554 // the process or kill the client waiting for it if this process has
10555 // gone bad.
10556 int NL = mLaunchingProviders.size();
10557 boolean restart = false;
10558 for (int i=0; i<NL; i++) {
10559 ContentProviderRecord cpr = (ContentProviderRecord)
10560 mLaunchingProviders.get(i);
10561 if (cpr.launchingApp == app) {
10562 if (!alwaysBad && !app.bad) {
10563 restart = true;
10564 } else {
10565 removeDyingProviderLocked(app, cpr);
10566 NL = mLaunchingProviders.size();
10567 }
10568 }
10569 }
10570 return restart;
10571 }
10572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010573 // =========================================================
10574 // SERVICES
10575 // =========================================================
10576
10577 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10578 ActivityManager.RunningServiceInfo info =
10579 new ActivityManager.RunningServiceInfo();
10580 info.service = r.name;
10581 if (r.app != null) {
10582 info.pid = r.app.pid;
10583 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010584 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 info.process = r.processName;
10586 info.foreground = r.isForeground;
10587 info.activeSince = r.createTime;
10588 info.started = r.startRequested;
10589 info.clientCount = r.connections.size();
10590 info.crashCount = r.crashCount;
10591 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010592 if (r.isForeground) {
10593 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10594 }
10595 if (r.startRequested) {
10596 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10597 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010598 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010599 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10600 }
10601 if (r.app != null && r.app.persistent) {
10602 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10603 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010604 for (ConnectionRecord conn : r.connections.values()) {
10605 if (conn.clientLabel != 0) {
10606 info.clientPackage = conn.binding.client.info.packageName;
10607 info.clientLabel = conn.clientLabel;
10608 break;
10609 }
10610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 return info;
10612 }
10613
10614 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10615 int flags) {
10616 synchronized (this) {
10617 ArrayList<ActivityManager.RunningServiceInfo> res
10618 = new ArrayList<ActivityManager.RunningServiceInfo>();
10619
10620 if (mServices.size() > 0) {
10621 Iterator<ServiceRecord> it = mServices.values().iterator();
10622 while (it.hasNext() && res.size() < maxNum) {
10623 res.add(makeRunningServiceInfoLocked(it.next()));
10624 }
10625 }
10626
10627 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10628 ServiceRecord r = mRestartingServices.get(i);
10629 ActivityManager.RunningServiceInfo info =
10630 makeRunningServiceInfoLocked(r);
10631 info.restarting = r.nextRestartTime;
10632 res.add(info);
10633 }
10634
10635 return res;
10636 }
10637 }
10638
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010639 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10640 synchronized (this) {
10641 ServiceRecord r = mServices.get(name);
10642 if (r != null) {
10643 for (ConnectionRecord conn : r.connections.values()) {
10644 if (conn.clientIntent != null) {
10645 return conn.clientIntent;
10646 }
10647 }
10648 }
10649 }
10650 return null;
10651 }
10652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010653 private final ServiceRecord findServiceLocked(ComponentName name,
10654 IBinder token) {
10655 ServiceRecord r = mServices.get(name);
10656 return r == token ? r : null;
10657 }
10658
10659 private final class ServiceLookupResult {
10660 final ServiceRecord record;
10661 final String permission;
10662
10663 ServiceLookupResult(ServiceRecord _record, String _permission) {
10664 record = _record;
10665 permission = _permission;
10666 }
10667 };
10668
10669 private ServiceLookupResult findServiceLocked(Intent service,
10670 String resolvedType) {
10671 ServiceRecord r = null;
10672 if (service.getComponent() != null) {
10673 r = mServices.get(service.getComponent());
10674 }
10675 if (r == null) {
10676 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10677 r = mServicesByIntent.get(filter);
10678 }
10679
10680 if (r == null) {
10681 try {
10682 ResolveInfo rInfo =
10683 ActivityThread.getPackageManager().resolveService(
10684 service, resolvedType, 0);
10685 ServiceInfo sInfo =
10686 rInfo != null ? rInfo.serviceInfo : null;
10687 if (sInfo == null) {
10688 return null;
10689 }
10690
10691 ComponentName name = new ComponentName(
10692 sInfo.applicationInfo.packageName, sInfo.name);
10693 r = mServices.get(name);
10694 } catch (RemoteException ex) {
10695 // pm is in same process, this will never happen.
10696 }
10697 }
10698 if (r != null) {
10699 int callingPid = Binder.getCallingPid();
10700 int callingUid = Binder.getCallingUid();
10701 if (checkComponentPermission(r.permission,
10702 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10703 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010704 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 + " from pid=" + callingPid
10706 + ", uid=" + callingUid
10707 + " requires " + r.permission);
10708 return new ServiceLookupResult(null, r.permission);
10709 }
10710 return new ServiceLookupResult(r, null);
10711 }
10712 return null;
10713 }
10714
10715 private class ServiceRestarter implements Runnable {
10716 private ServiceRecord mService;
10717
10718 void setService(ServiceRecord service) {
10719 mService = service;
10720 }
10721
10722 public void run() {
10723 synchronized(ActivityManagerService.this) {
10724 performServiceRestartLocked(mService);
10725 }
10726 }
10727 }
10728
10729 private ServiceLookupResult retrieveServiceLocked(Intent service,
10730 String resolvedType, int callingPid, int callingUid) {
10731 ServiceRecord r = null;
10732 if (service.getComponent() != null) {
10733 r = mServices.get(service.getComponent());
10734 }
10735 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10736 r = mServicesByIntent.get(filter);
10737 if (r == null) {
10738 try {
10739 ResolveInfo rInfo =
10740 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010741 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010742 ServiceInfo sInfo =
10743 rInfo != null ? rInfo.serviceInfo : null;
10744 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010745 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010746 ": not found");
10747 return null;
10748 }
10749
10750 ComponentName name = new ComponentName(
10751 sInfo.applicationInfo.packageName, sInfo.name);
10752 r = mServices.get(name);
10753 if (r == null) {
10754 filter = new Intent.FilterComparison(service.cloneFilter());
10755 ServiceRestarter res = new ServiceRestarter();
10756 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10757 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10758 synchronized (stats) {
10759 ss = stats.getServiceStatsLocked(
10760 sInfo.applicationInfo.uid, sInfo.packageName,
10761 sInfo.name);
10762 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010763 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 res.setService(r);
10765 mServices.put(name, r);
10766 mServicesByIntent.put(filter, r);
10767
10768 // Make sure this component isn't in the pending list.
10769 int N = mPendingServices.size();
10770 for (int i=0; i<N; i++) {
10771 ServiceRecord pr = mPendingServices.get(i);
10772 if (pr.name.equals(name)) {
10773 mPendingServices.remove(i);
10774 i--;
10775 N--;
10776 }
10777 }
10778 }
10779 } catch (RemoteException ex) {
10780 // pm is in same process, this will never happen.
10781 }
10782 }
10783 if (r != null) {
10784 if (checkComponentPermission(r.permission,
10785 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10786 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010787 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010788 + " from pid=" + Binder.getCallingPid()
10789 + ", uid=" + Binder.getCallingUid()
10790 + " requires " + r.permission);
10791 return new ServiceLookupResult(null, r.permission);
10792 }
10793 return new ServiceLookupResult(r, null);
10794 }
10795 return null;
10796 }
10797
10798 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10799 long now = SystemClock.uptimeMillis();
10800 if (r.executeNesting == 0 && r.app != null) {
10801 if (r.app.executingServices.size() == 0) {
10802 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10803 msg.obj = r.app;
10804 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10805 }
10806 r.app.executingServices.add(r);
10807 }
10808 r.executeNesting++;
10809 r.executingStart = now;
10810 }
10811
10812 private final void sendServiceArgsLocked(ServiceRecord r,
10813 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010814 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010815 if (N == 0) {
10816 return;
10817 }
10818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819 int i = 0;
10820 while (i < N) {
10821 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010822 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010823 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010824 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010825 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010826 // If somehow we got a dummy start at the front, then
10827 // just drop it here.
10828 i++;
10829 continue;
10830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 bumpServiceExecutingLocked(r);
10832 if (!oomAdjusted) {
10833 oomAdjusted = true;
10834 updateOomAdjLocked(r.app);
10835 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010836 int flags = 0;
10837 if (si.deliveryCount > 0) {
10838 flags |= Service.START_FLAG_RETRY;
10839 }
10840 if (si.doneExecutingCount > 0) {
10841 flags |= Service.START_FLAG_REDELIVERY;
10842 }
10843 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10844 si.deliveredTime = SystemClock.uptimeMillis();
10845 r.deliveredStarts.add(si);
10846 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010848 } catch (RemoteException e) {
10849 // Remote process gone... we'll let the normal cleanup take
10850 // care of this.
10851 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010852 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010853 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010854 break;
10855 }
10856 }
10857 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010858 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 } else {
10860 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010861 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010862 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010863 }
10864 }
10865 }
10866
10867 private final boolean requestServiceBindingLocked(ServiceRecord r,
10868 IntentBindRecord i, boolean rebind) {
10869 if (r.app == null || r.app.thread == null) {
10870 // If service is not currently running, can't yet bind.
10871 return false;
10872 }
10873 if ((!i.requested || rebind) && i.apps.size() > 0) {
10874 try {
10875 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010876 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 + ": shouldUnbind=" + i.hasBound);
10878 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10879 if (!rebind) {
10880 i.requested = true;
10881 }
10882 i.hasBound = true;
10883 i.doRebind = false;
10884 } catch (RemoteException e) {
10885 return false;
10886 }
10887 }
10888 return true;
10889 }
10890
10891 private final void requestServiceBindingsLocked(ServiceRecord r) {
10892 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10893 while (bindings.hasNext()) {
10894 IntentBindRecord i = bindings.next();
10895 if (!requestServiceBindingLocked(r, i, false)) {
10896 break;
10897 }
10898 }
10899 }
10900
10901 private final void realStartServiceLocked(ServiceRecord r,
10902 ProcessRecord app) throws RemoteException {
10903 if (app.thread == null) {
10904 throw new RemoteException();
10905 }
10906
10907 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010908 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010909
10910 app.services.add(r);
10911 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010912 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913
10914 boolean created = false;
10915 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010916 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010918 mStringBuilder.setLength(0);
10919 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010920 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010922 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 synchronized (r.stats.getBatteryStats()) {
10924 r.stats.startLaunchedLocked();
10925 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010926 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010928 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 created = true;
10930 } finally {
10931 if (!created) {
10932 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010933 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010934 }
10935 }
10936
10937 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010938
10939 // If the service is in the started state, and there are no
10940 // pending arguments, then fake up one so its onStartCommand() will
10941 // be called.
10942 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10943 r.lastStartId++;
10944 if (r.lastStartId < 1) {
10945 r.lastStartId = 1;
10946 }
10947 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10948 }
10949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 sendServiceArgsLocked(r, true);
10951 }
10952
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010953 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10954 boolean allowCancel) {
10955 boolean canceled = false;
10956
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010957 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010958 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010959 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010960
10961 // Any delivered but not yet finished starts should be put back
10962 // on the pending list.
10963 final int N = r.deliveredStarts.size();
10964 if (N > 0) {
10965 for (int i=N-1; i>=0; i--) {
10966 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10967 if (si.intent == null) {
10968 // We'll generate this again if needed.
10969 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10970 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10971 r.pendingStarts.add(0, si);
10972 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10973 dur *= 2;
10974 if (minDuration < dur) minDuration = dur;
10975 if (resetTime < dur) resetTime = dur;
10976 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010977 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010978 + r.name);
10979 canceled = true;
10980 }
10981 }
10982 r.deliveredStarts.clear();
10983 }
10984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 r.totalRestartCount++;
10986 if (r.restartDelay == 0) {
10987 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010988 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 } else {
10990 // If it has been a "reasonably long time" since the service
10991 // was started, then reset our restart duration back to
10992 // the beginning, so we don't infinitely increase the duration
10993 // on a service that just occasionally gets killed (which is
10994 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010995 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010997 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010999 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011000 if (r.restartDelay < minDuration) {
11001 r.restartDelay = minDuration;
11002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 }
11004 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011005
11006 r.nextRestartTime = now + r.restartDelay;
11007
11008 // Make sure that we don't end up restarting a bunch of services
11009 // all at the same time.
11010 boolean repeat;
11011 do {
11012 repeat = false;
11013 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11014 ServiceRecord r2 = mRestartingServices.get(i);
11015 if (r2 != r && r.nextRestartTime
11016 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11017 && r.nextRestartTime
11018 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11019 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11020 r.restartDelay = r.nextRestartTime - now;
11021 repeat = true;
11022 break;
11023 }
11024 }
11025 } while (repeat);
11026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 if (!mRestartingServices.contains(r)) {
11028 mRestartingServices.add(r);
11029 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011030
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011031 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011034 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011036 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011038 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011039 r.shortName, r.restartDelay);
11040
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011041 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 }
11043
11044 final void performServiceRestartLocked(ServiceRecord r) {
11045 if (!mRestartingServices.contains(r)) {
11046 return;
11047 }
11048 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11049 }
11050
11051 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11052 if (r.restartDelay == 0) {
11053 return false;
11054 }
11055 r.resetRestartCounter();
11056 mRestartingServices.remove(r);
11057 mHandler.removeCallbacks(r.restarter);
11058 return true;
11059 }
11060
11061 private final boolean bringUpServiceLocked(ServiceRecord r,
11062 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011063 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 //r.dump(" ");
11065
Dianne Hackborn36124872009-10-08 16:22:03 -070011066 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067 sendServiceArgsLocked(r, false);
11068 return true;
11069 }
11070
11071 if (!whileRestarting && r.restartDelay > 0) {
11072 // If waiting for a restart, then do nothing.
11073 return true;
11074 }
11075
Joe Onorato8a9b2202010-02-26 18:56:32 -080011076 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 + " " + r.intent);
11078
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011079 // We are now bringing the service up, so no longer in the
11080 // restarting state.
11081 mRestartingServices.remove(r);
11082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083 final String appName = r.processName;
11084 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11085 if (app != null && app.thread != null) {
11086 try {
11087 realStartServiceLocked(r, app);
11088 return true;
11089 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011090 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 }
11092
11093 // If a dead object exception was thrown -- fall through to
11094 // restart the application.
11095 }
11096
Dianne Hackborn36124872009-10-08 16:22:03 -070011097 // Not running -- get it started, and enqueue this service record
11098 // to be executed when the app comes up.
11099 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11100 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011101 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011102 + r.appInfo.packageName + "/"
11103 + r.appInfo.uid + " for service "
11104 + r.intent.getIntent() + ": process is bad");
11105 bringDownServiceLocked(r, true);
11106 return false;
11107 }
11108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 mPendingServices.add(r);
11111 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 return true;
11114 }
11115
11116 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011117 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 //r.dump(" ");
11119
11120 // Does it still need to run?
11121 if (!force && r.startRequested) {
11122 return;
11123 }
11124 if (r.connections.size() > 0) {
11125 if (!force) {
11126 // XXX should probably keep a count of the number of auto-create
11127 // connections directly in the service.
11128 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11129 while (it.hasNext()) {
11130 ConnectionRecord cr = it.next();
11131 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11132 return;
11133 }
11134 }
11135 }
11136
11137 // Report to all of the connections that the service is no longer
11138 // available.
11139 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11140 while (it.hasNext()) {
11141 ConnectionRecord c = it.next();
11142 try {
11143 // todo: shouldn't be a synchronous call!
11144 c.conn.connected(r.name, null);
11145 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011146 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011147 " to connection " + c.conn.asBinder() +
11148 " (in " + c.binding.client.processName + ")", e);
11149 }
11150 }
11151 }
11152
11153 // Tell the service that it has been unbound.
11154 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11155 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11156 while (it.hasNext()) {
11157 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011158 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 + ": hasBound=" + ibr.hasBound);
11160 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11161 try {
11162 bumpServiceExecutingLocked(r);
11163 updateOomAdjLocked(r.app);
11164 ibr.hasBound = false;
11165 r.app.thread.scheduleUnbindService(r,
11166 ibr.intent.getIntent());
11167 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011168 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 + r.shortName, e);
11170 serviceDoneExecutingLocked(r, true);
11171 }
11172 }
11173 }
11174 }
11175
Joe Onorato8a9b2202010-02-26 18:56:32 -080011176 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011178 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 System.identityHashCode(r), r.shortName,
11180 (r.app != null) ? r.app.pid : -1);
11181
11182 mServices.remove(r.name);
11183 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011184 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 r.totalRestartCount = 0;
11186 unscheduleServiceRestartLocked(r);
11187
11188 // Also make sure it is not on the pending list.
11189 int N = mPendingServices.size();
11190 for (int i=0; i<N; i++) {
11191 if (mPendingServices.get(i) == r) {
11192 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011193 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 TAG, "Removed pending service: " + r.shortName);
11195 i--;
11196 N--;
11197 }
11198 }
11199
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011200 r.cancelNotification();
11201 r.isForeground = false;
11202 r.foregroundId = 0;
11203 r.foregroundNoti = null;
11204
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011205 // Clear start entries.
11206 r.deliveredStarts.clear();
11207 r.pendingStarts.clear();
11208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209 if (r.app != null) {
11210 synchronized (r.stats.getBatteryStats()) {
11211 r.stats.stopLaunchedLocked();
11212 }
11213 r.app.services.remove(r);
11214 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011216 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011217 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 bumpServiceExecutingLocked(r);
11219 mStoppingServices.add(r);
11220 updateOomAdjLocked(r.app);
11221 r.app.thread.scheduleStopService(r);
11222 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011223 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011224 + r.shortName, e);
11225 serviceDoneExecutingLocked(r, true);
11226 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011227 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011229 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 TAG, "Removed service that has no process: " + r.shortName);
11231 }
11232 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011233 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234 TAG, "Removed service that is not running: " + r.shortName);
11235 }
11236 }
11237
11238 ComponentName startServiceLocked(IApplicationThread caller,
11239 Intent service, String resolvedType,
11240 int callingPid, int callingUid) {
11241 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011242 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 + " type=" + resolvedType + " args=" + service.getExtras());
11244
11245 if (caller != null) {
11246 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11247 if (callerApp == null) {
11248 throw new SecurityException(
11249 "Unable to find app for caller " + caller
11250 + " (pid=" + Binder.getCallingPid()
11251 + ") when starting service " + service);
11252 }
11253 }
11254
11255 ServiceLookupResult res =
11256 retrieveServiceLocked(service, resolvedType,
11257 callingPid, callingUid);
11258 if (res == null) {
11259 return null;
11260 }
11261 if (res.record == null) {
11262 return new ComponentName("!", res.permission != null
11263 ? res.permission : "private to package");
11264 }
11265 ServiceRecord r = res.record;
11266 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011267 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 + r.shortName);
11269 }
11270 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011271 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 r.lastStartId++;
11273 if (r.lastStartId < 1) {
11274 r.lastStartId = 1;
11275 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011276 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011277 r.lastActivity = SystemClock.uptimeMillis();
11278 synchronized (r.stats.getBatteryStats()) {
11279 r.stats.startRunningLocked();
11280 }
11281 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11282 return new ComponentName("!", "Service process is bad");
11283 }
11284 return r.name;
11285 }
11286 }
11287
11288 public ComponentName startService(IApplicationThread caller, Intent service,
11289 String resolvedType) {
11290 // Refuse possible leaked file descriptors
11291 if (service != null && service.hasFileDescriptors() == true) {
11292 throw new IllegalArgumentException("File descriptors passed in Intent");
11293 }
11294
11295 synchronized(this) {
11296 final int callingPid = Binder.getCallingPid();
11297 final int callingUid = Binder.getCallingUid();
11298 final long origId = Binder.clearCallingIdentity();
11299 ComponentName res = startServiceLocked(caller, service,
11300 resolvedType, callingPid, callingUid);
11301 Binder.restoreCallingIdentity(origId);
11302 return res;
11303 }
11304 }
11305
11306 ComponentName startServiceInPackage(int uid,
11307 Intent service, String resolvedType) {
11308 synchronized(this) {
11309 final long origId = Binder.clearCallingIdentity();
11310 ComponentName res = startServiceLocked(null, service,
11311 resolvedType, -1, uid);
11312 Binder.restoreCallingIdentity(origId);
11313 return res;
11314 }
11315 }
11316
11317 public int stopService(IApplicationThread caller, Intent service,
11318 String resolvedType) {
11319 // Refuse possible leaked file descriptors
11320 if (service != null && service.hasFileDescriptors() == true) {
11321 throw new IllegalArgumentException("File descriptors passed in Intent");
11322 }
11323
11324 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011325 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011326 + " type=" + resolvedType);
11327
11328 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11329 if (caller != null && callerApp == null) {
11330 throw new SecurityException(
11331 "Unable to find app for caller " + caller
11332 + " (pid=" + Binder.getCallingPid()
11333 + ") when stopping service " + service);
11334 }
11335
11336 // If this service is active, make sure it is stopped.
11337 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11338 if (r != null) {
11339 if (r.record != null) {
11340 synchronized (r.record.stats.getBatteryStats()) {
11341 r.record.stats.stopRunningLocked();
11342 }
11343 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011344 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 final long origId = Binder.clearCallingIdentity();
11346 bringDownServiceLocked(r.record, false);
11347 Binder.restoreCallingIdentity(origId);
11348 return 1;
11349 }
11350 return -1;
11351 }
11352 }
11353
11354 return 0;
11355 }
11356
11357 public IBinder peekService(Intent service, String resolvedType) {
11358 // Refuse possible leaked file descriptors
11359 if (service != null && service.hasFileDescriptors() == true) {
11360 throw new IllegalArgumentException("File descriptors passed in Intent");
11361 }
11362
11363 IBinder ret = null;
11364
11365 synchronized(this) {
11366 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11367
11368 if (r != null) {
11369 // r.record is null if findServiceLocked() failed the caller permission check
11370 if (r.record == null) {
11371 throw new SecurityException(
11372 "Permission Denial: Accessing service " + r.record.name
11373 + " from pid=" + Binder.getCallingPid()
11374 + ", uid=" + Binder.getCallingUid()
11375 + " requires " + r.permission);
11376 }
11377 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11378 if (ib != null) {
11379 ret = ib.binder;
11380 }
11381 }
11382 }
11383
11384 return ret;
11385 }
11386
11387 public boolean stopServiceToken(ComponentName className, IBinder token,
11388 int startId) {
11389 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011390 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 + " " + token + " startId=" + startId);
11392 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011393 if (r != null) {
11394 if (startId >= 0) {
11395 // Asked to only stop if done with all work. Note that
11396 // to avoid leaks, we will take this as dropping all
11397 // start items up to and including this one.
11398 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11399 if (si != null) {
11400 while (r.deliveredStarts.size() > 0) {
11401 if (r.deliveredStarts.remove(0) == si) {
11402 break;
11403 }
11404 }
11405 }
11406
11407 if (r.lastStartId != startId) {
11408 return false;
11409 }
11410
11411 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011412 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011413 + " is last, but have " + r.deliveredStarts.size()
11414 + " remaining args");
11415 }
11416 }
11417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 synchronized (r.stats.getBatteryStats()) {
11419 r.stats.stopRunningLocked();
11420 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011421 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 }
11423 final long origId = Binder.clearCallingIdentity();
11424 bringDownServiceLocked(r, false);
11425 Binder.restoreCallingIdentity(origId);
11426 return true;
11427 }
11428 }
11429 return false;
11430 }
11431
11432 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011433 int id, Notification notification, boolean removeNotification) {
11434 final long origId = Binder.clearCallingIdentity();
11435 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 synchronized(this) {
11437 ServiceRecord r = findServiceLocked(className, token);
11438 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011439 if (id != 0) {
11440 if (notification == null) {
11441 throw new IllegalArgumentException("null notification");
11442 }
11443 if (r.foregroundId != id) {
11444 r.cancelNotification();
11445 r.foregroundId = id;
11446 }
11447 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11448 r.foregroundNoti = notification;
11449 r.isForeground = true;
11450 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 if (r.app != null) {
11452 updateServiceForegroundLocked(r.app, true);
11453 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011454 } else {
11455 if (r.isForeground) {
11456 r.isForeground = false;
11457 if (r.app != null) {
11458 updateServiceForegroundLocked(r.app, true);
11459 }
11460 }
11461 if (removeNotification) {
11462 r.cancelNotification();
11463 r.foregroundId = 0;
11464 r.foregroundNoti = null;
11465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011466 }
11467 }
11468 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011469 } finally {
11470 Binder.restoreCallingIdentity(origId);
11471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 }
11473
11474 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11475 boolean anyForeground = false;
11476 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11477 if (sr.isForeground) {
11478 anyForeground = true;
11479 break;
11480 }
11481 }
11482 if (anyForeground != proc.foregroundServices) {
11483 proc.foregroundServices = anyForeground;
11484 if (oomAdj) {
11485 updateOomAdjLocked();
11486 }
11487 }
11488 }
11489
11490 public int bindService(IApplicationThread caller, IBinder token,
11491 Intent service, String resolvedType,
11492 IServiceConnection connection, int flags) {
11493 // Refuse possible leaked file descriptors
11494 if (service != null && service.hasFileDescriptors() == true) {
11495 throw new IllegalArgumentException("File descriptors passed in Intent");
11496 }
11497
11498 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011499 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 + " type=" + resolvedType + " conn=" + connection.asBinder()
11501 + " flags=0x" + Integer.toHexString(flags));
11502 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11503 if (callerApp == null) {
11504 throw new SecurityException(
11505 "Unable to find app for caller " + caller
11506 + " (pid=" + Binder.getCallingPid()
11507 + ") when binding service " + service);
11508 }
11509
11510 HistoryRecord activity = null;
11511 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011512 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011514 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515 return 0;
11516 }
11517 activity = (HistoryRecord)mHistory.get(aindex);
11518 }
11519
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011520 int clientLabel = 0;
11521 PendingIntent clientIntent = null;
11522
11523 if (callerApp.info.uid == Process.SYSTEM_UID) {
11524 // Hacky kind of thing -- allow system stuff to tell us
11525 // what they are, so we can report this elsewhere for
11526 // others to know why certain services are running.
11527 try {
11528 clientIntent = (PendingIntent)service.getParcelableExtra(
11529 Intent.EXTRA_CLIENT_INTENT);
11530 } catch (RuntimeException e) {
11531 }
11532 if (clientIntent != null) {
11533 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11534 if (clientLabel != 0) {
11535 // There are no useful extras in the intent, trash them.
11536 // System code calling with this stuff just needs to know
11537 // this will happen.
11538 service = service.cloneFilter();
11539 }
11540 }
11541 }
11542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 ServiceLookupResult res =
11544 retrieveServiceLocked(service, resolvedType,
11545 Binder.getCallingPid(), Binder.getCallingUid());
11546 if (res == null) {
11547 return 0;
11548 }
11549 if (res.record == null) {
11550 return -1;
11551 }
11552 ServiceRecord s = res.record;
11553
11554 final long origId = Binder.clearCallingIdentity();
11555
11556 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011557 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011558 + s.shortName);
11559 }
11560
11561 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11562 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011563 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564
11565 IBinder binder = connection.asBinder();
11566 s.connections.put(binder, c);
11567 b.connections.add(c);
11568 if (activity != null) {
11569 if (activity.connections == null) {
11570 activity.connections = new HashSet<ConnectionRecord>();
11571 }
11572 activity.connections.add(c);
11573 }
11574 b.client.connections.add(c);
11575 mServiceConnections.put(binder, c);
11576
11577 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11578 s.lastActivity = SystemClock.uptimeMillis();
11579 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11580 return 0;
11581 }
11582 }
11583
11584 if (s.app != null) {
11585 // This could have made the service more important.
11586 updateOomAdjLocked(s.app);
11587 }
11588
Joe Onorato8a9b2202010-02-26 18:56:32 -080011589 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 + ": received=" + b.intent.received
11591 + " apps=" + b.intent.apps.size()
11592 + " doRebind=" + b.intent.doRebind);
11593
11594 if (s.app != null && b.intent.received) {
11595 // Service is already running, so we can immediately
11596 // publish the connection.
11597 try {
11598 c.conn.connected(s.name, b.intent.binder);
11599 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011600 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011601 + " to connection " + c.conn.asBinder()
11602 + " (in " + c.binding.client.processName + ")", e);
11603 }
11604
11605 // If this is the first app connected back to this binding,
11606 // and the service had previously asked to be told when
11607 // rebound, then do so.
11608 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11609 requestServiceBindingLocked(s, b.intent, true);
11610 }
11611 } else if (!b.intent.requested) {
11612 requestServiceBindingLocked(s, b.intent, false);
11613 }
11614
11615 Binder.restoreCallingIdentity(origId);
11616 }
11617
11618 return 1;
11619 }
11620
11621 private void removeConnectionLocked(
11622 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11623 IBinder binder = c.conn.asBinder();
11624 AppBindRecord b = c.binding;
11625 ServiceRecord s = b.service;
11626 s.connections.remove(binder);
11627 b.connections.remove(c);
11628 if (c.activity != null && c.activity != skipAct) {
11629 if (c.activity.connections != null) {
11630 c.activity.connections.remove(c);
11631 }
11632 }
11633 if (b.client != skipApp) {
11634 b.client.connections.remove(c);
11635 }
11636 mServiceConnections.remove(binder);
11637
11638 if (b.connections.size() == 0) {
11639 b.intent.apps.remove(b.client);
11640 }
11641
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 + ": shouldUnbind=" + b.intent.hasBound);
11644 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11645 && b.intent.hasBound) {
11646 try {
11647 bumpServiceExecutingLocked(s);
11648 updateOomAdjLocked(s.app);
11649 b.intent.hasBound = false;
11650 // Assume the client doesn't want to know about a rebind;
11651 // we will deal with that later if it asks for one.
11652 b.intent.doRebind = false;
11653 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11654 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011655 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011656 serviceDoneExecutingLocked(s, true);
11657 }
11658 }
11659
11660 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11661 bringDownServiceLocked(s, false);
11662 }
11663 }
11664
11665 public boolean unbindService(IServiceConnection connection) {
11666 synchronized (this) {
11667 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011668 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 ConnectionRecord r = mServiceConnections.get(binder);
11670 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011671 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 + connection.asBinder());
11673 return false;
11674 }
11675
11676 final long origId = Binder.clearCallingIdentity();
11677
11678 removeConnectionLocked(r, null, null);
11679
11680 if (r.binding.service.app != null) {
11681 // This could have made the service less important.
11682 updateOomAdjLocked(r.binding.service.app);
11683 }
11684
11685 Binder.restoreCallingIdentity(origId);
11686 }
11687
11688 return true;
11689 }
11690
11691 public void publishService(IBinder token, Intent intent, IBinder service) {
11692 // Refuse possible leaked file descriptors
11693 if (intent != null && intent.hasFileDescriptors() == true) {
11694 throw new IllegalArgumentException("File descriptors passed in Intent");
11695 }
11696
11697 synchronized(this) {
11698 if (!(token instanceof ServiceRecord)) {
11699 throw new IllegalArgumentException("Invalid service token");
11700 }
11701 ServiceRecord r = (ServiceRecord)token;
11702
11703 final long origId = Binder.clearCallingIdentity();
11704
Joe Onorato8a9b2202010-02-26 18:56:32 -080011705 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 + " " + intent + ": " + service);
11707 if (r != null) {
11708 Intent.FilterComparison filter
11709 = new Intent.FilterComparison(intent);
11710 IntentBindRecord b = r.bindings.get(filter);
11711 if (b != null && !b.received) {
11712 b.binder = service;
11713 b.requested = true;
11714 b.received = true;
11715 if (r.connections.size() > 0) {
11716 Iterator<ConnectionRecord> it
11717 = r.connections.values().iterator();
11718 while (it.hasNext()) {
11719 ConnectionRecord c = it.next();
11720 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011721 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011723 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011724 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011725 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011726 TAG, "Published intent: " + intent);
11727 continue;
11728 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011729 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 try {
11731 c.conn.connected(r.name, service);
11732 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011733 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011734 " to connection " + c.conn.asBinder() +
11735 " (in " + c.binding.client.processName + ")", e);
11736 }
11737 }
11738 }
11739 }
11740
11741 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11742
11743 Binder.restoreCallingIdentity(origId);
11744 }
11745 }
11746 }
11747
11748 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11749 // Refuse possible leaked file descriptors
11750 if (intent != null && intent.hasFileDescriptors() == true) {
11751 throw new IllegalArgumentException("File descriptors passed in Intent");
11752 }
11753
11754 synchronized(this) {
11755 if (!(token instanceof ServiceRecord)) {
11756 throw new IllegalArgumentException("Invalid service token");
11757 }
11758 ServiceRecord r = (ServiceRecord)token;
11759
11760 final long origId = Binder.clearCallingIdentity();
11761
11762 if (r != null) {
11763 Intent.FilterComparison filter
11764 = new Intent.FilterComparison(intent);
11765 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011766 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 + " at " + b + ": apps="
11768 + (b != null ? b.apps.size() : 0));
11769 if (b != null) {
11770 if (b.apps.size() > 0) {
11771 // Applications have already bound since the last
11772 // unbind, so just rebind right here.
11773 requestServiceBindingLocked(r, b, true);
11774 } else {
11775 // Note to tell the service the next time there is
11776 // a new client.
11777 b.doRebind = true;
11778 }
11779 }
11780
11781 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11782
11783 Binder.restoreCallingIdentity(origId);
11784 }
11785 }
11786 }
11787
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011788 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 synchronized(this) {
11790 if (!(token instanceof ServiceRecord)) {
11791 throw new IllegalArgumentException("Invalid service token");
11792 }
11793 ServiceRecord r = (ServiceRecord)token;
11794 boolean inStopping = mStoppingServices.contains(token);
11795 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011796 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 + ": nesting=" + r.executeNesting
11798 + ", inStopping=" + inStopping);
11799 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011800 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 + " with incorrect token: given " + token
11802 + ", expected " + r);
11803 return;
11804 }
11805
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011806 if (type == 1) {
11807 // This is a call from a service start... take care of
11808 // book-keeping.
11809 r.callStart = true;
11810 switch (res) {
11811 case Service.START_STICKY_COMPATIBILITY:
11812 case Service.START_STICKY: {
11813 // We are done with the associated start arguments.
11814 r.findDeliveredStart(startId, true);
11815 // Don't stop if killed.
11816 r.stopIfKilled = false;
11817 break;
11818 }
11819 case Service.START_NOT_STICKY: {
11820 // We are done with the associated start arguments.
11821 r.findDeliveredStart(startId, true);
11822 if (r.lastStartId == startId) {
11823 // There is no more work, and this service
11824 // doesn't want to hang around if killed.
11825 r.stopIfKilled = true;
11826 }
11827 break;
11828 }
11829 case Service.START_REDELIVER_INTENT: {
11830 // We'll keep this item until they explicitly
11831 // call stop for it, but keep track of the fact
11832 // that it was delivered.
11833 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11834 if (si != null) {
11835 si.deliveryCount = 0;
11836 si.doneExecutingCount++;
11837 // Don't stop if killed.
11838 r.stopIfKilled = true;
11839 }
11840 break;
11841 }
11842 default:
11843 throw new IllegalArgumentException(
11844 "Unknown service start result: " + res);
11845 }
11846 if (res == Service.START_STICKY_COMPATIBILITY) {
11847 r.callStart = false;
11848 }
11849 }
11850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011851 final long origId = Binder.clearCallingIdentity();
11852 serviceDoneExecutingLocked(r, inStopping);
11853 Binder.restoreCallingIdentity(origId);
11854 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011855 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 + " with token " + token);
11857 }
11858 }
11859 }
11860
11861 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11862 r.executeNesting--;
11863 if (r.executeNesting <= 0 && r.app != null) {
11864 r.app.executingServices.remove(r);
11865 if (r.app.executingServices.size() == 0) {
11866 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11867 }
11868 if (inStopping) {
11869 mStoppingServices.remove(r);
11870 }
11871 updateOomAdjLocked(r.app);
11872 }
11873 }
11874
11875 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011876 String anrMessage = null;
11877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878 synchronized(this) {
11879 if (proc.executingServices.size() == 0 || proc.thread == null) {
11880 return;
11881 }
11882 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11883 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11884 ServiceRecord timeout = null;
11885 long nextTime = 0;
11886 while (it.hasNext()) {
11887 ServiceRecord sr = it.next();
11888 if (sr.executingStart < maxTime) {
11889 timeout = sr;
11890 break;
11891 }
11892 if (sr.executingStart > nextTime) {
11893 nextTime = sr.executingStart;
11894 }
11895 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011896 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011897 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011898 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 } else {
11900 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11901 msg.obj = proc;
11902 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11903 }
11904 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011905
11906 if (anrMessage != null) {
11907 appNotResponding(proc, null, null, anrMessage);
11908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 }
11910
11911 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011912 // BACKUP AND RESTORE
11913 // =========================================================
11914
11915 // Cause the target app to be launched if necessary and its backup agent
11916 // instantiated. The backup agent will invoke backupAgentCreated() on the
11917 // activity manager to announce its creation.
11918 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011919 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011920 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11921
11922 synchronized(this) {
11923 // !!! TODO: currently no check here that we're already bound
11924 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11925 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11926 synchronized (stats) {
11927 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11928 }
11929
11930 BackupRecord r = new BackupRecord(ss, app, backupMode);
11931 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11932 // startProcessLocked() returns existing proc's record if it's already running
11933 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011934 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011935 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011936 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011937 return false;
11938 }
11939
11940 r.app = proc;
11941 mBackupTarget = r;
11942 mBackupAppName = app.packageName;
11943
Christopher Tate6fa95972009-06-05 18:43:55 -070011944 // Try not to kill the process during backup
11945 updateOomAdjLocked(proc);
11946
Christopher Tate181fafa2009-05-14 11:12:14 -070011947 // If the process is already attached, schedule the creation of the backup agent now.
11948 // If it is not yet live, this will be done when it attaches to the framework.
11949 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011950 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011951 try {
11952 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11953 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011954 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011955 }
11956 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011957 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011958 }
11959 // Invariants: at this point, the target app process exists and the application
11960 // is either already running or in the process of coming up. mBackupTarget and
11961 // mBackupAppName describe the app, so that when it binds back to the AM we
11962 // know that it's scheduled for a backup-agent operation.
11963 }
11964
11965 return true;
11966 }
11967
11968 // A backup agent has just come up
11969 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011970 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011971 + " = " + agent);
11972
11973 synchronized(this) {
11974 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011975 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011976 return;
11977 }
11978
Christopher Tate043dadc2009-06-02 16:11:00 -070011979 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011980 try {
11981 IBackupManager bm = IBackupManager.Stub.asInterface(
11982 ServiceManager.getService(Context.BACKUP_SERVICE));
11983 bm.agentConnected(agentPackageName, agent);
11984 } catch (RemoteException e) {
11985 // can't happen; the backup manager service is local
11986 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011987 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011988 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011989 } finally {
11990 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011991 }
11992 }
11993 }
11994
11995 // done with this agent
11996 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011997 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011998 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011999 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012000 return;
12001 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012002
12003 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012004 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012005 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012006 return;
12007 }
12008
Christopher Tate181fafa2009-05-14 11:12:14 -070012009 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012010 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012011 return;
12012 }
12013
Christopher Tate6fa95972009-06-05 18:43:55 -070012014 ProcessRecord proc = mBackupTarget.app;
12015 mBackupTarget = null;
12016 mBackupAppName = null;
12017
12018 // Not backing this app up any more; reset its OOM adjustment
12019 updateOomAdjLocked(proc);
12020
Christopher Tatec7b31e32009-06-10 15:49:30 -070012021 // If the app crashed during backup, 'thread' will be null here
12022 if (proc.thread != null) {
12023 try {
12024 proc.thread.scheduleDestroyBackupAgent(appInfo);
12025 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012026 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012027 e.printStackTrace();
12028 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012029 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012030 }
12031 }
12032 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 // BROADCASTS
12034 // =========================================================
12035
Josh Bartel7f208742010-02-25 11:01:44 -060012036 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012037 List cur) {
12038 final ContentResolver resolver = mContext.getContentResolver();
12039 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12040 if (list == null) {
12041 return cur;
12042 }
12043 int N = list.size();
12044 for (int i=0; i<N; i++) {
12045 Intent intent = list.get(i);
12046 if (filter.match(resolver, intent, true, TAG) >= 0) {
12047 if (cur == null) {
12048 cur = new ArrayList<Intent>();
12049 }
12050 cur.add(intent);
12051 }
12052 }
12053 return cur;
12054 }
12055
12056 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012057 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 + mBroadcastsScheduled);
12059
12060 if (mBroadcastsScheduled) {
12061 return;
12062 }
12063 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12064 mBroadcastsScheduled = true;
12065 }
12066
12067 public Intent registerReceiver(IApplicationThread caller,
12068 IIntentReceiver receiver, IntentFilter filter, String permission) {
12069 synchronized(this) {
12070 ProcessRecord callerApp = null;
12071 if (caller != null) {
12072 callerApp = getRecordForAppLocked(caller);
12073 if (callerApp == null) {
12074 throw new SecurityException(
12075 "Unable to find app for caller " + caller
12076 + " (pid=" + Binder.getCallingPid()
12077 + ") when registering receiver " + receiver);
12078 }
12079 }
12080
12081 List allSticky = null;
12082
12083 // Look for any matching sticky broadcasts...
12084 Iterator actions = filter.actionsIterator();
12085 if (actions != null) {
12086 while (actions.hasNext()) {
12087 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012088 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 }
12090 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012091 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 }
12093
12094 // The first sticky in the list is returned directly back to
12095 // the client.
12096 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12097
Joe Onorato8a9b2202010-02-26 18:56:32 -080012098 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012099 + ": " + sticky);
12100
12101 if (receiver == null) {
12102 return sticky;
12103 }
12104
12105 ReceiverList rl
12106 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12107 if (rl == null) {
12108 rl = new ReceiverList(this, callerApp,
12109 Binder.getCallingPid(),
12110 Binder.getCallingUid(), receiver);
12111 if (rl.app != null) {
12112 rl.app.receivers.add(rl);
12113 } else {
12114 try {
12115 receiver.asBinder().linkToDeath(rl, 0);
12116 } catch (RemoteException e) {
12117 return sticky;
12118 }
12119 rl.linkedToDeath = true;
12120 }
12121 mRegisteredReceivers.put(receiver.asBinder(), rl);
12122 }
12123 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12124 rl.add(bf);
12125 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012126 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012127 }
12128 mReceiverResolver.addFilter(bf);
12129
12130 // Enqueue broadcasts for all existing stickies that match
12131 // this filter.
12132 if (allSticky != null) {
12133 ArrayList receivers = new ArrayList();
12134 receivers.add(bf);
12135
12136 int N = allSticky.size();
12137 for (int i=0; i<N; i++) {
12138 Intent intent = (Intent)allSticky.get(i);
12139 BroadcastRecord r = new BroadcastRecord(intent, null,
12140 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012141 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 if (mParallelBroadcasts.size() == 0) {
12143 scheduleBroadcastsLocked();
12144 }
12145 mParallelBroadcasts.add(r);
12146 }
12147 }
12148
12149 return sticky;
12150 }
12151 }
12152
12153 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012154 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012155
12156 boolean doNext = false;
12157
12158 synchronized(this) {
12159 ReceiverList rl
12160 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12161 if (rl != null) {
12162 if (rl.curBroadcast != null) {
12163 BroadcastRecord r = rl.curBroadcast;
12164 doNext = finishReceiverLocked(
12165 receiver.asBinder(), r.resultCode, r.resultData,
12166 r.resultExtras, r.resultAbort, true);
12167 }
12168
12169 if (rl.app != null) {
12170 rl.app.receivers.remove(rl);
12171 }
12172 removeReceiverLocked(rl);
12173 if (rl.linkedToDeath) {
12174 rl.linkedToDeath = false;
12175 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12176 }
12177 }
12178 }
12179
12180 if (!doNext) {
12181 return;
12182 }
12183
12184 final long origId = Binder.clearCallingIdentity();
12185 processNextBroadcast(false);
12186 trimApplications();
12187 Binder.restoreCallingIdentity(origId);
12188 }
12189
12190 void removeReceiverLocked(ReceiverList rl) {
12191 mRegisteredReceivers.remove(rl.receiver.asBinder());
12192 int N = rl.size();
12193 for (int i=0; i<N; i++) {
12194 mReceiverResolver.removeFilter(rl.get(i));
12195 }
12196 }
12197
12198 private final int broadcastIntentLocked(ProcessRecord callerApp,
12199 String callerPackage, Intent intent, String resolvedType,
12200 IIntentReceiver resultTo, int resultCode, String resultData,
12201 Bundle map, String requiredPermission,
12202 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12203 intent = new Intent(intent);
12204
Joe Onorato8a9b2202010-02-26 18:56:32 -080012205 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12207 + " ordered=" + ordered);
12208 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012209 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 }
12211
12212 // Handle special intents: if this broadcast is from the package
12213 // manager about a package being removed, we need to remove all of
12214 // its activities from the history stack.
12215 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12216 intent.getAction());
12217 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12218 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012219 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012220 || uidRemoved) {
12221 if (checkComponentPermission(
12222 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12223 callingPid, callingUid, -1)
12224 == PackageManager.PERMISSION_GRANTED) {
12225 if (uidRemoved) {
12226 final Bundle intentExtras = intent.getExtras();
12227 final int uid = intentExtras != null
12228 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12229 if (uid >= 0) {
12230 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12231 synchronized (bs) {
12232 bs.removeUidStatsLocked(uid);
12233 }
12234 }
12235 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012236 // If resources are unvailble just force stop all
12237 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012238 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012239 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12240 if (list != null && (list.length > 0)) {
12241 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012242 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012243 }
12244 }
12245 } else {
12246 Uri data = intent.getData();
12247 String ssp;
12248 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12249 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12250 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012251 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012253 }
12254 }
12255 }
12256 } else {
12257 String msg = "Permission Denial: " + intent.getAction()
12258 + " broadcast from " + callerPackage + " (pid=" + callingPid
12259 + ", uid=" + callingUid + ")"
12260 + " requires "
12261 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012262 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012263 throw new SecurityException(msg);
12264 }
12265 }
12266
12267 /*
12268 * If this is the time zone changed action, queue up a message that will reset the timezone
12269 * of all currently running processes. This message will get queued up before the broadcast
12270 * happens.
12271 */
12272 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12273 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12274 }
12275
Dianne Hackborn854060af2009-07-09 18:14:31 -070012276 /*
12277 * Prevent non-system code (defined here to be non-persistent
12278 * processes) from sending protected broadcasts.
12279 */
12280 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12281 || callingUid == Process.SHELL_UID || callingUid == 0) {
12282 // Always okay.
12283 } else if (callerApp == null || !callerApp.persistent) {
12284 try {
12285 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12286 intent.getAction())) {
12287 String msg = "Permission Denial: not allowed to send broadcast "
12288 + intent.getAction() + " from pid="
12289 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012290 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012291 throw new SecurityException(msg);
12292 }
12293 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012294 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012295 return BROADCAST_SUCCESS;
12296 }
12297 }
12298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012299 // Add to the sticky list if requested.
12300 if (sticky) {
12301 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12302 callingPid, callingUid)
12303 != PackageManager.PERMISSION_GRANTED) {
12304 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12305 + callingPid + ", uid=" + callingUid
12306 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012307 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 throw new SecurityException(msg);
12309 }
12310 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012311 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012312 + " and enforce permission " + requiredPermission);
12313 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12314 }
12315 if (intent.getComponent() != null) {
12316 throw new SecurityException(
12317 "Sticky broadcasts can't target a specific component");
12318 }
12319 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12320 if (list == null) {
12321 list = new ArrayList<Intent>();
12322 mStickyBroadcasts.put(intent.getAction(), list);
12323 }
12324 int N = list.size();
12325 int i;
12326 for (i=0; i<N; i++) {
12327 if (intent.filterEquals(list.get(i))) {
12328 // This sticky already exists, replace it.
12329 list.set(i, new Intent(intent));
12330 break;
12331 }
12332 }
12333 if (i >= N) {
12334 list.add(new Intent(intent));
12335 }
12336 }
12337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 // Figure out who all will receive this broadcast.
12339 List receivers = null;
12340 List<BroadcastFilter> registeredReceivers = null;
12341 try {
12342 if (intent.getComponent() != null) {
12343 // Broadcast is going to one specific receiver class...
12344 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012345 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 if (ai != null) {
12347 receivers = new ArrayList();
12348 ResolveInfo ri = new ResolveInfo();
12349 ri.activityInfo = ai;
12350 receivers.add(ri);
12351 }
12352 } else {
12353 // Need to resolve the intent to interested receivers...
12354 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12355 == 0) {
12356 receivers =
12357 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012358 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359 }
Mihai Preda074edef2009-05-18 17:13:31 +020012360 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012361 }
12362 } catch (RemoteException ex) {
12363 // pm is in same process, this will never happen.
12364 }
12365
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012366 final boolean replacePending =
12367 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12368
Joe Onorato8a9b2202010-02-26 18:56:32 -080012369 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012370 + " replacePending=" + replacePending);
12371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012372 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12373 if (!ordered && NR > 0) {
12374 // If we are not serializing this broadcast, then send the
12375 // registered receivers separately so they don't wait for the
12376 // components to be launched.
12377 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12378 callerPackage, callingPid, callingUid, requiredPermission,
12379 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012380 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012381 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382 TAG, "Enqueueing parallel broadcast " + r
12383 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012384 boolean replaced = false;
12385 if (replacePending) {
12386 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12387 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012388 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012389 "***** DROPPING PARALLEL: " + intent);
12390 mParallelBroadcasts.set(i, r);
12391 replaced = true;
12392 break;
12393 }
12394 }
12395 }
12396 if (!replaced) {
12397 mParallelBroadcasts.add(r);
12398 scheduleBroadcastsLocked();
12399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012400 registeredReceivers = null;
12401 NR = 0;
12402 }
12403
12404 // Merge into one list.
12405 int ir = 0;
12406 if (receivers != null) {
12407 // A special case for PACKAGE_ADDED: do not allow the package
12408 // being added to see this broadcast. This prevents them from
12409 // using this as a back door to get run as soon as they are
12410 // installed. Maybe in the future we want to have a special install
12411 // broadcast or such for apps, but we'd like to deliberately make
12412 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012413 String skipPackages[] = null;
12414 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12415 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12416 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12417 Uri data = intent.getData();
12418 if (data != null) {
12419 String pkgName = data.getSchemeSpecificPart();
12420 if (pkgName != null) {
12421 skipPackages = new String[] { pkgName };
12422 }
12423 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012424 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012425 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012426 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012427 if (skipPackages != null && (skipPackages.length > 0)) {
12428 for (String skipPackage : skipPackages) {
12429 if (skipPackage != null) {
12430 int NT = receivers.size();
12431 for (int it=0; it<NT; it++) {
12432 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12433 if (curt.activityInfo.packageName.equals(skipPackage)) {
12434 receivers.remove(it);
12435 it--;
12436 NT--;
12437 }
12438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012439 }
12440 }
12441 }
12442
12443 int NT = receivers != null ? receivers.size() : 0;
12444 int it = 0;
12445 ResolveInfo curt = null;
12446 BroadcastFilter curr = null;
12447 while (it < NT && ir < NR) {
12448 if (curt == null) {
12449 curt = (ResolveInfo)receivers.get(it);
12450 }
12451 if (curr == null) {
12452 curr = registeredReceivers.get(ir);
12453 }
12454 if (curr.getPriority() >= curt.priority) {
12455 // Insert this broadcast record into the final list.
12456 receivers.add(it, curr);
12457 ir++;
12458 curr = null;
12459 it++;
12460 NT++;
12461 } else {
12462 // Skip to the next ResolveInfo in the final list.
12463 it++;
12464 curt = null;
12465 }
12466 }
12467 }
12468 while (ir < NR) {
12469 if (receivers == null) {
12470 receivers = new ArrayList();
12471 }
12472 receivers.add(registeredReceivers.get(ir));
12473 ir++;
12474 }
12475
12476 if ((receivers != null && receivers.size() > 0)
12477 || resultTo != null) {
12478 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12479 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012480 receivers, resultTo, resultCode, resultData, map, ordered,
12481 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012482 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012483 TAG, "Enqueueing ordered broadcast " + r
12484 + ": prev had " + mOrderedBroadcasts.size());
12485 if (DEBUG_BROADCAST) {
12486 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012487 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012488 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012489 boolean replaced = false;
12490 if (replacePending) {
12491 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12492 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012493 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012494 "***** DROPPING ORDERED: " + intent);
12495 mOrderedBroadcasts.set(i, r);
12496 replaced = true;
12497 break;
12498 }
12499 }
12500 }
12501 if (!replaced) {
12502 mOrderedBroadcasts.add(r);
12503 scheduleBroadcastsLocked();
12504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012505 }
12506
12507 return BROADCAST_SUCCESS;
12508 }
12509
12510 public final int broadcastIntent(IApplicationThread caller,
12511 Intent intent, String resolvedType, IIntentReceiver resultTo,
12512 int resultCode, String resultData, Bundle map,
12513 String requiredPermission, boolean serialized, boolean sticky) {
12514 // Refuse possible leaked file descriptors
12515 if (intent != null && intent.hasFileDescriptors() == true) {
12516 throw new IllegalArgumentException("File descriptors passed in Intent");
12517 }
12518
12519 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012520 int flags = intent.getFlags();
12521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 if (!mSystemReady) {
12523 // if the caller really truly claims to know what they're doing, go
12524 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012525 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12526 intent = new Intent(intent);
12527 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12528 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012529 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012530 + " before boot completion");
12531 throw new IllegalStateException("Cannot broadcast before boot completed");
12532 }
12533 }
12534
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012535 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12536 throw new IllegalArgumentException(
12537 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12538 }
12539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12541 final int callingPid = Binder.getCallingPid();
12542 final int callingUid = Binder.getCallingUid();
12543 final long origId = Binder.clearCallingIdentity();
12544 int res = broadcastIntentLocked(callerApp,
12545 callerApp != null ? callerApp.info.packageName : null,
12546 intent, resolvedType, resultTo,
12547 resultCode, resultData, map, requiredPermission, serialized,
12548 sticky, callingPid, callingUid);
12549 Binder.restoreCallingIdentity(origId);
12550 return res;
12551 }
12552 }
12553
12554 int broadcastIntentInPackage(String packageName, int uid,
12555 Intent intent, String resolvedType, IIntentReceiver resultTo,
12556 int resultCode, String resultData, Bundle map,
12557 String requiredPermission, boolean serialized, boolean sticky) {
12558 synchronized(this) {
12559 final long origId = Binder.clearCallingIdentity();
12560 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12561 resultTo, resultCode, resultData, map, requiredPermission,
12562 serialized, sticky, -1, uid);
12563 Binder.restoreCallingIdentity(origId);
12564 return res;
12565 }
12566 }
12567
12568 public final void unbroadcastIntent(IApplicationThread caller,
12569 Intent intent) {
12570 // Refuse possible leaked file descriptors
12571 if (intent != null && intent.hasFileDescriptors() == true) {
12572 throw new IllegalArgumentException("File descriptors passed in Intent");
12573 }
12574
12575 synchronized(this) {
12576 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12577 != PackageManager.PERMISSION_GRANTED) {
12578 String msg = "Permission Denial: unbroadcastIntent() from pid="
12579 + Binder.getCallingPid()
12580 + ", uid=" + Binder.getCallingUid()
12581 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012582 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012583 throw new SecurityException(msg);
12584 }
12585 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12586 if (list != null) {
12587 int N = list.size();
12588 int i;
12589 for (i=0; i<N; i++) {
12590 if (intent.filterEquals(list.get(i))) {
12591 list.remove(i);
12592 break;
12593 }
12594 }
12595 }
12596 }
12597 }
12598
12599 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12600 String resultData, Bundle resultExtras, boolean resultAbort,
12601 boolean explicit) {
12602 if (mOrderedBroadcasts.size() == 0) {
12603 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012604 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012605 }
12606 return false;
12607 }
12608 BroadcastRecord r = mOrderedBroadcasts.get(0);
12609 if (r.receiver == null) {
12610 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012611 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012612 }
12613 return false;
12614 }
12615 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012616 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 return false;
12618 }
12619 int state = r.state;
12620 r.state = r.IDLE;
12621 if (state == r.IDLE) {
12622 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012623 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012624 }
12625 }
12626 r.receiver = null;
12627 r.intent.setComponent(null);
12628 if (r.curApp != null) {
12629 r.curApp.curReceiver = null;
12630 }
12631 if (r.curFilter != null) {
12632 r.curFilter.receiverList.curBroadcast = null;
12633 }
12634 r.curFilter = null;
12635 r.curApp = null;
12636 r.curComponent = null;
12637 r.curReceiver = null;
12638 mPendingBroadcast = null;
12639
12640 r.resultCode = resultCode;
12641 r.resultData = resultData;
12642 r.resultExtras = resultExtras;
12643 r.resultAbort = resultAbort;
12644
12645 // We will process the next receiver right now if this is finishing
12646 // an app receiver (which is always asynchronous) or after we have
12647 // come back from calling a receiver.
12648 return state == BroadcastRecord.APP_RECEIVE
12649 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12650 }
12651
12652 public void finishReceiver(IBinder who, int resultCode, String resultData,
12653 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012654 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012655
12656 // Refuse possible leaked file descriptors
12657 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12658 throw new IllegalArgumentException("File descriptors passed in Bundle");
12659 }
12660
12661 boolean doNext;
12662
12663 final long origId = Binder.clearCallingIdentity();
12664
12665 synchronized(this) {
12666 doNext = finishReceiverLocked(
12667 who, resultCode, resultData, resultExtras, resultAbort, true);
12668 }
12669
12670 if (doNext) {
12671 processNextBroadcast(false);
12672 }
12673 trimApplications();
12674
12675 Binder.restoreCallingIdentity(origId);
12676 }
12677
12678 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12679 if (r.nextReceiver > 0) {
12680 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12681 if (curReceiver instanceof BroadcastFilter) {
12682 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012683 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012684 System.identityHashCode(r),
12685 r.intent.getAction(),
12686 r.nextReceiver - 1,
12687 System.identityHashCode(bf));
12688 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012689 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012690 System.identityHashCode(r),
12691 r.intent.getAction(),
12692 r.nextReceiver - 1,
12693 ((ResolveInfo)curReceiver).toString());
12694 }
12695 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012696 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012698 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699 System.identityHashCode(r),
12700 r.intent.getAction(),
12701 r.nextReceiver,
12702 "NONE");
12703 }
12704 }
12705
12706 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012707 ProcessRecord app = null;
12708 String anrMessage = null;
12709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012710 synchronized (this) {
12711 if (mOrderedBroadcasts.size() == 0) {
12712 return;
12713 }
12714 long now = SystemClock.uptimeMillis();
12715 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012716 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012717 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012719 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012720 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012721 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 return;
12723 }
12724
Joe Onorato8a9b2202010-02-26 18:56:32 -080012725 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012726 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012727 r.anrCount++;
12728
12729 // Current receiver has passed its expiration date.
12730 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012731 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012732 return;
12733 }
12734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012735 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012736 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012737 logBroadcastReceiverDiscard(r);
12738 if (curReceiver instanceof BroadcastFilter) {
12739 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12740 if (bf.receiverList.pid != 0
12741 && bf.receiverList.pid != MY_PID) {
12742 synchronized (this.mPidsSelfLocked) {
12743 app = this.mPidsSelfLocked.get(
12744 bf.receiverList.pid);
12745 }
12746 }
12747 } else {
12748 app = r.curApp;
12749 }
12750
12751 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012752 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012753 }
12754
12755 if (mPendingBroadcast == r) {
12756 mPendingBroadcast = null;
12757 }
12758
12759 // Move on to the next receiver.
12760 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12761 r.resultExtras, r.resultAbort, true);
12762 scheduleBroadcastsLocked();
12763 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012764
12765 if (anrMessage != null) {
12766 appNotResponding(app, null, null, anrMessage);
12767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012768 }
12769
12770 private final void processCurBroadcastLocked(BroadcastRecord r,
12771 ProcessRecord app) throws RemoteException {
12772 if (app.thread == null) {
12773 throw new RemoteException();
12774 }
12775 r.receiver = app.thread.asBinder();
12776 r.curApp = app;
12777 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012778 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012779
12780 // Tell the application to launch this receiver.
12781 r.intent.setComponent(r.curComponent);
12782
12783 boolean started = false;
12784 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012785 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012786 "Delivering to component " + r.curComponent
12787 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012788 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012789 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12790 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12791 started = true;
12792 } finally {
12793 if (!started) {
12794 r.receiver = null;
12795 r.curApp = null;
12796 app.curReceiver = null;
12797 }
12798 }
12799
12800 }
12801
12802 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012803 Intent intent, int resultCode, String data, Bundle extras,
12804 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 if (app != null && app.thread != null) {
12806 // If we have an app thread, do the call through that so it is
12807 // correctly ordered with other one-way calls.
12808 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012809 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012810 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012811 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012812 }
12813 }
12814
12815 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12816 BroadcastFilter filter, boolean ordered) {
12817 boolean skip = false;
12818 if (filter.requiredPermission != null) {
12819 int perm = checkComponentPermission(filter.requiredPermission,
12820 r.callingPid, r.callingUid, -1);
12821 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012822 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012823 + r.intent.toString()
12824 + " from " + r.callerPackage + " (pid="
12825 + r.callingPid + ", uid=" + r.callingUid + ")"
12826 + " requires " + filter.requiredPermission
12827 + " due to registered receiver " + filter);
12828 skip = true;
12829 }
12830 }
12831 if (r.requiredPermission != null) {
12832 int perm = checkComponentPermission(r.requiredPermission,
12833 filter.receiverList.pid, filter.receiverList.uid, -1);
12834 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012835 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 + r.intent.toString()
12837 + " to " + filter.receiverList.app
12838 + " (pid=" + filter.receiverList.pid
12839 + ", uid=" + filter.receiverList.uid + ")"
12840 + " requires " + r.requiredPermission
12841 + " due to sender " + r.callerPackage
12842 + " (uid " + r.callingUid + ")");
12843 skip = true;
12844 }
12845 }
12846
12847 if (!skip) {
12848 // If this is not being sent as an ordered broadcast, then we
12849 // don't want to touch the fields that keep track of the current
12850 // state of ordered broadcasts.
12851 if (ordered) {
12852 r.receiver = filter.receiverList.receiver.asBinder();
12853 r.curFilter = filter;
12854 filter.receiverList.curBroadcast = r;
12855 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012856 if (filter.receiverList.app != null) {
12857 // Bump hosting application to no longer be in background
12858 // scheduling class. Note that we can't do that if there
12859 // isn't an app... but we can only be in that case for
12860 // things that directly call the IActivityManager API, which
12861 // are already core system stuff so don't matter for this.
12862 r.curApp = filter.receiverList.app;
12863 filter.receiverList.app.curReceiver = r;
12864 updateOomAdjLocked();
12865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 }
12867 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012868 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012870 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012871 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012872 }
12873 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12874 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012875 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012876 if (ordered) {
12877 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12878 }
12879 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012880 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 if (ordered) {
12882 r.receiver = null;
12883 r.curFilter = null;
12884 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012885 if (filter.receiverList.app != null) {
12886 filter.receiverList.app.curReceiver = null;
12887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 }
12889 }
12890 }
12891 }
12892
Dianne Hackborn12527f92009-11-11 17:39:50 -080012893 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12894 if (r.callingUid < 0) {
12895 // This was from a registerReceiver() call; ignore it.
12896 return;
12897 }
12898 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12899 MAX_BROADCAST_HISTORY-1);
12900 r.finishTime = SystemClock.uptimeMillis();
12901 mBroadcastHistory[0] = r;
12902 }
12903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 private final void processNextBroadcast(boolean fromMsg) {
12905 synchronized(this) {
12906 BroadcastRecord r;
12907
Joe Onorato8a9b2202010-02-26 18:56:32 -080012908 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012909 + mParallelBroadcasts.size() + " broadcasts, "
12910 + mOrderedBroadcasts.size() + " serialized broadcasts");
12911
12912 updateCpuStats();
12913
12914 if (fromMsg) {
12915 mBroadcastsScheduled = false;
12916 }
12917
12918 // First, deliver any non-serialized broadcasts right away.
12919 while (mParallelBroadcasts.size() > 0) {
12920 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012921 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012922 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012923 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012924 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012925 for (int i=0; i<N; i++) {
12926 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012927 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012928 "Delivering non-serialized to registered "
12929 + target + ": " + r);
12930 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12931 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012932 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012933 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012934 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012935 }
12936
12937 // Now take care of the next serialized one...
12938
12939 // If we are waiting for a process to come up to handle the next
12940 // broadcast, then do nothing at this point. Just in case, we
12941 // check that the process we're waiting for still exists.
12942 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012943 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012944 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012945 + mPendingBroadcast.curApp);
12946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012947
12948 boolean isDead;
12949 synchronized (mPidsSelfLocked) {
12950 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12951 }
12952 if (!isDead) {
12953 // It's still alive, so keep waiting
12954 return;
12955 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012956 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 + " died before responding to broadcast");
12958 mPendingBroadcast = null;
12959 }
12960 }
12961
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012962 boolean looped = false;
12963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012964 do {
12965 if (mOrderedBroadcasts.size() == 0) {
12966 // No more broadcasts pending, so all done!
12967 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012968 if (looped) {
12969 // If we had finished the last ordered broadcast, then
12970 // make sure all processes have correct oom and sched
12971 // adjustments.
12972 updateOomAdjLocked();
12973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012974 return;
12975 }
12976 r = mOrderedBroadcasts.get(0);
12977 boolean forceReceive = false;
12978
12979 // Ensure that even if something goes awry with the timeout
12980 // detection, we catch "hung" broadcasts here, discard them,
12981 // and continue to make progress.
12982 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12983 long now = SystemClock.uptimeMillis();
12984 if (r.dispatchTime > 0) {
12985 if ((numReceivers > 0) &&
12986 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012987 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012988 + " now=" + now
12989 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012990 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012991 + " intent=" + r.intent
12992 + " numReceivers=" + numReceivers
12993 + " nextReceiver=" + r.nextReceiver
12994 + " state=" + r.state);
12995 broadcastTimeout(); // forcibly finish this broadcast
12996 forceReceive = true;
12997 r.state = BroadcastRecord.IDLE;
12998 }
12999 }
13000
13001 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013002 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013003 "processNextBroadcast() called when not idle (state="
13004 + r.state + ")");
13005 return;
13006 }
13007
13008 if (r.receivers == null || r.nextReceiver >= numReceivers
13009 || r.resultAbort || forceReceive) {
13010 // No more receivers for this broadcast! Send the final
13011 // result if requested...
13012 if (r.resultTo != null) {
13013 try {
13014 if (DEBUG_BROADCAST) {
13015 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013016 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013017 + " seq=" + seq + " app=" + r.callerApp);
13018 }
13019 performReceive(r.callerApp, r.resultTo,
13020 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013021 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013022 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013023 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013024 }
13025 }
13026
Joe Onorato8a9b2202010-02-26 18:56:32 -080013027 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013028 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13029
Joe Onorato8a9b2202010-02-26 18:56:32 -080013030 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013031 + r);
13032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013033 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013034 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013035 mOrderedBroadcasts.remove(0);
13036 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013037 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013038 continue;
13039 }
13040 } while (r == null);
13041
13042 // Get the next receiver...
13043 int recIdx = r.nextReceiver++;
13044
13045 // Keep track of when this receiver started, and make sure there
13046 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013047 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013048 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013049 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013050
Joe Onorato8a9b2202010-02-26 18:56:32 -080013051 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013052 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013053 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013054 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013055 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013056 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013057 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 }
13059
13060 Object nextReceiver = r.receivers.get(recIdx);
13061 if (nextReceiver instanceof BroadcastFilter) {
13062 // Simple case: this is a registered receiver who gets
13063 // a direct call.
13064 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013065 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013066 "Delivering serialized to registered "
13067 + filter + ": " + r);
13068 deliverToRegisteredReceiver(r, filter, r.ordered);
13069 if (r.receiver == null || !r.ordered) {
13070 // The receiver has already finished, so schedule to
13071 // process the next one.
13072 r.state = BroadcastRecord.IDLE;
13073 scheduleBroadcastsLocked();
13074 }
13075 return;
13076 }
13077
13078 // Hard case: need to instantiate the receiver, possibly
13079 // starting its application process to host it.
13080
13081 ResolveInfo info =
13082 (ResolveInfo)nextReceiver;
13083
13084 boolean skip = false;
13085 int perm = checkComponentPermission(info.activityInfo.permission,
13086 r.callingPid, r.callingUid,
13087 info.activityInfo.exported
13088 ? -1 : info.activityInfo.applicationInfo.uid);
13089 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013090 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013091 + r.intent.toString()
13092 + " from " + r.callerPackage + " (pid=" + r.callingPid
13093 + ", uid=" + r.callingUid + ")"
13094 + " requires " + info.activityInfo.permission
13095 + " due to receiver " + info.activityInfo.packageName
13096 + "/" + info.activityInfo.name);
13097 skip = true;
13098 }
13099 if (r.callingUid != Process.SYSTEM_UID &&
13100 r.requiredPermission != null) {
13101 try {
13102 perm = ActivityThread.getPackageManager().
13103 checkPermission(r.requiredPermission,
13104 info.activityInfo.applicationInfo.packageName);
13105 } catch (RemoteException e) {
13106 perm = PackageManager.PERMISSION_DENIED;
13107 }
13108 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013109 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 + r.intent + " to "
13111 + info.activityInfo.applicationInfo.packageName
13112 + " requires " + r.requiredPermission
13113 + " due to sender " + r.callerPackage
13114 + " (uid " + r.callingUid + ")");
13115 skip = true;
13116 }
13117 }
13118 if (r.curApp != null && r.curApp.crashing) {
13119 // If the target process is crashing, just skip it.
13120 skip = true;
13121 }
13122
13123 if (skip) {
13124 r.receiver = null;
13125 r.curFilter = null;
13126 r.state = BroadcastRecord.IDLE;
13127 scheduleBroadcastsLocked();
13128 return;
13129 }
13130
13131 r.state = BroadcastRecord.APP_RECEIVE;
13132 String targetProcess = info.activityInfo.processName;
13133 r.curComponent = new ComponentName(
13134 info.activityInfo.applicationInfo.packageName,
13135 info.activityInfo.name);
13136 r.curReceiver = info.activityInfo;
13137
13138 // Is this receiver's application already running?
13139 ProcessRecord app = getProcessRecordLocked(targetProcess,
13140 info.activityInfo.applicationInfo.uid);
13141 if (app != null && app.thread != null) {
13142 try {
13143 processCurBroadcastLocked(r, app);
13144 return;
13145 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013146 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013147 + r.curComponent, e);
13148 }
13149
13150 // If a dead object exception was thrown -- fall through to
13151 // restart the application.
13152 }
13153
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013154 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013155 if ((r.curApp=startProcessLocked(targetProcess,
13156 info.activityInfo.applicationInfo, true,
13157 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013158 "broadcast", r.curComponent,
13159 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13160 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 // Ah, this recipient is unavailable. Finish it if necessary,
13162 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013163 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013164 + info.activityInfo.applicationInfo.packageName + "/"
13165 + info.activityInfo.applicationInfo.uid + " for broadcast "
13166 + r.intent + ": process is bad");
13167 logBroadcastReceiverDiscard(r);
13168 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13169 r.resultExtras, r.resultAbort, true);
13170 scheduleBroadcastsLocked();
13171 r.state = BroadcastRecord.IDLE;
13172 return;
13173 }
13174
13175 mPendingBroadcast = r;
13176 }
13177 }
13178
13179 // =========================================================
13180 // INSTRUMENTATION
13181 // =========================================================
13182
13183 public boolean startInstrumentation(ComponentName className,
13184 String profileFile, int flags, Bundle arguments,
13185 IInstrumentationWatcher watcher) {
13186 // Refuse possible leaked file descriptors
13187 if (arguments != null && arguments.hasFileDescriptors()) {
13188 throw new IllegalArgumentException("File descriptors passed in Bundle");
13189 }
13190
13191 synchronized(this) {
13192 InstrumentationInfo ii = null;
13193 ApplicationInfo ai = null;
13194 try {
13195 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013196 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013197 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013198 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199 } catch (PackageManager.NameNotFoundException e) {
13200 }
13201 if (ii == null) {
13202 reportStartInstrumentationFailure(watcher, className,
13203 "Unable to find instrumentation info for: " + className);
13204 return false;
13205 }
13206 if (ai == null) {
13207 reportStartInstrumentationFailure(watcher, className,
13208 "Unable to find instrumentation target package: " + ii.targetPackage);
13209 return false;
13210 }
13211
13212 int match = mContext.getPackageManager().checkSignatures(
13213 ii.targetPackage, ii.packageName);
13214 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13215 String msg = "Permission Denial: starting instrumentation "
13216 + className + " from pid="
13217 + Binder.getCallingPid()
13218 + ", uid=" + Binder.getCallingPid()
13219 + " not allowed because package " + ii.packageName
13220 + " does not have a signature matching the target "
13221 + ii.targetPackage;
13222 reportStartInstrumentationFailure(watcher, className, msg);
13223 throw new SecurityException(msg);
13224 }
13225
13226 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013227 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013228 ProcessRecord app = addAppLocked(ai);
13229 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013230 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013231 app.instrumentationProfileFile = profileFile;
13232 app.instrumentationArguments = arguments;
13233 app.instrumentationWatcher = watcher;
13234 app.instrumentationResultClass = className;
13235 Binder.restoreCallingIdentity(origId);
13236 }
13237
13238 return true;
13239 }
13240
13241 /**
13242 * Report errors that occur while attempting to start Instrumentation. Always writes the
13243 * error to the logs, but if somebody is watching, send the report there too. This enables
13244 * the "am" command to report errors with more information.
13245 *
13246 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13247 * @param cn The component name of the instrumentation.
13248 * @param report The error report.
13249 */
13250 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13251 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013252 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013253 try {
13254 if (watcher != null) {
13255 Bundle results = new Bundle();
13256 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13257 results.putString("Error", report);
13258 watcher.instrumentationStatus(cn, -1, results);
13259 }
13260 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013261 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013262 }
13263 }
13264
13265 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13266 if (app.instrumentationWatcher != null) {
13267 try {
13268 // NOTE: IInstrumentationWatcher *must* be oneway here
13269 app.instrumentationWatcher.instrumentationFinished(
13270 app.instrumentationClass,
13271 resultCode,
13272 results);
13273 } catch (RemoteException e) {
13274 }
13275 }
13276 app.instrumentationWatcher = null;
13277 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013278 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013279 app.instrumentationProfileFile = null;
13280 app.instrumentationArguments = null;
13281
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013282 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 }
13284
13285 public void finishInstrumentation(IApplicationThread target,
13286 int resultCode, Bundle results) {
13287 // Refuse possible leaked file descriptors
13288 if (results != null && results.hasFileDescriptors()) {
13289 throw new IllegalArgumentException("File descriptors passed in Intent");
13290 }
13291
13292 synchronized(this) {
13293 ProcessRecord app = getRecordForAppLocked(target);
13294 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013295 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013296 return;
13297 }
13298 final long origId = Binder.clearCallingIdentity();
13299 finishInstrumentationLocked(app, resultCode, results);
13300 Binder.restoreCallingIdentity(origId);
13301 }
13302 }
13303
13304 // =========================================================
13305 // CONFIGURATION
13306 // =========================================================
13307
13308 public ConfigurationInfo getDeviceConfigurationInfo() {
13309 ConfigurationInfo config = new ConfigurationInfo();
13310 synchronized (this) {
13311 config.reqTouchScreen = mConfiguration.touchscreen;
13312 config.reqKeyboardType = mConfiguration.keyboard;
13313 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013314 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13315 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013316 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13317 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013318 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13319 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13321 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013322 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013323 }
13324 return config;
13325 }
13326
13327 public Configuration getConfiguration() {
13328 Configuration ci;
13329 synchronized(this) {
13330 ci = new Configuration(mConfiguration);
13331 }
13332 return ci;
13333 }
13334
13335 public void updateConfiguration(Configuration values) {
13336 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13337 "updateConfiguration()");
13338
13339 synchronized(this) {
13340 if (values == null && mWindowManager != null) {
13341 // sentinel: fetch the current configuration from the window manager
13342 values = mWindowManager.computeNewConfiguration();
13343 }
13344
13345 final long origId = Binder.clearCallingIdentity();
13346 updateConfigurationLocked(values, null);
13347 Binder.restoreCallingIdentity(origId);
13348 }
13349 }
13350
13351 /**
13352 * Do either or both things: (1) change the current configuration, and (2)
13353 * make sure the given activity is running with the (now) current
13354 * configuration. Returns true if the activity has been left running, or
13355 * false if <var>starting</var> is being destroyed to match the new
13356 * configuration.
13357 */
13358 public boolean updateConfigurationLocked(Configuration values,
13359 HistoryRecord starting) {
13360 int changes = 0;
13361
13362 boolean kept = true;
13363
13364 if (values != null) {
13365 Configuration newConfig = new Configuration(mConfiguration);
13366 changes = newConfig.updateFrom(values);
13367 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013368 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013369 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370 }
13371
Doug Zongker2bec3d42009-12-04 12:52:44 -080013372 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013373
13374 if (values.locale != null) {
13375 saveLocaleLocked(values.locale,
13376 !values.locale.equals(mConfiguration.locale),
13377 values.userSetLocale);
13378 }
13379
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013380 mConfigurationSeq++;
13381 if (mConfigurationSeq <= 0) {
13382 mConfigurationSeq = 1;
13383 }
13384 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013386 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013387
13388 AttributeCache ac = AttributeCache.instance();
13389 if (ac != null) {
13390 ac.updateConfiguration(mConfiguration);
13391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013393 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13394 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13395 msg.obj = new Configuration(mConfiguration);
13396 mHandler.sendMessage(msg);
13397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013398
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013399 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13400 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401 try {
13402 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013403 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013404 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013405 app.thread.scheduleConfigurationChanged(mConfiguration);
13406 }
13407 } catch (Exception e) {
13408 }
13409 }
13410 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013411 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13412 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013413 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13414 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013415 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13416 broadcastIntentLocked(null, null,
13417 new Intent(Intent.ACTION_LOCALE_CHANGED),
13418 null, null, 0, null, null,
13419 null, false, false, MY_PID, Process.SYSTEM_UID);
13420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 }
13422 }
13423
13424 if (changes != 0 && starting == null) {
13425 // If the configuration changed, and the caller is not already
13426 // in the process of starting an activity, then find the top
13427 // activity to check if its configuration needs to change.
13428 starting = topRunningActivityLocked(null);
13429 }
13430
13431 if (starting != null) {
13432 kept = ensureActivityConfigurationLocked(starting, changes);
13433 if (kept) {
13434 // If this didn't result in the starting activity being
13435 // destroyed, then we need to make sure at this point that all
13436 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013437 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013438 + ", ensuring others are correct.");
13439 ensureActivitiesVisibleLocked(starting, changes);
13440 }
13441 }
13442
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013443 if (values != null && mWindowManager != null) {
13444 mWindowManager.setNewConfiguration(mConfiguration);
13445 }
13446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 return kept;
13448 }
13449
13450 private final boolean relaunchActivityLocked(HistoryRecord r,
13451 int changes, boolean andResume) {
13452 List<ResultInfo> results = null;
13453 List<Intent> newIntents = null;
13454 if (andResume) {
13455 results = r.results;
13456 newIntents = r.newIntents;
13457 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013458 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013459 + " with results=" + results + " newIntents=" + newIntents
13460 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013461 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13462 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013463 r.task.taskId, r.shortComponentName);
13464
13465 r.startFreezingScreenLocked(r.app, 0);
13466
13467 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013468 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013469 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013470 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013471 // Note: don't need to call pauseIfSleepingLocked() here, because
13472 // the caller will only pass in 'andResume' if this activity is
13473 // currently resumed, which implies we aren't sleeping.
13474 } catch (RemoteException e) {
13475 return false;
13476 }
13477
13478 if (andResume) {
13479 r.results = null;
13480 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013481 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013482 }
13483
13484 return true;
13485 }
13486
13487 /**
13488 * Make sure the given activity matches the current configuration. Returns
13489 * false if the activity had to be destroyed. Returns true if the
13490 * configuration is the same, or the activity will remain running as-is
13491 * for whatever reason. Ensures the HistoryRecord is updated with the
13492 * correct configuration and all other bookkeeping is handled.
13493 */
13494 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13495 int globalChanges) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013496 if (!mConfigWillChange) {
13497 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13498 "Skipping config check (will change): " + r);
13499 return true;
13500 }
13501
Joe Onorato8a9b2202010-02-26 18:56:32 -080013502 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013503 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013504
13505 // Short circuit: if the two configurations are the exact same
13506 // object (the common case), then there is nothing to do.
13507 Configuration newConfig = mConfiguration;
13508 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013509 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013510 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013511 return true;
13512 }
13513
13514 // We don't worry about activities that are finishing.
13515 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013516 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013517 "Configuration doesn't matter in finishing " + r);
13518 r.stopFreezingScreenLocked(false);
13519 return true;
13520 }
13521
13522 // Okay we now are going to make this activity have the new config.
13523 // But then we need to figure out how it needs to deal with that.
13524 Configuration oldConfig = r.configuration;
13525 r.configuration = newConfig;
13526
13527 // If the activity isn't currently running, just leave the new
13528 // configuration and it will pick that up next time it starts.
13529 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013530 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013531 "Configuration doesn't matter not running " + r);
13532 r.stopFreezingScreenLocked(false);
13533 return true;
13534 }
13535
13536 // If the activity isn't persistent, there is a chance we will
13537 // need to restart it.
13538 if (!r.persistent) {
13539
13540 // Figure out what has changed between the two configurations.
13541 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013542 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013543 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013544 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013545 + Integer.toHexString(r.info.configChanges)
13546 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013547 }
13548 if ((changes&(~r.info.configChanges)) != 0) {
13549 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13550 r.configChangeFlags |= changes;
13551 r.startFreezingScreenLocked(r.app, globalChanges);
13552 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013553 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013554 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013555 destroyActivityLocked(r, true);
13556 } else if (r.state == ActivityState.PAUSING) {
13557 // A little annoying: we are waiting for this activity to
13558 // finish pausing. Let's not do anything now, but just
13559 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013560 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013561 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013562 r.configDestroy = true;
13563 return true;
13564 } else if (r.state == ActivityState.RESUMED) {
13565 // Try to optimize this case: the configuration is changing
13566 // and we need to restart the top, resumed activity.
13567 // Instead of doing the normal handshaking, just say
13568 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013569 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013570 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013571 relaunchActivityLocked(r, r.configChangeFlags, true);
13572 r.configChangeFlags = 0;
13573 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013574 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013575 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013576 relaunchActivityLocked(r, r.configChangeFlags, false);
13577 r.configChangeFlags = 0;
13578 }
13579
13580 // All done... tell the caller we weren't able to keep this
13581 // activity around.
13582 return false;
13583 }
13584 }
13585
13586 // Default case: the activity can handle this new configuration, so
13587 // hand it over. Note that we don't need to give it the new
13588 // configuration, since we always send configuration changes to all
13589 // process when they happen so it can just use whatever configuration
13590 // it last got.
13591 if (r.app != null && r.app.thread != null) {
13592 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013593 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013594 r.app.thread.scheduleActivityConfigurationChanged(r);
13595 } catch (RemoteException e) {
13596 // If process died, whatever.
13597 }
13598 }
13599 r.stopFreezingScreenLocked(false);
13600
13601 return true;
13602 }
13603
13604 /**
13605 * Save the locale. You must be inside a synchronized (this) block.
13606 */
13607 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13608 if(isDiff) {
13609 SystemProperties.set("user.language", l.getLanguage());
13610 SystemProperties.set("user.region", l.getCountry());
13611 }
13612
13613 if(isPersist) {
13614 SystemProperties.set("persist.sys.language", l.getLanguage());
13615 SystemProperties.set("persist.sys.country", l.getCountry());
13616 SystemProperties.set("persist.sys.localevar", l.getVariant());
13617 }
13618 }
13619
13620 // =========================================================
13621 // LIFETIME MANAGEMENT
13622 // =========================================================
13623
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013624 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13625 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013626 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013627 // This adjustment has already been computed. If we are calling
13628 // from the top, we may have already computed our adjustment with
13629 // an earlier hidden adjustment that isn't really for us... if
13630 // so, use the new hidden adjustment.
13631 if (!recursed && app.hidden) {
13632 app.curAdj = hiddenAdj;
13633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013634 return app.curAdj;
13635 }
13636
13637 if (app.thread == null) {
13638 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013639 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013640 return (app.curAdj=EMPTY_APP_ADJ);
13641 }
13642
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013643 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13644 // The max adjustment doesn't allow this app to be anything
13645 // below foreground, so it is not worth doing work for it.
13646 app.adjType = "fixed";
13647 app.adjSeq = mAdjSeq;
13648 app.curRawAdj = app.maxAdj;
13649 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13650 return (app.curAdj=app.maxAdj);
13651 }
13652
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013653 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013654 app.adjSource = null;
13655 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013656 app.empty = false;
13657 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013658
The Android Open Source Project4df24232009-03-05 14:34:35 -080013659 // Determine the importance of the process, starting with most
13660 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013661 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013662 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013663 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013664 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013665 // The last app on the list is the foreground app.
13666 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013667 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013668 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013669 } else if (app.instrumentationClass != null) {
13670 // Don't want to kill running instrumentation.
13671 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013672 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013673 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013674 } else if (app.persistentActivities > 0) {
13675 // Special persistent activities... shouldn't be used these days.
13676 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013677 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013678 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013679 } else if (app.curReceiver != null ||
13680 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13681 // An app that is currently receiving a broadcast also
13682 // counts as being in the foreground.
13683 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013684 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013685 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013686 } else if (app.executingServices.size() > 0) {
13687 // An app that is currently executing a service callback also
13688 // counts as being in the foreground.
13689 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013690 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013691 app.adjType = "exec-service";
13692 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013693 // The user is aware of this app, so make it visible.
13694 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013695 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013696 app.adjType = "foreground-service";
13697 } else if (app.forcingToForeground != null) {
13698 // The user is aware of this app, so make it visible.
13699 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013700 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013701 app.adjType = "force-foreground";
13702 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013703 } else if (app == mHomeProcess) {
13704 // This process is hosting what we currently consider to be the
13705 // home app, so we don't want to let it go into the background.
13706 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013707 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013708 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013709 } else if ((N=app.activities.size()) != 0) {
13710 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013711 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013712 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013713 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013714 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013715 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013716 for (int j=0; j<N; j++) {
13717 if (((HistoryRecord)app.activities.get(j)).visible) {
13718 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013719 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013720 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013721 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013722 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013723 break;
13724 }
13725 }
13726 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013727 // A very not-needed process. If this is lower in the lru list,
13728 // we will push it in to the empty bucket.
13729 app.hidden = true;
13730 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013731 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013732 adj = hiddenAdj;
13733 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 }
13735
Joe Onorato8a9b2202010-02-26 18:56:32 -080013736 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013737
The Android Open Source Project4df24232009-03-05 14:34:35 -080013738 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013739 // there are applications dependent on our services or providers, but
13740 // this gives us a baseline and makes sure we don't get into an
13741 // infinite recursion.
13742 app.adjSeq = mAdjSeq;
13743 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013744
Christopher Tate6fa95972009-06-05 18:43:55 -070013745 if (mBackupTarget != null && app == mBackupTarget.app) {
13746 // If possible we want to avoid killing apps while they're being backed up
13747 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013748 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013749 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013750 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013751 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013752 }
13753 }
13754
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013755 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13756 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013757 final long now = SystemClock.uptimeMillis();
13758 // This process is more important if the top activity is
13759 // bound to the service.
13760 Iterator jt = app.services.iterator();
13761 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13762 ServiceRecord s = (ServiceRecord)jt.next();
13763 if (s.startRequested) {
13764 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13765 // This service has seen some activity within
13766 // recent memory, so we will keep its process ahead
13767 // of the background processes.
13768 if (adj > SECONDARY_SERVER_ADJ) {
13769 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013770 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013771 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013772 }
13773 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013774 // If we have let the service slide into the background
13775 // state, still have some text describing what it is doing
13776 // even though the service no longer has an impact.
13777 if (adj > SECONDARY_SERVER_ADJ) {
13778 app.adjType = "started-bg-services";
13779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013780 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013781 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13782 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013783 Iterator<ConnectionRecord> kt
13784 = s.connections.values().iterator();
13785 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13786 // XXX should compute this based on the max of
13787 // all connected clients.
13788 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013789 if (cr.binding.client == app) {
13790 // Binding to ourself is not interesting.
13791 continue;
13792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013793 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13794 ProcessRecord client = cr.binding.client;
13795 int myHiddenAdj = hiddenAdj;
13796 if (myHiddenAdj > client.hiddenAdj) {
13797 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13798 myHiddenAdj = client.hiddenAdj;
13799 } else {
13800 myHiddenAdj = VISIBLE_APP_ADJ;
13801 }
13802 }
13803 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013804 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013805 if (adj > clientAdj) {
13806 adj = clientAdj > VISIBLE_APP_ADJ
13807 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013808 if (!client.hidden) {
13809 app.hidden = false;
13810 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013811 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013812 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13813 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013814 app.adjSource = cr.binding.client;
13815 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013816 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013817 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13818 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13819 schedGroup = Process.THREAD_GROUP_DEFAULT;
13820 }
13821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013822 }
13823 HistoryRecord a = cr.activity;
13824 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013825 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013826 //}
13827 if (a != null && adj > FOREGROUND_APP_ADJ &&
13828 (a.state == ActivityState.RESUMED
13829 || a.state == ActivityState.PAUSING)) {
13830 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013831 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013832 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013833 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013834 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13835 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013836 app.adjSource = a;
13837 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013838 }
13839 }
13840 }
13841 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013842
13843 // Finally, f this process has active services running in it, we
13844 // would like to avoid killing it unless it would prevent the current
13845 // application from running. By default we put the process in
13846 // with the rest of the background processes; as we scan through
13847 // its services we may bump it up from there.
13848 if (adj > hiddenAdj) {
13849 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013850 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013851 app.adjType = "bg-services";
13852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013853 }
13854
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013855 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13856 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013857 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013858 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13859 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013860 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13861 if (cpr.clients.size() != 0) {
13862 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13863 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13864 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013865 if (client == app) {
13866 // Being our own client is not interesting.
13867 continue;
13868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013869 int myHiddenAdj = hiddenAdj;
13870 if (myHiddenAdj > client.hiddenAdj) {
13871 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13872 myHiddenAdj = client.hiddenAdj;
13873 } else {
13874 myHiddenAdj = FOREGROUND_APP_ADJ;
13875 }
13876 }
13877 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013878 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013879 if (adj > clientAdj) {
13880 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013881 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013882 if (!client.hidden) {
13883 app.hidden = false;
13884 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013885 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013886 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13887 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013888 app.adjSource = client;
13889 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013890 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013891 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13892 schedGroup = Process.THREAD_GROUP_DEFAULT;
13893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013894 }
13895 }
13896 // If the provider has external (non-framework) process
13897 // dependencies, ensure that its adjustment is at least
13898 // FOREGROUND_APP_ADJ.
13899 if (cpr.externals != 0) {
13900 if (adj > FOREGROUND_APP_ADJ) {
13901 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013902 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013903 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013904 app.adjType = "provider";
13905 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013906 }
13907 }
13908 }
13909 }
13910
13911 app.curRawAdj = adj;
13912
Joe Onorato8a9b2202010-02-26 18:56:32 -080013913 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013914 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13915 if (adj > app.maxAdj) {
13916 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013917 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13918 schedGroup = Process.THREAD_GROUP_DEFAULT;
13919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013920 }
13921
13922 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013923 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013925 return adj;
13926 }
13927
13928 /**
13929 * Ask a given process to GC right now.
13930 */
13931 final void performAppGcLocked(ProcessRecord app) {
13932 try {
13933 app.lastRequestedGc = SystemClock.uptimeMillis();
13934 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013935 if (app.reportLowMemory) {
13936 app.reportLowMemory = false;
13937 app.thread.scheduleLowMemory();
13938 } else {
13939 app.thread.processInBackground();
13940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013941 }
13942 } catch (Exception e) {
13943 // whatever.
13944 }
13945 }
13946
13947 /**
13948 * Returns true if things are idle enough to perform GCs.
13949 */
Josh Bartel7f208742010-02-25 11:01:44 -060013950 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013951 return mParallelBroadcasts.size() == 0
13952 && mOrderedBroadcasts.size() == 0
13953 && (mSleeping || (mResumedActivity != null &&
13954 mResumedActivity.idle));
13955 }
13956
13957 /**
13958 * Perform GCs on all processes that are waiting for it, but only
13959 * if things are idle.
13960 */
13961 final void performAppGcsLocked() {
13962 final int N = mProcessesToGc.size();
13963 if (N <= 0) {
13964 return;
13965 }
Josh Bartel7f208742010-02-25 11:01:44 -060013966 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013967 while (mProcessesToGc.size() > 0) {
13968 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013969 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13970 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13971 <= SystemClock.uptimeMillis()) {
13972 // To avoid spamming the system, we will GC processes one
13973 // at a time, waiting a few seconds between each.
13974 performAppGcLocked(proc);
13975 scheduleAppGcsLocked();
13976 return;
13977 } else {
13978 // It hasn't been long enough since we last GCed this
13979 // process... put it in the list to wait for its time.
13980 addProcessToGcListLocked(proc);
13981 break;
13982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013983 }
13984 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013985
13986 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013987 }
13988 }
13989
13990 /**
13991 * If all looks good, perform GCs on all processes waiting for them.
13992 */
13993 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060013994 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013995 performAppGcsLocked();
13996 return;
13997 }
13998 // Still not idle, wait some more.
13999 scheduleAppGcsLocked();
14000 }
14001
14002 /**
14003 * Schedule the execution of all pending app GCs.
14004 */
14005 final void scheduleAppGcsLocked() {
14006 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014007
14008 if (mProcessesToGc.size() > 0) {
14009 // Schedule a GC for the time to the next process.
14010 ProcessRecord proc = mProcessesToGc.get(0);
14011 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14012
14013 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14014 long now = SystemClock.uptimeMillis();
14015 if (when < (now+GC_TIMEOUT)) {
14016 when = now + GC_TIMEOUT;
14017 }
14018 mHandler.sendMessageAtTime(msg, when);
14019 }
14020 }
14021
14022 /**
14023 * Add a process to the array of processes waiting to be GCed. Keeps the
14024 * list in sorted order by the last GC time. The process can't already be
14025 * on the list.
14026 */
14027 final void addProcessToGcListLocked(ProcessRecord proc) {
14028 boolean added = false;
14029 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14030 if (mProcessesToGc.get(i).lastRequestedGc <
14031 proc.lastRequestedGc) {
14032 added = true;
14033 mProcessesToGc.add(i+1, proc);
14034 break;
14035 }
14036 }
14037 if (!added) {
14038 mProcessesToGc.add(0, proc);
14039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014040 }
14041
14042 /**
14043 * Set up to ask a process to GC itself. This will either do it
14044 * immediately, or put it on the list of processes to gc the next
14045 * time things are idle.
14046 */
14047 final void scheduleAppGcLocked(ProcessRecord app) {
14048 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014049 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014050 return;
14051 }
14052 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014053 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014054 scheduleAppGcsLocked();
14055 }
14056 }
14057
14058 private final boolean updateOomAdjLocked(
14059 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14060 app.hiddenAdj = hiddenAdj;
14061
14062 if (app.thread == null) {
14063 return true;
14064 }
14065
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014066 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014067
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014068 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014069 if (app.curRawAdj != app.setRawAdj) {
14070 if (app.curRawAdj > FOREGROUND_APP_ADJ
14071 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14072 // If this app is transitioning from foreground to
14073 // non-foreground, have it do a gc.
14074 scheduleAppGcLocked(app);
14075 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14076 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14077 // Likewise do a gc when an app is moving in to the
14078 // background (such as a service stopping).
14079 scheduleAppGcLocked(app);
14080 }
14081 app.setRawAdj = app.curRawAdj;
14082 }
14083 if (adj != app.setAdj) {
14084 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014085 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014086 TAG, "Set app " + app.processName +
14087 " oom adj to " + adj);
14088 app.setAdj = adj;
14089 } else {
14090 return false;
14091 }
14092 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014093 if (app.setSchedGroup != app.curSchedGroup) {
14094 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014095 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014096 "Setting process group of " + app.processName
14097 + " to " + app.curSchedGroup);
14098 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014099 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014100 try {
14101 Process.setProcessGroup(app.pid, app.curSchedGroup);
14102 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014103 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014104 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014105 e.printStackTrace();
14106 } finally {
14107 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014108 }
14109 }
14110 if (false) {
14111 if (app.thread != null) {
14112 try {
14113 app.thread.setSchedulingGroup(app.curSchedGroup);
14114 } catch (RemoteException e) {
14115 }
14116 }
14117 }
14118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119 }
14120
14121 return true;
14122 }
14123
14124 private final HistoryRecord resumedAppLocked() {
14125 HistoryRecord resumedActivity = mResumedActivity;
14126 if (resumedActivity == null || resumedActivity.app == null) {
14127 resumedActivity = mPausingActivity;
14128 if (resumedActivity == null || resumedActivity.app == null) {
14129 resumedActivity = topRunningActivityLocked(null);
14130 }
14131 }
14132 return resumedActivity;
14133 }
14134
14135 private final boolean updateOomAdjLocked(ProcessRecord app) {
14136 final HistoryRecord TOP_ACT = resumedAppLocked();
14137 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14138 int curAdj = app.curAdj;
14139 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14140 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14141
14142 mAdjSeq++;
14143
14144 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14145 if (res) {
14146 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14147 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14148 if (nowHidden != wasHidden) {
14149 // Changed to/from hidden state, so apps after it in the LRU
14150 // list may also be changed.
14151 updateOomAdjLocked();
14152 }
14153 }
14154 return res;
14155 }
14156
14157 private final boolean updateOomAdjLocked() {
14158 boolean didOomAdj = true;
14159 final HistoryRecord TOP_ACT = resumedAppLocked();
14160 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14161
14162 if (false) {
14163 RuntimeException e = new RuntimeException();
14164 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014165 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014166 }
14167
14168 mAdjSeq++;
14169
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014170 // Let's determine how many processes we have running vs.
14171 // how many slots we have for background processes; we may want
14172 // to put multiple processes in a slot of there are enough of
14173 // them.
14174 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14175 int factor = (mLruProcesses.size()-4)/numSlots;
14176 if (factor < 1) factor = 1;
14177 int step = 0;
14178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014179 // First try updating the OOM adjustment for each of the
14180 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014181 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014182 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14183 while (i > 0) {
14184 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014185 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014186 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014187 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014188 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014189 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014190 step++;
14191 if (step >= factor) {
14192 step = 0;
14193 curHiddenAdj++;
14194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014195 }
14196 } else {
14197 didOomAdj = false;
14198 }
14199 }
14200
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014201 // If we return false, we will fall back on killing processes to
14202 // have a fixed limit. Do this if a limit has been requested; else
14203 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014204 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14205 }
14206
14207 private final void trimApplications() {
14208 synchronized (this) {
14209 int i;
14210
14211 // First remove any unused application processes whose package
14212 // has been removed.
14213 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14214 final ProcessRecord app = mRemovedProcesses.get(i);
14215 if (app.activities.size() == 0
14216 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014217 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014218 TAG, "Exiting empty application process "
14219 + app.processName + " ("
14220 + (app.thread != null ? app.thread.asBinder() : null)
14221 + ")\n");
14222 if (app.pid > 0 && app.pid != MY_PID) {
14223 Process.killProcess(app.pid);
14224 } else {
14225 try {
14226 app.thread.scheduleExit();
14227 } catch (Exception e) {
14228 // Ignore exceptions.
14229 }
14230 }
14231 cleanUpApplicationRecordLocked(app, false, -1);
14232 mRemovedProcesses.remove(i);
14233
14234 if (app.persistent) {
14235 if (app.persistent) {
14236 addAppLocked(app.info);
14237 }
14238 }
14239 }
14240 }
14241
14242 // Now try updating the OOM adjustment for each of the
14243 // application processes based on their current state.
14244 // If the setOomAdj() API is not supported, then go with our
14245 // back-up plan...
14246 if (!updateOomAdjLocked()) {
14247
14248 // Count how many processes are running services.
14249 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014250 for (i=mLruProcesses.size()-1; i>=0; i--) {
14251 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014252
14253 if (app.persistent || app.services.size() != 0
14254 || app.curReceiver != null
14255 || app.persistentActivities > 0) {
14256 // Don't count processes holding services against our
14257 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014258 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014259 TAG, "Not trimming app " + app + " with services: "
14260 + app.services);
14261 numServiceProcs++;
14262 }
14263 }
14264
14265 int curMaxProcs = mProcessLimit;
14266 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14267 if (mAlwaysFinishActivities) {
14268 curMaxProcs = 1;
14269 }
14270 curMaxProcs += numServiceProcs;
14271
14272 // Quit as many processes as we can to get down to the desired
14273 // process count. First remove any processes that no longer
14274 // have activites running in them.
14275 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014276 i<mLruProcesses.size()
14277 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014278 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014279 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014280 // Quit an application only if it is not currently
14281 // running any activities.
14282 if (!app.persistent && app.activities.size() == 0
14283 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014284 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014285 TAG, "Exiting empty application process "
14286 + app.processName + " ("
14287 + (app.thread != null ? app.thread.asBinder() : null)
14288 + ")\n");
14289 if (app.pid > 0 && app.pid != MY_PID) {
14290 Process.killProcess(app.pid);
14291 } else {
14292 try {
14293 app.thread.scheduleExit();
14294 } catch (Exception e) {
14295 // Ignore exceptions.
14296 }
14297 }
14298 // todo: For now we assume the application is not buggy
14299 // or evil, and will quit as a result of our request.
14300 // Eventually we need to drive this off of the death
14301 // notification, and kill the process if it takes too long.
14302 cleanUpApplicationRecordLocked(app, false, i);
14303 i--;
14304 }
14305 }
14306
14307 // If we still have too many processes, now from the least
14308 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014309 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014310 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014311 " of " + curMaxProcs + " processes");
14312 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014313 i<mLruProcesses.size()
14314 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014315 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014316 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014317 // Quit the application only if we have a state saved for
14318 // all of its activities.
14319 boolean canQuit = !app.persistent && app.curReceiver == null
14320 && app.services.size() == 0
14321 && app.persistentActivities == 0;
14322 int NUMA = app.activities.size();
14323 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014324 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014325 TAG, "Looking to quit " + app.processName);
14326 for (j=0; j<NUMA && canQuit; j++) {
14327 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014328 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014329 TAG, " " + r.intent.getComponent().flattenToShortString()
14330 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14331 canQuit = (r.haveState || !r.stateNotNeeded)
14332 && !r.visible && r.stopped;
14333 }
14334 if (canQuit) {
14335 // Finish all of the activities, and then the app itself.
14336 for (j=0; j<NUMA; j++) {
14337 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14338 if (!r.finishing) {
14339 destroyActivityLocked(r, false);
14340 }
14341 r.resultTo = null;
14342 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014343 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014344 + app.processName + " ("
14345 + (app.thread != null ? app.thread.asBinder() : null)
14346 + ")\n");
14347 if (app.pid > 0 && app.pid != MY_PID) {
14348 Process.killProcess(app.pid);
14349 } else {
14350 try {
14351 app.thread.scheduleExit();
14352 } catch (Exception e) {
14353 // Ignore exceptions.
14354 }
14355 }
14356 // todo: For now we assume the application is not buggy
14357 // or evil, and will quit as a result of our request.
14358 // Eventually we need to drive this off of the death
14359 // notification, and kill the process if it takes too long.
14360 cleanUpApplicationRecordLocked(app, false, i);
14361 i--;
14362 //dump();
14363 }
14364 }
14365
14366 }
14367
14368 int curMaxActivities = MAX_ACTIVITIES;
14369 if (mAlwaysFinishActivities) {
14370 curMaxActivities = 1;
14371 }
14372
14373 // Finally, if there are too many activities now running, try to
14374 // finish as many as we can to get back down to the limit.
14375 for ( i=0;
14376 i<mLRUActivities.size()
14377 && mLRUActivities.size() > curMaxActivities;
14378 i++) {
14379 final HistoryRecord r
14380 = (HistoryRecord)mLRUActivities.get(i);
14381
14382 // We can finish this one if we have its icicle saved and
14383 // it is not persistent.
14384 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14385 && r.stopped && !r.persistent && !r.finishing) {
14386 final int origSize = mLRUActivities.size();
14387 destroyActivityLocked(r, true);
14388
14389 // This will remove it from the LRU list, so keep
14390 // our index at the same value. Note that this check to
14391 // see if the size changes is just paranoia -- if
14392 // something unexpected happens, we don't want to end up
14393 // in an infinite loop.
14394 if (origSize > mLRUActivities.size()) {
14395 i--;
14396 }
14397 }
14398 }
14399 }
14400 }
14401
14402 /** This method sends the specified signal to each of the persistent apps */
14403 public void signalPersistentProcesses(int sig) throws RemoteException {
14404 if (sig != Process.SIGNAL_USR1) {
14405 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14406 }
14407
14408 synchronized (this) {
14409 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14410 != PackageManager.PERMISSION_GRANTED) {
14411 throw new SecurityException("Requires permission "
14412 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14413 }
14414
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014415 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14416 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014417 if (r.thread != null && r.persistent) {
14418 Process.sendSignal(r.pid, sig);
14419 }
14420 }
14421 }
14422 }
14423
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014424 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014425 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014426
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014427 try {
14428 synchronized (this) {
14429 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14430 // its own permission.
14431 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14432 != PackageManager.PERMISSION_GRANTED) {
14433 throw new SecurityException("Requires permission "
14434 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014435 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014436
14437 if (start && fd == null) {
14438 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014439 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014440
14441 ProcessRecord proc = null;
14442 try {
14443 int pid = Integer.parseInt(process);
14444 synchronized (mPidsSelfLocked) {
14445 proc = mPidsSelfLocked.get(pid);
14446 }
14447 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014448 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014449
14450 if (proc == null) {
14451 HashMap<String, SparseArray<ProcessRecord>> all
14452 = mProcessNames.getMap();
14453 SparseArray<ProcessRecord> procs = all.get(process);
14454 if (procs != null && procs.size() > 0) {
14455 proc = procs.valueAt(0);
14456 }
14457 }
14458
14459 if (proc == null || proc.thread == null) {
14460 throw new IllegalArgumentException("Unknown process: " + process);
14461 }
14462
14463 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14464 if (isSecure) {
14465 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14466 throw new SecurityException("Process not debuggable: " + proc);
14467 }
14468 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014469
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014470 proc.thread.profilerControl(start, path, fd);
14471 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014472 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014473 }
14474 } catch (RemoteException e) {
14475 throw new IllegalStateException("Process disappeared");
14476 } finally {
14477 if (fd != null) {
14478 try {
14479 fd.close();
14480 } catch (IOException e) {
14481 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014482 }
14483 }
14484 }
14485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014486 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14487 public void monitor() {
14488 synchronized (this) { }
14489 }
14490}